[evolution-data-server/wip/mcrha/libical-glib] Port to libical-glib



commit 02f0186a4b4b19815cee464310e487d5cf422fc0
Author: Milan Crha <mcrha redhat com>
Date:   Thu Apr 25 14:44:15 2019 +0200

    Port to libical-glib

 CMakeLists.txt                                     |   63 +-
 cmake/modules/GObjectIntrospection.cmake           |    8 +-
 config.h.in                                        |   12 -
 .../evolution-data-server-docs.sgml.in             |   24 +-
 po/POTFILES.in                                     |    1 -
 src/CMakeLists.txt                                 |    6 +-
 src/addressbook/CMakeLists.txt                     |    4 +-
 .../backends/caldav/e-cal-backend-caldav.c         |  347 +-
 .../backends/contacts/e-cal-backend-contacts.c     |  205 +-
 src/calendar/backends/file/e-cal-backend-file.c    | 1349 ++--
 .../backends/gtasks/e-cal-backend-gtasks.c         |  250 +-
 src/calendar/backends/http/e-cal-backend-http.c    |  114 +-
 .../backends/weather/e-cal-backend-weather.c       |  286 +-
 src/calendar/libecal/CMakeLists.txt                |   72 +-
 src/calendar/libecal/e-cal-check-timezones.c       |  603 +-
 src/calendar/libecal/e-cal-check-timezones.h       |   39 +-
 src/calendar/libecal/e-cal-client-view.c           |   66 +-
 src/calendar/libecal/e-cal-client-view.h           |   13 +-
 src/calendar/libecal/e-cal-client.c                | 1507 ++--
 src/calendar/libecal/e-cal-client.h                |  167 +-
 .../libecal/e-cal-component-alarm-instance.c       |  265 +
 .../libecal/e-cal-component-alarm-instance.h       |   75 +
 .../libecal/e-cal-component-alarm-repeat.c         |  242 +
 .../libecal/e-cal-component-alarm-repeat.h         |   71 +
 .../libecal/e-cal-component-alarm-trigger.c        |  615 ++
 .../libecal/e-cal-component-alarm-trigger.h        |   96 +
 src/calendar/libecal/e-cal-component-alarm.c       | 1121 +++
 src/calendar/libecal/e-cal-component-alarm.h       |  139 +
 src/calendar/libecal/e-cal-component-alarms.c      |  264 +
 src/calendar/libecal/e-cal-component-alarms.h      |   71 +
 src/calendar/libecal/e-cal-component-attendee.c    |  848 +++
 src/calendar/libecal/e-cal-component-attendee.h    |  133 +
 src/calendar/libecal/e-cal-component-datetime.c    |  299 +
 src/calendar/libecal/e-cal-component-datetime.h    |   74 +
 src/calendar/libecal/e-cal-component-id.c          |  271 +
 src/calendar/libecal/e-cal-component-id.h          |   61 +
 src/calendar/libecal/e-cal-component-organizer.c   |  486 ++
 src/calendar/libecal/e-cal-component-organizer.h   |   88 +
 .../libecal/e-cal-component-parameter-bag.c        |  425 ++
 .../libecal/e-cal-component-parameter-bag.h        |  105 +
 src/calendar/libecal/e-cal-component-period.c      |  369 +
 src/calendar/libecal/e-cal-component-period.h      |   76 +
 .../libecal/e-cal-component-property-bag.c         |  425 ++
 .../libecal/e-cal-component-property-bag.h         |  104 +
 src/calendar/libecal/e-cal-component-range.c       |  235 +
 src/calendar/libecal/e-cal-component-range.h       |   65 +
 src/calendar/libecal/e-cal-component-text.c        |  175 +
 src/calendar/libecal/e-cal-component-text.h        |   54 +
 src/calendar/libecal/e-cal-component.c             | 7232 +++++++-------------
 src/calendar/libecal/e-cal-component.h             |  708 +-
 src/calendar/libecal/e-cal-enums.h                 |  240 +
 src/calendar/libecal/e-cal-recur.c                 | 1718 ++---
 src/calendar/libecal/e-cal-recur.h                 |  136 +-
 src/calendar/libecal/e-cal-system-timezone.c       |   22 +-
 src/calendar/libecal/e-cal-system-timezone.h       |    2 +-
 src/calendar/libecal/e-cal-time-util.c             |  339 +-
 src/calendar/libecal/e-cal-time-util.h             |   85 +-
 src/calendar/libecal/e-cal-types.h                 |  199 -
 src/calendar/libecal/e-cal-util.c                  | 1942 +++---
 src/calendar/libecal/e-cal-util.h                  |  318 +-
 src/calendar/libecal/e-cal-view-private.h          |   37 -
 src/calendar/libecal/e-cal-view.c                  |  383 --
 src/calendar/libecal/e-cal-view.h                  |   93 -
 src/calendar/libecal/e-cal.c                       | 2346 -------
 src/calendar/libecal/e-cal.h                       |  269 -
 src/calendar/libecal/e-reminder-watcher.c          |  499 +-
 src/calendar/libecal/e-reminder-watcher.h          |   37 +-
 src/calendar/libecal/e-timezone-cache.c            |   31 +-
 src/calendar/libecal/e-timezone-cache.h            |   19 +-
 src/calendar/libecal/libecal.h                     |   24 +-
 src/calendar/libecal/libecal.pc.in                 |    6 +-
 src/calendar/libedata-cal/CMakeLists.txt           |   53 +-
 src/calendar/libedata-cal/e-cal-backend-cache.c    |  735 --
 src/calendar/libedata-cal/e-cal-backend-cache.h    |  127 -
 src/calendar/libedata-cal/e-cal-backend-factory.h  |    4 +-
 .../libedata-cal/e-cal-backend-intervaltree.c      |    7 +-
 src/calendar/libedata-cal/e-cal-backend-sexp.c     |  287 +-
 src/calendar/libedata-cal/e-cal-backend-store.c    | 1675 -----
 src/calendar/libedata-cal/e-cal-backend-store.h    |  198 -
 src/calendar/libedata-cal/e-cal-backend-sync.c     |  153 +-
 src/calendar/libedata-cal/e-cal-backend-sync.h     |   25 +-
 src/calendar/libedata-cal/e-cal-backend-util.c     |   18 +-
 src/calendar/libedata-cal/e-cal-backend-util.h     |    2 +-
 src/calendar/libedata-cal/e-cal-backend.c          |  261 +-
 src/calendar/libedata-cal/e-cal-backend.h          |   58 +-
 src/calendar/libedata-cal/e-cal-cache.c            |  830 ++-
 src/calendar/libedata-cal/e-cal-cache.h            |   41 +-
 src/calendar/libedata-cal/e-cal-meta-backend.c     |  992 +--
 src/calendar/libedata-cal/e-cal-meta-backend.h     |   16 +-
 src/calendar/libedata-cal/e-data-cal-factory.c     |   65 +-
 src/calendar/libedata-cal/e-data-cal-view.c        |  101 +-
 src/calendar/libedata-cal/e-data-cal.c             |  364 +-
 src/calendar/libedata-cal/e-data-cal.h             |   85 -
 .../libedata-cal/e-subprocess-cal-factory.c        |   63 +-
 src/calendar/libedata-cal/libedata-cal.h           |    7 +-
 src/calendar/libedata-cal/libedata-cal.pc.in       |    4 +-
 src/camel/providers/imapx/camel-imapx-server.c     |    2 +-
 src/libebackend/e-backend-enums.h                  |   22 -
 src/libebackend/e-server-side-source.c             |    1 +
 src/libedataserver/e-client.c                      |   55 +-
 src/libedataserver/e-client.h                      |   12 +-
 src/libedataserver/e-source-enums.h                |   22 +
 src/libedataserverui/CMakeLists.txt                |    1 +
 src/libedataserverui/e-reminders-widget.c          |   31 +-
 src/libedataserverui/libedataserverui.pc.in        |    2 +-
 .../org.gnome.evolution.dataserver.Calendar.xml    |    6 +
 .../evolution-alarm-notify/e-alarm-notify.c        |   96 +-
 .../evolution-calendar-factory.c                   |    8 +-
 src/vala/CMakeLists.txt                            |   91 +
 src/vala/ECal-2.0.metadata                         |    2 +
 src/vala/EDataCal-2.0.metadata                     |    0
 src/vala/libecal-2.0.deps                          |    3 +
 src/vala/libedata-cal-2.0.deps                     |    3 +
 src/vala/libedataserverui-1.2.deps                 |    1 +
 tests/libecal/CMakeLists.txt                       |  109 +-
 tests/libecal/client/CMakeLists.txt                |   50 -
 .../libecal/client/test-cal-client-bulk-methods.c  |  228 -
 tests/libecal/ecal-test-utils.c                    |  572 --
 tests/libecal/ecal-test-utils.h                    |  126 -
 .../{client => }/test-cal-client-add-timezone.c    |   61 +-
 tests/libecal/test-cal-client-bulk-methods.c       |  407 ++
 .../{client => }/test-cal-client-create-object.c   |  159 +-
 .../test-cal-client-get-attachment-uris.c          |   54 +-
 .../{client => }/test-cal-client-get-free-busy.c   |   19 +-
 .../{client => }/test-cal-client-get-object-list.c |   55 +-
 .../{client => }/test-cal-client-get-revision.c    |   28 +-
 .../{client => }/test-cal-client-get-view.c        |   39 +-
 .../{client => }/test-cal-client-modify-object.c   |   65 +-
 .../{client => }/test-cal-client-receive-objects.c |   45 +-
 .../libecal/{client => }/test-cal-client-refresh.c |   26 +-
 .../{client => }/test-cal-client-remove-object.c   |   32 +-
 .../{client => }/test-cal-client-revision-view.c   |  104 +-
 .../{client => }/test-cal-client-send-objects.c    |   90 +-
 tests/libecal/test-cal-component.c                 | 4022 +++++++++++
 tests/libecal/test-cal-recur.c                     |  407 ++
 tests/libecal/test-ecal-add-timezone.c             |   78 -
 tests/libecal/test-ecal-create-object--2.c         |   74 -
 tests/libecal/test-ecal-create-object.c            |   69 -
 tests/libecal/test-ecal-get-alarm-email-address.c  |   56 -
 tests/libecal/test-ecal-get-cal-address.c          |   56 -
 tests/libecal/test-ecal-get-capabilities.c         |   52 -
 tests/libecal/test-ecal-get-default-object.c       |   60 -
 tests/libecal/test-ecal-get-free-busy.c            |  134 -
 tests/libecal/test-ecal-get-ldap-attribute.c       |   62 -
 tests/libecal/test-ecal-get-object-list.c          |   83 -
 tests/libecal/test-ecal-get-objects-for-uid.c      |   82 -
 tests/libecal/test-ecal-get-query.c                |  219 -
 tests/libecal/test-ecal-get-timezone.c             |   59 -
 tests/libecal/test-ecal-modify-object.c            |   98 -
 tests/libecal/test-ecal-receive-objects.c          |   67 -
 tests/libecal/test-ecal-recur-description.c        |  216 -
 tests/libecal/test-ecal-remove-object.c            |   70 -
 tests/libecal/test-ecal-send-objects.c             |   76 -
 tests/libecal/test-ecal-set-default-timezone.c     |   82 -
 tests/libedata-cal/components/event-8.ics          |    4 +-
 tests/libedata-cal/components/event-9.ics          |    6 +-
 tests/libedata-cal/components/invite-1.ics         |    4 +-
 tests/libedata-cal/components/invite-2.ics         |    4 +-
 tests/libedata-cal/components/invite-3.ics         |    4 +-
 tests/libedata-cal/components/invite-4.ics         |    4 +-
 tests/libedata-cal/components/invite-5.ics         |    4 +-
 tests/libedata-cal/components/invite-6.ics         |    4 +-
 tests/libedata-cal/components/invite-7.ics         |    8 +-
 tests/libedata-cal/test-cal-backend-sexp.c         |    2 +
 tests/libedata-cal/test-cal-cache-getters.c        |   24 +-
 tests/libedata-cal/test-cal-cache-intervals.c      |   65 +-
 tests/libedata-cal/test-cal-cache-offline.c        |  143 +-
 tests/libedata-cal/test-cal-cache-search.c         |   33 +-
 tests/libedata-cal/test-cal-cache-utils.c          |    2 +-
 tests/libedata-cal/test-cal-meta-backend.c         |  901 +--
 tests/libedata-cal/test-intervaltree.c             |  114 +-
 tests/test-server-utils/e-test-server-utils.c      |   47 +-
 tests/test-server-utils/e-test-server-utils.h      |   11 +-
 tests/test-server-utils/test-fixture.c             |   16 -
 174 files changed, 23292 insertions(+), 22101 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2490f34b2..8f4eafcd8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,9 @@ set(BASE_VERSION 3.34)
 # library names for backward compatibility.
 set(API_VERSION 1.2)
 
+# API version of the calendar part
+set(CAL_API_VERSION 2.0)
+
 # Required for FindIntltool module
 set(GETTEXT_PACKAGE ${PROJECT_NAME})
 set(GETTEXT_PO_DIR ${CMAKE_SOURCE_DIR}/po)
@@ -38,7 +41,7 @@ set(PROJECT_DISTCONFIGURE_PARAMS
 # ******************************
 # Actual name can be modified with DBUS_SERVICES_PREFIX option
 set(ADDRESS_BOOK_DBUS_SERVICE_NAME     "org.gnome.evolution.dataserver.AddressBook9")
-set(CALENDAR_DBUS_SERVICE_NAME         "org.gnome.evolution.dataserver.Calendar7")
+set(CALENDAR_DBUS_SERVICE_NAME         "org.gnome.evolution.dataserver.Calendar8")
 set(SOURCES_DBUS_SERVICE_NAME          "org.gnome.evolution.dataserver.Sources5")
 set(USER_PROMPTER_DBUS_SERVICE_NAME    "org.gnome.evolution.dataserver.UserPrompter0")
 
@@ -73,11 +76,11 @@ set(LIBEDATABOOK_CURRENT 25)
 set(LIBEDATABOOK_REVISION 0)
 set(LIBEDATABOOK_AGE 0)
 
-set(LIBECAL_CURRENT 19)
+set(LIBECAL_CURRENT 1)
 set(LIBECAL_REVISION 0)
 set(LIBECAL_AGE 0)
 
-set(LIBEDATACAL_CURRENT 29)
+set(LIBEDATACAL_CURRENT 1)
 set(LIBEDATACAL_REVISION 0)
 set(LIBEDATACAL_AGE 0)
 
@@ -108,7 +111,7 @@ add_definitions(-DSOUP_VERSION_MIN_REQUIRED=${soup_encoded_version})
 
 set(gcr_minimum_version 3.4)
 set(libgdata_minimum_version 0.15.1)
-set(libical_minimum_version 2.0)
+set(libical_glib_minimum_version 3.0.5)
 set(libsecret_minimum_version 0.5)
 set(libxml_minimum_version 2.0.0)
 set(sqlite_minimum_version 3.7.17)
@@ -891,24 +894,6 @@ else(ENABLE_LARGEFILE)
        set(HAVE_O_LARGEFILE OFF)
 endif(ENABLE_LARGEFILE)
 
-# ******************************
-# libical tweaks, part I
-# ******************************
-
-pkg_check_at_least_version(HAVE_LIBICAL_2_0 libical 2.0)
-
-# *****
-# libical.pc from libical-0.43 has a bug in its CFlags.
-# It wants apps to include <libical/ical*.h> but it's CFlags make it difficult
-# to differentiate between <libical/ical.h> and <ical.h>
-# We have fixed all our instances to use <libical/ical.h>.
-# Work-around the buggy CFlags for the 0.43 version.
-# *****
-pkg_check_exact_version(libical_is_0_43 libical 0.43)
-if(libical_is_0_43)
-       pkg_check_variable(LIBICAL_EXTRA_CFLAGS libical includedir)
-endif(libical_is_0_43)
-
 # ******************************
 # subparts flags
 # ******************************
@@ -920,11 +905,11 @@ set(E_DATA_SERVER_LDFLAGS ${E_DATA_SERVER_LDFLAGS} ${MANUAL_NSPR_LIBS} ${MANUAL_
 
 pkg_check_modules(BACKEND REQUIRED gio-2.0 gmodule-2.0 libsecret-1 libsoup-2.4 libxml-2.0)
 pkg_check_modules(ADDRESSBOOK REQUIRED gio-2.0 libxml-2.0 libsoup-2.4 libsecret-1)
-pkg_check_modules(CALENDAR REQUIRED gio-2.0 libical>=${libical_minimum_version} libsoup-2.4 libxml-2.0 
libsecret-1)
+pkg_check_modules(CALENDAR REQUIRED gio-2.0 libical-glib>=${libical_glib_minimum_version} libsoup-2.4 
libxml-2.0 libsecret-1)
 set(ADDRESSBOOK_CFLAGS ${ADDRESSBOOK_CFLAGS} ${PHONENUMBER_DEFINITIONS})
 set(ADDRESSBOOK_INCLUDE_DIRS ${ADDRESSBOOK_INCLUDE_DIRS} ${PHONENUMBER_INCLUDE_DIRS})
 set(ADDRESSBOOK_LDFLAGS ${ADDRESSBOOK_LDFLAGS} ${PHONENUMBER_LDFLAGS})
-set(CALENDAR_CFLAGS ${CALENDAR_CFLAGS} ${LIBICAL_EXTRA_CFLAGS})
+set(CALENDAR_CFLAGS ${CALENDAR_CFLAGS} -DLIBICAL_GLIB_UNSTABLE_API=1)
 
 pkg_check_modules(CAMEL REQUIRED gio-2.0 gmodule-2.0 ${mozilla_nss} ${mozilla_nspr} 
sqlite3>=${sqlite_minimum_version})
 set(CAMEL_CFLAGS ${CAMEL_CFLAGS} ${KRB5_CFLAGS} ${MANUAL_NSS_CFLAGS} ${MANUAL_NSPR_CFLAGS} ${ICU_CFLAGS})
@@ -938,36 +923,6 @@ if(NOT (MANUAL_NSS_INCLUDES STREQUAL ""))
        list(APPEND CAMEL_INCLUDE_DIRS ${MANUAL_NSS_INCLUDES})
 endif(NOT (MANUAL_NSS_INCLUDES STREQUAL ""))
 
-# ******************************
-# libical tweaks, part II (re-using CALENDAR modules)
-# ******************************
-
-set(CMAKE_REQUIRED_DEFINITIONS ${CALENDAR_CFLAGS_OTHER})
-set(CMAKE_REQUIRED_INCLUDES ${CALENDAR_INCLUDE_DIRS})
-set(CMAKE_REQUIRED_LIBRARIES ${CALENDAR_LDFLAGS})
-
-CHECK_C_SOURCE_COMPILES("#include <libical/ical.h>
-                       int main(void) {
-                               ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN);
-                               return 0;
-                       }" HAVE_ICAL_UNKNOWN_TOKEN_HANDLING)
-
-CHECK_C_SOURCE_COMPILES("#include <libical/ical.h>
-                       int main(void) {
-                               icaltzutil_set_exact_vtimezones_support (0);
-                               return 0;
-                       }" HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT)
-
-CHECK_C_SOURCE_COMPILES("#include <libical/ical.h>
-                       int main(void) {
-                               icalproperty_status_to_string (ICAL_STATUS_DELETED);
-                               return 0;
-                       }" HAVE_ICAL_STATUS_DELETED)
-
-unset(CMAKE_REQUIRED_DEFINITIONS)
-unset(CMAKE_REQUIRED_INCLUDES)
-unset(CMAKE_REQUIRED_LIBRARIES)
-
 # ******************************
 # Vala binding
 # ******************************
diff --git a/cmake/modules/GObjectIntrospection.cmake b/cmake/modules/GObjectIntrospection.cmake
index 52dd9bb67..5e00d26d1 100644
--- a/cmake/modules/GObjectIntrospection.cmake
+++ b/cmake/modules/GObjectIntrospection.cmake
@@ -39,7 +39,12 @@ endmacro(_gir_list_prefix)
 macro(_gir_list_prefix_libs _outvar _listvar _prefix)
        set(${_outvar})
        foreach(_item IN LISTS ${_listvar})
-               list(APPEND ${_outvar} ${_prefix}${_item}-${API_VERSION})
+               if(TARGET ${_item})
+                       get_target_property(_output_name ${_item} OUTPUT_NAME)
+                       list(APPEND ${_outvar} ${_prefix}${_output_name})
+               else(TARGET ${_item})
+                       message(FATAL_ERROR "'${_item}' not found as a target, possibly typo or reorder 
target definitions")
+               endif(TARGET ${_item})
        endforeach()
 endmacro(_gir_list_prefix_libs)
 
@@ -150,6 +155,7 @@ macro(gir_add_introspection gir)
                                COMMAND ${G_IR_COMPILER}
                                        ${INTROSPECTION_COMPILER_ARGS}
                                        --includedir=${CMAKE_CURRENT_SOURCE_DIR}
+                                       --includedir=${SHARE_INSTALL_PREFIX}/gir-1.0
                                        ${CMAKE_CURRENT_BINARY_DIR}/${gir}
                                        -o ${CMAKE_CURRENT_BINARY_DIR}/${_typelib}
                                DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${gir}
diff --git a/config.h.in b/config.h.in
index 4f5d97e1c..2343e2444 100644
--- a/config.h.in
+++ b/config.h.in
@@ -174,18 +174,6 @@
 /* Have <et/com_err.h> */
 #cmakedefine HAVE_ET_COM_ERR_H 1
 
-/* Define if compiled with libical 2.0 */
-#cmakedefine HAVE_LIBICAL_2_0 1
-
-/* libical provides ical_set_unknown_token_handling_setting function */
-#cmakedefine HAVE_ICAL_UNKNOWN_TOKEN_HANDLING 1
-
-/* libical provides icaltzutil_set_exact_vtimezones_support function */
-#cmakedefine HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT 1
-
-/* libical has ICAL_STATUS_DELETED icalproperty_status value */
-#cmakedefine HAVE_ICAL_STATUS_DELETED 1
-
 /* Define to 1 if you have the libgdata package */
 #cmakedefine HAVE_LIBGDATA 1
 
diff --git a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in 
b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
index a5ba6f283..f3834222c 100644
--- a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
+++ b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
@@ -148,6 +148,20 @@
       <xi:include href="xml/e-cal-client.xml"/>
       <xi:include href="xml/e-cal-client-view.xml"/>
       <xi:include href="xml/e-cal-component.xml"/>
+      <xi:include href="xml/e-cal-component-alarm.xml"/>
+      <xi:include href="xml/e-cal-component-alarm-instance.xml"/>
+      <xi:include href="xml/e-cal-component-alarm-repeat.xml"/>
+      <xi:include href="xml/e-cal-component-alarms.xml"/>
+      <xi:include href="xml/e-cal-component-alarm-trigger.xml"/>
+      <xi:include href="xml/e-cal-component-attendee.xml"/>
+      <xi:include href="xml/e-cal-component-datetime.xml"/>
+      <xi:include href="xml/e-cal-component-id.xml"/>
+      <xi:include href="xml/e-cal-component-organizer.xml"/>
+      <xi:include href="xml/e-cal-component-parameter-bag.xml"/>
+      <xi:include href="xml/e-cal-component-period.xml"/>
+      <xi:include href="xml/e-cal-component-property-bag.xml"/>
+      <xi:include href="xml/e-cal-component-range.xml"/>
+      <xi:include href="xml/e-cal-component-text.xml"/>
     </chapter>
   </part>
 
@@ -200,10 +214,8 @@
     <chapter>
       <title>Calendar Backend Classes</title>
       <xi:include href="xml/e-cal-backend.xml"/>
-      <xi:include href="xml/e-cal-backend-cache.xml"/>
       <xi:include href="xml/e-cal-backend-factory.xml"/>
       <xi:include href="xml/e-cal-backend-sexp.xml"/>
-      <xi:include href="xml/e-cal-backend-store.xml"/>
       <xi:include href="xml/e-cal-backend-sync.xml"/>
       <xi:include href="xml/e-cal-backend-intervaltree.xml"/>
       <xi:include href="xml/e-cal-cache.xml"/>
@@ -286,7 +298,7 @@
       <xi:include href="xml/e-cal-check-timezones.xml"/>
       <xi:include href="xml/e-timezone-cache.xml"/>
       <xi:include href="xml/e-cal-backend-util.xml"/>
-      <xi:include href="xml/e-cal-types.xml"/>
+      <xi:include href="xml/e-cal-enums.xml"/>
       <xi:include href="xml/e-reminder-watcher.xml"/>
     </chapter>
 
@@ -324,8 +336,6 @@
       <title>Client Deprecated Classes</title>
       <xi:include href="xml/e-book.xml"/>
       <xi:include href="xml/e-book-view.xml"/>
-      <xi:include href="xml/e-cal.xml"/>
-      <xi:include href="xml/e-cal-view.xml"/>
       <xi:include href="xml/e-book-types.xml"/>
     </chapter>
     <chapter>
@@ -347,6 +357,10 @@
     <title>Index of deprecated symbols</title>
     <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
   </index>
+  <index id="api-index-3-36" role="3.36">
+    <title>Index of new symbols in 3.36</title>
+    <xi:include href="xml/api-index-3.36.xml"><xi:fallback /></xi:include>
+  </index>
   <index id="api-index-3-32" role="3.32">
     <title>Index of new symbols in 3.32</title>
     <xi:include href="xml/api-index-3.32.xml"><xi:fallback /></xi:include>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 02a78215e..0e1a75036 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -31,7 +31,6 @@ src/calendar/backends/contacts/e-cal-backend-contacts.c
 src/calendar/backends/file/e-cal-backend-file.c
 src/calendar/backends/http/e-cal-backend-http.c
 src/calendar/backends/weather/e-cal-backend-weather.c
-src/calendar/libecal/e-cal.c
 src/calendar/libecal/e-cal-client.c
 src/calendar/libecal/e-cal-client-view.c
 src/calendar/libecal/e-cal-component.c
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5bb6e9dc7..50ab1cdc9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,8 +1,8 @@
-add_subdirectory(addressbook)
-add_subdirectory(calendar)
 add_subdirectory(camel)
-add_subdirectory(libebackend)
 add_subdirectory(libedataserver)
+add_subdirectory(libebackend)
+add_subdirectory(addressbook)
+add_subdirectory(calendar)
 add_subdirectory(modules)
 add_subdirectory(private)
 add_subdirectory(services)
diff --git a/src/addressbook/CMakeLists.txt b/src/addressbook/CMakeLists.txt
index 85d56e647..815e915e1 100644
--- a/src/addressbook/CMakeLists.txt
+++ b/src/addressbook/CMakeLists.txt
@@ -1,4 +1,4 @@
 add_subdirectory(backends)
-add_subdirectory(libebook)
-add_subdirectory(libebook-contacts)
 add_subdirectory(libedata-book)
+add_subdirectory(libebook-contacts)
+add_subdirectory(libebook)
diff --git a/src/calendar/backends/caldav/e-cal-backend-caldav.c 
b/src/calendar/backends/caldav/e-cal-backend-caldav.c
index 9c1914a8f..7ce3b611f 100644
--- a/src/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/src/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -30,8 +30,8 @@
 
 #define E_CALDAV_X_ETAG "X-EVOLUTION-CALDAV-ETAG"
 
-#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 ECC_ERROR(_code) e_cal_client_error_create (_code, NULL)
+#define ECC_ERROR_EX(_code, _msg) e_cal_client_error_create (_code, _msg)
 
 struct _ECalBackendCalDAVPrivate {
        /* The main WebDAV session  */
@@ -325,37 +325,39 @@ ecb_caldav_disconnect_sync (ECalMetaBackend *meta_backend,
 }
 
 static const gchar *
-ecb_caldav_get_vcalendar_uid (icalcomponent *vcalendar)
+ecb_caldav_get_vcalendar_uid (ICalComponent *vcalendar)
 {
        const gchar *uid = NULL;
-       icalcomponent *subcomp;
+       ICalComponent *subcomp;
 
        g_return_val_if_fail (vcalendar != NULL, NULL);
-       g_return_val_if_fail (icalcomponent_isa (vcalendar) == ICAL_VCALENDAR_COMPONENT, NULL);
+       g_return_val_if_fail (i_cal_component_isa (vcalendar) == I_CAL_VCALENDAR_COMPONENT, NULL);
 
-       for (subcomp = icalcomponent_get_first_component (vcalendar, ICAL_ANY_COMPONENT);
+       for (subcomp = i_cal_component_get_first_component (vcalendar, I_CAL_ANY_COMPONENT);
             subcomp && !uid;
-            subcomp = icalcomponent_get_next_component (vcalendar, ICAL_ANY_COMPONENT)) {
-               icalcomponent_kind kind = icalcomponent_isa (subcomp);
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (vcalendar, 
I_CAL_ANY_COMPONENT)) {
+               ICalComponentKind kind = i_cal_component_isa (subcomp);
 
-               if (kind == ICAL_VEVENT_COMPONENT ||
-                   kind == ICAL_VJOURNAL_COMPONENT ||
-                   kind == ICAL_VTODO_COMPONENT) {
-                       uid = icalcomponent_get_uid (subcomp);
+               if (kind == I_CAL_VEVENT_COMPONENT ||
+                   kind == I_CAL_VJOURNAL_COMPONENT ||
+                   kind == I_CAL_VTODO_COMPONENT) {
+                       uid = i_cal_component_get_uid (subcomp);
                        if (uid && !*uid)
                                uid = NULL;
                }
        }
 
+       g_clear_object (&subcomp);
+
        return uid;
 }
 
 static void
 ecb_caldav_update_nfo_with_vcalendar (ECalMetaBackendInfo *nfo,
-                                     icalcomponent *vcalendar,
+                                     ICalComponent *vcalendar,
                                      const gchar *etag)
 {
-       icalcomponent *subcomp;
+       ICalComponent *subcomp;
        const gchar *uid;
 
        g_return_if_fail (nfo != NULL);
@@ -366,20 +368,20 @@ ecb_caldav_update_nfo_with_vcalendar (ECalMetaBackendInfo *nfo,
        if (!etag || !*etag)
                etag = nfo->revision;
 
-       for (subcomp = icalcomponent_get_first_component (vcalendar, ICAL_ANY_COMPONENT);
+       for (subcomp = i_cal_component_get_first_component (vcalendar, I_CAL_ANY_COMPONENT);
             subcomp;
-            subcomp = icalcomponent_get_next_component (vcalendar, ICAL_ANY_COMPONENT)) {
-               icalcomponent_kind kind = icalcomponent_isa (subcomp);
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (vcalendar, 
I_CAL_ANY_COMPONENT)) {
+               ICalComponentKind kind = i_cal_component_isa (subcomp);
 
-               if (kind == ICAL_VEVENT_COMPONENT ||
-                   kind == ICAL_VJOURNAL_COMPONENT ||
-                   kind == ICAL_VTODO_COMPONENT) {
-                       e_cal_util_set_x_property (subcomp, E_CALDAV_X_ETAG, etag);
+               if (kind == I_CAL_VEVENT_COMPONENT ||
+                   kind == I_CAL_VJOURNAL_COMPONENT ||
+                   kind == I_CAL_VTODO_COMPONENT) {
+                       e_cal_util_component_set_x_property (subcomp, E_CALDAV_X_ETAG, etag);
                }
        }
 
        g_warn_if_fail (nfo->object == NULL);
-       nfo->object = icalcomponent_as_ical_string_r (vcalendar);
+       nfo->object = i_cal_component_as_ical_string_r (vcalendar);
 
        if (!nfo->uid || !*(nfo->uid)) {
                g_free (nfo->uid);
@@ -418,9 +420,9 @@ ecb_caldav_multiget_response_cb (EWebDAVSession *webdav,
                etag = e_webdav_session_util_maybe_dequote (e_xml_xpath_eval_as_string (xpath_ctx, 
"%s/D:getetag", xpath_prop_prefix));
 
                if (calendar_data) {
-                       icalcomponent *vcalendar;
+                       ICalComponent *vcalendar;
 
-                       vcalendar = icalcomponent_new_from_string (calendar_data);
+                       vcalendar = i_cal_component_new_from_string (calendar_data);
                        if (vcalendar) {
                                const gchar *uid;
 
@@ -447,7 +449,7 @@ ecb_caldav_multiget_response_cb (EWebDAVSession *webdav,
                                        }
                                }
 
-                               icalcomponent_free (vcalendar);
+                               g_object_unref (vcalendar);
                        }
                }
 
@@ -511,12 +513,12 @@ ecb_caldav_multiget_from_sets_sync (ECalBackendCalDAV *cbdav,
                                nfo->extra, NULL, &etag, &calendar_data, NULL, cancellable, error);
 
                        if (success && calendar_data) {
-                               icalcomponent *vcalendar;
+                               ICalComponent *vcalendar;
 
-                               vcalendar = icalcomponent_new_from_string (calendar_data);
+                               vcalendar = i_cal_component_new_from_string (calendar_data);
                                if (vcalendar) {
                                        ecb_caldav_update_nfo_with_vcalendar (nfo, vcalendar, etag);
-                                       icalcomponent_free (vcalendar);
+                                       g_object_unref (vcalendar);
                                }
                        }
 
@@ -615,6 +617,7 @@ ecb_caldav_search_changes_cb (ECalCache *cal_cache,
                              const gchar *revision,
                              const gchar *object,
                              const gchar *extra,
+                             guint32 custom_flags,
                              EOfflineState offline_state,
                              gpointer user_data)
 {
@@ -659,19 +662,19 @@ ecb_caldav_check_credentials_error (ECalBackendCalDAV *cbdav,
        g_return_if_fail (E_IS_CAL_BACKEND_CALDAV (cbdav));
 
        if (g_error_matches (op_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) && webdav) {
-               op_error->domain = E_DATA_CAL_ERROR;
-               op_error->code = TLSNotAvailable;
+               op_error->domain = E_CLIENT_ERROR;
+               op_error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
        } else if (g_error_matches (op_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
                   g_error_matches (op_error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN)) {
-               op_error->domain = E_DATA_CAL_ERROR;
-               op_error->code = AuthenticationRequired;
+               op_error->domain = E_CLIENT_ERROR;
+               op_error->code = E_CLIENT_ERROR_AUTHENTICATION_REQUIRED;
 
                if (webdav) {
                        ENamedParameters *credentials;
 
                        credentials = e_soup_session_dup_credentials (E_SOUP_SESSION (webdav));
                        if (credentials && e_named_parameters_count (credentials) > 0)
-                               op_error->code = AuthenticationFailed;
+                               op_error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
 
                        e_named_parameters_free (credentials);
                }
@@ -766,7 +769,7 @@ ecb_caldav_get_changes_sync (ECalMetaBackend *meta_backend,
        }
 
        if (!is_repeat) {
-               icaltimezone *utc = icaltimezone_get_utc_timezone ();
+               ICalTimezone *utc = i_cal_timezone_get_utc_timezone ();
                time_t now;
                gchar *tmp;
 
@@ -875,9 +878,9 @@ ecb_caldav_extract_existing_cb (EWebDAVSession *webdav,
                calendar_data = e_xml_xpath_eval_as_string (xpath_ctx, "%s/C:calendar-data", 
xpath_prop_prefix);
 
                if (calendar_data) {
-                       icalcomponent *vcalendar;
+                       ICalComponent *vcalendar;
 
-                       vcalendar = icalcomponent_new_from_string (calendar_data);
+                       vcalendar = i_cal_component_new_from_string (calendar_data);
                        if (vcalendar) {
                                const gchar *uid;
 
@@ -889,7 +892,7 @@ ecb_caldav_extract_existing_cb (EWebDAVSession *webdav,
                                                e_cal_meta_backend_info_new (uid, etag, NULL, href));
                                }
 
-                               icalcomponent_free (vcalendar);
+                               g_object_unref (vcalendar);
                        }
                }
 
@@ -909,7 +912,7 @@ ecb_caldav_list_existing_sync (ECalMetaBackend *meta_backend,
 {
        ECalBackendCalDAV *cbdav;
        EWebDAVSession *webdav;
-       icalcomponent_kind kind;
+       ICalComponentKind kind;
        EXmlDocument *xml;
        GError *local_error = NULL;
        gboolean success;
@@ -920,7 +923,6 @@ ecb_caldav_list_existing_sync (ECalMetaBackend *meta_backend,
        *out_existing_objects = NULL;
 
        cbdav = E_CAL_BACKEND_CALDAV (meta_backend);
-
        kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbdav));
 
        xml = e_xml_document_new (E_WEBDAV_NS_CALDAV, "calendar-query");
@@ -934,11 +936,11 @@ ecb_caldav_list_existing_sync (ECalMetaBackend *meta_backend,
        e_xml_document_start_element (xml, E_WEBDAV_NS_CALDAV, "comp");
        e_xml_document_add_attribute (xml, NULL, "name", "VCALENDAR");
        e_xml_document_start_element (xml, E_WEBDAV_NS_CALDAV, "comp");
-       if (kind == ICAL_VEVENT_COMPONENT)
+       if (kind == I_CAL_VEVENT_COMPONENT)
                e_xml_document_add_attribute (xml, NULL, "name", "VEVENT");
-       else if (kind == ICAL_VJOURNAL_COMPONENT)
+       else if (kind == I_CAL_VJOURNAL_COMPONENT)
                e_xml_document_add_attribute (xml, NULL, "name", "VJOURNAL");
-       else if (kind == ICAL_VTODO_COMPONENT)
+       else if (kind == I_CAL_VTODO_COMPONENT)
                e_xml_document_add_attribute (xml, NULL, "name", "VTODO");
        else
                g_warn_if_reached ();
@@ -954,11 +956,11 @@ ecb_caldav_list_existing_sync (ECalMetaBackend *meta_backend,
        e_xml_document_start_element (xml, E_WEBDAV_NS_CALDAV, "comp-filter");
        e_xml_document_add_attribute (xml, NULL, "name", "VCALENDAR");
        e_xml_document_start_element (xml, E_WEBDAV_NS_CALDAV, "comp-filter");
-       if (kind == ICAL_VEVENT_COMPONENT)
+       if (kind == I_CAL_VEVENT_COMPONENT)
                e_xml_document_add_attribute (xml, NULL, "name", "VEVENT");
-       else if (kind == ICAL_VJOURNAL_COMPONENT)
+       else if (kind == I_CAL_VJOURNAL_COMPONENT)
                e_xml_document_add_attribute (xml, NULL, "name", "VJOURNAL");
-       else if (kind == ICAL_VTODO_COMPONENT)
+       else if (kind == I_CAL_VTODO_COMPONENT)
                e_xml_document_add_attribute (xml, NULL, "name", "VTODO");
        e_xml_document_end_element (xml); /* comp-filter / VEVENT|VJOURNAL|VTODO */
        e_xml_document_end_element (xml); /* comp-filter / VCALENDAR */
@@ -1042,25 +1044,25 @@ ecb_caldav_uid_to_uri (ECalBackendCalDAV *cbdav,
 }
 
 static void
-ecb_caldav_store_component_etag (icalcomponent *icalcomp,
+ecb_caldav_store_component_etag (ICalComponent *icomp,
                                 const gchar *etag)
 {
-       icalcomponent *subcomp;
+       ICalComponent *subcomp;
 
-       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (icomp != NULL);
        g_return_if_fail (etag != NULL);
 
-       e_cal_util_set_x_property (icalcomp, E_CALDAV_X_ETAG, etag);
+       e_cal_util_component_set_x_property (icomp, E_CALDAV_X_ETAG, etag);
 
-       for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT);
+       for (subcomp = i_cal_component_get_first_component (icomp, I_CAL_ANY_COMPONENT);
             subcomp;
-            subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT)) {
-               icalcomponent_kind kind = icalcomponent_isa (subcomp);
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (icomp, 
I_CAL_ANY_COMPONENT)) {
+               ICalComponentKind kind = i_cal_component_isa (subcomp);
 
-               if (kind == ICAL_VEVENT_COMPONENT ||
-                   kind == ICAL_VJOURNAL_COMPONENT ||
-                   kind == ICAL_VTODO_COMPONENT) {
-                       e_cal_util_set_x_property (subcomp, E_CALDAV_X_ETAG, etag);
+               if (kind == I_CAL_VEVENT_COMPONENT ||
+                   kind == I_CAL_VJOURNAL_COMPONENT ||
+                   kind == I_CAL_VTODO_COMPONENT) {
+                       e_cal_util_component_set_x_property (subcomp, E_CALDAV_X_ETAG, etag);
                }
        }
 }
@@ -1069,7 +1071,7 @@ static gboolean
 ecb_caldav_load_component_sync (ECalMetaBackend *meta_backend,
                                const gchar *uid,
                                const gchar *extra,
-                               icalcomponent **out_component,
+                               ICalComponent **out_component,
                                gchar **out_extra,
                                GCancellable *cancellable,
                                GError **error)
@@ -1096,9 +1098,9 @@ ecb_caldav_load_component_sync (ECalMetaBackend *meta_backend,
 
                newline = strchr (extra, '\n');
                if (newline && newline[1] && newline != extra) {
-                       icalcomponent *vcalendar;
+                       ICalComponent *vcalendar;
 
-                       vcalendar = icalcomponent_new_from_string (newline + 1);
+                       vcalendar = i_cal_component_new_from_string (newline + 1);
                        if (vcalendar) {
                                *out_extra = g_strndup (extra, newline - extra);
                                *out_component = vcalendar;
@@ -1136,7 +1138,7 @@ ecb_caldav_load_component_sync (ECalMetaBackend *meta_backend,
                                g_free (last_sync_tag);
                                g_free (new_sync_tag);
 
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
 
                                return FALSE;
                        }
@@ -1174,14 +1176,14 @@ ecb_caldav_load_component_sync (ECalMetaBackend *meta_backend,
                *out_component = NULL;
 
                if (href && etag && bytes && length != ((gsize) -1)) {
-                       icalcomponent *icalcomp;
+                       ICalComponent *icomp;
 
-                       icalcomp = icalcomponent_new_from_string (bytes);
+                       icomp = i_cal_component_new_from_string (bytes);
 
-                       if (icalcomp) {
-                               ecb_caldav_store_component_etag (icalcomp, etag);
+                       if (icomp) {
+                               ecb_caldav_store_component_etag (icomp, etag);
 
-                               *out_component = icalcomp;
+                               *out_component = icomp;
                        }
                }
 
@@ -1189,11 +1191,11 @@ ecb_caldav_load_component_sync (ECalMetaBackend *meta_backend,
                        success = FALSE;
 
                        if (!href)
-                               g_propagate_error (&local_error, EDC_ERROR_EX (InvalidObject, _("Server 
didn’t return object’s href")));
+                               g_propagate_error (&local_error, ECC_ERROR_EX 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, _("Server didn’t return object’s href")));
                        else if (!etag)
-                               g_propagate_error (&local_error, EDC_ERROR_EX (InvalidObject, _("Server 
didn’t return object’s ETag")));
+                               g_propagate_error (&local_error, ECC_ERROR_EX 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, _("Server didn’t return object’s ETag")));
                        else
-                               g_propagate_error (&local_error, EDC_ERROR (InvalidObject));
+                               g_propagate_error (&local_error, ECC_ERROR 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                } else if (out_extra) {
                        *out_extra = g_strdup (href);
                }
@@ -1220,6 +1222,7 @@ ecb_caldav_save_component_sync (ECalMetaBackend *meta_backend,
                                EConflictResolution conflict_resolution,
                                const GSList *instances,
                                const gchar *extra,
+                               guint32 opflags,
                                gchar **out_new_uid,
                                gchar **out_new_extra,
                                GCancellable *cancellable,
@@ -1227,7 +1230,7 @@ ecb_caldav_save_component_sync (ECalMetaBackend *meta_backend,
 {
        ECalBackendCalDAV *cbdav;
        EWebDAVSession *webdav;
-       icalcomponent *vcalendar, *subcomp;
+       ICalComponent *vcalendar, *subcomp;
        gchar *href = NULL, *etag = NULL, *uid = NULL;
        gchar *ical_string = NULL;
        gboolean success;
@@ -1243,24 +1246,24 @@ ecb_caldav_save_component_sync (ECalMetaBackend *meta_backend,
        vcalendar = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
        g_return_val_if_fail (vcalendar != NULL, FALSE);
 
-       for (subcomp = icalcomponent_get_first_component (vcalendar, ICAL_ANY_COMPONENT);
+       for (subcomp = i_cal_component_get_first_component (vcalendar, I_CAL_ANY_COMPONENT);
             subcomp;
-            subcomp = icalcomponent_get_next_component (vcalendar, ICAL_ANY_COMPONENT)) {
-               icalcomponent_kind kind = icalcomponent_isa (subcomp);
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (vcalendar, 
I_CAL_ANY_COMPONENT)) {
+               ICalComponentKind kind = i_cal_component_isa (subcomp);
 
-               if (kind == ICAL_VEVENT_COMPONENT ||
-                   kind == ICAL_VJOURNAL_COMPONENT ||
-                   kind == ICAL_VTODO_COMPONENT) {
+               if (kind == I_CAL_VEVENT_COMPONENT ||
+                   kind == I_CAL_VJOURNAL_COMPONENT ||
+                   kind == I_CAL_VTODO_COMPONENT) {
                        if (!etag)
-                               etag = e_cal_util_dup_x_property (subcomp, E_CALDAV_X_ETAG);
+                               etag = e_cal_util_component_dup_x_property (subcomp, E_CALDAV_X_ETAG);
                        if (!uid)
-                               uid = g_strdup (icalcomponent_get_uid (subcomp));
+                               uid = g_strdup (i_cal_component_get_uid (subcomp));
 
-                       e_cal_util_remove_x_property (subcomp, E_CALDAV_X_ETAG);
+                       e_cal_util_component_remove_x_property (subcomp, E_CALDAV_X_ETAG);
                }
        }
 
-       ical_string = icalcomponent_as_ical_string_r (vcalendar);
+       ical_string = i_cal_component_as_ical_string_r (vcalendar);
 
        webdav = ecb_caldav_ref_session (cbdav);
 
@@ -1297,7 +1300,7 @@ ecb_caldav_save_component_sync (ECalMetaBackend *meta_backend,
                                ecb_caldav_store_component_etag (vcalendar, new_etag);
 
                                g_free (ical_string);
-                               ical_string = icalcomponent_as_ical_string_r (vcalendar);
+                               ical_string = i_cal_component_as_ical_string_r (vcalendar);
 
                                /* Encodes the href and the component into one string, which
                                   will be decoded in the load function */
@@ -1319,13 +1322,13 @@ ecb_caldav_save_component_sync (ECalMetaBackend *meta_backend,
                g_free (new_etag);
        } else if (uid && ical_string) {
                success = FALSE;
-               g_propagate_error (error, EDC_ERROR_EX (InvalidObject, _("Missing information about component 
URL, local cache is possibly incomplete or broken. Remove it, please.")));
+               g_propagate_error (error, ECC_ERROR_EX (E_CAL_CLIENT_ERROR_INVALID_OBJECT, _("Missing 
information about component URL, local cache is possibly incomplete or broken. Remove it, please.")));
        } else {
                success = FALSE;
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
        }
 
-       icalcomponent_free (vcalendar);
+       g_object_unref (vcalendar);
        g_free (ical_string);
        g_free (href);
        g_free (etag);
@@ -1347,12 +1350,13 @@ ecb_caldav_remove_component_sync (ECalMetaBackend *meta_backend,
                                  const gchar *uid,
                                  const gchar *extra,
                                  const gchar *object,
+                                 guint32 opflags,
                                  GCancellable *cancellable,
                                  GError **error)
 {
        ECalBackendCalDAV *cbdav;
        EWebDAVSession *webdav;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        gchar *etag = NULL;
        gboolean success;
        GError *local_error = NULL;
@@ -1364,18 +1368,18 @@ ecb_caldav_remove_component_sync (ECalMetaBackend *meta_backend,
        cbdav = E_CAL_BACKEND_CALDAV (meta_backend);
 
        if (!extra || !*extra) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return FALSE;
        }
 
-       icalcomp = icalcomponent_new_from_string (object);
-       if (!icalcomp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+       icomp = i_cal_component_new_from_string (object);
+       if (!icomp) {
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return FALSE;
        }
 
        if (conflict_resolution == E_CONFLICT_RESOLUTION_FAIL)
-               etag = e_cal_util_dup_x_property (icalcomp, E_CALDAV_X_ETAG);
+               etag = e_cal_util_component_dup_x_property (icomp, E_CALDAV_X_ETAG);
 
        webdav = ecb_caldav_ref_session (cbdav);
 
@@ -1406,7 +1410,7 @@ ecb_caldav_remove_component_sync (ECalMetaBackend *meta_backend,
                }
        }
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_free (etag);
 
        /* Ignore not found errors, this was a delete and the resource is gone.
@@ -1576,42 +1580,40 @@ ecb_caldav_receive_schedule_outbox_url_sync (ECalBackendCalDAV *cbdav,
 }
 
 static void
-ecb_caldav_extract_objects (icalcomponent *icomp,
-                           icalcomponent_kind ekind,
+ecb_caldav_extract_objects (ICalComponent *icomp,
+                           ICalComponentKind ekind,
                            GSList **out_objects,
                            GError **error)
 {
-       icalcomponent *scomp;
-       icalcomponent_kind kind;
+       ICalComponent *scomp;
+       ICalComponentKind kind;
        GSList *link;
 
        g_return_if_fail (icomp != NULL);
        g_return_if_fail (out_objects != NULL);
 
-       kind = icalcomponent_isa (icomp);
+       kind = i_cal_component_isa (icomp);
 
        if (kind == ekind) {
-               *out_objects = g_slist_prepend (NULL, icalcomponent_new_clone (icomp));
+               *out_objects = g_slist_prepend (NULL, i_cal_component_new_clone (icomp));
                return;
        }
 
-       if (kind != ICAL_VCALENDAR_COMPONENT) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+       if (kind != I_CAL_VCALENDAR_COMPONENT) {
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return;
        }
 
        *out_objects = NULL;
-       scomp = icalcomponent_get_first_component (icomp, ekind);
-
-       while (scomp) {
-               *out_objects = g_slist_prepend (*out_objects, scomp);
-
-               scomp = icalcomponent_get_next_component (icomp, ekind);
+       for (scomp = i_cal_component_get_first_component (icomp, ekind);
+            scomp;
+            g_object_unref (scomp), scomp = i_cal_component_get_next_component (icomp, ekind)) {
+               *out_objects = g_slist_prepend (*out_objects, g_object_ref (scomp));
        }
 
        for (link = *out_objects; link; link = g_slist_next (link)) {
                /* Remove components from toplevel here */
-               icalcomponent_remove_component (icomp, link->data);
+               i_cal_component_remove_component (icomp, link->data);
        }
 
        *out_objects = g_slist_reverse (*out_objects);
@@ -1679,20 +1681,19 @@ ecb_caldav_get_free_busy_from_schedule_outbox_sync (ECalBackendCalDAV *cbdav,
                                                    GCancellable *cancellable,
                                                    GError **error)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        ECalComponent *comp;
-       ECalComponentDateTime dt;
-       ECalComponentOrganizer organizer = { NULL };
+       ECalComponentDateTime *dt;
+       ECalComponentOrganizer *organizer;
        ESourceAuthentication *auth_extension;
        ESource *source;
        EWebDAVSession *webdav;
-       struct icaltimetype dtvalue;
-       icaltimezone *utc;
+       ICalTimezone *utc;
        gchar *str;
        GSList *link;
-       GSList *attendees = NULL, *to_free = NULL;
+       GSList *attendees = NULL;
        const gchar *extension_name;
-       gchar *usermail;
+       gchar *usermail, *organizer_value;
        GByteArray *response = NULL;
        GError *local_error = NULL;
 
@@ -1716,18 +1717,18 @@ ecb_caldav_get_free_busy_from_schedule_outbox_sync (ECalBackendCalDAV *cbdav,
        e_cal_component_set_uid (comp, str);
        g_free (str);
 
-       utc = icaltimezone_get_utc_timezone ();
-       dt.value = &dtvalue;
-       dt.tzid = icaltimezone_get_tzid (utc);
+       utc = i_cal_timezone_get_utc_timezone ();
+       dt = e_cal_component_datetime_new_take (i_cal_time_current_time_with_zone (utc), g_strdup 
(i_cal_timezone_get_tzid (utc)));
+
+       e_cal_component_set_dtstamp (comp, e_cal_component_datetime_get_value (dt));
 
-       dtvalue = icaltime_current_time_with_zone (utc);
-       e_cal_component_set_dtstamp (comp, &dtvalue);
+       e_cal_component_datetime_take_value (dt, i_cal_time_from_timet_with_zone (start, FALSE, utc));
+       e_cal_component_set_dtstart (comp, dt);
 
-       dtvalue = icaltime_from_timet_with_zone (start, FALSE, utc);
-       e_cal_component_set_dtstart (comp, &dt);
+       e_cal_component_datetime_take_value (dt, i_cal_time_from_timet_with_zone (end, FALSE, utc));
+       e_cal_component_set_dtend (comp, dt);
 
-       dtvalue = icaltime_from_timet_with_zone (end, FALSE, utc);
-       e_cal_component_set_dtend (comp, &dt);
+       e_cal_component_datetime_free (dt);
 
        usermail = ecb_caldav_get_usermail (cbdav);
        if (usermail != NULL && *usermail == '\0') {
@@ -1742,9 +1743,13 @@ ecb_caldav_get_free_busy_from_schedule_outbox_sync (ECalBackendCalDAV *cbdav,
        if (!usermail)
                usermail = e_source_authentication_dup_user (auth_extension);
 
-       organizer.value = g_strconcat ("mailto:";, usermail, NULL);
-       e_cal_component_set_organizer (comp, &organizer);
-       g_free ((gchar *) organizer.value);
+       organizer_value = g_strconcat ("mailto:";, usermail, NULL);
+       organizer = e_cal_component_organizer_new ();
+       e_cal_component_organizer_set_value (organizer, organizer_value);
+       g_free (organizer_value);
+
+       e_cal_component_set_organizer (comp, organizer);
+       e_cal_component_organizer_free (organizer);
 
        g_free (usermail);
 
@@ -1752,32 +1757,32 @@ ecb_caldav_get_free_busy_from_schedule_outbox_sync (ECalBackendCalDAV *cbdav,
                ECalComponentAttendee *ca;
                gchar *temp = g_strconcat ("mailto:";, (const gchar *) link->data, NULL);
 
-               ca = g_new0 (ECalComponentAttendee, 1);
+               ca = e_cal_component_attendee_new ();
+
+               e_cal_component_attendee_set_value (ca, temp);
+               e_cal_component_attendee_set_cutype (ca, I_CAL_CUTYPE_INDIVIDUAL);
+               e_cal_component_attendee_set_partstat (ca, I_CAL_PARTSTAT_NEEDSACTION);
+               e_cal_component_attendee_set_role (ca, I_CAL_ROLE_CHAIR);
 
-               ca->value = temp;
-               ca->cutype = ICAL_CUTYPE_INDIVIDUAL;
-               ca->status = ICAL_PARTSTAT_NEEDSACTION;
-               ca->role = ICAL_ROLE_CHAIR;
+               g_free (temp);
 
-               to_free = g_slist_prepend (to_free, temp);
                attendees = g_slist_append (attendees, ca);
        }
 
-       e_cal_component_set_attendee_list (comp, attendees);
+       e_cal_component_set_attendees (comp, attendees);
 
-       g_slist_free_full (attendees, g_free);
-       g_slist_free_full (to_free, g_free);
+       g_slist_free_full (attendees, e_cal_component_attendee_free);
 
        e_cal_component_abort_sequence (comp);
 
        /* put the free/busy request to a VCALENDAR */
-       icalcomp = e_cal_util_new_top_level ();
-       icalcomponent_set_method (icalcomp, ICAL_METHOD_REQUEST);
-       icalcomponent_add_component (icalcomp, icalcomponent_new_clone (e_cal_component_get_icalcomponent 
(comp)));
+       icomp = e_cal_util_new_top_level ();
+       i_cal_component_set_method (icomp, ICAL_METHOD_REQUEST);
+       i_cal_component_take_component (icomp, i_cal_component_new_clone (e_cal_component_get_icalcomponent 
(comp)));
 
-       str = icalcomponent_as_ical_string_r (icalcomp);
+       str = i_cal_component_as_ical_string_r (icomp);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_object_unref (comp);
 
        webdav = ecb_caldav_ref_session (cbdav);
@@ -1818,12 +1823,12 @@ ecb_caldav_get_free_busy_from_schedule_outbox_sync (ECalBackendCalDAV *cbdav,
                                        if (tmp && *tmp) {
                                                GSList *objects = NULL;
 
-                                               icalcomp = icalparser_parse_string (tmp);
-                                               if (icalcomp)
-                                                       ecb_caldav_extract_objects (icalcomp, 
ICAL_VFREEBUSY_COMPONENT, &objects, &local_error);
-                                               if (icalcomp && !local_error) {
+                                               icomp = i_cal_parser_parse_string (tmp);
+                                               if (icomp)
+                                                       ecb_caldav_extract_objects (icomp, 
I_CAL_VFREEBUSY_COMPONENT, &objects, &local_error);
+                                               if (icomp && !local_error) {
                                                        for (link = objects; link; link = g_slist_next 
(link)) {
-                                                               gchar *obj_str = 
icalcomponent_as_ical_string_r (link->data);
+                                                               gchar *obj_str = 
i_cal_component_as_ical_string_r (link->data);
 
                                                                if (obj_str && *obj_str)
                                                                        *out_freebusy = g_slist_prepend 
(*out_freebusy, obj_str);
@@ -1832,10 +1837,9 @@ ecb_caldav_get_free_busy_from_schedule_outbox_sync (ECalBackendCalDAV *cbdav,
                                                        }
                                                }
 
-                                               g_slist_free_full (objects, (GDestroyNotify) 
icalcomponent_free);
+                                               g_slist_free_full (objects, g_object_unref);
 
-                                               if (icalcomp)
-                                                       icalcomponent_free (icalcomp);
+                                               g_clear_object (&icomp);
                                                g_clear_error (&local_error);
                                        }
 
@@ -1924,30 +1928,30 @@ ecb_caldav_get_free_busy_from_principal_sync (ECalBackendCalDAV *cbdav,
 
        if (success && content_type && content && content->data && content->len &&
            g_ascii_strcasecmp (content_type, "text/calendar") == 0) {
-               icalcomponent *vcalendar;
+               ICalComponent *vcalendar;
 
-               vcalendar = icalcomponent_new_from_string ((const gchar *) content->data);
+               vcalendar = i_cal_component_new_from_string ((const gchar *) content->data);
                if (vcalendar) {
                        GSList *comps = NULL, *link;
 
-                       ecb_caldav_extract_objects (vcalendar, ICAL_VFREEBUSY_COMPONENT, &comps, NULL);
+                       ecb_caldav_extract_objects (vcalendar, I_CAL_VFREEBUSY_COMPONENT, &comps, NULL);
 
                        for (link = comps; link; link = g_slist_next (link)) {
-                               icalcomponent *subcomp = link->data;
+                               ICalComponent *subcomp = link->data;
                                gchar *obj_str;
 
-                               if (!icalcomponent_get_first_property (subcomp, ICAL_ATTENDEE_PROPERTY)) {
-                                       icalproperty *prop;
+                               if (!e_cal_util_component_has_property (subcomp, I_CAL_ATTENDEE_PROPERTY)) {
+                                       ICalProperty *prop;
                                        gchar *mailto;
 
                                        mailto = g_strconcat ("mailto:";, usermail, NULL);
-                                       prop = icalproperty_new_attendee (mailto);
+                                       prop = i_cal_property_new_attendee (mailto);
                                        g_free (mailto);
 
-                                       icalcomponent_add_property (subcomp, prop);
+                                       i_cal_component_take_property (subcomp, prop);
                                }
 
-                               obj_str = icalcomponent_as_ical_string_r (subcomp);
+                               obj_str = i_cal_component_as_ical_string_r (subcomp);
 
                                if (obj_str && *obj_str)
                                        *out_freebusy = g_slist_prepend (*out_freebusy, obj_str);
@@ -1957,7 +1961,8 @@ ecb_caldav_get_free_busy_from_principal_sync (ECalBackendCalDAV *cbdav,
 
                        success = comps != NULL;
 
-                       g_slist_free_full (comps, (GDestroyNotify) icalcomponent_free);
+                       g_slist_free_full (comps, g_object_unref);
+                       g_object_unref (vcalendar);
                } else {
                        success = FALSE;
                }
@@ -2042,16 +2047,16 @@ ecb_caldav_get_backend_property (ECalBackend *backend,
                gchar *usermail;
 
                caps = g_string_new (
-                       CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
-                       CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED ","
-                       CAL_STATIC_CAPABILITY_TASK_CAN_RECUR ","
-                       CAL_STATIC_CAPABILITY_COMPONENT_COLOR);
+                       E_CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+                       E_CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED ","
+                       E_CAL_STATIC_CAPABILITY_TASK_CAN_RECUR ","
+                       E_CAL_STATIC_CAPABILITY_COMPONENT_COLOR);
                g_string_append (caps, ",");
                g_string_append (caps, e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (backend)));
 
                usermail = ecb_caldav_get_usermail (cbdav);
                if (!usermail || !*usermail)
-                       g_string_append (caps, "," CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS);
+                       g_string_append (caps, "," E_CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS);
                g_free (usermail);
 
                source = e_backend_get_source (E_BACKEND (backend));
@@ -2060,13 +2065,13 @@ ecb_caldav_get_backend_property (ECalBackend *backend,
                if (e_source_webdav_get_calendar_auto_schedule (extension)) {
                        g_string_append (
                                caps,
-                               "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
-                               "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+                               "," E_CAL_STATIC_CAPABILITY_CREATE_MESSAGES
+                               "," E_CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
                }
 
                return g_string_free (caps, FALSE);
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
-                  g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+                  g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
                return ecb_caldav_get_usermail (E_CAL_BACKEND_CALDAV (backend));
        }
 
@@ -2099,20 +2104,20 @@ ecb_caldav_notify_property_changed_cb (GObject *object,
        }
 
        if (email_address_changed) {
-               value = ecb_caldav_get_backend_property (cal_backend, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
-               e_cal_backend_notify_property_changed (cal_backend, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, 
value);
-               e_cal_backend_notify_property_changed (cal_backend, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, 
value);
+               value = ecb_caldav_get_backend_property (cal_backend, 
E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
+               e_cal_backend_notify_property_changed (cal_backend, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, 
value);
+               e_cal_backend_notify_property_changed (cal_backend, 
E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, value);
                g_free (value);
        }
 }
 
 static gchar *
 ecb_caldav_dup_component_revision_cb (ECalCache *cal_cache,
-                                     icalcomponent *icalcomp)
+                                     ICalComponent *icomp)
 {
-       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (icomp != NULL, NULL);
 
-       return e_cal_util_dup_x_property (icalcomp, E_CALDAV_X_ETAG);
+       return e_cal_util_component_dup_x_property (icomp, E_CALDAV_X_ETAG);
 }
 
 static void
diff --git a/src/calendar/backends/contacts/e-cal-backend-contacts.c 
b/src/calendar/backends/contacts/e-cal-backend-contacts.c
index de1716941..d9cff70ef 100644
--- a/src/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/src/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -36,7 +36,8 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_CAL_BACKEND_CONTACTS, ECalBackendContactsPrivate))
 
-#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
+#define EC_ERROR(_code) e_client_error_create (_code, NULL)
+#define ECC_ERROR(_code) e_cal_client_error_create (_code, NULL)
 
 G_DEFINE_TYPE (
        ECalBackendContacts,
@@ -461,7 +462,7 @@ contact_record_free (ContactRecord *cr)
                id = e_cal_component_get_id (cr->comp_birthday);
                e_cal_backend_notify_component_removed (E_CAL_BACKEND (cr->cbc), id, cr->comp_birthday, NULL);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
                g_object_unref (G_OBJECT (cr->comp_birthday));
        }
 
@@ -471,7 +472,7 @@ contact_record_free (ContactRecord *cr)
 
                e_cal_backend_notify_component_removed (E_CAL_BACKEND (cr->cbc), id, cr->comp_anniversary, 
NULL);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
                g_object_unref (G_OBJECT (cr->comp_anniversary));
        }
 
@@ -699,19 +700,20 @@ contacts_removed_cb (EBookClientView *book_view,
 }
 
 /************************************************************************************/
-static struct icaltimetype
+static ICalTime *
 cdate_to_icaltime (EContactDate *cdate)
 {
-       struct icaltimetype ret = icaltime_null_time ();
-
-       ret.year = cdate->year;
-       ret.month = cdate->month;
-       ret.day = cdate->day;
-       ret.is_date = TRUE;
-       ret.zone = NULL;
-       ret.is_daylight = FALSE;
-
-       ret.hour = ret.minute = ret.second = 0;
+       ICalTime *ret = i_cal_time_null_time ();
+
+       i_cal_time_set_year (ret, cdate->year);
+       i_cal_time_set_month (ret, cdate->month);
+       i_cal_time_set_day (ret, cdate->day);
+       i_cal_time_set_hour (ret, 0);
+       i_cal_time_set_minute (ret, 0);
+       i_cal_time_set_second (ret, 0);
+       i_cal_time_set_timezone (ret, NULL);
+       i_cal_time_set_is_daylight (ret, FALSE);
+       i_cal_time_set_is_date (ret, TRUE);
 
        return ret;
 }
@@ -805,8 +807,9 @@ setup_alarm (ECalBackendContacts *cbc,
              ECalComponent *comp)
 {
        ECalComponentAlarm *alarm;
-       ECalComponentAlarmTrigger trigger;
-       ECalComponentText summary;
+       ECalComponentAlarmTrigger *trigger;
+       ECalComponentText *summary;
+       ICalDuration *duration;
 
        g_return_if_fail (cbc != NULL);
 
@@ -847,27 +850,24 @@ setup_alarm (ECalBackendContacts *cbc,
                return;
 
        alarm = e_cal_component_alarm_new ();
-       e_cal_component_get_summary (comp, &summary);
-       e_cal_component_alarm_set_description (alarm, &summary);
+       summary = e_cal_component_get_summary (comp);
+       e_cal_component_alarm_take_description (alarm, summary);
        e_cal_component_alarm_set_action (alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
 
-       trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
-
-       memset (&trigger.u.rel_duration, 0, sizeof (trigger.u.rel_duration));
-
-       trigger.u.rel_duration.is_neg = TRUE;
+       duration = i_cal_duration_null_duration ();
+       i_cal_duration_set_is_neg (duration, TRUE);
 
        switch (cbc->priv->alarm_units) {
        case CAL_MINUTES:
-               trigger.u.rel_duration.minutes = cbc->priv->alarm_interval;
+               i_cal_duration_set_minutes (duration, cbc->priv->alarm_interval);
                break;
 
        case CAL_HOURS:
-               trigger.u.rel_duration.hours = cbc->priv->alarm_interval;
+               i_cal_duration_set_hours (duration, cbc->priv->alarm_interval);
                break;
 
        case CAL_DAYS:
-               trigger.u.rel_duration.days = cbc->priv->alarm_interval;
+               i_cal_duration_set_days (duration, cbc->priv->alarm_interval);
                break;
 
        default:
@@ -876,7 +876,11 @@ setup_alarm (ECalBackendContacts *cbc,
                return;
        }
 
-       e_cal_component_alarm_set_trigger (alarm, trigger);
+       trigger = e_cal_component_alarm_trigger_new_relative (E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START, 
duration);
+
+       g_object_unref (duration);
+
+       e_cal_component_alarm_take_trigger (alarm, trigger);
        e_cal_component_add_alarm (comp, alarm);
        e_cal_component_alarm_free (alarm);
 }
@@ -892,15 +896,14 @@ create_component (ECalBackendContacts *cbc,
                   EContactDate *cdate,
                   const gchar *summary)
 {
-       ECalComponent             *cal_comp;
-       ECalComponentText          comp_summary;
-       icalcomponent             *ical_comp;
-       icalproperty              *prop;
-       struct icaltimetype        itt;
-       ECalComponentDateTime      dt;
-       struct icalrecurrencetype  r;
-       gchar                     *since_year;
-       GSList recur_list;
+       ECalComponent *cal_comp;
+       ECalComponentText *comp_summary;
+       ECalComponentDateTime *dt;
+       ICalComponent *icomp;
+       ICalTime *itt;
+       ICalRecurrence *rt;
+       gchar *since_year;
+       GSList *recur_list;
        gboolean is_leap_day;
 
        g_return_val_if_fail (E_IS_CAL_BACKEND_CONTACTS (cbc), NULL);
@@ -908,17 +911,14 @@ create_component (ECalBackendContacts *cbc,
        if (!cdate)
                return NULL;
 
-       ical_comp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
 
        since_year = g_strdup_printf ("%04d", cdate->year);
-       prop = icalproperty_new_x (since_year);
-       icalproperty_set_x_name (prop, "X-EVOLUTION-SINCE-YEAR");
-       icalcomponent_add_property (ical_comp, prop);
+       e_cal_util_component_set_x_property (icomp, "X-EVOLUTION-SINCE-YEAR", since_year);
        g_free (since_year);
 
        /* Create the event object */
-       cal_comp = e_cal_component_new ();
-       e_cal_component_set_icalcomponent (cal_comp, ical_comp);
+       cal_comp = e_cal_component_new_from_icalcomponent (icomp);
 
        /* Set uid */
        d (g_message ("Creating UID: %s", uid));
@@ -926,34 +926,35 @@ create_component (ECalBackendContacts *cbc,
 
        /* Set all-day event's date from contact data */
        itt = cdate_to_icaltime (cdate);
-       dt.value = &itt;
-       dt.tzid = NULL;
-       e_cal_component_set_dtstart (cal_comp, &dt);
 
-       itt = icaltime_normalize (itt);
-       is_leap_day = itt.day == 29 && itt.month == 2;
+       i_cal_time_normalize_inplace (itt);
+       is_leap_day = i_cal_time_get_day (itt) == 29 && i_cal_time_get_month (itt) == 2;
+
+       dt = e_cal_component_datetime_new_take (itt, NULL);
+       e_cal_component_set_dtstart (cal_comp, dt);
+       e_cal_component_datetime_free (dt);
 
        itt = cdate_to_icaltime (cdate);
-       icaltime_adjust (&itt, 1, 0, 0, 0);
-       dt.value = &itt;
-       dt.tzid = NULL;
        /* We have to add 1 day to DTEND, as it is not inclusive. */
-       e_cal_component_set_dtend (cal_comp, &dt);
+       i_cal_time_adjust (itt, 1, 0, 0, 0);
+       dt = e_cal_component_datetime_new_take (itt, NULL);
+       e_cal_component_set_dtend (cal_comp, dt);
+       e_cal_component_datetime_free (dt);
 
        /* Create yearly recurrence */
-       icalrecurrencetype_clear (&r);
-       r.freq = ICAL_YEARLY_RECURRENCE;
-       r.interval = 1;
+       rt = i_cal_recurrence_new ();
+       i_cal_recurrence_set_freq (rt, I_CAL_YEARLY_RECURRENCE);
+       i_cal_recurrence_set_interval (rt, 1);
        if (is_leap_day)
-               r.by_month_day[0] = -1;
-       recur_list.data = &r;
-       recur_list.next = NULL;
-       e_cal_component_set_rrule_list (cal_comp, &recur_list);
+               i_cal_recurrence_set_by_month_day (rt, 0, -1);
+       recur_list = g_slist_prepend (NULL, rt);
+       e_cal_component_set_rrules (cal_comp, recur_list);
+       g_slist_free_full (recur_list, g_object_unref);
 
        /* Create summary */
-       comp_summary.value = summary;
-       comp_summary.altrep = NULL;
-       e_cal_component_set_summary (cal_comp, &comp_summary);
+       comp_summary = e_cal_component_text_new (summary, NULL);
+       e_cal_component_set_summary (cal_comp, comp_summary);
+       e_cal_component_text_free (comp_summary);
 
        /* Set category and visibility */
        if (g_str_has_suffix (uid, ANNIVERSARY_UID_EXT))
@@ -1051,14 +1052,14 @@ e_cal_backend_contacts_get_backend_property (ECalBackend *backend,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return NULL;
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
-                  g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+                  g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
                /* A contact backend has no particular email address associated
                 * with it (although that would be a useful feature some day).
                 */
                return NULL;
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
                return NULL;
        }
 
@@ -1082,14 +1083,14 @@ e_cal_backend_contacts_get_object (ECalBackendSync *backend,
        gchar *real_uid;
 
        if (!uid) {
-               g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (perror, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return;
        } else if (g_str_has_suffix (uid, ANNIVERSARY_UID_EXT))
                real_uid = g_strndup (uid, strlen (uid) - strlen (ANNIVERSARY_UID_EXT));
        else if (g_str_has_suffix (uid, BIRTHDAY_UID_EXT))
                real_uid = g_strndup (uid, strlen (uid) - strlen (BIRTHDAY_UID_EXT));
        else {
-               g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (perror, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return;
        }
 
@@ -1099,7 +1100,7 @@ e_cal_backend_contacts_get_object (ECalBackendSync *backend,
 
        if (!record) {
                g_rec_mutex_unlock (&priv->tracked_contacts_lock);
-               g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (perror, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return;
        }
 
@@ -1123,7 +1124,7 @@ e_cal_backend_contacts_get_object (ECalBackendSync *backend,
 
        d (g_message ("Returning nothing for uid: %s", uid));
 
-       g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+       g_propagate_error (perror, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
 }
 
 static void
@@ -1138,32 +1139,22 @@ e_cal_backend_contacts_get_free_busy (ECalBackendSync *backend,
 {
        /* Birthdays/anniversaries don't count as busy time */
 
-       icalcomponent *vfb = icalcomponent_new_vfreebusy ();
-       icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
+       ICalComponent *vfb = i_cal_component_new_vfreebusy ();
+       ICalTimezone *utc_zone = i_cal_timezone_get_utc_timezone ();
+       ICalTime *itt;
        gchar *calobj;
 
-#if 0
-       icalproperty *prop;
-       icalparameter *param;
-
-       prop = icalproperty_new_organizer (address);
-       if (prop != NULL && cn != NULL) {
-               param = icalparameter_new_cn (cn);
-               icalproperty_add_parameter (prop, param);
-       }
-       if (prop != NULL)
-               icalcomponent_add_property (vfb, prop);
-#endif
+       itt = i_cal_time_from_timet_with_zone (start, FALSE, utc_zone);
+       i_cal_component_set_dtstart (vfb, itt);
+       g_object_unref (itt);
 
-       icalcomponent_set_dtstart (vfb, icaltime_from_timet_with_zone (start, FALSE, utc_zone));
-       icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
+       itt = i_cal_time_from_timet_with_zone (end, FALSE, utc_zone);
+       i_cal_component_set_dtend (vfb, itt);
+       g_object_unref (itt);
 
-       calobj = icalcomponent_as_ical_string_r (vfb);
+       calobj = i_cal_component_as_ical_string_r (vfb);
        *freebusy = g_slist_append (NULL, calobj);
-       icalcomponent_free (vfb);
-
-       /* WRITE ME */
-       /* Success */
+       g_object_unref (vfb);
 }
 
 static void
@@ -1171,9 +1162,10 @@ e_cal_backend_contacts_receive_objects (ECalBackendSync *backend,
                                         EDataCal *cal,
                                         GCancellable *cancellable,
                                         const gchar *calobj,
+                                       guint32 opflags,
                                         GError **perror)
 {
-       g_propagate_error (perror, EDC_ERROR (PermissionDenied));
+       g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_PERMISSION_DENIED));
 }
 
 static void
@@ -1181,6 +1173,7 @@ e_cal_backend_contacts_send_objects (ECalBackendSync *backend,
                                      EDataCal *cal,
                                      GCancellable *cancellable,
                                      const gchar *calobj,
+                                    guint32 opflags,
                                      GSList **users,
                                      gchar **modified_calobj,
                                      GError **perror)
@@ -1188,7 +1181,7 @@ e_cal_backend_contacts_send_objects (ECalBackendSync *backend,
        *users = NULL;
        *modified_calobj = NULL;
        /* TODO: Investigate this */
-       g_propagate_error (perror, EDC_ERROR (PermissionDenied));
+       g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_PERMISSION_DENIED));
 }
 
 /* Then the real implementations */
@@ -1230,24 +1223,27 @@ e_cal_backend_contacts_add_timezone (ECalBackendSync *backend,
                                      const gchar *tzobj,
                                      GError **error)
 {
-       icalcomponent *tz_comp;
-       icaltimezone *zone;
+       ICalComponent *tz_comp;
+       ICalTimezone *zone;
 
-       tz_comp = icalparser_parse_string (tzobj);
+       tz_comp = i_cal_parser_parse_string (tzobj);
        if (!tz_comp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return;
        }
 
-       if (icalcomponent_isa (tz_comp) != ICAL_VTIMEZONE_COMPONENT) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+       if (i_cal_component_isa (tz_comp) != I_CAL_VTIMEZONE_COMPONENT) {
+               g_object_unref (tz_comp);
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return;
        }
 
-       zone = icaltimezone_new ();
-       icaltimezone_set_component (zone, tz_comp);
-       e_timezone_cache_add_timezone (E_TIMEZONE_CACHE (backend), zone);
-       icaltimezone_free (zone, TRUE);
+       zone = i_cal_timezone_new ();
+       if (i_cal_timezone_set_component (zone, tz_comp))
+               e_timezone_cache_add_timezone (E_TIMEZONE_CACHE (backend), zone);
+
+       g_object_unref (zone);
+       g_object_unref (tz_comp);
 }
 
 static void
@@ -1264,7 +1260,7 @@ e_cal_backend_contacts_get_object_list (ECalBackendSync *backend,
        ContactRecordCB *cb_data;
 
        if (!sexp) {
-               g_propagate_error (perror, EDC_ERROR (InvalidQuery));
+               g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_INVALID_QUERY));
                return;
        }
 
@@ -1290,7 +1286,7 @@ e_cal_backend_contacts_start_view (ECalBackend *backend,
 
        sexp = e_data_cal_view_get_sexp (query);
        if (!sexp) {
-               GError *error = EDC_ERROR (InvalidQuery);
+               GError *error = ECC_ERROR (E_CLIENT_ERROR_INVALID_QUERY);
                e_data_cal_view_notify_complete (query, error);
                g_error_free (error);
                return;
@@ -1414,11 +1410,12 @@ e_cal_backend_contacts_create_objects (ECalBackendSync *backend,
                                        EDataCal *cal,
                                        GCancellable *cancellable,
                                        const GSList *calobjs,
+                                      guint32 opflags,
                                        GSList **uids,
                                        GSList **new_components,
                                        GError **perror)
 {
-       g_propagate_error (perror, EDC_ERROR (PermissionDenied));
+       g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_PERMISSION_DENIED));
 }
 
 /* Class initialization function for the contacts backend */
diff --git a/src/calendar/backends/file/e-cal-backend-file.c b/src/calendar/backends/file/e-cal-backend-file.c
index b5103ae3b..7505d5006 100644
--- a/src/calendar/backends/file/e-cal-backend-file.c
+++ b/src/calendar/backends/file/e-cal-backend-file.c
@@ -42,8 +42,10 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_CAL_BACKEND_FILE, ECalBackendFilePrivate))
 
-#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
-#define EDC_ERROR_NO_URI() e_data_cal_create_error (OtherError, "Cannot get URI")
+#define EC_ERROR(_code) e_client_error_create (_code, NULL)
+#define EC_ERROR_EX(_code, _msg) e_client_error_create (_code, _msg)
+#define EC_ERROR_NO_URI() e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Cannot get URI"))
+#define ECC_ERROR(_code) e_cal_client_error_create (_code, NULL)
 
 #define ECAL_REVISION_X_PROP  "X-EVOLUTION-DATA-REVISION"
 
@@ -72,7 +74,7 @@ struct _ECalBackendFilePrivate {
        GRecMutex idle_save_rmutex;
 
        /* Toplevel VCALENDAR component */
-       icalcomponent *icalcomp;
+       ICalComponent *vcalendar;
 
        /* All the objects in the calendar, hashed by UID.  The
         * hash key *is* the uid returned by cal_component_get_uid(); it is not
@@ -100,15 +102,13 @@ struct _ECalBackendFilePrivate {
 
        /* Just an incremental number to ensure uniqueness across revisions */
        guint revision_counter;
-};
 
-
+       /* Only for ETimezoneCache::get_timezone() call */
+       GHashTable *cached_timezones; /* gchar *tzid ~> ICalTimezone * */
+};
 
 #define d(x)
 
-static void e_cal_backend_file_dispose (GObject *object);
-static void e_cal_backend_file_finalize (GObject *object);
-
 static void free_refresh_data (ECalBackendFile *cbfile);
 
 static void bump_revision (ECalBackendFile *cbfile);
@@ -156,7 +156,7 @@ save_file_when_idle (gpointer user_data)
 
        priv = cbfile->priv;
        g_return_val_if_fail (priv->path != NULL, FALSE);
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+       g_return_val_if_fail (priv->vcalendar != NULL, FALSE);
 
        writable = e_cal_backend_get_writable (E_CAL_BACKEND (cbfile));
 
@@ -202,7 +202,7 @@ save_file_when_idle (gpointer user_data)
                goto error;
        }
 
-       buf = icalcomponent_as_ical_string_r (priv->icalcomp);
+       buf = i_cal_component_as_ical_string_r (priv->vcalendar);
        succeeded = g_output_stream_write_all (G_OUTPUT_STREAM (stream), buf, strlen (buf) * sizeof (gchar), 
NULL, NULL, &e);
        g_free (buf);
 
@@ -280,13 +280,13 @@ save (ECalBackendFile *cbfile,
 
 static void
 free_calendar_components (GHashTable *comp_uid_hash,
-                          icalcomponent *top_icomp)
+                         ICalComponent *top_icomp)
 {
        if (comp_uid_hash)
                g_hash_table_destroy (comp_uid_hash);
 
        if (top_icomp)
-               icalcomponent_free (top_icomp);
+               g_object_unref (top_icomp);
 }
 
 static void
@@ -301,9 +301,9 @@ free_calendar_data (ECalBackendFile *cbfile)
        e_intervaltree_destroy (priv->interval_tree);
        priv->interval_tree = NULL;
 
-       free_calendar_components (priv->comp_uid_hash, priv->icalcomp);
+       free_calendar_components (priv->comp_uid_hash, priv->vcalendar);
        priv->comp_uid_hash = NULL;
-       priv->icalcomp = NULL;
+       priv->vcalendar = NULL;
 
        g_list_free (priv->comp);
        priv->comp = NULL;
@@ -354,6 +354,7 @@ e_cal_backend_file_finalize (GObject *object)
        g_mutex_clear (&priv->refresh_lock);
 
        g_rec_mutex_clear (&priv->idle_save_rmutex);
+       g_hash_table_destroy (priv->cached_timezones);
 
        g_free (priv->path);
        g_free (priv->file_name);
@@ -362,8 +363,6 @@ e_cal_backend_file_finalize (GObject *object)
        G_OBJECT_CLASS (e_cal_backend_file_parent_class)->finalize (object);
 }
 
-
-
 /* Looks up an component by its UID on the backend's component hash table
  * and returns TRUE if any event (regardless whether it is the master or a child)
  * with that UID exists */
@@ -380,28 +379,13 @@ uid_in_use (ECalBackendFile *cbfile,
        return obj_data != NULL;
 }
 
-
-
-static icalproperty *
+static ICalProperty *
 get_revision_property (ECalBackendFile *cbfile)
 {
-       icalproperty *prop = NULL;
-
-       if (cbfile->priv->icalcomp != NULL)
-               prop = icalcomponent_get_first_property (
-                       cbfile->priv->icalcomp, ICAL_X_PROPERTY);
-
-       while (prop != NULL) {
-               const gchar *name = icalproperty_get_x_name (prop);
-
-               if (name && strcmp (name, ECAL_REVISION_X_PROP) == 0)
-                       return prop;
-
-               prop = icalcomponent_get_next_property (
-                       cbfile->priv->icalcomp, ICAL_X_PROPERTY);
-       }
+       if (!cbfile->priv->vcalendar)
+               return NULL;
 
-       return NULL;
+       return e_cal_util_component_find_x_property (cbfile->priv->vcalendar, ECAL_REVISION_X_PROP);
 }
 
 static gchar *
@@ -420,27 +404,25 @@ make_revision_string (ECalBackendFile *cbfile)
        return revision;
 }
 
-static icalproperty *
+static ICalProperty *
 ensure_revision (ECalBackendFile *cbfile)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
-       if (cbfile->priv->icalcomp == NULL)
+       if (cbfile->priv->vcalendar == NULL)
                return NULL;
 
        prop = get_revision_property (cbfile);
 
-       if (prop == NULL) {
+       if (!prop) {
                gchar *revision = make_revision_string (cbfile);
 
-               prop = icalproperty_new (ICAL_X_PROPERTY);
-
-               icalproperty_set_x_name (prop, ECAL_REVISION_X_PROP);
-               icalproperty_set_x (prop, revision);
-
-               icalcomponent_add_property (cbfile->priv->icalcomp, prop);
+               e_cal_util_component_set_x_property (cbfile->priv->vcalendar, ECAL_REVISION_X_PROP, revision);
 
                g_free (revision);
+
+               prop = get_revision_property (cbfile);
+               g_warn_if_fail (prop != NULL);
        }
 
        return prop;
@@ -450,15 +432,16 @@ static void
 bump_revision (ECalBackendFile *cbfile)
 {
        /* Update the revision string */
-       icalproperty *prop = ensure_revision (cbfile);
-       gchar        *revision = make_revision_string (cbfile);
+       ICalProperty *prop = ensure_revision (cbfile);
+       gchar *revision = make_revision_string (cbfile);
 
-       icalproperty_set_x (prop, revision);
+       i_cal_property_set_x (prop, revision);
 
        e_cal_backend_notify_property_changed (E_CAL_BACKEND (cbfile),
-                                             CAL_BACKEND_PROPERTY_REVISION,
+                                             E_CAL_BACKEND_PROPERTY_REVISION,
                                              revision);
 
+       g_object_unref (prop);
        g_free (revision);
 }
 
@@ -474,26 +457,26 @@ e_cal_backend_file_get_backend_property (ECalBackend *backend,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strjoin (
                        ",",
-                       CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS,
-                       CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
-                       CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED,
-                       CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS,
-                       CAL_STATIC_CAPABILITY_BULK_ADDS,
-                       CAL_STATIC_CAPABILITY_BULK_MODIFIES,
-                       CAL_STATIC_CAPABILITY_BULK_REMOVES,
-                       CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION,
-                       CAL_STATIC_CAPABILITY_TASK_CAN_RECUR,
-                       CAL_STATIC_CAPABILITY_COMPONENT_COLOR,
+                       E_CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS,
+                       E_CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
+                       E_CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED,
+                       E_CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS,
+                       E_CAL_STATIC_CAPABILITY_BULK_ADDS,
+                       E_CAL_STATIC_CAPABILITY_BULK_MODIFIES,
+                       E_CAL_STATIC_CAPABILITY_BULK_REMOVES,
+                       E_CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION,
+                       E_CAL_STATIC_CAPABILITY_TASK_CAN_RECUR,
+                       E_CAL_STATIC_CAPABILITY_COMPONENT_COLOR,
                        NULL);
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
-                  g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+                  g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
                /* A file backend has no particular email address associated
                 * with it (although that would be a useful feature some day).
                 */
                return NULL;
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
                ECalComponent *comp;
                gchar *prop_value;
 
@@ -520,16 +503,18 @@ e_cal_backend_file_get_backend_property (ECalBackend *backend,
 
                return prop_value;
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_REVISION)) {
-               icalproperty *prop;
-               const gchar *revision = NULL;
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_REVISION)) {
+               ICalProperty *prop;
+               gchar *revision = NULL;
 
-               /* This returns NULL if backend lacks an icalcomp. */
+               /* This returns NULL if backend lacks a vcalendar. */
                prop = ensure_revision (E_CAL_BACKEND_FILE (backend));
-               if (prop != NULL)
-                       revision = icalproperty_get_x (prop);
+               if (prop) {
+                       revision = g_strdup (i_cal_property_get_x (prop));
+                       g_object_unref (prop);
+               }
 
-               return g_strdup (revision);
+               return revision;
        }
 
        /* Chain up to parent's get_backend_property() method. */
@@ -537,23 +522,62 @@ e_cal_backend_file_get_backend_property (ECalBackend *backend,
                get_backend_property (backend, prop_name);
 }
 
+typedef struct _ResolveTzidData {
+       ICalComponent *vcalendar;
+       GHashTable *zones; /* gchar *tzid ~> ICalTimezone * */
+} ResolveTzidData;
+
+static void
+resolve_tzid_data_init (ResolveTzidData *rtd,
+                       ICalComponent *vcalendar)
+{
+       if (rtd) {
+               rtd->vcalendar = vcalendar;
+               rtd->zones = NULL;
+       }
+}
+
+/* Clears the content, not the structure */
+static void
+resolve_tzid_data_clear (ResolveTzidData *rtd)
+{
+       if (rtd && rtd->zones)
+               g_hash_table_destroy (rtd->zones);
+}
+
 /* function to resolve timezones */
-static icaltimezone *
-resolve_tzid (const gchar *tzid,
-              gpointer user_data)
+static ICalTimezone *
+resolve_tzid_cb (const gchar *tzid,
+                gpointer user_data,
+                GCancellable *cancellable,
+                GError **error)
 {
-       icalcomponent *vcalendar_comp = user_data;
-       icaltimezone * zone;
+       ResolveTzidData *rtd = user_data;
+       ICalTimezone *zone;
 
        if (!tzid || !tzid[0])
                return NULL;
        else if (!strcmp (tzid, "UTC"))
-               return icaltimezone_get_utc_timezone ();
+               return i_cal_timezone_get_utc_timezone ();
+
+       if (rtd->zones) {
+               zone = g_hash_table_lookup (rtd->zones, tzid);
+               if (zone)
+                       return zone;
+       }
+
+       zone = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
+       if (zone)
+               g_object_ref (zone);
+       else if (rtd->vcalendar)
+               zone = i_cal_component_get_timezone (rtd->vcalendar, tzid);
 
-       zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+       if (zone) {
+               if (!rtd->zones)
+                       rtd->zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 
-       if (!zone)
-               zone = icalcomponent_get_timezone (vcalendar_comp, tzid);
+               g_hash_table_insert (rtd->zones, g_strdup (tzid), zone);
+       }
 
        return zone;
 }
@@ -569,13 +593,13 @@ check_dup_uid (ECalBackendFile *cbfile,
 {
        ECalBackendFilePrivate *priv;
        ECalBackendFileObject *obj_data;
-       const gchar *uid = NULL;
+       const gchar *uid;
        gchar *new_uid = NULL;
        gchar *rid = NULL;
 
        priv = cbfile->priv;
 
-       e_cal_component_get_uid (comp, &uid);
+       uid = e_cal_component_get_uid (comp);
 
        if (!uid) {
                g_warning ("Checking for duplicate uid, the component does not have a valid UID skipping 
it\n");
@@ -616,19 +640,28 @@ check_dup_uid (ECalBackendFile *cbfile,
        g_free (new_uid);
 }
 
-static struct icaltimetype
-get_rid_icaltime (ECalComponent *comp)
+static time_t
+get_rid_as_time_t (ECalComponent *comp)
 {
-       ECalComponentRange range;
-       struct icaltimetype tt;
+       ECalComponentRange *range;
+       ECalComponentDateTime *dt;
+       time_t tmt = (time_t) -1;
+
+       range = e_cal_component_get_recurid (comp);
+       if (!range)
+               return tmt;
+
+       dt = e_cal_component_range_get_datetime (range);
+       if (!dt) {
+               e_cal_component_range_free (range);
+               return tmt;
+       }
+
+       tmt = i_cal_time_as_timet (e_cal_component_datetime_get_value (dt));
 
-       e_cal_component_get_recurid (comp, &range);
-       if (!range.datetime.value)
-               return icaltime_null_time ();
-       tt = *range.datetime.value;
-       e_cal_component_free_range (&range);
+       e_cal_component_range_free (range);
 
-       return tt;
+       return tmt;
 }
 
 /* Adds component to the interval tree
@@ -639,17 +672,22 @@ add_component_to_intervaltree (ECalBackendFile *cbfile,
 {
        time_t time_start = -1, time_end = -1;
        ECalBackendFilePrivate *priv;
+       ResolveTzidData rtd;
 
        g_return_if_fail (cbfile != NULL);
        g_return_if_fail (comp != NULL);
 
        priv = cbfile->priv;
 
+       resolve_tzid_data_init (&rtd, cbfile->priv->vcalendar);
+
        e_cal_util_get_component_occur_times (
                comp, &time_start, &time_end,
-               resolve_tzid, priv->icalcomp, icaltimezone_get_utc_timezone (),
+               resolve_tzid_cb, &rtd, i_cal_timezone_get_utc_timezone (),
                e_cal_backend_get_kind (E_CAL_BACKEND (cbfile)));
 
+       resolve_tzid_data_clear (&rtd);
+
        if (time_end != -1 && time_start > time_end) {
                gchar *str = e_cal_component_get_as_string (comp);
                g_print ("Bogus component %s\n", str);
@@ -665,7 +703,7 @@ static gboolean
 remove_component_from_intervaltree (ECalBackendFile *cbfile,
                                     ECalComponent *comp)
 {
-       const gchar *uid = NULL;
+       const gchar *uid;
        gchar *rid;
        gboolean res;
        ECalBackendFilePrivate *priv;
@@ -675,8 +713,8 @@ remove_component_from_intervaltree (ECalBackendFile *cbfile,
 
        priv = cbfile->priv;
 
+       uid = e_cal_component_get_uid (comp);
        rid = e_cal_component_get_recurid_as_string (comp);
-       e_cal_component_get_uid (comp, &uid);
 
        g_rec_mutex_lock (&priv->idle_save_rmutex);
        res = e_intervaltree_remove (priv->interval_tree, uid, rid);
@@ -687,7 +725,7 @@ remove_component_from_intervaltree (ECalBackendFile *cbfile,
        return res;
 }
 
-/* Tries to add an icalcomponent to the file backend.  We only store the objects
+/* Tries to add an ICalComponent to the file backend.  We only store the objects
  * of the types we support; all others just remain in the toplevel component so
  * that we don't lose them.
  *
@@ -701,11 +739,11 @@ add_component (ECalBackendFile *cbfile,
 {
        ECalBackendFilePrivate *priv;
        ECalBackendFileObject *obj_data;
-       const gchar *uid = NULL;
+       const gchar *uid;
 
        priv = cbfile->priv;
 
-       e_cal_component_get_uid (comp, &uid);
+       uid = e_cal_component_get_uid (comp);
 
        if (!uid) {
                g_warning ("The component does not have a valid UID skipping it\n");
@@ -756,12 +794,12 @@ add_component (ECalBackendFile *cbfile,
        /* Put the object in the toplevel component if required */
 
        if (add_to_toplevel) {
-               icalcomponent *icalcomp;
+               ICalComponent *icomp;
 
-               icalcomp = e_cal_component_get_icalcomponent (comp);
-               g_return_if_fail (icalcomp != NULL);
+               icomp = e_cal_component_get_icalcomponent (comp);
+               g_return_if_fail (icomp != NULL);
 
-               icalcomponent_add_component (priv->icalcomp, icalcomp);
+               i_cal_component_add_component (priv->vcalendar, icomp);
        }
 }
 
@@ -771,8 +809,7 @@ remove_recurrence_cb (gpointer key,
                       gpointer value,
                       gpointer data)
 {
-       GList *l;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        ECalBackendFilePrivate *priv;
        ECalComponent *comp = value;
        ECalBackendFile *cbfile = data;
@@ -780,24 +817,27 @@ remove_recurrence_cb (gpointer key,
        priv = cbfile->priv;
 
        /* remove the recurrence from the top-level calendar */
-       icalcomp = e_cal_component_get_icalcomponent (comp);
-       g_return_val_if_fail (icalcomp != NULL, FALSE);
+       icomp = e_cal_component_get_icalcomponent (comp);
+       g_return_val_if_fail (icomp != NULL, FALSE);
+
+       icomp = g_object_ref (icomp);
 
        if (!remove_component_from_intervaltree (cbfile, comp)) {
                g_message (G_STRLOC " Could not remove component from interval tree!");
        }
-       icalcomponent_remove_component (priv->icalcomp, icalcomp);
+       i_cal_component_remove_component (priv->vcalendar, icomp);
+
+       g_object_unref (icomp);
 
        /* remove it from our mapping */
-       l = g_list_find (priv->comp, comp);
-       priv->comp = g_list_delete_link (priv->comp, l);
+       priv->comp = g_list_remove (priv->comp, comp);
 
        return TRUE;
 }
 
 /* Removes a component from the backend's hash and lists.  Does not perform
  * notification on the clients.  Also removes the component from the toplevel
- * icalcomponent.
+ * ICalComponent.
  */
 static void
 remove_component (ECalBackendFile *cbfile,
@@ -805,17 +845,17 @@ remove_component (ECalBackendFile *cbfile,
                   ECalBackendFileObject *obj_data)
 {
        ECalBackendFilePrivate *priv;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        GList *l;
 
        priv = cbfile->priv;
 
-       /* Remove the icalcomp from the toplevel */
+       /* Remove the ICalComponent from the toplevel */
        if (obj_data->full_object) {
-               icalcomp = e_cal_component_get_icalcomponent (obj_data->full_object);
-               g_return_if_fail (icalcomp != NULL);
+               icomp = e_cal_component_get_icalcomponent (obj_data->full_object);
+               g_return_if_fail (icomp != NULL);
 
-               icalcomponent_remove_component (priv->icalcomp, icalcomp);
+               i_cal_component_remove_component (priv->vcalendar, icomp);
 
                /* Remove it from our mapping */
                l = g_list_find (priv->comp, obj_data->full_object);
@@ -840,37 +880,43 @@ static void
 scan_vcalendar (ECalBackendFile *cbfile)
 {
        ECalBackendFilePrivate *priv;
-       icalcompiter iter;
+       ICalCompIter *iter;
+       ICalComponent *icomp;
 
        priv = cbfile->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_if_fail (priv->vcalendar != NULL);
        g_return_if_fail (priv->comp_uid_hash != NULL);
 
-       for (iter = icalcomponent_begin_component (priv->icalcomp, ICAL_ANY_COMPONENT);
-            icalcompiter_deref (&iter) != NULL;
-            icalcompiter_next (&iter)) {
-               icalcomponent *icalcomp;
-               icalcomponent_kind kind;
+       iter = i_cal_component_begin_component (priv->vcalendar, I_CAL_ANY_COMPONENT);
+       icomp = iter ? i_cal_comp_iter_deref (iter) : NULL;
+       while (icomp) {
+               ICalComponentKind kind;
                ECalComponent *comp;
 
-               icalcomp = icalcompiter_deref (&iter);
+               kind = i_cal_component_isa (icomp);
 
-               kind = icalcomponent_isa (icalcomp);
-
-               if (!(kind == ICAL_VEVENT_COMPONENT
-                     || kind == ICAL_VTODO_COMPONENT
-                     || kind == ICAL_VJOURNAL_COMPONENT))
-                       continue;
+               if (kind == I_CAL_VEVENT_COMPONENT ||
+                   kind == I_CAL_VTODO_COMPONENT ||
+                   kind == I_CAL_VJOURNAL_COMPONENT) {
+                       comp = e_cal_component_new ();
 
-               comp = e_cal_component_new ();
+                       if (e_cal_component_set_icalcomponent (comp, icomp)) {
+                               /* Thus it's not freed while being used in the 'comp' */
+                               g_object_ref (icomp);
 
-               if (!e_cal_component_set_icalcomponent (comp, icalcomp))
-                       continue;
+                               check_dup_uid (cbfile, comp);
 
-               check_dup_uid (cbfile, comp);
+                               add_component (cbfile, comp, FALSE);
+                       } else {
+                               g_object_unref (comp);
+                       }
+               }
 
-               add_component (cbfile, comp, FALSE);
+               g_object_unref (icomp);
+               icomp = i_cal_comp_iter_next (iter);
        }
+
+       g_clear_object (&iter);
 }
 
 static gchar *
@@ -1090,20 +1136,22 @@ free_refresh_data (ECalBackendFile *cbfile)
 }
 
 static void
-cal_backend_file_take_icalcomp (ECalBackendFile *cbfile,
-                                icalcomponent *icalcomp)
+cal_backend_file_take_icomp (ECalBackendFile *cbfile,
+                            ICalComponent *icomp)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
-       g_warn_if_fail (cbfile->priv->icalcomp == NULL);
-       cbfile->priv->icalcomp = icalcomp;
+       g_warn_if_fail (cbfile->priv->vcalendar == NULL);
+       cbfile->priv->vcalendar = icomp;
 
        prop = ensure_revision (cbfile);
 
        e_cal_backend_notify_property_changed (
                E_CAL_BACKEND (cbfile),
-               CAL_BACKEND_PROPERTY_REVISION,
-               icalproperty_get_x (prop));
+               E_CAL_BACKEND_PROPERTY_REVISION,
+               i_cal_property_get_x (prop));
+
+       g_clear_object (&prop);
 }
 
 /* Parses an open iCalendar file and loads it into the backend */
@@ -1113,15 +1161,15 @@ open_cal (ECalBackendFile *cbfile,
           GError **perror)
 {
        ECalBackendFilePrivate *priv;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        priv = cbfile->priv;
 
        free_refresh_data (cbfile);
 
-       icalcomp = e_cal_util_parse_ics_file (uristr);
-       if (!icalcomp) {
-               g_propagate_error (perror, e_data_cal_create_error_fmt (OtherError, "Cannot parse ISC file 
'%s'", uristr));
+       icomp = e_cal_util_parse_ics_file (uristr);
+       if (!icomp) {
+               g_propagate_error (perror, e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR, _("Cannot 
parse ISC file “%s”"), uristr));
                return;
        }
 
@@ -1129,16 +1177,16 @@ open_cal (ECalBackendFile *cbfile,
         * individual components as well?
         */
 
-       if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) {
-               icalcomponent_free (icalcomp);
+       if (i_cal_component_isa (icomp) != I_CAL_VCALENDAR_COMPONENT) {
+               g_object_unref (icomp);
 
-               g_propagate_error (perror, e_data_cal_create_error_fmt (OtherError, "File '%s' is not v 
VCALENDAR component", uristr));
+               g_propagate_error (perror, e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR, _("File 
“%s” is not a VCALENDAR component"), uristr));
                return;
        }
 
        g_rec_mutex_lock (&priv->idle_save_rmutex);
 
-       cal_backend_file_take_icalcomp (cbfile, icalcomp);
+       cal_backend_file_take_icomp (cbfile, icomp);
        priv->path = uri_to_path (E_CAL_BACKEND (cbfile));
 
        priv->comp_uid_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_object_data);
@@ -1179,7 +1227,7 @@ notify_removals_cb (gpointer key,
 
                e_cal_backend_notify_component_removed (context->backend, id, old_obj_data->full_object, 
NULL);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
        }
 }
 
@@ -1207,7 +1255,7 @@ notify_adds_modifies_cb (gpointer key,
                if (!old_obj_data->full_object || !new_obj_data->full_object)
                        return;
 
-               /* There should be better ways to compare an icalcomponent
+               /* There should be better ways to compare an ICalComponent
                 * than serializing and comparing the strings...
                 */
                old_obj_str = e_cal_component_get_as_string (old_obj_data->full_object);
@@ -1243,14 +1291,14 @@ reload_cal (ECalBackendFile *cbfile,
             GError **perror)
 {
        ECalBackendFilePrivate *priv;
-       icalcomponent *icalcomp, *icalcomp_old;
+       ICalComponent *icomp, *icomp_old;
        GHashTable *comp_uid_hash_old;
 
        priv = cbfile->priv;
 
-       icalcomp = e_cal_util_parse_ics_file (uristr);
-       if (!icalcomp) {
-               g_propagate_error (perror, e_data_cal_create_error_fmt (OtherError, "Cannot parse ISC file 
'%s'", uristr));
+       icomp = e_cal_util_parse_ics_file (uristr);
+       if (!icomp) {
+               g_propagate_error (perror, e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR, _("Cannot 
parse ISC file “%s”"), uristr));
                return;
        }
 
@@ -1258,10 +1306,10 @@ reload_cal (ECalBackendFile *cbfile,
         * individual components as well?
         */
 
-       if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) {
-               icalcomponent_free (icalcomp);
+       if (i_cal_component_isa (icomp) != I_CAL_VCALENDAR_COMPONENT) {
+               g_object_unref (icomp);
 
-               g_propagate_error (perror, e_data_cal_create_error_fmt (OtherError, "File '%s' is not v 
VCALENDAR component", uristr));
+               g_propagate_error (perror, e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR, _("File 
“%s” is not a VCALENDAR component"), uristr));
                return;
        }
 
@@ -1269,8 +1317,8 @@ reload_cal (ECalBackendFile *cbfile,
 
        g_rec_mutex_lock (&priv->idle_save_rmutex);
 
-       icalcomp_old = priv->icalcomp;
-       priv->icalcomp = NULL;
+       icomp_old = priv->vcalendar;
+       priv->vcalendar = NULL;
 
        comp_uid_hash_old = priv->comp_uid_hash;
        priv->comp_uid_hash = NULL;
@@ -1279,7 +1327,7 @@ reload_cal (ECalBackendFile *cbfile,
 
        free_calendar_data (cbfile);
 
-       cal_backend_file_take_icalcomp (cbfile, icalcomp);
+       cal_backend_file_take_icomp (cbfile, icomp);
 
        priv->comp_uid_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_object_data);
        priv->interval_tree = e_intervaltree_new ();
@@ -1295,7 +1343,7 @@ reload_cal (ECalBackendFile *cbfile,
 
        /* Free old data */
 
-       free_calendar_components (comp_uid_hash_old, icalcomp_old);
+       free_calendar_components (comp_uid_hash_old, icomp_old);
 }
 
 static void
@@ -1305,7 +1353,7 @@ create_cal (ECalBackendFile *cbfile,
 {
        gchar *dirname;
        ECalBackendFilePrivate *priv;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        free_refresh_data (cbfile);
 
@@ -1315,7 +1363,7 @@ create_cal (ECalBackendFile *cbfile,
        dirname = g_path_get_dirname (uristr);
        if (g_mkdir_with_parents (dirname, 0700) != 0) {
                g_free (dirname);
-               g_propagate_error (perror, EDC_ERROR (NoSuchCal));
+               g_propagate_error (perror, ECC_ERROR (E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR));
                return;
        }
 
@@ -1324,8 +1372,8 @@ create_cal (ECalBackendFile *cbfile,
        g_rec_mutex_lock (&priv->idle_save_rmutex);
 
        /* Create the new calendar information */
-       icalcomp = e_cal_util_new_top_level ();
-       cal_backend_file_take_icalcomp (cbfile, icalcomp);
+       icomp = e_cal_util_new_top_level ();
+       cal_backend_file_take_icomp (cbfile, icomp);
 
        /* Create our internal data */
        priv->comp_uid_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_object_data);
@@ -1419,7 +1467,7 @@ e_cal_backend_file_open (ECalBackendSync *backend,
 
        str_uri = get_uri_string (E_CAL_BACKEND (backend));
        if (!str_uri) {
-               err = EDC_ERROR_NO_URI ();
+               err = EC_ERROR_NO_URI ();
                goto done;
        }
 
@@ -1430,7 +1478,7 @@ e_cal_backend_file_open (ECalBackendSync *backend,
                        writable = FALSE;
        } else {
                if (only_if_exists)
-                       err = EDC_ERROR (NoSuchCal);
+                       err = ECC_ERROR (E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR);
                else
                        create_cal (cbfile, str_uri, &err);
        }
@@ -1467,11 +1515,11 @@ add_detached_recur_to_vcalendar (gpointer key,
                                  gpointer user_data)
 {
        ECalComponent *recurrence = value;
-       icalcomponent *vcalendar = user_data;
+       ICalComponent *vcalendar = user_data;
 
-       icalcomponent_add_component (
+       i_cal_component_take_component (
                vcalendar,
-               icalcomponent_new_clone (e_cal_component_get_icalcomponent (recurrence)));
+               i_cal_component_new_clone (e_cal_component_get_icalcomponent (recurrence)));
 }
 
 /* Get_object_component handler for the file backend */
@@ -1491,7 +1539,7 @@ e_cal_backend_file_get_object (ECalBackendSync *backend,
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
 
-       if (priv->icalcomp == NULL) {
+       if (priv->vcalendar == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_INVALID_OBJECT,
@@ -1508,7 +1556,7 @@ e_cal_backend_file_get_object (ECalBackendSync *backend,
        obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
        if (!obj_data) {
                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return;
        }
 
@@ -1519,48 +1567,50 @@ e_cal_backend_file_get_object (ECalBackendSync *backend,
                if (comp) {
                        *object = e_cal_component_get_as_string (comp);
                } else {
-                       icalcomponent *icalcomp;
-                       struct icaltimetype itt;
+                       ICalComponent *icomp;
+                       ICalTime *itt;
 
                        if (!obj_data->full_object) {
                                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                                return;
                        }
 
-                       itt = icaltime_from_string (rid);
-                       icalcomp = e_cal_util_construct_instance (
+                       itt = i_cal_time_from_string (rid);
+                       icomp = e_cal_util_construct_instance (
                                e_cal_component_get_icalcomponent (obj_data->full_object),
                                itt);
-                       if (!icalcomp) {
+                       g_object_unref (itt);
+
+                       if (!icomp) {
                                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                                return;
                        }
 
-                       *object = icalcomponent_as_ical_string_r (icalcomp);
+                       *object = i_cal_component_as_ical_string_r (icomp);
 
-                       icalcomponent_free (icalcomp);
+                       g_object_unref (icomp);
                }
        } else {
                if (g_hash_table_size (obj_data->recurrences) > 0) {
-                       icalcomponent *icalcomp;
+                       ICalComponent *icomp;
 
                        /* if we have detached recurrences, return a VCALENDAR */
-                       icalcomp = e_cal_util_new_top_level ();
+                       icomp = e_cal_util_new_top_level ();
 
                        /* detached recurrences don't have full_object */
                        if (obj_data->full_object)
-                               icalcomponent_add_component (
-                                       icalcomp,
-                                       icalcomponent_new_clone (e_cal_component_get_icalcomponent 
(obj_data->full_object)));
+                               i_cal_component_take_component (
+                                       icomp,
+                                       i_cal_component_new_clone (e_cal_component_get_icalcomponent 
(obj_data->full_object)));
 
                        /* add all detached recurrences */
-                       g_hash_table_foreach (obj_data->recurrences, (GHFunc) 
add_detached_recur_to_vcalendar, icalcomp);
+                       g_hash_table_foreach (obj_data->recurrences, (GHFunc) 
add_detached_recur_to_vcalendar, icomp);
 
-                       *object = icalcomponent_as_ical_string_r (icalcomp);
+                       *object = i_cal_component_as_ical_string_r (icomp);
 
-                       icalcomponent_free (icalcomp);
+                       g_object_unref (icomp);
                } else if (obj_data->full_object)
                        *object = e_cal_component_get_as_string (obj_data->full_object);
        }
@@ -1577,24 +1627,26 @@ e_cal_backend_file_add_timezone (ECalBackendSync *backend,
                                  GError **error)
 {
        ETimezoneCache *timezone_cache;
-       icalcomponent *tz_comp;
+       ICalComponent *tz_comp;
 
        timezone_cache = E_TIMEZONE_CACHE (backend);
 
-       tz_comp = icalparser_parse_string (tzobj);
+       tz_comp = i_cal_parser_parse_string (tzobj);
        if (!tz_comp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return;
        }
 
-       if (icalcomponent_isa (tz_comp) == ICAL_VTIMEZONE_COMPONENT) {
-               icaltimezone *zone;
+       if (i_cal_component_isa (tz_comp) == I_CAL_VTIMEZONE_COMPONENT) {
+               ICalTimezone *zone;
 
-               zone = icaltimezone_new ();
-               icaltimezone_set_component (zone, tz_comp);
-               e_timezone_cache_add_timezone (timezone_cache, zone);
-               icaltimezone_free (zone, 1);
+               zone = i_cal_timezone_new ();
+               if (i_cal_timezone_set_component (zone, tz_comp))
+                       e_timezone_cache_add_timezone (timezone_cache, zone);
+               g_object_unref (zone);
        }
+
+       g_object_unref (tz_comp);
 }
 
 typedef struct {
@@ -1611,15 +1663,11 @@ static void
 match_object_sexp_to_component (gpointer value,
                                 gpointer data)
 {
-       ECalComponent * comp = value;
+       ECalComponent *comp = value;
        MatchObjectData *match_data = data;
        ETimezoneCache *timezone_cache;
-       const gchar *uid;
-
-       e_cal_component_get_uid (comp, &uid);
 
        g_return_if_fail (comp != NULL);
-
        g_return_if_fail (match_data->backend != NULL);
 
        timezone_cache = E_TIMEZONE_CACHE (match_data->backend);
@@ -1713,7 +1761,7 @@ e_cal_backend_file_get_object_list (ECalBackendSync *backend,
 
        match_data.obj_sexp = e_cal_backend_sexp_new (sexp);
        if (!match_data.obj_sexp) {
-               g_propagate_error (perror, EDC_ERROR (InvalidQuery));
+               g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_INVALID_QUERY));
                return;
        }
 
@@ -1752,36 +1800,34 @@ e_cal_backend_file_get_object_list (ECalBackendSync *backend,
 
 static void
 add_attach_uris (GSList **attachment_uris,
-                 icalcomponent *icalcomp)
+                ICalComponent *icomp)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
        g_return_if_fail (attachment_uris != NULL);
-       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (icomp != NULL);
 
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTACH_PROPERTY)) {
-               icalattach *attach = icalproperty_get_attach (prop);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icomp, I_CAL_ATTACH_PROPERTY)) {
+               ICalAttach *attach = i_cal_property_get_attach (prop);
 
-               if (attach && icalattach_get_is_url (attach)) {
+               if (attach && i_cal_attach_get_is_url (attach)) {
                        const gchar *url;
 
-                       url = icalattach_get_url (attach);
+                       url = i_cal_attach_get_url (attach);
                        if (url) {
-                               gsize buf_size;
                                gchar *buf;
 
-                               buf_size = strlen (url);
-                               buf = g_malloc0 (buf_size + 1);
-
-                               icalvalue_decode_ical_string (url, buf, buf_size);
+                               buf = i_cal_value_decode_ical_string (url);
 
                                *attachment_uris = g_slist_prepend (*attachment_uris, g_strdup (buf));
 
                                g_free (buf);
                        }
                }
+
+               g_clear_object (&attach);
        }
 }
 
@@ -1820,7 +1866,7 @@ e_cal_backend_file_get_attachment_uris (ECalBackendSync *backend,
        obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
        if (!obj_data) {
                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return;
        }
 
@@ -1831,28 +1877,29 @@ e_cal_backend_file_get_attachment_uris (ECalBackendSync *backend,
                if (comp) {
                        add_attach_uris (attachment_uris, e_cal_component_get_icalcomponent (comp));
                } else {
-                       icalcomponent *icalcomp;
-                       struct icaltimetype itt;
+                       ICalComponent *icomp;
+                       ICalTime *itt;
 
                        if (!obj_data->full_object) {
                                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                                return;
                        }
 
-                       itt = icaltime_from_string (rid);
-                       icalcomp = e_cal_util_construct_instance (
+                       itt = i_cal_time_from_string (rid);
+                       icomp = e_cal_util_construct_instance (
                                e_cal_component_get_icalcomponent (obj_data->full_object),
                                itt);
-                       if (!icalcomp) {
+                       g_object_unref (itt);
+                       if (!icomp) {
                                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                                return;
                        }
 
-                       add_attach_uris (attachment_uris, icalcomp);
+                       add_attach_uris (attachment_uris, icomp);
 
-                       icalcomponent_free (icalcomp);
+                       g_object_unref (icomp);
                }
        } else {
                if (g_hash_table_size (obj_data->recurrences) > 0) {
@@ -1903,7 +1950,7 @@ e_cal_backend_file_start_view (ECalBackend *backend,
                match_data.search_needed = FALSE;
 
        if (!match_data.obj_sexp) {
-               GError *error = EDC_ERROR (InvalidQuery);
+               GError *error = EC_ERROR (E_CLIENT_ERROR_INVALID_QUERY);
                e_data_cal_view_notify_complete (query, error);
                g_error_free (error);
                return;
@@ -1961,76 +2008,82 @@ e_cal_backend_file_start_view (ECalBackend *backend,
 }
 
 static gboolean
-free_busy_instance (ECalComponent *comp,
-                    time_t instance_start,
-                    time_t instance_end,
-                    gpointer data)
+free_busy_instance (ICalComponent *icomp,
+                   ICalTime *instance_start,
+                   ICalTime *instance_end,
+                   gpointer user_data,
+                   GCancellable *cancellable,
+                   GError **error)
 {
-       icalcomponent *vfb = data;
-       icalproperty *prop;
-       icalparameter *param;
-       struct icalperiodtype ipt;
-       icaltimezone *utc_zone;
+       ICalComponent *vfb = user_data;
+       ICalProperty *prop;
+       ICalParameter *param;
+       ICalPeriod *ipt;
        const gchar *summary, *location;
 
-       utc_zone = icaltimezone_get_utc_timezone ();
-
-       ipt.start = icaltime_from_timet_with_zone (instance_start, FALSE, utc_zone);
-       ipt.end = icaltime_from_timet_with_zone (instance_end, FALSE, utc_zone);
-       ipt.duration = icaldurationtype_null_duration ();
+       ipt = i_cal_period_null_period ();
+       i_cal_period_set_start (ipt, instance_start);
+       i_cal_period_set_end (ipt, instance_end);
 
         /* add busy information to the vfb component */
-       prop = icalproperty_new (ICAL_FREEBUSY_PROPERTY);
-       icalproperty_set_freebusy (prop, ipt);
+       prop = i_cal_property_new (I_CAL_FREEBUSY_PROPERTY);
+       i_cal_property_set_freebusy (prop, ipt);
+       g_object_unref (ipt);
 
-       param = icalparameter_new_fbtype (ICAL_FBTYPE_BUSY);
-       icalproperty_add_parameter (prop, param);
+       param = i_cal_parameter_new_fbtype (I_CAL_FBTYPE_BUSY);
+       i_cal_property_take_parameter (prop, param);
 
-       summary = icalcomponent_get_summary (e_cal_component_get_icalcomponent (comp));
+       summary = i_cal_component_get_summary (icomp);
        if (summary && *summary)
-               icalproperty_set_parameter_from_string (prop, "X-SUMMARY", summary);
-       location = icalcomponent_get_location (e_cal_component_get_icalcomponent (comp));
+               i_cal_property_set_parameter_from_string (prop, "X-SUMMARY", summary);
+       location = i_cal_component_get_location (icomp);
        if (location && *location)
-               icalproperty_set_parameter_from_string (prop, "X-LOCATION", location);
+               i_cal_property_set_parameter_from_string (prop, "X-LOCATION", location);
 
-       icalcomponent_add_property (vfb, prop);
+       i_cal_component_take_property (vfb, prop);
 
        return TRUE;
 }
 
-static icalcomponent *
+static ICalComponent *
 create_user_free_busy (ECalBackendFile *cbfile,
                        const gchar *address,
                        const gchar *cn,
                        time_t start,
-                       time_t end)
+                       time_t end,
+                      GCancellable *cancellable)
 {
        ECalBackendFilePrivate *priv;
        GList *l;
-       icalcomponent *vfb;
-       icaltimezone *utc_zone;
+       ICalComponent *vfb;
+       ICalTimezone *utc_zone;
+       ICalTime *starttt, *endtt;
        ECalBackendSExp *obj_sexp;
        gchar *query, *iso_start, *iso_end;
 
        priv = cbfile->priv;
 
        /* create the (unique) VFREEBUSY object that we'll return */
-       vfb = icalcomponent_new_vfreebusy ();
+       vfb = i_cal_component_new_vfreebusy ();
        if (address != NULL) {
-               icalproperty *prop;
-               icalparameter *param;
+               ICalProperty *prop;
+               ICalParameter *param;
 
-               prop = icalproperty_new_organizer (address);
+               prop = i_cal_property_new_organizer (address);
                if (prop != NULL && cn != NULL) {
-                       param = icalparameter_new_cn (cn);
-                       icalproperty_add_parameter (prop, param);
+                       param = i_cal_parameter_new_cn (cn);
+                       i_cal_property_take_parameter (prop, param);
                }
                if (prop != NULL)
-                       icalcomponent_add_property (vfb, prop);
+                       i_cal_component_take_property (vfb, prop);
        }
-       utc_zone = icaltimezone_get_utc_timezone ();
-       icalcomponent_set_dtstart (vfb, icaltime_from_timet_with_zone (start, FALSE, utc_zone));
-       icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+
+       starttt = i_cal_time_from_timet_with_zone (start, FALSE, utc_zone);
+       i_cal_component_set_dtstart (vfb, starttt);
+
+       endtt = i_cal_time_from_timet_with_zone (end, FALSE, utc_zone);
+       i_cal_component_set_dtend (vfb, endtt);
 
        /* add all objects in the given interval */
        iso_start = isodate_from_time_t (start);
@@ -2043,43 +2096,56 @@ create_user_free_busy (ECalBackendFile *cbfile,
        g_free (iso_start);
        g_free (iso_end);
 
-       if (!obj_sexp)
+       if (!obj_sexp) {
+               g_clear_object (&starttt);
+               g_clear_object (&endtt);
                return vfb;
+       }
 
        for (l = priv->comp; l; l = l->next) {
                ECalComponent *comp = l->data;
-               icalcomponent *icalcomp, *vcalendar_comp;
-               icalproperty *prop;
+               ICalComponent *icomp, *vcalendar_comp;
+               ICalProperty *prop;
+               ResolveTzidData rtd;
 
-               icalcomp = e_cal_component_get_icalcomponent (comp);
-               if (!icalcomp)
+               icomp = e_cal_component_get_icalcomponent (comp);
+               if (!icomp)
                        continue;
 
                /* If the event is TRANSPARENT, skip it. */
-               prop = icalcomponent_get_first_property (
-                       icalcomp,
-                       ICAL_TRANSP_PROPERTY);
+               prop = i_cal_component_get_first_property (icomp, I_CAL_TRANSP_PROPERTY);
                if (prop) {
-                       icalproperty_transp transp_val = icalproperty_get_transp (prop);
-                       if (transp_val == ICAL_TRANSP_TRANSPARENT ||
-                           transp_val == ICAL_TRANSP_TRANSPARENTNOCONFLICT)
+                       ICalPropertyTransp transp_val = i_cal_property_get_transp (prop);
+
+                       g_object_unref (prop);
+
+                       if (transp_val == I_CAL_TRANSP_TRANSPARENT ||
+                           transp_val == I_CAL_TRANSP_TRANSPARENTNOCONFLICT)
                                continue;
                }
 
-               if (!e_cal_backend_sexp_match_comp (
-                       obj_sexp, l->data,
-                       E_TIMEZONE_CACHE (cbfile)))
+               if (!e_cal_backend_sexp_match_comp (obj_sexp, comp, E_TIMEZONE_CACHE (cbfile)))
                        continue;
 
-               vcalendar_comp = icalcomponent_get_parent (icalcomp);
-               e_cal_recur_generate_instances (
-                       comp, start, end,
+               vcalendar_comp = i_cal_component_get_parent (icomp);
+
+               resolve_tzid_data_init (&rtd, vcalendar_comp);
+
+               e_cal_recur_generate_instances_sync (
+                       e_cal_component_get_icalcomponent (comp), starttt, endtt,
                        free_busy_instance,
                        vfb,
-                       resolve_tzid,
-                       vcalendar_comp,
-                       icaltimezone_get_utc_timezone ());
+                       resolve_tzid_cb,
+                       &rtd,
+                       i_cal_timezone_get_utc_timezone (),
+                       cancellable, NULL);
+
+               resolve_tzid_data_clear (&rtd);
+               g_clear_object (&vcalendar_comp);
        }
+
+       g_clear_object (&starttt);
+       g_clear_object (&endtt);
        g_object_unref (obj_sexp);
 
        return vfb;
@@ -2100,14 +2166,14 @@ e_cal_backend_file_get_free_busy (ECalBackendSync *backend,
        ECalBackendFile *cbfile;
        ECalBackendFilePrivate *priv;
        gchar *address, *name;
-       icalcomponent *vfb;
+       ICalComponent *vfb;
        gchar *calobj;
        const GSList *l;
 
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
 
-       if (priv->icalcomp == NULL) {
+       if (priv->vcalendar == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR,
@@ -2124,10 +2190,10 @@ e_cal_backend_file_get_free_busy (ECalBackendSync *backend,
 
        if (users == NULL) {
                if (e_cal_backend_mail_account_get_default (registry, &address, &name)) {
-                       vfb = create_user_free_busy (cbfile, address, name, start, end);
-                       calobj = icalcomponent_as_ical_string_r (vfb);
+                       vfb = create_user_free_busy (cbfile, address, name, start, end, cancellable);
+                       calobj = i_cal_component_as_ical_string_r (vfb);
                        *freebusy = g_slist_append (*freebusy, calobj);
-                       icalcomponent_free (vfb);
+                       g_object_unref (vfb);
                        g_free (address);
                        g_free (name);
                }
@@ -2135,10 +2201,10 @@ e_cal_backend_file_get_free_busy (ECalBackendSync *backend,
                for (l = users; l != NULL; l = l->next ) {
                        address = l->data;
                        if (e_cal_backend_mail_account_is_valid (registry, address, &name)) {
-                               vfb = create_user_free_busy (cbfile, address, name, start, end);
-                               calobj = icalcomponent_as_ical_string_r (vfb);
+                               vfb = create_user_free_busy (cbfile, address, name, start, end, cancellable);
+                               calobj = i_cal_component_as_ical_string_r (vfb);
                                *freebusy = g_slist_append (*freebusy, calobj);
-                               icalcomponent_free (vfb);
+                               g_object_unref (vfb);
                                g_free (name);
                        }
                }
@@ -2151,49 +2217,43 @@ static void
 sanitize_component (ECalBackendFile *cbfile,
                     ECalComponent *comp)
 {
-       ECalComponentDateTime dt;
-       icaltimezone *zone;
+       ECalComponentDateTime *dt;
+       ICalTimezone *zone;
 
        /* Check dtstart, dtend and due's timezone, and convert it to local
         * default timezone if the timezone is not in our builtin timezone
         * list */
-       e_cal_component_get_dtstart (comp, &dt);
-       if (dt.value && dt.tzid) {
-               zone = e_timezone_cache_get_timezone (
-                       E_TIMEZONE_CACHE (cbfile), dt.tzid);
+       dt = e_cal_component_get_dtstart (comp);
+       if (dt && e_cal_component_datetime_get_value (dt) && e_cal_component_datetime_get_tzid (dt)) {
+               zone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (cbfile), 
e_cal_component_datetime_get_tzid (dt));
                if (!zone) {
-                       g_free ((gchar *) dt.tzid);
-                       dt.tzid = g_strdup ("UTC");
-                       e_cal_component_set_dtstart (comp, &dt);
+                       e_cal_component_datetime_set_tzid (dt, "UTC");
+                       e_cal_component_set_dtstart (comp, dt);
                }
        }
-       e_cal_component_free_datetime (&dt);
+       e_cal_component_datetime_free (dt);
 
-       e_cal_component_get_dtend (comp, &dt);
-       if (dt.value && dt.tzid) {
-               zone = e_timezone_cache_get_timezone (
-                       E_TIMEZONE_CACHE (cbfile), dt.tzid);
+       dt = e_cal_component_get_dtend (comp);
+       if (dt && e_cal_component_datetime_get_value (dt) && e_cal_component_datetime_get_tzid (dt)) {
+               zone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (cbfile), 
e_cal_component_datetime_get_tzid (dt));
                if (!zone) {
-                       g_free ((gchar *) dt.tzid);
-                       dt.tzid = g_strdup ("UTC");
-                       e_cal_component_set_dtend (comp, &dt);
+                       e_cal_component_datetime_set_tzid (dt, "UTC");
+                       e_cal_component_set_dtend (comp, dt);
                }
        }
-       e_cal_component_free_datetime (&dt);
+       e_cal_component_datetime_free (dt);
 
-       e_cal_component_get_due (comp, &dt);
-       if (dt.value && dt.tzid) {
-               zone = e_timezone_cache_get_timezone (
-                       E_TIMEZONE_CACHE (cbfile), dt.tzid);
+       dt = e_cal_component_get_due (comp);
+       if (dt && e_cal_component_datetime_get_value (dt) && e_cal_component_datetime_get_tzid (dt)) {
+               zone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (cbfile), 
e_cal_component_datetime_get_tzid (dt));
                if (!zone) {
-                       g_free ((gchar *) dt.tzid);
-                       dt.tzid = g_strdup ("UTC");
-                       e_cal_component_set_due (comp, &dt);
+                       e_cal_component_datetime_set_tzid (dt, "UTC");
+                       e_cal_component_set_due (comp, dt);
                }
        }
-       e_cal_component_free_datetime (&dt);
-       e_cal_component_abort_sequence (comp);
+       e_cal_component_datetime_free (dt);
 
+       e_cal_component_abort_sequence (comp);
 }
 
 static void
@@ -2201,19 +2261,20 @@ e_cal_backend_file_create_objects (ECalBackendSync *backend,
                                    EDataCal *cal,
                                    GCancellable *cancellable,
                                    const GSList *in_calobjs,
+                                  guint32 opflags,
                                    GSList **uids,
                                    GSList **new_components,
                                    GError **error)
 {
        ECalBackendFile *cbfile;
        ECalBackendFilePrivate *priv;
-       GSList *icalcomps = NULL;
+       GSList *icomps = NULL;
        const GSList *l;
 
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
 
-       if (priv->icalcomp == NULL) {
+       if (priv->vcalendar == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR,
@@ -2229,81 +2290,84 @@ e_cal_backend_file_create_objects (ECalBackendSync *backend,
 
        /* First step, parse input strings and do uid verification: may fail */
        for (l = in_calobjs; l; l = l->next) {
-               icalcomponent *icalcomp;
+               ICalComponent *icomp;
                const gchar *comp_uid;
 
                /* Parse the icalendar text */
-               icalcomp = icalparser_parse_string ((gchar *) l->data);
-               if (!icalcomp) {
-                       g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+               icomp = i_cal_parser_parse_string ((gchar *) l->data);
+               if (!icomp) {
+                       g_slist_free_full (icomps, g_object_unref);
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (InvalidObject));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                        return;
                }
 
                /* Append icalcomponent to icalcomps */
-               icalcomps = g_slist_prepend (icalcomps, icalcomp);
+               icomps = g_slist_prepend (icomps, icomp);
 
                /* Check kind with the parent */
-               if (icalcomponent_isa (icalcomp) != e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
-                       g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+               if (i_cal_component_isa (icomp) != e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+                       g_slist_free_full (icomps, g_object_unref);
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (InvalidObject));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                        return;
                }
 
                /* Get the UID */
-               comp_uid = icalcomponent_get_uid (icalcomp);
+               comp_uid = i_cal_component_get_uid (icomp);
                if (!comp_uid) {
                        gchar *new_uid;
 
                        new_uid = e_util_generate_uid ();
                        if (!new_uid) {
-                               g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+                               g_slist_free_full (icomps, g_object_unref);
                                g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                               g_propagate_error (error, EDC_ERROR (InvalidObject));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                                return;
                        }
 
-                       icalcomponent_set_uid (icalcomp, new_uid);
-                       comp_uid = icalcomponent_get_uid (icalcomp);
+                       i_cal_component_set_uid (icomp, new_uid);
+                       comp_uid = i_cal_component_get_uid (icomp);
 
                        g_free (new_uid);
                }
 
                /* check that the object is not in our cache */
                if (uid_in_use (cbfile, comp_uid)) {
-                       g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+                       g_slist_free_full (icomps, g_object_unref);
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (ObjectIdAlreadyExists));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS));
                        return;
                }
        }
 
-       icalcomps = g_slist_reverse (icalcomps);
+       icomps = g_slist_reverse (icomps);
 
        /* Second step, add the objects */
-       for (l = icalcomps; l; l = l->next) {
+       for (l = icomps; l; l = l->next) {
                ECalComponent *comp;
-               struct icaltimetype current;
-               icalcomponent *icalcomp = l->data;
+               ICalTime *current;
+               ICalComponent *icomp = l->data;
 
                /* Create the cal component */
-               comp = e_cal_component_new ();
-               e_cal_component_set_icalcomponent (comp, icalcomp);
+               comp = e_cal_component_new_from_icalcomponent (icomp);
+               if (!comp)
+                       continue;
 
                /* Set the created and last modified times on the component, if not there already */
-               current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+               current = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
 
-               if (!icalcomponent_get_first_property (icalcomp, ICAL_CREATED_PROPERTY)) {
+               if (!e_cal_util_component_has_property (icomp, I_CAL_CREATED_PROPERTY)) {
                        /* Update both when CREATED is missing, to make sure the LAST-MODIFIED
                           is not before CREATED */
-                       e_cal_component_set_created (comp, &current);
-                       e_cal_component_set_last_modified (comp, &current);
-               } else if (!icalcomponent_get_first_property (icalcomp, ICAL_LASTMODIFIED_PROPERTY)) {
-                       e_cal_component_set_last_modified (comp, &current);
+                       e_cal_component_set_created (comp, current);
+                       e_cal_component_set_last_modified (comp, current);
+               } else if (!e_cal_util_component_has_property (icomp, I_CAL_LASTMODIFIED_PROPERTY)) {
+                       e_cal_component_set_last_modified (comp, current);
                }
 
+               g_object_unref (current);
+
                /* sanitize the component*/
                sanitize_component (cbfile, comp);
 
@@ -2312,12 +2376,12 @@ e_cal_backend_file_create_objects (ECalBackendSync *backend,
 
                /* Keep the UID and the modified component to return them later */
                if (uids)
-                       *uids = g_slist_prepend (*uids, g_strdup (icalcomponent_get_uid (icalcomp)));
+                       *uids = g_slist_prepend (*uids, g_strdup (i_cal_component_get_uid (icomp)));
 
                *new_components = g_slist_prepend (*new_components, e_cal_component_clone (comp));
        }
 
-       g_slist_free (icalcomps);
+       g_slist_free (icomps);
 
        /* Save the file */
        save (cbfile, TRUE);
@@ -2343,18 +2407,22 @@ remove_object_instance_cb (gpointer key,
                            gpointer user_data)
 {
        time_t fromtt, instancett;
+       ICalTime *itt;
        ECalComponent *instance = value;
        RemoveRecurrenceData *rrdata = user_data;
 
-       fromtt = icaltime_as_timet (icaltime_from_string (rrdata->rid));
-       instancett = icaltime_as_timet (get_rid_icaltime (instance));
+       itt = i_cal_time_from_string (rrdata->rid);
+       fromtt = i_cal_time_as_timet (itt);
+       g_object_unref (itt);
+
+       instancett = get_rid_as_time_t (instance);
 
        if (fromtt > 0 && instancett > 0) {
                if ((rrdata->mod == E_CAL_OBJ_MOD_THIS_AND_PRIOR && instancett <= fromtt) ||
                    (rrdata->mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE && instancett >= fromtt)) {
                        /* remove the component from our data */
-                       icalcomponent_remove_component (
-                               rrdata->cbfile->priv->icalcomp,
+                       i_cal_component_remove_component (
+                               rrdata->cbfile->priv->vcalendar,
                                e_cal_component_get_icalcomponent (instance));
                        rrdata->cbfile->priv->comp = g_list_remove (rrdata->cbfile->priv->comp, instance);
 
@@ -2373,19 +2441,21 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                                    GCancellable *cancellable,
                                    const GSList *calobjs,
                                    ECalObjModType mod,
+                                  guint32 opflags,
                                    GSList **old_components,
                                    GSList **new_components,
                                    GError **error)
 {
        ECalBackendFile *cbfile;
        ECalBackendFilePrivate *priv;
-       GSList *icalcomps = NULL;
+       GSList *icomps = NULL;
        const GSList *l;
+       ResolveTzidData rtd;
 
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
 
-       if (priv->icalcomp == NULL) {
+       if (priv->vcalendar == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR,
@@ -2394,6 +2464,8 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                return;
        }
 
+       resolve_tzid_data_init (&rtd, priv->vcalendar);
+
        switch (mod) {
        case E_CAL_OBJ_MOD_THIS:
        case E_CAL_OBJ_MOD_THIS_AND_PRIOR:
@@ -2401,7 +2473,7 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
        case E_CAL_OBJ_MOD_ALL:
                break;
        default:
-               g_propagate_error (error, EDC_ERROR (NotSupported));
+               g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_NOT_SUPPORTED));
                return;
        }
 
@@ -2415,63 +2487,65 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
        /* First step, parse input strings and do uid verification: may fail */
        for (l = calobjs; l; l = l->next) {
                const gchar *comp_uid;
-               icalcomponent *icalcomp;
+               ICalComponent *icomp;
 
-               /* Parse the icalendar text */
-               icalcomp = icalparser_parse_string (l->data);
-               if (!icalcomp) {
-                       g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+               /* Parse the iCalendar text */
+               icomp = i_cal_parser_parse_string (l->data);
+               if (!icomp) {
+                       g_slist_free_full (icomps, g_object_unref);
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (InvalidObject));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                        return;
                }
 
-               icalcomps = g_slist_prepend (icalcomps, icalcomp);
+               icomps = g_slist_prepend (icomps, icomp);
 
                /* Check kind with the parent */
-               if (icalcomponent_isa (icalcomp) != e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
-                       g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+               if (i_cal_component_isa (icomp) != e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+                       g_slist_free_full (icomps, g_object_unref);
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (InvalidObject));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                        return;
                }
 
                /* Get the uid */
-               comp_uid = icalcomponent_get_uid (icalcomp);
+               comp_uid = i_cal_component_get_uid (icomp);
 
                /* Get the object from our cache */
                if (!g_hash_table_lookup (priv->comp_uid_hash, comp_uid)) {
-                       g_slist_free_full (icalcomps, (GDestroyNotify) icalcomponent_free);
+                       g_slist_free_full (icomps, g_object_unref);
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                        return;
                }
        }
 
-       icalcomps = g_slist_reverse (icalcomps);
+       icomps = g_slist_reverse (icomps);
 
        /* Second step, update the objects */
-       for (l = icalcomps; l; l = l->next) {
-               struct icaltimetype current;
+       for (l = icomps; l; l = l->next) {
+               ICalTime *current;
                RemoveRecurrenceData rrdata;
                GList *detached = NULL;
                gchar *rid = NULL;
-               gchar *real_rid;
                const gchar *comp_uid;
-               icalcomponent * icalcomp = l->data, *split_icalcomp = NULL;
+               ICalComponent * icomp = l->data, *split_icomp = NULL;
                ECalComponent *comp, *recurrence;
                ECalBackendFileObject *obj_data;
-
-               comp_uid = icalcomponent_get_uid (icalcomp);
-               obj_data = g_hash_table_lookup (priv->comp_uid_hash, comp_uid);
+               gpointer value;
 
                /* Create the cal component */
-               comp = e_cal_component_new ();
-               e_cal_component_set_icalcomponent (comp, icalcomp);
+               comp = e_cal_component_new_from_icalcomponent (icomp);
+               if (!comp)
+                       continue;
+
+               comp_uid = i_cal_component_get_uid (icomp);
+               obj_data = g_hash_table_lookup (priv->comp_uid_hash, comp_uid);
 
                /* Set the last modified time on the component */
-               current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-               e_cal_component_set_last_modified (comp, &current);
+               current = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+               e_cal_component_set_last_modified (comp, current);
+               g_object_unref (current);
 
                /* sanitize the component*/
                sanitize_component (cbfile, comp);
@@ -2486,8 +2560,8 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
 
                                /* replace only the full object */
                                if (obj_data->full_object) {
-                                       icalcomponent_remove_component (
-                                               priv->icalcomp,
+                                       i_cal_component_remove_component (
+                                               priv->vcalendar,
                                                e_cal_component_get_icalcomponent (obj_data->full_object));
                                        priv->comp = g_list_remove (priv->comp, obj_data->full_object);
 
@@ -2497,7 +2571,7 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                                /* add the new object */
                                obj_data->full_object = comp;
 
-                               e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid, priv->icalcomp);
+                               e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid_cb, &rtd, cancellable, 
NULL);
 
                                if (!remove_component_from_intervaltree (cbfile, comp)) {
                                        g_message (G_STRLOC " Could not remove component from interval 
tree!");
@@ -2505,20 +2579,22 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
 
                                add_component_to_intervaltree (cbfile, comp);
 
-                               icalcomponent_add_component (
-                                       priv->icalcomp,
+                               i_cal_component_add_component (
+                                       priv->vcalendar,
                                        e_cal_component_get_icalcomponent (obj_data->full_object));
                                priv->comp = g_list_prepend (priv->comp, obj_data->full_object);
                                break;
                        }
 
-                       if (g_hash_table_lookup_extended (obj_data->recurrences, rid, (gpointer *) &real_rid, 
(gpointer *) &recurrence)) {
+                       if (g_hash_table_lookup_extended (obj_data->recurrences, rid, NULL, &value)) {
+                               recurrence = value;
+
                                if (old_components)
                                        *old_components = g_slist_prepend (*old_components, 
e_cal_component_clone (recurrence));
 
                                /* remove the component from our data */
-                               icalcomponent_remove_component (
-                                       priv->icalcomp,
+                               i_cal_component_remove_component (
+                                       priv->vcalendar,
                                        e_cal_component_get_icalcomponent (recurrence));
                                priv->comp = g_list_remove (priv->comp, recurrence);
                                obj_data->recurrences_list = g_list_remove (obj_data->recurrences_list, 
recurrence);
@@ -2533,8 +2609,8 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                                obj_data->recurrences,
                                g_strdup (rid),
                                comp);
-                       icalcomponent_add_component (
-                               priv->icalcomp,
+                       i_cal_component_add_component (
+                               priv->vcalendar,
                                e_cal_component_get_icalcomponent (comp));
                        priv->comp = g_list_append (priv->comp, comp);
                        obj_data->recurrences_list = g_list_append (obj_data->recurrences_list, comp);
@@ -2546,33 +2622,41 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
 
                        /* remove the component from our data, temporarily */
                        if (obj_data->full_object) {
-                               if (mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE &&
-                                   e_cal_util_is_first_instance (obj_data->full_object, 
icalcomponent_get_recurrenceid (icalcomp), resolve_tzid, priv->icalcomp)) {
-                                       icalproperty *prop = icalcomponent_get_first_property (icalcomp, 
ICAL_RECURRENCEID_PROPERTY);
+                               if (mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE) {
+                                       ICalTime *itt = i_cal_component_get_recurrenceid (icomp);
+
+                                       if (e_cal_util_is_first_instance (obj_data->full_object, itt, 
resolve_tzid_cb, &rtd)) {
+                                               ICalProperty *prop = i_cal_component_get_first_property 
(icomp, I_CAL_RECURRENCEID_PROPERTY);
 
-                                       if (prop)
-                                               icalcomponent_remove_property (icalcomp, prop);
+                                               g_clear_object (&itt);
 
-                                       e_cal_component_rescan (comp);
+                                               if (prop) {
+                                                       i_cal_component_remove_property (icomp, prop);
+                                                       g_object_unref (prop);
+                                               }
 
-                                       goto like_mod_all;
+                                               goto like_mod_all;
+                                       }
+
+                                       g_clear_object (&itt);
                                }
 
-                               icalcomponent_remove_component (
-                                       priv->icalcomp,
+                               i_cal_component_remove_component (
+                                       priv->vcalendar,
                                        e_cal_component_get_icalcomponent (obj_data->full_object));
                                priv->comp = g_list_remove (priv->comp, obj_data->full_object);
                        }
 
                        /* now deal with the detached recurrence */
-                       if (g_hash_table_lookup_extended (obj_data->recurrences, rid,
-                                                         (gpointer *) &real_rid, (gpointer *) &recurrence)) {
+                       if (g_hash_table_lookup_extended (obj_data->recurrences, rid, NULL, &value)) {
+                               recurrence = value;
+
                                if (old_components)
                                        *old_components = g_slist_prepend (*old_components, 
e_cal_component_clone (recurrence));
 
                                /* remove the component from our data */
-                               icalcomponent_remove_component (
-                                       priv->icalcomp,
+                               i_cal_component_remove_component (
+                                       priv->vcalendar,
                                        e_cal_component_get_icalcomponent (recurrence));
                                priv->comp = g_list_remove (priv->comp, recurrence);
                                obj_data->recurrences_list = g_list_remove (obj_data->recurrences_list, 
recurrence);
@@ -2592,50 +2676,61 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                         * so that it's always before any detached instance we
                         * might have */
                        if (obj_data->full_object) {
-                               struct icaltimetype rid_struct = icalcomponent_get_recurrenceid (icalcomp), 
master_dtstart;
-                               icalcomponent *master_icalcomp = e_cal_component_get_icalcomponent 
(obj_data->full_object);
-                               icalproperty *prop = icalcomponent_get_first_property (icalcomp, 
ICAL_RECURRENCEID_PROPERTY);
-
-                               if (prop)
-                                       icalcomponent_remove_property (icalcomp, prop);
-
-                               master_dtstart = icalcomponent_get_dtstart (master_icalcomp);
-                               if (master_dtstart.zone && master_dtstart.zone != rid_struct.zone)
-                                       rid_struct = icaltime_convert_to_zone (rid_struct, (icaltimezone *) 
master_dtstart.zone);
-                               split_icalcomp = e_cal_util_split_at_instance (icalcomp, rid_struct, 
master_dtstart);
-                               if (split_icalcomp) {
+                               ICalTime *rid_struct = i_cal_component_get_recurrenceid (icomp), 
*master_dtstart;
+                               ICalComponent *master_icomp = e_cal_component_get_icalcomponent 
(obj_data->full_object);
+                               ICalProperty *prop = i_cal_component_get_first_property (icomp, 
I_CAL_RECURRENCEID_PROPERTY);
+
+                               if (prop) {
+                                       i_cal_component_remove_property (icomp, prop);
+                                       g_object_unref (prop);
+                               }
+
+                               master_dtstart = i_cal_component_get_dtstart (master_icomp);
+                               if (master_dtstart && i_cal_time_get_timezone (master_dtstart) &&
+                                   i_cal_time_get_timezone (master_dtstart) != i_cal_time_get_timezone 
(rid_struct)) {
+                                       i_cal_time_convert_to_zone_inplace (rid_struct, 
i_cal_time_get_timezone (master_dtstart));
+                               }
+
+                               split_icomp = e_cal_util_split_at_instance (icomp, rid_struct, 
master_dtstart);
+                               if (split_icomp) {
                                        ECalComponent *prev_comp;
+
                                        prev_comp = e_cal_component_clone (obj_data->full_object);
 
-                                       rid_struct = icaltime_convert_to_zone (rid_struct, 
icaltimezone_get_utc_timezone ());
+                                       i_cal_time_convert_to_zone_inplace (rid_struct, 
i_cal_timezone_get_utc_timezone ());
+
                                        e_cal_util_remove_instances (e_cal_component_get_icalcomponent 
(obj_data->full_object), rid_struct, mod);
-                                       e_cal_component_rescan (obj_data->full_object);
-                                       e_cal_recur_ensure_end_dates (obj_data->full_object, TRUE, 
resolve_tzid, priv->icalcomp);
+                                       e_cal_recur_ensure_end_dates (obj_data->full_object, TRUE, 
resolve_tzid_cb, &rtd, cancellable, NULL);
 
                                        e_cal_backend_notify_component_modified (E_CAL_BACKEND (backend), 
prev_comp, obj_data->full_object);
 
                                        g_clear_object (&prev_comp);
                                }
 
-                               icalcomponent_add_component (
-                                       priv->icalcomp,
+                               i_cal_component_add_component (
+                                       priv->vcalendar,
                                        e_cal_component_get_icalcomponent (obj_data->full_object));
                                priv->comp = g_list_prepend (priv->comp, obj_data->full_object);
+
+                               g_clear_object (&rid_struct);
+                               g_clear_object (&master_dtstart);
                        } else {
-                               struct icaltimetype rid_struct = icalcomponent_get_recurrenceid (icalcomp);
+                               ICalTime *rid_struct = i_cal_component_get_recurrenceid (icomp);
 
-                               split_icalcomp = e_cal_util_split_at_instance (icalcomp, rid_struct, 
icaltime_null_time ());
+                               split_icomp = e_cal_util_split_at_instance (icomp, rid_struct, NULL);
+
+                               g_object_unref (rid_struct);
                        }
 
-                       if (split_icalcomp) {
+                       if (split_icomp) {
                                gchar *new_uid;
 
                                new_uid = e_util_generate_uid ();
-                               icalcomponent_set_uid (split_icalcomp, new_uid);
+                               i_cal_component_set_uid (split_icomp, new_uid);
                                g_free (new_uid);
 
-                               g_warn_if_fail (e_cal_component_set_icalcomponent (comp, split_icalcomp));
-                               e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid, priv->icalcomp);
+                               g_warn_if_fail (e_cal_component_set_icalcomponent (comp, split_icomp));
+                               e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid_cb, &rtd, cancellable, 
NULL);
 
                                /* sanitize the component */
                                sanitize_component (cbfile, comp);
@@ -2661,14 +2756,14 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
 
                        remove_component (cbfile, comp_uid, obj_data);
 
-                       e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid, priv->icalcomp);
+                       e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid_cb, &rtd, cancellable, NULL);
 
                        /* Add the new object */
                        add_component (cbfile, comp, TRUE);
 
                        if (detached) {
                                /* it had some detached components, place them back */
-                               comp_uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (comp));
+                               comp_uid = i_cal_component_get_uid (e_cal_component_get_icalcomponent (comp));
 
                                if ((obj_data = g_hash_table_lookup (priv->comp_uid_hash, comp_uid)) != NULL) 
{
                                        GList *ll;
@@ -2677,7 +2772,7 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                                                ECalComponent *c = ll->data;
 
                                                g_hash_table_insert (obj_data->recurrences, 
e_cal_component_get_recurid_as_string (c), c);
-                                               icalcomponent_add_component (priv->icalcomp, 
e_cal_component_get_icalcomponent (c));
+                                               i_cal_component_add_component (priv->vcalendar, 
e_cal_component_get_icalcomponent (c));
                                                priv->comp = g_list_append (priv->comp, c);
                                                obj_data->recurrences_list = g_list_append 
(obj_data->recurrences_list, c);
                                        }
@@ -2700,7 +2795,9 @@ e_cal_backend_file_modify_objects (ECalBackendSync *backend,
                }
        }
 
-       g_slist_free (icalcomps);
+       resolve_tzid_data_clear (&rtd);
+
+       g_slist_free (icomps);
 
        /* All the components were updated, now we save the file */
        save (cbfile, TRUE);
@@ -2738,20 +2835,21 @@ remove_instance (ECalBackendFile *cbfile,
                  ECalComponent **new_comp,
                  GError **error)
 {
-       gchar *hash_rid;
        ECalComponent *comp;
-       struct icaltimetype current;
+       ICalTime *current;
 
        /* only check for non-NULL below, empty string is detected here */
        if (rid && !*rid)
                rid = NULL;
 
        if (rid) {
-               struct icaltimetype rid_struct;
+               ICalTime *rid_struct;
+               gpointer value;
 
                /* remove recurrence */
-               if (g_hash_table_lookup_extended (obj_data->recurrences, rid,
-                                                 (gpointer *) &hash_rid, (gpointer *) &comp)) {
+               if (g_hash_table_lookup_extended (obj_data->recurrences, rid, NULL, &value)) {
+                       comp = value;
+
                        /* Removing without parent or not modifying parent?
                         * Report removal to caller. */
                        if (old_comp &&
@@ -2766,22 +2864,23 @@ remove_instance (ECalBackendFile *cbfile,
                                /* old object string not provided,
                                 * instead rely on the view detecting
                                 * whether it contains the id */
-                               ECalComponentId id;
-                               id.uid = (gchar *) uid;
-                               id.rid = (gchar *) rid;
-                               e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbfile), &id, NULL, 
NULL);
+                               ECalComponentId *id;
+
+                               id = e_cal_component_id_new (uid, rid);
+                               e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbfile), id, NULL, 
NULL);
+                               e_cal_component_id_free (id);
                        }
 
                        /* remove the component from our data */
-                       icalcomponent_remove_component (
-                               cbfile->priv->icalcomp,
+                       i_cal_component_remove_component (
+                               cbfile->priv->vcalendar,
                                e_cal_component_get_icalcomponent (comp));
                        cbfile->priv->comp = g_list_remove (cbfile->priv->comp, comp);
                        obj_data->recurrences_list = g_list_remove (obj_data->recurrences_list, comp);
                        g_hash_table_remove (obj_data->recurrences, rid);
                } else if (mod == E_CAL_OBJ_MOD_ONLY_THIS) {
                        if (error)
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                        return obj_data;
                } else {
                        /* not an error, only add EXDATE */
@@ -2802,8 +2901,8 @@ remove_instance (ECalBackendFile *cbfile,
                        return obj_data;
 
                /* remove the main component from our data before modifying it */
-               icalcomponent_remove_component (
-                       cbfile->priv->icalcomp,
+               i_cal_component_remove_component (
+                       cbfile->priv->vcalendar,
                        e_cal_component_get_icalcomponent (obj_data->full_object));
                cbfile->priv->comp = g_list_remove (cbfile->priv->comp, obj_data->full_object);
 
@@ -2812,22 +2911,28 @@ remove_instance (ECalBackendFile *cbfile,
                        *old_comp = e_cal_component_clone (obj_data->full_object);
                }
 
-               rid_struct = icaltime_from_string (rid);
-               if (!rid_struct.zone) {
-                       struct icaltimetype master_dtstart = icalcomponent_get_dtstart 
(e_cal_component_get_icalcomponent (obj_data->full_object));
-                       if (master_dtstart.zone && master_dtstart.zone != rid_struct.zone)
-                               rid_struct = icaltime_convert_to_zone (rid_struct, (icaltimezone *) 
master_dtstart.zone);
-                       rid_struct = icaltime_convert_to_zone (rid_struct, icaltimezone_get_utc_timezone ());
+               rid_struct = i_cal_time_from_string (rid);
+               if (!i_cal_time_get_timezone (rid_struct)) {
+                       ICalTime *master_dtstart = i_cal_component_get_dtstart 
(e_cal_component_get_icalcomponent (obj_data->full_object));
+
+                       if (master_dtstart && i_cal_time_get_timezone (master_dtstart)) {
+                               i_cal_time_convert_to_zone_inplace (rid_struct, i_cal_time_get_timezone 
(master_dtstart));
+                       }
+
+                       i_cal_time_convert_to_zone_inplace (rid_struct, i_cal_timezone_get_utc_timezone ());
                }
 
                e_cal_util_remove_instances (
                        e_cal_component_get_icalcomponent (obj_data->full_object),
                        rid_struct, E_CAL_OBJ_MOD_THIS);
 
+               g_clear_object (&rid_struct);
+
                /* Since we are only removing one instance of recurrence
                 * event, update the last modified time on the component */
-               current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-               e_cal_component_set_last_modified (obj_data->full_object, &current);
+               current = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+               e_cal_component_set_last_modified (obj_data->full_object, current);
+               g_object_unref (current);
 
                /* report update */
                if (new_comp) {
@@ -2837,8 +2942,8 @@ remove_instance (ECalBackendFile *cbfile,
                /* add the modified object to the beginning of the list,
                 * so that it's always before any detached instance we
                 * might have */
-               icalcomponent_add_component (
-                       cbfile->priv->icalcomp,
+               i_cal_component_add_component (
+                       cbfile->priv->vcalendar,
                        e_cal_component_get_icalcomponent (obj_data->full_object));
                cbfile->priv->comp = g_list_prepend (cbfile->priv->comp, obj_data->full_object);
        } else {
@@ -2847,7 +2952,7 @@ remove_instance (ECalBackendFile *cbfile,
                         * caller about this? Not an error with
                         * E_CAL_OBJ_MOD_THIS. */
                        if (mod == E_CAL_OBJ_MOD_ONLY_THIS && error)
-                               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                        return obj_data;
                }
 
@@ -2857,8 +2962,8 @@ remove_instance (ECalBackendFile *cbfile,
                        g_message (G_STRLOC " Could not remove component from interval tree!");
                        return obj_data;
                }
-               icalcomponent_remove_component (
-                       cbfile->priv->icalcomp,
+               i_cal_component_remove_component (
+                       cbfile->priv->vcalendar,
                        e_cal_component_get_icalcomponent (obj_data->full_object));
                cbfile->priv->comp = g_list_remove (cbfile->priv->comp, obj_data->full_object);
 
@@ -2885,14 +2990,16 @@ clone_ecalcomp_from_fileobject (ECalBackendFileObject *obj_data,
                                 const gchar *rid)
 {
        ECalComponent *comp = obj_data->full_object;
-       gchar         *real_rid;
 
        if (!comp)
                return NULL;
 
        if (rid) {
-               if (!g_hash_table_lookup_extended (obj_data->recurrences, rid,
-                                                 (gpointer *) &real_rid, (gpointer *) &comp)) {
+               gpointer value;
+
+               if (g_hash_table_lookup_extended (obj_data->recurrences, rid, NULL, &value)) {
+                       comp = value;
+               } else {
                        /* FIXME remove this once we delete an instance from master object through
                         * modify request by setting exception */
                        comp = obj_data->full_object;
@@ -2918,7 +3025,7 @@ notify_comp_removed_cb (gpointer pecalcomp,
 
        e_cal_backend_notify_component_removed (backend, id, comp, NULL);
 
-       e_cal_component_free_id (id);
+       e_cal_component_id_free (id);
 }
 
 /* Remove_object handler for the file backend */
@@ -2928,6 +3035,7 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
                                    GCancellable *cancellable,
                                    const GSList *ids,
                                    ECalObjModType mod,
+                                  guint32 opflags,
                                    GSList **old_components,
                                    GSList **new_components,
                                    GError **error)
@@ -2939,7 +3047,7 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
 
-       if (priv->icalcomp == NULL) {
+       if (priv->vcalendar == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR,
@@ -2956,7 +3064,7 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
        case E_CAL_OBJ_MOD_ALL:
                break;
        default:
-               g_propagate_error (error, EDC_ERROR (NotSupported));
+               g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_NOT_SUPPORTED));
                return;
        }
 
@@ -2967,24 +3075,24 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
        /* First step, validate the input */
        for (l = ids; l; l = l->next) {
                ECalComponentId *id = l->data;
-                               /* Make the ID contains a uid */
-               if (!id || !id->uid) {
+               /* Make the ID contains a uid */
+               if (!id || !e_cal_component_id_get_uid (id)) {
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                        return;
                }
                                /* Check that it has a recurrence id if mod is E_CAL_OBJ_MOD_THIS_AND_PRIOR
                                         or E_CAL_OBJ_MOD_THIS_AND_FUTURE */
                if ((mod == E_CAL_OBJ_MOD_THIS_AND_PRIOR || mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE) &&
-                       (!id->rid || !*(id->rid))) {
+                   !e_cal_component_id_get_rid (id)) {
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                        return;
                }
                                /* Make sure the uid exists in the local hash table */
-               if (!g_hash_table_lookup (priv->comp_uid_hash, id->uid)) {
+               if (!g_hash_table_lookup (priv->comp_uid_hash, e_cal_component_id_get_uid (id))) {
                        g_rec_mutex_unlock (&priv->idle_save_rmutex);
-                       g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+                       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                        return;
                }
        }
@@ -2997,10 +3105,8 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
                ECalBackendFileObject *obj_data;
                ECalComponentId *id = l->data;
 
-               obj_data = g_hash_table_lookup (priv->comp_uid_hash, id->uid);
-
-               if (id->rid && *(id->rid))
-                       recur_id = id->rid;
+               obj_data = g_hash_table_lookup (priv->comp_uid_hash, e_cal_component_id_get_uid (id));
+               recur_id = e_cal_component_id_get_rid (id);
 
                switch (mod) {
                case E_CAL_OBJ_MOD_ALL :
@@ -3009,7 +3115,7 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
 
                        if (obj_data->recurrences_list)
                                g_list_foreach (obj_data->recurrences_list, notify_comp_removed_cb, cbfile);
-                       remove_component (cbfile, id->uid, obj_data);
+                       remove_component (cbfile, e_cal_component_id_get_uid (id), obj_data);
                        break;
                case E_CAL_OBJ_MOD_ONLY_THIS:
                case E_CAL_OBJ_MOD_THIS: {
@@ -3017,7 +3123,7 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
                        ECalComponent *new_component = NULL;
 
                        remove_instance (
-                               cbfile, obj_data, id->uid, recur_id, mod,
+                               cbfile, obj_data, e_cal_component_id_get_uid (id), recur_id, mod,
                                &old_component, &new_component, error);
 
                        *old_components = g_slist_prepend (*old_components, old_component);
@@ -3029,26 +3135,31 @@ e_cal_backend_file_remove_objects (ECalBackendSync *backend,
                        comp = obj_data->full_object;
 
                        if (comp) {
-                               struct icaltimetype rid_struct;
+                               ICalTime *rid_struct;
 
                                *old_components = g_slist_prepend (*old_components, e_cal_component_clone 
(comp));
 
                                /* remove the component from our data, temporarily */
-                               icalcomponent_remove_component (
-                                       priv->icalcomp,
+                               i_cal_component_remove_component (
+                                       priv->vcalendar,
                                        e_cal_component_get_icalcomponent (comp));
                                priv->comp = g_list_remove (priv->comp, comp);
 
-                               rid_struct = icaltime_from_string (recur_id);
-                               if (!rid_struct.zone) {
-                                       struct icaltimetype master_dtstart = icalcomponent_get_dtstart 
(e_cal_component_get_icalcomponent (comp));
-                                       if (master_dtstart.zone && master_dtstart.zone != rid_struct.zone)
-                                               rid_struct = icaltime_convert_to_zone (rid_struct, 
(icaltimezone *) master_dtstart.zone);
-                                       rid_struct = icaltime_convert_to_zone (rid_struct, 
icaltimezone_get_utc_timezone ());
+                               rid_struct = i_cal_time_from_string (recur_id);
+                               if (!i_cal_time_get_timezone (rid_struct)) {
+                                       ICalTime *master_dtstart = i_cal_component_get_dtstart 
(e_cal_component_get_icalcomponent (comp));
+
+                                       if (master_dtstart && i_cal_time_get_timezone (master_dtstart)) {
+                                               i_cal_time_convert_to_zone_inplace (rid_struct, 
i_cal_time_get_timezone (master_dtstart));
+                                       }
+
+                                       i_cal_time_convert_to_zone_inplace (rid_struct, 
i_cal_timezone_get_utc_timezone ());
                                }
                                e_cal_util_remove_instances (
                                        e_cal_component_get_icalcomponent (comp),
                                        rid_struct, mod);
+
+                               g_object_unref (rid_struct);
                        } else {
                                *old_components = g_slist_prepend (*old_components, NULL);
                        }
@@ -3092,17 +3203,17 @@ cancel_received_object (ECalBackendFile *cbfile,
        ECalBackendFileObject *obj_data;
        ECalBackendFilePrivate *priv;
        gchar *rid;
-       const gchar *uid = NULL;
+       const gchar *uid;
 
        priv = cbfile->priv;
 
        *old_comp = NULL;
        *new_comp = NULL;
 
-       e_cal_component_get_uid (comp, &uid);
+       uid = e_cal_component_get_uid (comp);
 
        /* Find the old version of the component. */
-       obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+       obj_data = uid ? g_hash_table_lookup (priv->comp_uid_hash, uid) : NULL;
        if (!obj_data)
                return FALSE;
 
@@ -3135,13 +3246,13 @@ typedef struct {
 } ECalBackendFileTzidData;
 
 static void
-check_tzids (icalparameter *param,
+check_tzids (ICalParameter *param,
              gpointer data)
 {
        ECalBackendFileTzidData *tzdata = data;
        const gchar *tzid;
 
-       tzid = icalparameter_get_tzid (param);
+       tzid = i_cal_parameter_get_tzid (param);
        if (!tzid || g_hash_table_lookup (tzdata->zones, tzid))
                tzdata->found = FALSE;
 }
@@ -3153,21 +3264,26 @@ static void
 fetch_attachments (ECalBackendSync *backend,
                    ECalComponent *comp)
 {
-       GSList *attach_list = NULL, *new_attach_list = NULL;
+       GSList *attach_list;
        GSList *l;
        gchar *dest_url, *dest_file;
        gint fd, fileindex;
        const gchar *uid;
 
-       e_cal_component_get_attachment_list (comp, &attach_list);
-       e_cal_component_get_uid (comp, &uid);
+       attach_list = e_cal_component_get_attachments (comp);
+       uid = e_cal_component_get_uid (comp);
 
        for (l = attach_list, fileindex = 0; l; l = l->next, fileindex++) {
-               gchar *sfname = g_filename_from_uri ((const gchar *) l->data, NULL, NULL);
+               ICalAttach *attach = l->data;
+               gchar *sfname;
                gchar *filename;
                GMappedFile *mapped_file;
                GError *error = NULL;
 
+               if (!attach || !i_cal_attach_get_is_url (attach))
+                       continue;
+
+               sfname = g_filename_from_uri (i_cal_attach_get_url (attach), NULL, NULL);
                if (!sfname)
                        continue;
 
@@ -3201,27 +3317,33 @@ fetch_attachments (ECalBackendSync *backend,
                        close (fd);
                dest_url = g_filename_to_uri (dest_file, NULL, NULL);
                g_free (dest_file);
-               new_attach_list = g_slist_append (new_attach_list, dest_url);
+
+               g_object_unref (attach);
+               l->data = i_cal_attach_new_from_url (dest_url);
+
+               g_free (dest_url);
                g_free (sfname);
        }
 
-       e_cal_component_set_attachment_list (comp, new_attach_list);
+       e_cal_component_set_attachments (comp, attach_list);
+
+       g_slist_free_full (attach_list, g_object_unref);
 }
 
 static gint
 masters_first_cmp (gconstpointer ptr1,
                   gconstpointer ptr2)
 {
-       icalcomponent *icomp1 = (icalcomponent *) ptr1;
-       icalcomponent *icomp2 = (icalcomponent *) ptr2;
+       ICalComponent *icomp1 = (ICalComponent *) ptr1;
+       ICalComponent *icomp2 = (ICalComponent *) ptr2;
        gboolean has_rid1, has_rid2;
 
-       has_rid1 = (icomp1 && icalcomponent_get_first_property (icomp1, ICAL_RECURRENCEID_PROPERTY)) ? 1 : 0;
-       has_rid2 = (icomp2 && icalcomponent_get_first_property (icomp2, ICAL_RECURRENCEID_PROPERTY)) ? 1 : 0;
+       has_rid1 = (icomp1 && e_cal_util_component_has_property (icomp1, I_CAL_RECURRENCEID_PROPERTY)) ? 1 : 
0;
+       has_rid2 = (icomp2 && e_cal_util_component_has_property (icomp2, I_CAL_RECURRENCEID_PROPERTY)) ? 1 : 
0;
 
        if (has_rid1 == has_rid2)
-               return g_strcmp0 (icomp1 ? icalcomponent_get_uid (icomp1) : NULL,
-                                 icomp2 ? icalcomponent_get_uid (icomp2) : NULL);
+               return g_strcmp0 (icomp1 ? i_cal_component_get_uid (icomp1) : NULL,
+                                 icomp2 ? i_cal_component_get_uid (icomp2) : NULL);
 
        if (has_rid1)
                return 1;
@@ -3235,25 +3357,25 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
                                     EDataCal *cal,
                                     GCancellable *cancellable,
                                     const gchar *calobj,
+                                   guint32 opflags,
                                     GError **error)
 {
        ESourceRegistry *registry;
        ECalBackendFile *cbfile;
        ECalBackendFilePrivate *priv;
-       icalcomponent *toplevel_comp, *icalcomp = NULL;
-       icalcomponent_kind kind;
-       icalproperty_method toplevel_method, method;
-       icalcomponent *subcomp;
-       GList *comps, *del_comps, *l;
+       ICalComponent *toplevel_comp, *icomp = NULL;
+       ICalComponentKind kind;
+       ICalPropertyMethod toplevel_method, method;
+       ICalComponent *subcomp;
+       GSList *comps = NULL, *del_comps = NULL, *link;
        ECalComponent *comp;
-       struct icaltimetype current;
        ECalBackendFileTzidData tzdata;
        GError *err = NULL;
 
        cbfile = E_CAL_BACKEND_FILE (backend);
        priv = cbfile->priv;
 
-       if (priv->icalcomp == NULL) {
+       if (priv->vcalendar == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR,
@@ -3263,9 +3385,9 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
        }
 
        /* Pull the component from the string and ensure that it is sane */
-       toplevel_comp = icalparser_parse_string ((gchar *) calobj);
+       toplevel_comp = i_cal_parser_parse_string (calobj);
        if (!toplevel_comp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return;
        }
 
@@ -3273,97 +3395,94 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
 
        registry = e_cal_backend_get_registry (E_CAL_BACKEND (backend));
 
-       kind = icalcomponent_isa (toplevel_comp);
-       if (kind != ICAL_VCALENDAR_COMPONENT) {
+       kind = i_cal_component_isa (toplevel_comp);
+       if (kind != I_CAL_VCALENDAR_COMPONENT) {
                /* If its not a VCALENDAR, make it one to simplify below */
-               icalcomp = toplevel_comp;
+               icomp = toplevel_comp;
                toplevel_comp = e_cal_util_new_top_level ();
-               if (icalcomponent_get_method (icalcomp) == ICAL_METHOD_CANCEL)
-                       icalcomponent_set_method (toplevel_comp, ICAL_METHOD_CANCEL);
+               if (i_cal_component_get_method (icomp) == I_CAL_METHOD_CANCEL)
+                       i_cal_component_set_method (toplevel_comp, I_CAL_METHOD_CANCEL);
                else
-                       icalcomponent_set_method (toplevel_comp, ICAL_METHOD_PUBLISH);
-               icalcomponent_add_component (toplevel_comp, icalcomp);
+                       i_cal_component_set_method (toplevel_comp, I_CAL_METHOD_PUBLISH);
+               i_cal_component_take_component (toplevel_comp, icomp);
        } else {
-               if (!icalcomponent_get_first_property (toplevel_comp, ICAL_METHOD_PROPERTY))
-                       icalcomponent_set_method (toplevel_comp, ICAL_METHOD_PUBLISH);
+               if (!e_cal_util_component_has_property (toplevel_comp, I_CAL_METHOD_PROPERTY))
+                       i_cal_component_set_method (toplevel_comp, I_CAL_METHOD_PUBLISH);
        }
 
-       toplevel_method = icalcomponent_get_method (toplevel_comp);
+       toplevel_method = i_cal_component_get_method (toplevel_comp);
 
        /* Build a list of timezones so we can make sure all the objects have valid info */
        tzdata.zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
-       subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_VTIMEZONE_COMPONENT);
-       while (subcomp) {
-               icaltimezone *zone;
+       for (subcomp = i_cal_component_get_first_component (toplevel_comp, I_CAL_VTIMEZONE_COMPONENT);
+            subcomp;
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (toplevel_comp, 
I_CAL_VTIMEZONE_COMPONENT)) {
+               ICalTimezone *zone;
 
-               zone = icaltimezone_new ();
-               if (icaltimezone_set_component (zone, subcomp))
-                       g_hash_table_insert (tzdata.zones, g_strdup (icaltimezone_get_tzid (zone)), NULL);
-               icaltimezone_free (zone, 1);
-
-               subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_VTIMEZONE_COMPONENT);
+               zone = i_cal_timezone_new ();
+               if (i_cal_timezone_set_component (zone, subcomp))
+                       g_hash_table_insert (tzdata.zones, g_strdup (i_cal_timezone_get_tzid (zone)), NULL);
+               g_object_unref (zone);
        }
 
        /* First we make sure all the components are usuable */
-       comps = del_comps = NULL;
        kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
 
-       subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_ANY_COMPONENT);
-       while (subcomp) {
-               icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
+       for (subcomp = i_cal_component_get_first_component (toplevel_comp, I_CAL_ANY_COMPONENT);
+            subcomp;
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (toplevel_comp, 
I_CAL_ANY_COMPONENT)) {
+               ICalComponentKind child_kind = i_cal_component_isa (subcomp);
 
                if (child_kind != kind) {
                        /* remove the component from the toplevel VCALENDAR */
-                       if (child_kind != ICAL_VTIMEZONE_COMPONENT)
-                               del_comps = g_list_prepend (del_comps, subcomp);
-
-                       subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT);
+                       if (child_kind != I_CAL_VTIMEZONE_COMPONENT)
+                               del_comps = g_slist_prepend (del_comps, g_object_ref (subcomp));
                        continue;
                }
 
                tzdata.found = TRUE;
-               icalcomponent_foreach_tzid (subcomp, check_tzids, &tzdata);
+               i_cal_component_foreach_tzid (subcomp, check_tzids, &tzdata);
 
                if (!tzdata.found) {
-                       err = EDC_ERROR (InvalidObject);
+                       err = ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT);
+                       g_object_unref (subcomp);
                        goto error;
                }
 
-               if (!icalcomponent_get_uid (subcomp)) {
-                       if (toplevel_method == ICAL_METHOD_PUBLISH) {
-
+               if (!i_cal_component_get_uid (subcomp)) {
+                       if (toplevel_method == I_CAL_METHOD_PUBLISH) {
                                gchar *new_uid = NULL;
 
                                new_uid = e_util_generate_uid ();
-                               icalcomponent_set_uid (subcomp, new_uid);
+                               i_cal_component_set_uid (subcomp, new_uid);
                                g_free (new_uid);
                        } else {
-                               err = EDC_ERROR (InvalidObject);
+                               err = ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT);
+                               g_object_unref (subcomp);
                                goto error;
                        }
 
                }
 
-               comps = g_list_prepend (comps, subcomp);
-               subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT);
+               comps = g_slist_prepend (comps, g_object_ref (subcomp));
        }
 
        /* Now we remove the components we don't care about */
-       for (l = del_comps; l; l = l->next) {
-               subcomp = l->data;
+       for (link = del_comps; link; link = g_slist_next (link)) {
+               subcomp = link->data;
 
-               icalcomponent_remove_component (toplevel_comp, subcomp);
-               icalcomponent_free (subcomp);
+               i_cal_component_remove_component (toplevel_comp, subcomp);
        }
 
-       g_list_free (del_comps);
+       g_slist_free_full (del_comps, g_object_unref);
+       del_comps = NULL;
 
         /* check and patch timezones */
-       if (!e_cal_client_check_timezones (toplevel_comp,
+       if (!e_cal_client_check_timezones_sync (toplevel_comp,
                               NULL,
-                              e_cal_client_tzlookup_icomp,
-                              priv->icalcomp,
+                              e_cal_client_tzlookup_icalcomp_cb,
+                              priv->vcalendar,
                               NULL,
                               &err)) {
                /*
@@ -3378,43 +3497,47 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
 
        /* Merge the iCalendar components with our existing VCALENDAR,
         * resolving any conflicting TZIDs. It also frees the toplevel_comp. */
-       icalcomponent_merge_component (priv->icalcomp, toplevel_comp);
-       toplevel_comp = NULL;
+       i_cal_component_merge_component (priv->vcalendar, toplevel_comp);
+       g_clear_object (&toplevel_comp);
 
        /* Now we manipulate the components we care about */
-       comps = g_list_sort (comps, masters_first_cmp);
+       comps = g_slist_sort (comps, masters_first_cmp);
 
-       for (l = comps; l; l = l->next) {
+       for (link = comps; link; link = g_slist_next (link)) {
                ECalComponent *old_component = NULL;
                ECalComponent *new_component = NULL;
+               ICalTime *current;
                const gchar *uid;
                gchar *rid;
                ECalBackendFileObject *obj_data;
                gboolean is_declined;
 
-               subcomp = l->data;
+               subcomp = link->data;
 
                /* Create the cal component */
-               comp = e_cal_component_new ();
-               e_cal_component_set_icalcomponent (comp, subcomp);
+               comp = e_cal_component_new_from_icalcomponent (g_object_ref (subcomp));
+               if (!comp)
+                       continue;
 
                /* Set the created and last modified times on the component, if not there already */
-               current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+               current = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
 
-               if (!icalcomponent_get_first_property (icalcomp, ICAL_CREATED_PROPERTY)) {
+               if (!e_cal_util_component_has_property (subcomp, ICAL_CREATED_PROPERTY)) {
                        /* Update both when CREATED is missing, to make sure the LAST-MODIFIED
                           is not before CREATED */
-                       e_cal_component_set_created (comp, &current);
-                       e_cal_component_set_last_modified (comp, &current);
-               } else if (!icalcomponent_get_first_property (icalcomp, ICAL_LASTMODIFIED_PROPERTY)) {
-                       e_cal_component_set_last_modified (comp, &current);
+                       e_cal_component_set_created (comp, current);
+                       e_cal_component_set_last_modified (comp, current);
+               } else if (!e_cal_util_component_has_property (subcomp, ICAL_LASTMODIFIED_PROPERTY)) {
+                       e_cal_component_set_last_modified (comp, current);
                }
 
-               e_cal_component_get_uid (comp, &uid);
+               g_clear_object (&current);
+
+               uid = e_cal_component_get_uid (comp);
                rid = e_cal_component_get_recurid_as_string (comp);
 
-               if (icalcomponent_get_first_property (subcomp, ICAL_METHOD_PROPERTY))
-                       method = icalcomponent_get_method (subcomp);
+               if (e_cal_util_component_has_property (subcomp, I_CAL_METHOD_PROPERTY))
+                       method = i_cal_component_get_method (subcomp);
                else
                        method = toplevel_method;
 
@@ -3459,7 +3582,7 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
                                                                                id, old_component,
                                                                                rid ? comp : NULL);
 
-                                       e_cal_component_free_id (id);
+                                       e_cal_component_id_free (id);
                                        g_object_unref (comp);
                                }
 
@@ -3477,19 +3600,19 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
                        break;
                case ICAL_METHOD_ADD:
                        /* FIXME This should be doable once all the recurid stuff is done */
-                       err = EDC_ERROR (UnsupportedMethod);
+                       err = EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("Unsupported method"));
                        g_object_unref (comp);
                        g_free (rid);
                        goto error;
                        break;
                case ICAL_METHOD_COUNTER:
-                       err = EDC_ERROR (UnsupportedMethod);
+                       err = EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("Unsupported method"));
                        g_object_unref (comp);
                        g_free (rid);
                        goto error;
                        break;
                case ICAL_METHOD_DECLINECOUNTER:
-                       err = EDC_ERROR (UnsupportedMethod);
+                       err = EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("Unsupported method"));
                        g_object_unref (comp);
                        g_free (rid);
                        goto error;
@@ -3504,8 +3627,8 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
                                                                        id, old_component, new_component);
 
                                /* remove the component from the toplevel VCALENDAR */
-                               icalcomponent_remove_component (priv->icalcomp, subcomp);
-                               e_cal_component_free_id (id);
+                               i_cal_component_remove_component (priv->vcalendar, subcomp);
+                               e_cal_component_id_free (id);
 
                                if (new_component)
                                        g_object_unref (new_component);
@@ -3516,18 +3639,19 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend,
                        g_free (rid);
                        break;
                default:
-                       err = EDC_ERROR (UnsupportedMethod);
+                       err = EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("Unsupported method"));
                        g_object_unref (comp);
                        g_free (rid);
                        goto error;
                }
        }
 
-       g_list_free (comps);
-
        save (cbfile, TRUE);
 
  error:
+       g_slist_free_full (del_comps, g_object_unref);
+       g_slist_free_full (comps, g_object_unref);
+
        g_hash_table_destroy (tzdata.zones);
        g_rec_mutex_unlock (&priv->idle_save_rmutex);
 
@@ -3540,6 +3664,7 @@ e_cal_backend_file_send_objects (ECalBackendSync *backend,
                                  EDataCal *cal,
                                  GCancellable *cancellable,
                                  const gchar *calobj,
+                                guint32 opflags,
                                  GSList **users,
                                  gchar **modified_calobj,
                                  GError **perror)
@@ -3555,7 +3680,7 @@ cal_backend_file_constructed (GObject *object)
        ESourceRegistry *registry;
        ESource *builtin_source;
        ESource *source;
-       icalcomponent_kind kind;
+       ICalComponentKind kind;
        const gchar *user_data_dir;
        const gchar *component_type;
        const gchar *uid;
@@ -3577,15 +3702,15 @@ cal_backend_file_constructed (GObject *object)
        g_return_if_fail (uid != NULL);
 
        switch (kind) {
-               case ICAL_VEVENT_COMPONENT:
+               case I_CAL_VEVENT_COMPONENT:
                        component_type = "calendar";
                        builtin_source = e_source_registry_ref_builtin_calendar (registry);
                        break;
-               case ICAL_VTODO_COMPONENT:
+               case I_CAL_VTODO_COMPONENT:
                        component_type = "tasks";
                        builtin_source = e_source_registry_ref_builtin_task_list (registry);
                        break;
-               case ICAL_VJOURNAL_COMPONENT:
+               case I_CAL_VJOURNAL_COMPONENT:
                        component_type = "memos";
                        builtin_source = e_source_registry_ref_builtin_memo_list (registry);
                        break;
@@ -3614,7 +3739,7 @@ cal_backend_file_constructed (GObject *object)
 
 static void
 cal_backend_file_add_cached_timezone (ETimezoneCache *cache,
-                                      icaltimezone *zone)
+                                      ICalTimezone *zone)
 {
        ECalBackendFilePrivate *priv;
        const gchar *tzid;
@@ -3624,13 +3749,15 @@ cal_backend_file_add_cached_timezone (ETimezoneCache *cache,
 
        g_rec_mutex_lock (&priv->idle_save_rmutex);
 
-       tzid = icaltimezone_get_tzid (zone);
-       if (icalcomponent_get_timezone (priv->icalcomp, tzid) == NULL) {
-               icalcomponent *tz_comp;
+       tzid = i_cal_timezone_get_tzid (zone);
+       if (!i_cal_component_get_timezone (priv->vcalendar, tzid)) {
+               ICalComponent *tz_comp;
+
+               tz_comp = i_cal_timezone_get_component (zone);
+
+               i_cal_component_take_component (priv->vcalendar, i_cal_component_new_clone (tz_comp));
 
-               tz_comp = icaltimezone_get_component (zone);
-               tz_comp = icalcomponent_new_clone (tz_comp);
-               icalcomponent_add_component (priv->icalcomp, tz_comp);
+               g_clear_object (&tz_comp);
 
                timezone_added = TRUE;
                save (E_CAL_BACKEND_FILE (cache), TRUE);
@@ -3643,24 +3770,29 @@ cal_backend_file_add_cached_timezone (ETimezoneCache *cache,
                g_signal_emit_by_name (cache, "timezone-added", zone);
 }
 
-static icaltimezone *
+static ICalTimezone *
 cal_backend_file_get_cached_timezone (ETimezoneCache *cache,
                                       const gchar *tzid)
 {
        ECalBackendFilePrivate *priv;
-       icaltimezone *zone;
+       ICalTimezone *zone;
 
        priv = E_CAL_BACKEND_FILE_GET_PRIVATE (cache);
 
        g_rec_mutex_lock (&priv->idle_save_rmutex);
-       zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
+       zone = g_hash_table_lookup (priv->cached_timezones, tzid);
+       if (!zone) {
+               zone = i_cal_component_get_timezone (priv->vcalendar, tzid);
+               if (zone)
+                       g_hash_table_insert (priv->cached_timezones, g_strdup (tzid), zone);
+       }
        g_rec_mutex_unlock (&priv->idle_save_rmutex);
 
        if (zone != NULL)
                return zone;
 
        /* Chain up and let ECalBackend try to match
-        * the TZID against a built-in icaltimezone. */
+        * the TZID against a built-in ICalTimezone. */
        return parent_timezone_cache_interface->get_timezone (cache, tzid);
 }
 
@@ -3732,6 +3864,8 @@ e_cal_backend_file_init (ECalBackendFile *cbfile)
        g_rec_mutex_init (&cbfile->priv->idle_save_rmutex);
 
        g_mutex_init (&cbfile->priv->refresh_lock);
+
+       cbfile->priv->cached_timezones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
g_object_unref);
 }
 
 void
@@ -3782,7 +3916,7 @@ e_cal_backend_file_reload (ECalBackendFile *cbfile,
 
        str_uri = get_uri_string (E_CAL_BACKEND (cbfile));
        if (!str_uri) {
-               err = EDC_ERROR_NO_URI ();
+               err = EC_ERROR_NO_URI ();
                goto done;
        }
 
@@ -3793,7 +3927,7 @@ e_cal_backend_file_reload (ECalBackendFile *cbfile,
                if (g_access (str_uri, W_OK) != 0)
                        writable = FALSE;
        } else {
-               err = EDC_ERROR (NoSuchCal);
+               err = ECC_ERROR (E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR);
        }
 
        g_free (str_uri);
@@ -3867,7 +4001,7 @@ write_list (GSList *list)
                const gchar *str = l->data;
                ECalComponent *comp = e_cal_component_new_from_string (str);
                const gchar *uid;
-               e_cal_component_get_uid (comp, &uid);
+               uid = e_cal_component_get_uid (comp);
                g_print ("%s\n", uid);
        }
 }
@@ -3884,14 +4018,14 @@ get_difference_of_lists (ECalBackendFile *cbfile,
                const gchar *uid;
                ECalComponent *comp = e_cal_component_new_from_string (str);
                gboolean found = FALSE;
-               e_cal_component_get_uid (comp, &uid);
+               uid = e_cal_component_get_uid (comp);
 
                for (lsmaller = smaller; lsmaller && !found; lsmaller = lsmaller->next)
                {
                        gchar *strsmaller = lsmaller->data;
                        const gchar *uidsmaller;
                        ECalComponent *compsmaller = e_cal_component_new_from_string (strsmaller);
-                       e_cal_component_get_uid (compsmaller, &uidsmaller);
+                       uidsmaller = e_cal_component_get_uid (compsmaller);
 
                        found = strcmp (uid, uidsmaller) == 0;
 
@@ -3901,14 +4035,19 @@ get_difference_of_lists (ECalBackendFile *cbfile,
                if (!found)
                {
                        time_t time_start, time_end;
+                       ResolveTzidData rtd;
                        printf ("%s IS MISSING\n", uid);
 
+                       resolve_tzid_data_init (&rtd, cbfile->priv->vcalendar);
+
                        e_cal_util_get_component_occur_times (
                                comp, &time_start, &time_end,
-                               resolve_tzid, cbfile->priv->icalcomp,
-                               icaltimezone_get_utc_timezone (),
+                               resolve_tzid_cb, &rtd,
+                               i_cal_timezone_get_utc_timezone (),
                                e_cal_backend_get_kind (E_CAL_BACKEND (cbfile)));
 
+                       resolve_tzid_data_clear (&rtd);
+
                        d (printf ("start %s\n", asctime (gmtime (&time_start))));
                        d (printf ("end %s\n", asctime (gmtime (&time_end))));
                }
diff --git a/src/calendar/backends/gtasks/e-cal-backend-gtasks.c 
b/src/calendar/backends/gtasks/e-cal-backend-gtasks.c
index 62adfd8d2..c1d7c0ff2 100644
--- a/src/calendar/backends/gtasks/e-cal-backend-gtasks.c
+++ b/src/calendar/backends/gtasks/e-cal-backend-gtasks.c
@@ -27,8 +27,8 @@
 
 #define d(x)
 
-#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 ECC_ERROR(_code) e_cal_client_error_create (_code, NULL)
+#define ECC_ERROR_EX(_code, _msg) e_cal_client_error_create (_code, _msg)
 
 #define GTASKS_DEFAULT_TASKLIST_NAME "@default"
 #define X_EVO_GTASKS_SELF_LINK "X-EVOLUTION-GTASKS-SELF-LINK"
@@ -77,20 +77,21 @@ ecb_gtasks_store_data_version (ECalCache *cal_cache)
 }
 
 static void
-ecb_gtasks_update_ical_time_property (icalcomponent *icomp,
-                                     icalproperty_kind kind,
-                                     icalproperty * (* prop_new_func) (struct icaltimetype v),
-                                     void (* prop_set_func) (icalproperty *prop, struct icaltimetype v),
-                                     struct icaltimetype t)
+ecb_gtasks_update_ical_time_property (ICalComponent *icomp,
+                                     ICalPropertyKind kind,
+                                     ICalProperty * (* prop_new_func) (ICalTime *v),
+                                     void (* prop_set_func) (ICalProperty *prop, ICalTime *v),
+                                     ICalTime *tt)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
-       prop = icalcomponent_get_first_property (icomp, kind);
+       prop = i_cal_component_get_first_property (icomp, kind);
        if (prop) {
-               prop_set_func (prop, t);
+               prop_set_func (prop, tt);
+               g_object_unref (prop);
        } else {
-               prop = prop_new_func (t);
-               icalcomponent_add_property (icomp, prop);
+               prop = prop_new_func (tt);
+               i_cal_component_take_property (icomp, prop);
        }
 }
 
@@ -100,81 +101,97 @@ ecb_gtasks_gdata_to_comp (GDataTasksTask *task)
        GDataEntry *entry;
        GDataLink *data_link;
        ECalComponent *comp;
-       icalcomponent *icomp;
+       ICalComponent *icomp;
+       ICalTime *tt;
+       ICalTimezone *utc_zone;
        const gchar *position;
        const gchar *parent;
        const gchar *text;
-       struct icaltimetype tt;
 
        g_return_val_if_fail (GDATA_IS_TASKS_TASK (task), NULL);
 
        entry = GDATA_ENTRY (task);
-       icomp = icalcomponent_new (ICAL_VTODO_COMPONENT);
+       icomp = i_cal_component_new (I_CAL_VTODO_COMPONENT);
 
-       icalcomponent_set_uid (icomp, gdata_entry_get_id (entry));
+       i_cal_component_set_uid (icomp, gdata_entry_get_id (entry));
 
-       tt = icaltime_from_timet_with_zone (gdata_entry_get_published (entry), 0, 
icaltimezone_get_utc_timezone ());
-       if (!icaltime_is_valid_time (tt) || icaltime_is_null_time (tt))
-               tt = icaltime_from_timet_with_zone (gdata_entry_get_updated (entry), 0, 
icaltimezone_get_utc_timezone ());
-       if (!icaltime_is_valid_time (tt) || icaltime_is_null_time (tt))
-               tt = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+       utc_zone = i_cal_timezone_get_utc_timezone ();
 
-       ecb_gtasks_update_ical_time_property (icomp, ICAL_CREATED_PROPERTY,
-               icalproperty_new_created,
-               icalproperty_set_created,
+       tt = i_cal_time_from_timet_with_zone (gdata_entry_get_published (entry), 0, utc_zone);
+       if (!tt || !i_cal_time_is_valid_time (tt) || i_cal_time_is_null_time (tt)) {
+               g_clear_object (&tt);
+               tt = i_cal_time_from_timet_with_zone (gdata_entry_get_updated (entry), 0, utc_zone);
+       }
+       if (!tt || !i_cal_time_is_valid_time (tt) || i_cal_time_is_null_time (tt)) {
+               g_clear_object (&tt);
+               tt = i_cal_time_current_time_with_zone (utc_zone);
+       }
+
+       ecb_gtasks_update_ical_time_property (icomp, I_CAL_CREATED_PROPERTY,
+               i_cal_property_new_created,
+               i_cal_property_set_created,
                tt);
 
-       tt = icaltime_from_timet_with_zone (gdata_entry_get_updated (entry), 0, icaltimezone_get_utc_timezone 
());
-       if (!icaltime_is_valid_time (tt) || icaltime_is_null_time (tt))
-               tt = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomponent_set_dtstamp (icomp, tt);
+       g_clear_object (&tt);
 
-       ecb_gtasks_update_ical_time_property (icomp, ICAL_LASTMODIFIED_PROPERTY,
-               icalproperty_new_lastmodified,
-               icalproperty_set_lastmodified,
+       tt = i_cal_time_from_timet_with_zone (gdata_entry_get_updated (entry), 0, utc_zone);
+       if (!tt || !i_cal_time_is_valid_time (tt) || i_cal_time_is_null_time (tt)) {
+               g_clear_object (&tt);
+               tt = i_cal_time_current_time_with_zone (utc_zone);
+       }
+       i_cal_component_set_dtstamp (icomp, tt);
+
+       ecb_gtasks_update_ical_time_property (icomp, I_CAL_LASTMODIFIED_PROPERTY,
+               i_cal_property_new_lastmodified,
+               i_cal_property_set_lastmodified,
                tt);
 
+       g_clear_object (&tt);
+
        if (gdata_tasks_task_get_due (task) > 0) {
-               tt = icaltime_from_timet_with_zone (gdata_tasks_task_get_due (task), 1, NULL);
-               if (icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt))
-                       icalcomponent_set_due (icomp, tt);
+               tt = i_cal_time_from_timet_with_zone (gdata_tasks_task_get_due (task), 1, NULL);
+               if (tt && i_cal_time_is_valid_time (tt) && !i_cal_time_is_null_time (tt))
+                       i_cal_component_set_due (icomp, tt);
+               g_clear_object (&tt);
        }
 
        if (gdata_tasks_task_get_completed (task) > 0) {
-               tt = icaltime_from_timet_with_zone (gdata_tasks_task_get_completed (task), 0, 
icaltimezone_get_utc_timezone ());
-               if (icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt))
-                       ecb_gtasks_update_ical_time_property (icomp, ICAL_COMPLETED_PROPERTY,
-                               icalproperty_new_completed,
-                               icalproperty_set_completed,
+               tt = i_cal_time_from_timet_with_zone (gdata_tasks_task_get_completed (task), 0, utc_zone);
+               if (tt && i_cal_time_is_valid_time (tt) && !i_cal_time_is_null_time (tt)) {
+                       ecb_gtasks_update_ical_time_property (icomp, I_CAL_COMPLETED_PROPERTY,
+                               i_cal_property_new_completed,
+                               i_cal_property_set_completed,
                                tt);
+               }
+               g_clear_object (&tt);
        }
 
        text = gdata_entry_get_title (entry);
        if (text && *text)
-               icalcomponent_set_summary (icomp, text);
+               i_cal_component_set_summary (icomp, text);
 
        text = gdata_tasks_task_get_notes (task);
        if (text && *text)
-               icalcomponent_set_description (icomp, text);
+               i_cal_component_set_description (icomp, text);
 
        /* "needsAction" or "completed" */
        text = gdata_tasks_task_get_status (task);
        if (g_strcmp0 (text, "completed") == 0)
-               icalcomponent_set_status (icomp, ICAL_STATUS_COMPLETED);
+               i_cal_component_set_status (icomp, I_CAL_STATUS_COMPLETED);
        else if (g_strcmp0 (text, "needsAction") == 0)
-               icalcomponent_set_status (icomp, ICAL_STATUS_NEEDSACTION);
+               i_cal_component_set_status (icomp, I_CAL_STATUS_NEEDSACTION);
 
        data_link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
        if (data_link)
-               e_cal_util_set_x_property (icomp, X_EVO_GTASKS_SELF_LINK, gdata_link_get_uri (data_link));
+               e_cal_util_component_set_x_property (icomp, X_EVO_GTASKS_SELF_LINK, gdata_link_get_uri 
(data_link));
 
        position = gdata_tasks_task_get_position (task);
        if (position)
-               e_cal_util_set_x_property (icomp, X_EVO_GTASKS_POSITION, position);
+               e_cal_util_component_set_x_property (icomp, X_EVO_GTASKS_POSITION, position);
 
        parent = gdata_tasks_task_get_parent (task);
        if (parent)
-               icalcomponent_add_property (icomp, icalproperty_new_relatedto (parent));
+               i_cal_component_take_property (icomp, i_cal_property_new_relatedto (parent));
 
        comp = e_cal_component_new_from_icalcomponent (icomp);
        g_warn_if_fail (comp != NULL);
@@ -189,60 +206,66 @@ ecb_gtasks_comp_to_gdata (ECalComponent *comp,
 {
        GDataEntry *entry;
        GDataTasksTask *task;
-       icalcomponent *icomp;
-       icalproperty *prop;
+       ICalComponent *icomp;
+       ICalProperty *prop;
+       ICalTime *tt;
+       ICalTimezone *utc_zone;
        const gchar *text;
+       gchar *tmp;
 #if GDATA_CHECK_VERSION(0, 17, 10)
        gchar *position;
 #endif
-       gchar *tmp;
-       struct icaltimetype tt;
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
        icomp = e_cal_component_get_icalcomponent (comp);
        g_return_val_if_fail (icomp != NULL, NULL);
 
-       text = icalcomponent_get_uid (icomp);
+       text = i_cal_component_get_uid (icomp);
        task = gdata_tasks_task_new ((!ignore_uid && text && *text) ? text : NULL);
        entry = GDATA_ENTRY (task);
 
-       tt = icalcomponent_get_due (icomp);
-       if (icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt)) {
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+
+       tt = i_cal_component_get_due (icomp);
+       if (tt && i_cal_time_is_valid_time (tt) && !i_cal_time_is_null_time (tt)) {
                gint64 due;
 
-               due = (gint64) icaltime_as_timet_with_zone (tt, icaltimezone_get_utc_timezone ());
+               due = (gint64) i_cal_time_as_timet_with_zone (tt, utc_zone);
                gdata_tasks_task_set_due (task, due);
        }
+       g_clear_object (&tt);
 
-       prop = icalcomponent_get_first_property (icomp, ICAL_COMPLETED_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_COMPLETED_PROPERTY);
        if (prop) {
-               tt = icalproperty_get_completed (prop);
+               tt = i_cal_property_get_completed (prop);
 
-               if (icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt)) {
+               if (tt && i_cal_time_is_valid_time (tt) && !i_cal_time_is_null_time (tt)) {
                        gint64 completed;
 
-                       completed = (gint64) icaltime_as_timet_with_zone (tt, icaltimezone_get_utc_timezone 
());
+                       completed = (gint64) i_cal_time_as_timet_with_zone (tt, utc_zone);
                        gdata_tasks_task_set_completed (task, completed);
                        gdata_tasks_task_set_status (task, "completed");
                }
+               g_clear_object (&tt);
+               g_object_unref (prop);
        }
 
-       text = icalcomponent_get_summary (icomp);
+       text = i_cal_component_get_summary (icomp);
        if (text && *text)
                gdata_entry_set_title (entry, text);
 
-       text = icalcomponent_get_description (icomp);
+       text = i_cal_component_get_description (icomp);
        if (text && *text)
                gdata_tasks_task_set_notes (task, text);
 
        /* "needsAction" or "completed" */
-       if (icalcomponent_get_status (icomp) == ICAL_STATUS_COMPLETED)
+       if (i_cal_component_get_status (icomp) == I_CAL_STATUS_COMPLETED)
                gdata_tasks_task_set_status (task, "completed");
-       else if (icalcomponent_get_status (icomp) == ICAL_STATUS_NEEDSACTION)
+       else if (i_cal_component_get_status (icomp) == I_CAL_STATUS_NEEDSACTION)
                gdata_tasks_task_set_status (task, "needsAction");
 
-       tmp = e_cal_util_dup_x_property (icomp, X_EVO_GTASKS_SELF_LINK);
+       tmp = e_cal_util_component_dup_x_property (icomp, X_EVO_GTASKS_SELF_LINK);
        if (!tmp || !*tmp) {
                g_free (tmp);
                tmp = NULL;
@@ -250,7 +273,7 @@ ecb_gtasks_comp_to_gdata (ECalComponent *comp,
                /* If the passed-in component doesn't contain the libgdata self link,
                   then get it from the cached comp */
                if (cached_comp) {
-                       tmp = e_cal_util_dup_x_property (
+                       tmp = e_cal_util_component_dup_x_property (
                                e_cal_component_get_icalcomponent (cached_comp),
                                X_EVO_GTASKS_SELF_LINK);
                }
@@ -268,7 +291,7 @@ ecb_gtasks_comp_to_gdata (ECalComponent *comp,
 
 #if GDATA_CHECK_VERSION(0, 17, 10)
        /* Position */
-       position = e_cal_util_dup_x_property (icomp, X_EVO_GTASKS_POSITION);
+       position = e_cal_util_component_dup_x_property (icomp, X_EVO_GTASKS_POSITION);
        if (!position || !*position) {
                g_free (position);
                position = NULL;
@@ -276,7 +299,7 @@ ecb_gtasks_comp_to_gdata (ECalComponent *comp,
                /* If the passed-in component doesn't contain the libgdata position,
                   then get it from the cached comp */
                if (cached_comp) {
-                       position = e_cal_util_dup_x_property (
+                       position = e_cal_util_component_dup_x_property (
                                e_cal_component_get_icalcomponent (cached_comp),
                                X_EVO_GTASKS_POSITION);
                }
@@ -288,15 +311,17 @@ ecb_gtasks_comp_to_gdata (ECalComponent *comp,
        g_free (position);
 
        /* Parent */
-       prop = icalcomponent_get_first_property (icomp, ICAL_RELATEDTO_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_RELATEDTO_PROPERTY);
        if (!prop && cached_comp) {
-               prop = icalcomponent_get_first_property (
+               prop = i_cal_component_get_first_property (
                        e_cal_component_get_icalcomponent (cached_comp),
-                       ICAL_RELATEDTO_PROPERTY);
+                       I_CAL_RELATEDTO_PROPERTY);
        }
 
-       if (prop)
-               gdata_tasks_task_set_parent (task, icalproperty_get_relatedto (prop));
+       if (prop) {
+               gdata_tasks_task_set_parent (task, i_cal_property_get_relatedto (prop));
+               g_object_unref (prop);
+       }
 #endif
 
        return task;
@@ -438,14 +463,14 @@ ecb_gtasks_get_backend_property (ECalBackend *cal_backend,
 
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strjoin (",",
-                       CAL_STATIC_CAPABILITY_NO_THISANDFUTURE,
-                       CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
-                       CAL_STATIC_CAPABILITY_TASK_DATE_ONLY,
-                       CAL_STATIC_CAPABILITY_TASK_NO_ALARM,
+                       E_CAL_STATIC_CAPABILITY_NO_THISANDFUTURE,
+                       E_CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
+                       E_CAL_STATIC_CAPABILITY_TASK_DATE_ONLY,
+                       E_CAL_STATIC_CAPABILITY_TASK_NO_ALARM,
                        e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (cal_backend)),
                        NULL);
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
-                  g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+                  g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
                ESourceAuthentication *authentication;
                ESource *source;
                const gchar *user;
@@ -723,13 +748,13 @@ ecb_gtasks_get_changes_sync (ECalMetaBackend *meta_backend,
                                        object = e_cal_component_get_as_string (new_comp);
 
                                        if (cached_comp) {
-                                               struct icaltimetype *cached_tt = NULL, *new_tt = NULL;
+                                               ICalTime *cached_tt, *new_tt;
 
-                                               e_cal_component_get_last_modified (cached_comp, &cached_tt);
-                                               e_cal_component_get_last_modified (new_comp, &new_tt);
+                                               cached_tt = e_cal_component_get_last_modified (cached_comp);
+                                               new_tt = e_cal_component_get_last_modified (new_comp);
 
                                                if (!cached_tt || !new_tt ||
-                                                   icaltime_compare (*cached_tt, *new_tt) != 0) {
+                                                   i_cal_time_compare (cached_tt, new_tt) != 0) {
                                                        /* Google doesn't store/provide 'created', thus use 
'created,
                                                           as first seen by the backend' */
                                                        if (cached_tt)
@@ -739,10 +764,8 @@ ecb_gtasks_get_changes_sync (ECalMetaBackend *meta_backend,
                                                                e_cal_meta_backend_info_new (uid, revision, 
object, NULL));
                                                }
 
-                                               if (cached_tt)
-                                                       e_cal_component_free_icaltimetype (cached_tt);
-                                               if (new_tt)
-                                                       e_cal_component_free_icaltimetype (new_tt);
+                                               g_clear_object (&cached_tt);
+                                               g_clear_object (&new_tt);
                                        } else {
                                                *out_created_objects = g_slist_prepend (*out_created_objects,
                                                        e_cal_meta_backend_info_new (uid, revision, object, 
NULL));
@@ -799,7 +822,7 @@ static gboolean
 ecb_gtasks_load_component_sync (ECalMetaBackend *meta_backend,
                                const gchar *uid,
                                const gchar *extra,
-                               icalcomponent **out_instances,
+                               ICalComponent **out_instances,
                                gchar **out_extra,
                                GCancellable *cancellable,
                                GError **error)
@@ -820,20 +843,20 @@ ecb_gtasks_load_component_sync (ECalMetaBackend *meta_backend,
 
                comp = g_hash_table_lookup (cbgtasks->priv->preloaded, uid);
                if (comp) {
-                       icalcomponent *icalcomp;
+                       ICalComponent *icomp;
 
-                       icalcomp = e_cal_component_get_icalcomponent (comp);
-                       if (icalcomp)
-                               *out_instances = icalcomponent_new_clone (icalcomp);
+                       icomp = e_cal_component_get_icalcomponent (comp);
+                       if (icomp)
+                               *out_instances = i_cal_component_new_clone (icomp);
 
                        g_hash_table_remove (cbgtasks->priv->preloaded, uid);
 
-                       if (icalcomp)
+                       if (icomp)
                                return TRUE;
                }
        }
 
-       g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+       g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
 
        return FALSE;
 }
@@ -844,6 +867,7 @@ ecb_gtasks_save_component_sync (ECalMetaBackend *meta_backend,
                                EConflictResolution conflict_resolution,
                                const GSList *instances, /* ECalComponent * */
                                const gchar *extra,
+                               guint32 opflags,
                                gchar **out_new_uid,
                                gchar **out_new_extra,
                                GCancellable *cancellable,
@@ -853,7 +877,6 @@ ecb_gtasks_save_component_sync (ECalMetaBackend *meta_backend,
        ECalCache *cal_cache;
        GDataTasksTask *new_task, *comp_task;
        ECalComponent *comp, *cached_comp = NULL;
-       icalcomponent *icalcomp;
        const gchar *uid;
 
        g_return_val_if_fail (E_IS_CAL_BACKEND_GTASKS (meta_backend), FALSE);
@@ -865,7 +888,7 @@ ecb_gtasks_save_component_sync (ECalMetaBackend *meta_backend,
        cbgtasks = E_CAL_BACKEND_GTASKS (meta_backend);
 
        if (g_slist_length ((GSList *) instances) != 1) {
-               g_propagate_error (error, EDC_ERROR (InvalidArg));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                g_clear_object (&cal_cache);
                return FALSE;
        }
@@ -873,14 +896,13 @@ ecb_gtasks_save_component_sync (ECalMetaBackend *meta_backend,
        comp = instances->data;
 
        if (!comp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                g_clear_object (&cal_cache);
                return FALSE;
        }
 
-       if (!overwrite_existing || !e_cal_cache_get_component (cal_cache,
-               icalcomponent_get_uid (e_cal_component_get_icalcomponent (comp)),
-               NULL, &cached_comp, cancellable, NULL)) {
+       if (!overwrite_existing ||
+           !e_cal_cache_get_component (cal_cache, e_cal_component_get_uid (comp), NULL, &cached_comp, 
cancellable, NULL)) {
                cached_comp = NULL;
        }
 
@@ -890,7 +912,7 @@ ecb_gtasks_save_component_sync (ECalMetaBackend *meta_backend,
        g_clear_object (&cal_cache);
 
        if (!comp_task) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return FALSE;
        }
 
@@ -912,16 +934,15 @@ ecb_gtasks_save_component_sync (ECalMetaBackend *meta_backend,
        g_object_unref (new_task);
 
        if (!comp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return FALSE;
        }
 
-       icalcomp = e_cal_component_get_icalcomponent (comp);
-       uid = icalcomp ? icalcomponent_get_uid (icalcomp) : NULL;
+       uid = e_cal_component_get_uid (comp);
 
-       if (!icalcomp || !uid) {
+       if (!uid) {
                g_object_unref (comp);
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return FALSE;
        }
 
@@ -941,6 +962,7 @@ ecb_gtasks_remove_component_sync (ECalMetaBackend *meta_backend,
                                  const gchar *uid,
                                  const gchar *extra,
                                  const gchar *object,
+                                 guint32 opflags,
                                  GCancellable *cancellable,
                                  GError **error)
 {
@@ -955,7 +977,7 @@ ecb_gtasks_remove_component_sync (ECalMetaBackend *meta_backend,
 
        cached_comp = e_cal_component_new_from_string (object);
        if (!cached_comp) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return FALSE;
        }
 
@@ -964,7 +986,7 @@ ecb_gtasks_remove_component_sync (ECalMetaBackend *meta_backend,
        task = ecb_gtasks_comp_to_gdata (cached_comp, NULL, FALSE);
        if (!task) {
                g_object_unref (cached_comp);
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
 
                return FALSE;
        }
@@ -1027,20 +1049,22 @@ ecb_gtasks_requires_reconnect (ECalMetaBackend *meta_backend)
 
 static gchar *
 ecb_gtasks_dup_component_revision (ECalCache *cal_cache,
-                                  icalcomponent *icalcomp,
+                                  ICalComponent *icomp,
                                   gpointer user_data)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
        gchar *revision = NULL;
 
-       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (icomp != NULL, NULL);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_LASTMODIFIED_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_LASTMODIFIED_PROPERTY);
        if (prop) {
-               struct icaltimetype itt;
+               ICalTime *itt;
 
-               itt = icalproperty_get_lastmodified (prop);
-               revision = icaltime_as_ical_string_r (itt);
+               itt = i_cal_property_get_lastmodified (prop);
+               revision = i_cal_time_as_ical_string_r (itt);
+               g_clear_object (&itt);
+               g_object_unref (prop);
        }
 
        return revision;
diff --git a/src/calendar/backends/http/e-cal-backend-http.c b/src/calendar/backends/http/e-cal-backend-http.c
index b000195ba..6b722be15 100644
--- a/src/calendar/backends/http/e-cal-backend-http.c
+++ b/src/calendar/backends/http/e-cal-backend-http.c
@@ -29,8 +29,9 @@
 
 #include "e-cal-backend-http.h"
 
-#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 EC_ERROR(_code) e_client_error_create (_code, NULL)
+#define EC_ERROR_EX(_code, _msg) e_client_error_create (_code, _msg)
+#define ECC_ERROR(_code) e_cal_client_error_create (_code, NULL)
 
 G_DEFINE_TYPE (ECalBackendHttp, e_cal_backend_http, E_TYPE_CAL_META_BACKEND)
 
@@ -40,7 +41,7 @@ struct _ECalBackendHttpPrivate {
        SoupRequestHTTP *request;
        GInputStream *input_stream;
        GRecMutex conn_lock;
-       GHashTable *components; /* gchar *uid ~> icalcomponent * */
+       GHashTable *components; /* gchar *uid ~> ICalComponent * */
 };
 
 static gchar *
@@ -165,7 +166,7 @@ ecb_http_connect_sync (ECalMetaBackend *meta_backend,
                g_rec_mutex_unlock (&cbhttp->priv->conn_lock);
                g_free (uri);
 
-               g_propagate_error (error, EDC_ERROR_EX (OtherError, _("URI not set")));
+               g_propagate_error (error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("URI not set")));
                return FALSE;
        }
 
@@ -244,7 +245,7 @@ ecb_http_connect_sync (ECalMetaBackend *meta_backend,
        } else {
                e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
 
-               g_set_error (error, E_DATA_CAL_ERROR, OtherError, _("Malformed URI “%s”: %s"),
+               g_set_error (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, _("Malformed URI “%s”: %s"),
                        uri, local_error ? local_error->message : _("Unknown error"));
        }
 
@@ -313,9 +314,9 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
        ECalBackendHttp *cbhttp;
        SoupMessage *message;
        gchar *icalstring;
-       icalcompiter iter;
-       icalcomponent *maincomp, *subcomp;
-       icalcomponent_kind backend_kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
+       ICalCompIter *iter = NULL;
+       ICalComponent *maincomp, *subcomp;
+       ICalComponentKind backend_kind;
        GHashTable *components = NULL;
        gboolean success = TRUE;
 
@@ -326,12 +327,13 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
        g_return_val_if_fail (out_removed_objects != NULL, FALSE);
 
        cbhttp = E_CAL_BACKEND_HTTP (meta_backend);
+       backend_kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
 
        g_rec_mutex_lock (&cbhttp->priv->conn_lock);
 
        if (!cbhttp->priv->request || !cbhttp->priv->input_stream) {
                g_rec_mutex_unlock (&cbhttp->priv->conn_lock);
-               g_propagate_error (error, EDC_ERROR (RepositoryOffline));
+               g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
                return FALSE;
        }
 
@@ -378,9 +380,9 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
        if (((guchar) icalstring[0]) == 0xEF &&
            ((guchar) icalstring[1]) == 0xBB &&
            ((guchar) icalstring[2]) == 0xBF)
-               maincomp = icalparser_parse_string (icalstring + 3);
+               maincomp = i_cal_parser_parse_string (icalstring + 3);
        else
-               maincomp = icalparser_parse_string (icalstring);
+               maincomp = i_cal_parser_parse_string (icalstring);
 
        g_free (icalstring);
 
@@ -391,96 +393,99 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
                return FALSE;
        }
 
-       if (icalcomponent_isa (maincomp) != ICAL_VCALENDAR_COMPONENT &&
-           icalcomponent_isa (maincomp) != ICAL_XROOT_COMPONENT) {
-               icalcomponent_free (maincomp);
+       if (i_cal_component_isa (maincomp) != I_CAL_VCALENDAR_COMPONENT &&
+           i_cal_component_isa (maincomp) != I_CAL_XROOT_COMPONENT) {
+               g_object_unref (maincomp);
                g_set_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Not a calendar."));
                e_cal_meta_backend_empty_cache_sync (meta_backend, cancellable, NULL);
                ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
                return FALSE;
        }
 
-       if (icalcomponent_isa (maincomp) == ICAL_VCALENDAR_COMPONENT) {
-               subcomp = maincomp;
+       if (i_cal_component_isa (maincomp) == I_CAL_VCALENDAR_COMPONENT) {
+               subcomp = g_object_ref (maincomp);
        } else {
-               iter = icalcomponent_begin_component (maincomp, ICAL_VCALENDAR_COMPONENT);
-               subcomp = icalcompiter_deref (&iter);
+               iter = i_cal_component_begin_component (maincomp, I_CAL_VCALENDAR_COMPONENT);
+               subcomp = i_cal_comp_iter_deref (iter);
        }
 
        while (subcomp && success) {
-               if (subcomp != maincomp)
-                       icalcompiter_next (&iter);
+               ICalComponent *next_subcomp = NULL;
 
-               if (icalcomponent_isa (subcomp) == ICAL_VCALENDAR_COMPONENT) {
+               if (iter)
+                       next_subcomp = i_cal_comp_iter_next (iter);
+
+               if (i_cal_component_isa (subcomp) == I_CAL_VCALENDAR_COMPONENT) {
                        success = e_cal_meta_backend_gather_timezones_sync (meta_backend, subcomp, TRUE, 
cancellable, error);
                        if (success) {
-                               icalcomponent *icalcomp;
+                               ICalComponent *icomp;
 
-                               while (icalcomp = icalcomponent_get_first_component (subcomp, backend_kind), 
icalcomp) {
-                                       icalcomponent *existing_icalcomp;
+                               while (icomp = i_cal_component_get_first_component (subcomp, backend_kind), 
icomp) {
+                                       ICalComponent *existing_icomp;
                                        gpointer orig_key, orig_value;
                                        const gchar *uid;
 
-                                       icalcomponent_remove_component (subcomp, icalcomp);
+                                       i_cal_component_remove_component (subcomp, icomp);
 
                                        if (!components)
-                                               components = g_hash_table_new_full (g_str_hash, g_str_equal, 
g_free, (GDestroyNotify) icalcomponent_free);
+                                               components = g_hash_table_new_full (g_str_hash, g_str_equal, 
g_free, g_object_unref);
 
-                                       if (!icalcomponent_get_first_property (icalcomp, ICAL_UID_PROPERTY)) {
+                                       if (!e_cal_util_component_has_property (icomp, I_CAL_UID_PROPERTY)) {
                                                gchar *new_uid = e_util_generate_uid ();
-                                               icalcomponent_set_uid (icalcomp, new_uid);
+                                               i_cal_component_set_uid (icomp, new_uid);
                                                g_free (new_uid);
                                        }
 
-                                       uid = icalcomponent_get_uid (icalcomp);
+                                       uid = i_cal_component_get_uid (icomp);
 
                                        if (!g_hash_table_lookup_extended (components, uid, &orig_key, 
&orig_value)) {
                                                orig_key = NULL;
                                                orig_value = NULL;
                                        }
 
-                                       existing_icalcomp = orig_value;
-                                       if (existing_icalcomp) {
-                                               if (icalcomponent_isa (existing_icalcomp) != 
ICAL_VCALENDAR_COMPONENT) {
-                                                       icalcomponent *vcal;
+                                       existing_icomp = orig_value;
+                                       if (existing_icomp) {
+                                               if (i_cal_component_isa (existing_icomp) != 
I_CAL_VCALENDAR_COMPONENT) {
+                                                       ICalComponent *vcal;
 
                                                        vcal = e_cal_util_new_top_level ();
 
                                                        g_warn_if_fail (g_hash_table_steal (components, uid));
 
-                                                       icalcomponent_add_component (vcal, existing_icalcomp);
+                                                       i_cal_component_take_component (vcal, existing_icomp);
                                                        g_hash_table_insert (components, g_strdup (uid), 
vcal);
 
                                                        g_free (orig_key);
 
-                                                       existing_icalcomp = vcal;
+                                                       existing_icomp = vcal;
                                                }
 
-                                               icalcomponent_add_component (existing_icalcomp, icalcomp);
+                                               i_cal_component_take_component (existing_icomp, icomp);
                                        } else {
-                                               g_hash_table_insert (components, g_strdup (uid), icalcomp);
+                                               g_hash_table_insert (components, g_strdup (uid), icomp);
                                        }
                                }
                        }
                }
 
-               if (subcomp == maincomp)
-                       subcomp = NULL;
-               else
-                       subcomp = icalcompiter_deref (&iter);
+               g_object_unref (subcomp);
+               subcomp = next_subcomp;
        }
 
+       g_clear_object (&subcomp);
+       g_clear_object (&iter);
+
        if (components) {
                g_warn_if_fail (cbhttp->priv->components == NULL);
                cbhttp->priv->components = components;
 
-               icalcomponent_free (maincomp);
+               g_object_unref (maincomp);
 
                success = E_CAL_META_BACKEND_CLASS (e_cal_backend_http_parent_class)->get_changes_sync 
(meta_backend,
                        last_sync_tag, is_repeat, out_new_sync_tag, out_repeat, out_created_objects,
                        out_modified_objects, out_removed_objects, cancellable, error);
        } else {
-               icalcomponent_free (maincomp);
+               g_object_unref (maincomp);
        }
 
        if (!success)
@@ -498,7 +503,7 @@ ecb_http_list_existing_sync (ECalMetaBackend *meta_backend,
 {
        ECalBackendHttp *cbhttp;
        ECalCache *cal_cache;
-       icalcomponent_kind kind;
+       ICalComponentKind kind;
        GHashTableIter iter;
        gpointer key, value;
 
@@ -518,25 +523,28 @@ ecb_http_list_existing_sync (ECalMetaBackend *meta_backend,
 
        g_hash_table_iter_init (&iter, cbhttp->priv->components);
        while (g_hash_table_iter_next (&iter, &key, &value)) {
-               icalcomponent *icalcomp = value;
+               ICalComponent *icomp = value;
                ECalMetaBackendInfo *nfo;
                const gchar *uid;
                gchar *revision, *object;
 
-               if (icalcomp && icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT)
-                       icalcomp = icalcomponent_get_first_component (icalcomp, kind);
+               if (icomp && i_cal_component_isa (icomp) == I_CAL_VCALENDAR_COMPONENT)
+                       icomp = i_cal_component_get_first_component (icomp, kind);
+               else if (icomp)
+                       icomp = g_object_ref (icomp);
 
-               if (!icalcomp)
+               if (!icomp)
                        continue;
 
-               uid = icalcomponent_get_uid (icalcomp);
-               revision = e_cal_cache_dup_component_revision (cal_cache, icalcomp);
-               object = icalcomponent_as_ical_string_r (value);
+               uid = i_cal_component_get_uid (icomp);
+               revision = e_cal_cache_dup_component_revision (cal_cache, icomp);
+               object = i_cal_component_as_ical_string_r (value);
 
                nfo = e_cal_meta_backend_info_new (uid, revision, object, NULL);
 
                *out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
 
+               g_object_unref (icomp);
                g_free (revision);
                g_free (object);
        }
@@ -552,7 +560,7 @@ static gboolean
 ecb_http_load_component_sync (ECalMetaBackend *meta_backend,
                              const gchar *uid,
                              const gchar *extra,
-                             icalcomponent **out_component,
+                             ICalComponent **out_component,
                              gchar **out_extra,
                              GCancellable *cancellable,
                              GError **error)
@@ -569,7 +577,7 @@ ecb_http_load_component_sync (ECalMetaBackend *meta_backend,
 
        if (!cbhttp->priv->components ||
            !g_hash_table_contains (cbhttp->priv->components, uid)) {
-               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return FALSE;
        }
 
diff --git a/src/calendar/backends/weather/e-cal-backend-weather.c 
b/src/calendar/backends/weather/e-cal-backend-weather.c
index 17f7c5fd1..0fa5513f1 100644
--- a/src/calendar/backends/weather/e-cal-backend-weather.c
+++ b/src/calendar/backends/weather/e-cal-backend-weather.c
@@ -33,8 +33,9 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_CAL_BACKEND_WEATHER, ECalBackendWeatherPrivate))
 
-#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 EC_ERROR(_code) e_client_error_create (_code, NULL)
+#define EC_ERROR_EX(_code, _msg) e_client_error_create (_code, _msg)
+#define ECC_ERROR(_code) e_cal_client_error_create (_code, NULL)
 
 G_DEFINE_TYPE (ECalBackendWeather, e_cal_backend_weather, E_TYPE_CAL_BACKEND_SYNC)
 
@@ -59,7 +60,7 @@ struct _ECalBackendWeatherPrivate {
        gchar *uri;
 
        /* The file cache */
-       ECalBackendStore *store;
+       ECalCache *cache;
 
        /* Reload */
        guint reload_timeout_id;
@@ -129,33 +130,11 @@ maybe_start_reload_timeout (ECalBackendWeather *cbw)
        }
 }
 
-/* TODO Do not replicate this in every backend */
-static icaltimezone *
-resolve_tzid (const gchar *tzid,
-              gpointer user_data)
-{
-       ETimezoneCache *timezone_cache;
-
-       timezone_cache = E_TIMEZONE_CACHE (user_data);
-
-       return e_timezone_cache_get_timezone (timezone_cache, tzid);
-}
-
 static void
 put_component_to_store (ECalBackendWeather *cb,
                         ECalComponent *comp)
 {
-       time_t time_start, time_end;
-       ECalBackendWeatherPrivate *priv;
-
-       priv = cb->priv;
-
-       e_cal_util_get_component_occur_times (
-               comp, &time_start, &time_end,
-               resolve_tzid, cb, icaltimezone_get_utc_timezone (),
-               e_cal_backend_get_kind (E_CAL_BACKEND (cb)));
-
-       e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end);
+       e_cal_cache_put_component (cb->priv->cache, comp, NULL, 0, E_CACHE_IS_ONLINE, NULL, NULL);
 }
 
 static gint
@@ -185,7 +164,7 @@ finished_retrieval_cb (GWeatherInfo *info,
 {
        ECalBackendWeatherPrivate *priv;
        ECalComponent *comp;
-       GSList *comps, *l;
+       GSList *ids, *link;
        GWeatherTemperatureUnit unit;
        ESource *source;
        ESourceWeather *weather_extension;
@@ -218,21 +197,16 @@ finished_retrieval_cb (GWeatherInfo *info,
        g_mutex_unlock (&priv->last_used_mutex);
 
        /* update cache */
-       comps = e_cal_backend_store_get_components (priv->store);
-
-       for (l = comps; l != NULL; l = g_slist_next (l)) {
-               ECalComponentId *id;
+       if (!e_cal_cache_search_ids (priv->cache, NULL, &ids, NULL, NULL))
+               ids = NULL;
 
-               comp = E_CAL_COMPONENT (l->data);
-               id = e_cal_component_get_id (comp);
+       for (link = ids; link; link = g_slist_next (link)) {
+               ECalComponentId *id = link->data;
 
-               e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbw), id, comp, NULL);
-
-               e_cal_component_free_id (id);
-               g_object_unref (comp);
+               e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbw), id, NULL, NULL);
        }
-       g_slist_free (comps);
-       e_cal_backend_store_clean (priv->store);
+       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_id_free);
+       e_cache_remove_all (E_CACHE (priv->cache), NULL, NULL);
 
        comp = create_weather (cbw, info, unit, FALSE, NULL);
        if (comp) {
@@ -370,7 +344,7 @@ begin_retrieval_cb (ECalBackendWeather *cbw)
 }
 
 static const gchar *
-getCategory (GWeatherInfo *report)
+get_category (GWeatherInfo *report)
 {
        struct {
                const gchar *description;
@@ -474,16 +448,16 @@ create_weather (ECalBackendWeather *cbw,
                GSList *same_day_forecasts)
 {
        ECalComponent             *cal_comp;
-       ECalComponentText          comp_summary;
-       icalcomponent             *ical_comp;
-       struct icaltimetype        itt;
-       ECalComponentDateTime      dt;
+       ECalComponentText         *comp_summary;
+       ICalComponent             *icomp;
+       ICalTime              *itt;
+       ECalComponentDateTime     *dt;
        gchar                     *uid;
-       GSList                    *text_list = NULL, *link;
+       GSList                    *text_list, *link;
        ECalComponentText         *description;
-       gchar                     *tmp, *city_name;
+       gchar                     *tmp, *city_name, *summary_text;
        time_t                     update_time;
-       icaltimezone              *update_zone = NULL;
+       ICalTimezone              *update_zone = NULL;
        const GWeatherLocation    *location;
        const GWeatherTimezone    *w_timezone;
        gdouble tmin = 0.0, tmax = 0.0, temp = 0.0;
@@ -494,9 +468,8 @@ create_weather (ECalBackendWeather *cbw,
                return NULL;
 
        /* create the component and event object */
-       ical_comp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       cal_comp = e_cal_component_new ();
-       e_cal_component_set_icalcomponent (cal_comp, ical_comp);
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       cal_comp = e_cal_component_new_from_icalcomponent (icomp);
 
        /* set uid */
        uid = e_util_generate_uid ();
@@ -506,30 +479,30 @@ create_weather (ECalBackendWeather *cbw,
        /* use timezone of the location to determine date for which this is set */
        location = gweather_info_get_location (report);
        if (location && (w_timezone = gweather_location_get_timezone ((GWeatherLocation *) location)))
-               update_zone = icaltimezone_get_builtin_timezone (gweather_timezone_get_tzid 
((GWeatherTimezone *) w_timezone));
+               update_zone = i_cal_timezone_get_builtin_timezone (gweather_timezone_get_tzid 
((GWeatherTimezone *) w_timezone));
 
        if (!update_zone)
-               update_zone = icaltimezone_get_utc_timezone ();
+               update_zone = i_cal_timezone_get_utc_timezone ();
 
        /* Set all-day event's date from forecast data - cannot set is_date,
         * because in that case no timezone conversion is done */
-       itt = icaltime_from_timet_with_zone (update_time, 0, update_zone);
-       itt.hour = 0;
-       itt.minute = 0;
-       itt.second = 0;
-       itt.is_date = 1;
+       itt = i_cal_time_from_timet_with_zone (update_time, 0, update_zone);
+       i_cal_time_set_hour (itt, 0);
+       i_cal_time_set_minute (itt, 0);
+       i_cal_time_set_second (itt, 0);
+       i_cal_time_set_is_date (itt, TRUE);
 
-       dt.value = &itt;
-       if (update_zone)
-               dt.tzid = icaltimezone_get_tzid (update_zone);
-       else
-               dt.tzid = NULL;
+       dt = e_cal_component_datetime_new (itt, update_zone ? i_cal_timezone_get_tzid (update_zone) : NULL);
+       e_cal_component_set_dtstart (cal_comp, dt);
+       e_cal_component_datetime_free (dt);
 
-       e_cal_component_set_dtstart (cal_comp, &dt);
-
-       icaltime_adjust (&itt, 1, 0, 0, 0);
        /* We have to add 1 day to DTEND, as it is not inclusive. */
-       e_cal_component_set_dtend (cal_comp, &dt);
+       i_cal_time_adjust (itt, 1, 0, 0, 0);
+
+       dt = e_cal_component_datetime_new (itt, update_zone ? i_cal_timezone_get_tzid (update_zone) : NULL);
+       e_cal_component_set_dtend (cal_comp, dt);
+       e_cal_component_datetime_free (dt);
+       g_object_unref (itt);
 
        city_name = gweather_info_get_location_name (report);
        if (gweather_info_get_value_temp_min (report, unit, &tmin) &&
@@ -539,31 +512,30 @@ create_weather (ECalBackendWeather *cbw,
 
                min = cal_backend_weather_get_temp (tmin, unit);
                max = cal_backend_weather_get_temp (tmax, unit);
-               comp_summary.value = g_strdup_printf ("%s : %s / %s", city_name, min, max);
+               summary_text = g_strdup_printf ("%s : %s / %s", city_name, min, max);
 
-               g_free (min); g_free (max);
+               g_free (min);
+               g_free (max);
        } else if (gweather_info_get_value_temp (report, unit, &temp)) {
                tmp = cal_backend_weather_get_temp (temp, unit);
-               comp_summary.value = g_strdup_printf ("%s : %s", city_name, tmp);
+               summary_text = g_strdup_printf ("%s : %s", city_name, tmp);
 
                g_free (tmp);
        } else {
-               gchar *temp;
-
-               temp = gweather_info_get_temp (report);
-               comp_summary.value = g_strdup_printf ("%s : %s", city_name, temp);
-
-               g_free (temp);
+               tmp = gweather_info_get_temp (report);
+               summary_text = g_strdup_printf ("%s : %s", city_name, tmp);
+               g_free (tmp);
        }
        g_free (city_name);
 
-       comp_summary.altrep = NULL;
-       e_cal_component_set_summary (cal_comp, &comp_summary);
-       g_free ((gchar *) comp_summary.value);
+       comp_summary = e_cal_component_text_new (summary_text, NULL);
+       e_cal_component_set_summary (cal_comp, comp_summary);
+       e_cal_component_text_free (comp_summary);
+       g_free (summary_text);
 
-       comp_summary.value = gweather_info_get_weather_summary (report);
+       summary_text = gweather_info_get_weather_summary (report);
 
-       description = g_new0 (ECalComponentText, 1);
+       description = e_cal_component_text_new ("", NULL);
        {
                GString *builder;
                gboolean has_forecast_word = FALSE;
@@ -571,7 +543,7 @@ create_weather (ECalBackendWeather *cbw,
                builder = g_string_new (NULL);
 
                if (!is_forecast) {
-                       g_string_append (builder, comp_summary.value);
+                       g_string_append (builder, summary_text);
                        g_string_append_c (builder, '\n');
                }
 
@@ -630,19 +602,18 @@ create_weather (ECalBackendWeather *cbw,
                        }
                }
 
-               description->value = g_string_free (builder, FALSE);
+               e_cal_component_text_set_value (description, builder->str);
+               g_string_free (builder, TRUE);
                g_free (tmp);
        }
-       description->altrep = "";
-       text_list = g_slist_append (text_list, description);
-       e_cal_component_set_description_list (cal_comp, text_list);
-       g_slist_free (text_list);
-       g_free ((gchar *) (description->value));
-       g_free (description);
-       g_free ((gchar *) comp_summary.value);
+
+       text_list = g_slist_prepend (NULL, description);
+       e_cal_component_set_descriptions (cal_comp, text_list);
+       g_slist_free_full (text_list, e_cal_component_text_free);
+       g_free (summary_text);
 
        /* Set category and visibility */
-       e_cal_component_set_categories (cal_comp, getCategory (report));
+       e_cal_component_set_categories (cal_comp, get_category (report));
        e_cal_component_set_classification (cal_comp, E_CAL_COMPONENT_CLASS_PUBLIC);
 
        /* Weather is shown as free time */
@@ -662,22 +633,22 @@ e_cal_backend_weather_get_backend_property (ECalBackend *backend,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strjoin (
                        ","
-                       CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT,
-                       CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS,
-                       CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS,
-                       CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS,
-                       CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT,
-                       CAL_STATIC_CAPABILITY_NO_THISANDFUTURE,
-                       CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
-                       CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED,
+                       E_CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT,
+                       E_CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS,
+                       E_CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS,
+                       E_CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS,
+                       E_CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT,
+                       E_CAL_STATIC_CAPABILITY_NO_THISANDFUTURE,
+                       E_CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
+                       E_CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED,
                        NULL);
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
-                  g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+                  g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
                /* Weather has no particular email addresses associated with it */
                return NULL;
 
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
                return NULL;
        }
 
@@ -704,19 +675,25 @@ e_cal_backend_weather_open (ECalBackendSync *backend,
 
        e_cal_backend_set_writable (E_CAL_BACKEND (backend), FALSE);
 
-       if (!priv->store) {
-               e_cal_backend_cache_remove (cache_dir, "cache.xml");
-               priv->store = e_cal_backend_store_new (
-                       cache_dir, E_TIMEZONE_CACHE (backend));
+       if (!priv->cache) {
+               GError *local_error = NULL;
+               gchar *filename;
+
+               filename = g_build_filename (cache_dir, "cache.db", NULL);
+               priv->cache = e_cal_cache_new (filename, NULL, &local_error);
+               g_free (filename);
+
+               if (!priv->cache) {
+                       if (!local_error)
+                               local_error = EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("Could not create 
cache file"));
+                       else
+                               g_prefix_error (&local_error, _("Could not create cache file: "));
+
+                       g_propagate_error (perror, local_error);
 
-               if (!priv->store) {
-                       g_propagate_error (perror, EDC_ERROR_EX (OtherError, _("Could not create cache 
file")));
                        return;
                }
 
-               /* do we require to load this new store */
-               e_cal_backend_store_load (priv->store);
-
                if (!e_backend_get_online (E_BACKEND (backend)))
                        return;
 
@@ -756,9 +733,10 @@ e_cal_backend_weather_receive_objects (ECalBackendSync *backend,
                                        EDataCal *cal,
                                        GCancellable *cancellable,
                                        const gchar *calobj,
+                                      guint32 opflags,
                                        GError **perror)
 {
-       g_propagate_error (perror, EDC_ERROR (PermissionDenied));
+       g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_PERMISSION_DENIED));
 }
 
 static void
@@ -772,11 +750,13 @@ e_cal_backend_weather_get_object (ECalBackendSync *backend,
 {
        ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
        ECalBackendWeatherPrivate *priv = cbw->priv;
-       ECalComponent *comp;
+       ECalComponent *comp = NULL;
+
+       if (!e_cal_cache_get_component (priv->cache, uid, rid, &comp, NULL, NULL))
+               comp = NULL;
 
-       comp = e_cal_backend_store_get_component (priv->store, uid, rid);
        if (!comp) {
-               g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
                return;
        }
 
@@ -796,13 +776,13 @@ e_cal_backend_weather_get_object_list (ECalBackendSync *backend,
        ECalBackendWeatherPrivate *priv = cbw->priv;
        ECalBackendSExp *sexp;
        ETimezoneCache *timezone_cache;
-       GSList *components, *l;
+       GSList *components = NULL, *l;
        time_t occur_start = -1, occur_end = -1;
        gboolean prunning_by_time;
 
        sexp = e_cal_backend_sexp_new (sexp_string);
        if (sexp == NULL) {
-               g_propagate_error (perror, EDC_ERROR (InvalidQuery));
+               g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_INVALID_QUERY));
                return;
        }
 
@@ -814,9 +794,13 @@ e_cal_backend_weather_get_object_list (ECalBackendSync *backend,
                &occur_start,
                &occur_end);
 
-       components = prunning_by_time ?
-               e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
-               : e_cal_backend_store_get_components (priv->store);
+       if (prunning_by_time) {
+               if (!e_cal_cache_get_components_in_range (priv->cache, occur_start, occur_end, &components, 
NULL, NULL))
+                       components = NULL;
+       } else {
+               if (!e_cal_cache_search_components (priv->cache, NULL, &components, NULL, NULL))
+                       components = NULL;
+       }
 
        for (l = components; l != NULL; l = g_slist_next (l)) {
                if (e_cal_backend_sexp_match_comp (sexp, E_CAL_COMPONENT (l->data), timezone_cache))
@@ -835,10 +819,10 @@ e_cal_backend_weather_add_timezone (ECalBackendSync *backend,
                                     const gchar *tzobj,
                                     GError **error)
 {
-       icalcomponent *tz_comp;
-       icaltimezone *zone;
+       ICalComponent *tz_comp;
+       ICalTimezone *zone;
 
-       tz_comp = icalparser_parse_string (tzobj);
+       tz_comp = i_cal_parser_parse_string (tzobj);
        if (tz_comp == NULL) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
@@ -848,15 +832,17 @@ e_cal_backend_weather_add_timezone (ECalBackendSync *backend,
                return;
        }
 
-       if (icalcomponent_isa (tz_comp) != ICAL_VTIMEZONE_COMPONENT) {
-               g_propagate_error (error, EDC_ERROR (InvalidObject));
+       if (i_cal_component_isa (tz_comp) != I_CAL_VTIMEZONE_COMPONENT) {
+               g_object_unref (tz_comp);
+               g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
                return;
        }
 
-       zone = icaltimezone_new ();
-       icaltimezone_set_component (zone, tz_comp);
-       e_timezone_cache_add_timezone (E_TIMEZONE_CACHE (backend), zone);
-       icaltimezone_free (zone, TRUE);
+       zone = i_cal_timezone_new ();
+       if (i_cal_timezone_set_component (zone, tz_comp))
+               e_timezone_cache_add_timezone (E_TIMEZONE_CACHE (backend), zone);
+       g_object_unref (zone);
+       g_object_unref (tz_comp);
 }
 
 static void
@@ -870,16 +856,22 @@ e_cal_backend_weather_get_free_busy (ECalBackendSync *backend,
                                      GError **perror)
 {
        /* Weather doesn't count as busy time */
-       icalcomponent *vfb = icalcomponent_new_vfreebusy ();
-       icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
+       ICalComponent *vfb = i_cal_component_new_vfreebusy ();
+       ICalTimezone *utc_zone = i_cal_timezone_get_utc_timezone ();
+       ICalTime *itt;
        gchar *calobj;
 
-       icalcomponent_set_dtstart (vfb, icaltime_from_timet_with_zone (start, FALSE, utc_zone));
-       icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
+       itt = i_cal_time_from_timet_with_zone (start, FALSE, utc_zone);
+       i_cal_component_set_dtstart (vfb, itt);
+       g_object_unref (itt);
+
+       itt = i_cal_time_from_timet_with_zone (end, FALSE, utc_zone);
+       i_cal_component_set_dtend (vfb, itt);
+       g_object_unref (itt);
 
-       calobj = icalcomponent_as_ical_string_r (vfb);
+       calobj = i_cal_component_as_ical_string_r (vfb);
        *freebusy = g_slist_append (NULL, calobj);
-       icalcomponent_free (vfb);
+       g_object_unref (vfb);
 }
 
 static void
@@ -890,7 +882,7 @@ e_cal_backend_weather_start_view (ECalBackend *backend,
        ECalBackendWeatherPrivate *priv;
        ECalBackendSExp *sexp;
        ETimezoneCache *timezone_cache;
-       GSList *components, *l;
+       GSList *components = NULL, *l;
        GSList *objects;
        GError *error;
        time_t occur_start = -1, occur_end = -1;
@@ -899,8 +891,8 @@ e_cal_backend_weather_start_view (ECalBackend *backend,
        cbw = E_CAL_BACKEND_WEATHER (backend);
        priv = cbw->priv;
 
-       if (!priv->store) {
-               error = EDC_ERROR (NoSuchCal);
+       if (!priv->cache) {
+               error = ECC_ERROR (E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR);
                e_data_cal_view_notify_complete (query, error);
                g_error_free (error);
                return;
@@ -908,7 +900,7 @@ e_cal_backend_weather_start_view (ECalBackend *backend,
 
        sexp = e_data_cal_view_get_sexp (query);
        if (!sexp) {
-               error = EDC_ERROR (InvalidQuery);
+               error = EC_ERROR (E_CLIENT_ERROR_INVALID_QUERY);
                e_data_cal_view_notify_complete (query, error);
                g_error_free (error);
                return;
@@ -918,9 +910,13 @@ e_cal_backend_weather_start_view (ECalBackend *backend,
 
        objects = NULL;
        prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (sexp, &occur_start, &occur_end);
-       components = prunning_by_time ?
-               e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
-               : e_cal_backend_store_get_components (priv->store);
+       if (prunning_by_time) {
+               if (!e_cal_cache_get_components_in_range (priv->cache, occur_start, occur_end, &components, 
NULL, NULL))
+                       components = NULL;
+       } else {
+               if (!e_cal_cache_search_components (priv->cache, NULL, &components, NULL, NULL))
+                       components = NULL;
+       }
 
        for (l = components; l != NULL; l = g_slist_next (l)) {
                if (e_cal_backend_sexp_match_comp (sexp, E_CAL_COMPONENT (l->data), timezone_cache))
@@ -1047,11 +1043,7 @@ e_cal_backend_weather_finalize (GObject *object)
 
        priv = E_CAL_BACKEND_WEATHER_GET_PRIVATE (object);
 
-       if (priv->store) {
-               g_object_unref (priv->store);
-               priv->store = NULL;
-       }
-
+       g_clear_object (&priv->cache);
        g_mutex_clear (&priv->last_used_mutex);
 
        /* Chain up to parent's finalize() method. */
@@ -1105,5 +1097,5 @@ e_cal_backend_weather_class_init (ECalBackendWeatherClass *class)
        backend_class->start_view = e_cal_backend_weather_start_view;
 
        /* Register our ESource extension. */
-       E_TYPE_SOURCE_WEATHER;
+       g_type_ensure (E_TYPE_SOURCE_WEATHER);
 }
diff --git a/src/calendar/libecal/CMakeLists.txt b/src/calendar/libecal/CMakeLists.txt
index b1cdf8d5a..e2b22c893 100644
--- a/src/calendar/libecal/CMakeLists.txt
+++ b/src/calendar/libecal/CMakeLists.txt
@@ -1,6 +1,6 @@
-glib_mkenums(e-cal-enumtypes e-cal-types.h E_CAL_ENUMTYPES_H)
+glib_mkenums(e-cal-enumtypes e-cal-enums.h E_CAL_ENUMTYPES_H)
 
-add_pkgconfig_file(libecal.pc.in libecal-${API_VERSION}.pc)
+add_pkgconfig_file(libecal.pc.in libecal-${CAL_API_VERSION}.pc)
 
 set(DEPENDENCIES
        edbus-private
@@ -8,17 +8,28 @@ set(DEPENDENCIES
 )
 
 set(SOURCES
-       e-cal.c
        e-cal-client.c
        e-cal-client-view.c
        e-cal-component.c
+       e-cal-component-alarm.c
+       e-cal-component-alarm-instance.c
+       e-cal-component-alarm-repeat.c
+       e-cal-component-alarm-trigger.c
+       e-cal-component-alarms.c
+       e-cal-component-attendee.c
+       e-cal-component-datetime.c
+       e-cal-component-id.c
+       e-cal-component-organizer.c
+       e-cal-component-parameter-bag.c
+       e-cal-component-period.c
+       e-cal-component-property-bag.c
+       e-cal-component-range.c
+       e-cal-component-text.c
        e-cal-recur.c
        e-cal-time-util.c
        e-cal-check-timezones.c
        e-cal-system-timezone.c
        e-cal-util.c
-       e-cal-view.c
-       e-cal-view-private.h
        e-reminder-watcher.c
        e-timezone-cache.c
        ${CMAKE_CURRENT_BINARY_DIR}/e-cal-enumtypes.c
@@ -26,17 +37,29 @@ set(SOURCES
 
 set(HEADERS
        libecal.h
-       e-cal.h
        e-cal-client.h
        e-cal-client-view.h
        e-cal-component.h
+       e-cal-component-alarm.h
+       e-cal-component-alarm-instance.h
+       e-cal-component-alarm-repeat.h
+       e-cal-component-alarm-trigger.h
+       e-cal-component-alarms.h
+       e-cal-component-attendee.h
+       e-cal-component-datetime.h
+       e-cal-component-id.h
+       e-cal-component-parameter-bag.h
+       e-cal-component-organizer.h
+       e-cal-component-period.h
+       e-cal-component-property-bag.h
+       e-cal-component-range.h
+       e-cal-component-text.h
+       e-cal-enums.h
        e-cal-recur.h
        e-cal-time-util.h
-        e-cal-check-timezones.h
+       e-cal-check-timezones.h
        e-cal-system-timezone.h
-       e-cal-types.h
        e-cal-util.h
-       e-cal-view.h
        e-reminder-watcher.h
        e-timezone-cache.h
        ${CMAKE_CURRENT_BINARY_DIR}/e-cal-enumtypes.h
@@ -54,7 +77,7 @@ add_dependencies(ecal
 set_target_properties(ecal PROPERTIES
        VERSION "${LIBECAL_CURRENT}.${LIBECAL_REVISION}.${LIBECAL_AGE}"
        SOVERSION ${LIBECAL_CURRENT}
-       OUTPUT_NAME ecal-${API_VERSION}
+       OUTPUT_NAME ecal-${CAL_API_VERSION}
 )
 
 target_compile_definitions(ecal PRIVATE
@@ -91,3 +114,32 @@ install(TARGETS ecal
 install(FILES ${HEADERS}
        DESTINATION ${privincludedir}/libecal
 )
+
+set(gir_sources ${SOURCES} ${HEADERS})
+set(gir_identifies_prefixes ECal E)
+set(gir_includes GObject-2.0 Gio-2.0 Soup-2.4 libxml2-2.0 ICalGLib-3.0)
+set(gir_cflags
+       -DLIBECAL_COMPILATION
+       -I${CMAKE_BINARY_DIR}/src/calendar
+       -I${CMAKE_SOURCE_DIR}/src/calendar
+)
+set(gir_libdirs)
+set(gir_libs ecal)
+set(gir_deps
+       ${CMAKE_BINARY_DIR}/src/camel/Camel-${API_VERSION}.gir
+       ${CMAKE_BINARY_DIR}/src/libedataserver/EDataServer-${API_VERSION}.gir
+)
+
+gir_add_introspection_simple(
+       ECal
+       libecal
+       ${CAL_API_VERSION}
+       "libecal/libecal.h"
+       gir_identifies_prefixes
+       gir_includes
+       gir_cflags
+       gir_libdirs
+       gir_libs
+       gir_deps
+       gir_sources
+)
diff --git a/src/calendar/libecal/e-cal-check-timezones.c b/src/calendar/libecal/e-cal-check-timezones.c
index 32b18187c..8c6898190 100644
--- a/src/calendar/libecal/e-cal-check-timezones.c
+++ b/src/calendar/libecal/e-cal-check-timezones.c
@@ -18,13 +18,13 @@
 
 #include "evolution-data-server-config.h"
 
-#include <libical/ical.h>
-
-#include "e-cal-check-timezones.h"
-#include <libecal/e-cal.h>
-#include <libecal/e-cal-client.h>
 #include <string.h>
 #include <ctype.h>
+#include <libical-glib/libical-glib.h>
+
+#include "e-cal-client.h"
+
+#include "e-cal-check-timezones.h"
 
 /*
  * Matches a location to a system timezone definition via a fuzzy
@@ -36,14 +36,14 @@
 static const gchar *
 e_cal_match_location (const gchar *location)
 {
-       icaltimezone *icomp;
+       icaltimezone *zone;
        const gchar *tail;
        gsize len;
        gchar *buffer;
 
-       icomp = icaltimezone_get_builtin_timezone (location);
-       if (icomp) {
-               return icaltimezone_get_tzid (icomp);
+       zone = icaltimezone_get_builtin_timezone (location);
+       if (zone) {
+               return icaltimezone_get_tzid (zone);
        }
 
        /* try a bit harder by stripping trailing suffix */
@@ -54,10 +54,10 @@ e_cal_match_location (const gchar *location)
        if (buffer) {
                memcpy (buffer, location, len);
                buffer[len] = 0;
-               icomp = icaltimezone_get_builtin_timezone (buffer);
+               zone = icaltimezone_get_builtin_timezone (buffer);
                g_free (buffer);
-               if (icomp) {
-                       return icaltimezone_get_tzid (icomp);
+               if (zone) {
+                       return icaltimezone_get_tzid (zone);
                }
        }
 
@@ -144,23 +144,27 @@ e_cal_match_tzid (const gchar *tzid)
 }
 
 static void
-patch_tzids (icalcomponent *subcomp,
+patch_tzids (ICalComponent *subcomp,
              GHashTable *mapping)
 {
        gchar *tzid = NULL;
 
-       if (icalcomponent_isa (subcomp) != ICAL_VTIMEZONE_COMPONENT) {
-               icalproperty *prop = icalcomponent_get_first_property (
-                       subcomp, ICAL_ANY_PROPERTY);
-               while (prop) {
-                       icalparameter *param = icalproperty_get_first_parameter (
-                               prop, ICAL_TZID_PARAMETER);
-                       while (param) {
+       if (i_cal_component_isa (subcomp) != I_CAL_VTIMEZONE_COMPONENT) {
+               ICalProperty *prop;
+
+               for (prop = i_cal_component_get_first_property (subcomp, I_CAL_ANY_PROPERTY);
+                    prop;
+                    g_object_unref (prop), prop = i_cal_component_get_next_property (subcomp, 
I_CAL_ANY_PROPERTY)) {
+                       ICalParameter *param;
+
+                       for (param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+                            param;
+                            g_object_unref (param), param = i_cal_property_get_next_parameter (prop, 
I_CAL_TZID_PARAMETER)) {
                                const gchar *oldtzid;
                                const gchar *newtzid;
 
                                g_free (tzid);
-                               tzid = g_strdup (icalparameter_get_tzid (param));
+                               tzid = g_strdup (i_cal_parameter_get_tzid (param));
 
                                if (!g_hash_table_lookup_extended (
                                        mapping, tzid,
@@ -170,13 +174,9 @@ patch_tzids (icalcomponent *subcomp,
                                        newtzid = e_cal_match_tzid (tzid);
                                }
                                if (newtzid) {
-                                       icalparameter_set_tzid (param, newtzid);
+                                       i_cal_parameter_set_tzid (param, newtzid);
                                }
-                               param = icalproperty_get_next_parameter (
-                                       prop, ICAL_TZID_PARAMETER);
                        }
-                       prop = icalcomponent_get_next_property (
-                               subcomp, ICAL_ANY_PROPERTY);
                }
        }
 
@@ -189,367 +189,38 @@ addsystemtz (gpointer key,
              gpointer user_data)
 {
        const gchar *tzid = key;
-       icalcomponent *comp = user_data;
-       icaltimezone *zone;
+       ICalComponent *vcalendar = user_data;
+       ICalTimezone *zone;
 
-       zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+       zone = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
        if (zone) {
-               icalcomponent_add_component (
-                       comp,
-                       icalcomponent_new_clone (
-                       icaltimezone_get_component (zone)));
-       }
-}
-
-/**
- * e_cal_check_timezones:
- * @comp:     a VCALENDAR containing a list of
- *            VTIMEZONE and arbitrary other components, in
- *            arbitrary order: these other components are
- *            modified by this call
- * @comps: (element-type icalcomponent) (allow-none): a list of #icalcomponent
- * instances which also have to be patched; may be %NULL
- * @tzlookup: (allow-none): a callback function which is called to retrieve
- *            a calendar's VTIMEZONE definition; the returned
- *            definition is *not* freed by e_cal_check_timezones()
- *            (to be compatible with e_cal_get_timezone());
- *            %NULL indicates that no such timezone exists
- *            or an error occurred
- * @custom:   an arbitrary pointer which is passed through to
- *            the tzlookup function
- * @error:    an error description in case of a failure
- *
- * This function cleans up VEVENT, VJOURNAL, VTODO and VTIMEZONE
- * items which are to be imported into Evolution.
- *
- * Using VTIMEZONE definitions is problematic because they cannot be
- * updated properly when timezone definitions change. They are also
- * incomplete (for compatibility reason only one set of rules for
- * summer saving changes can be included, even if different rules
- * apply in different years). This function looks for matches of the
- * used TZIDs against system timezones and replaces such TZIDs with
- * the corresponding system timezone. This works for TZIDs containing
- * a location (found via a fuzzy string search) and for Outlook TZIDs
- * (via a hard-coded lookup table).
- *
- * Some programs generate broken meeting invitations with TZID, but
- * without including the corresponding VTIMEZONE. Importing such
- * invitations unchanged causes problems later on (meeting displayed
- * incorrectly, e_cal_get_component_as_string() fails). The situation
- * where this occurred in the past (found by a SyncEvolution user) is
- * now handled via the location based mapping.
- *
- * If this mapping fails, this function also deals with VTIMEZONE
- * conflicts: such conflicts occur when the calendar already contains
- * an old VTIMEZONE definition with the same TZID, but different
- * summer saving rules. Replacing the VTIMEZONE potentially breaks
- * displaying of old events, whereas not replacing it breaks the new
- * events (the behavior in Evolution <= 2.22.1).
- *
- * The way this problem is resolved is by renaming the new VTIMEZONE
- * definition until the TZID is unique. A running count is appended to
- * the TZID. All items referencing the renamed TZID are adapted
- * accordingly.
- *
- * Returns: TRUE if successful, FALSE otherwise.
- *
- * Since: 2.24
- *
- * Deprecated: 3.2: Use e_cal_client_check_timezones() instead.
- */
-gboolean
-e_cal_check_timezones (icalcomponent *comp,
-                       GList *comps,
-                       icaltimezone *(*tzlookup)(const gchar *tzid,
-                                                 gconstpointer custom,
-                                                 GError **error),
-                       gconstpointer custom,
-                       GError **error)
-{
-       gboolean success = TRUE;
-       icalcomponent *subcomp = NULL;
-       icaltimezone *zone = icaltimezone_new ();
-       gchar *key = NULL, *value = NULL;
-       gchar *buffer = NULL;
-       gchar *zonestr = NULL;
-       gchar *tzid = NULL;
-       GList *l;
-
-       /* a hash from old to new tzid; strings dynamically allocated */
-       GHashTable *mapping = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-       /* a hash of all system time zone IDs which have to be added; strings are shared with mapping hash */
-       GHashTable *systemtzids = g_hash_table_new (g_str_hash, g_str_equal);
-
-       *error = NULL;
-
-       if (!mapping || !zone) {
-               goto nomem;
-       }
-
-       /* iterate over all VTIMEZONE definitions */
-       subcomp = icalcomponent_get_first_component (
-               comp, ICAL_VTIMEZONE_COMPONENT);
-       while (subcomp) {
-               if (icaltimezone_set_component (zone, subcomp)) {
-                       g_free (tzid);
-                       tzid = g_strdup (icaltimezone_get_tzid (zone));
-                       if (tzid) {
-                               const gchar *newtzid = e_cal_match_tzid (tzid);
-                               if (newtzid) {
-                                       /* matched against system time zone */
-                                       g_free (key);
-                                       key = g_strdup (tzid);
-                                       if (!key) {
-                                               goto nomem;
-                                       }
-
-                                       g_free (value);
-                                       value = g_strdup (newtzid);
-                                       if (!value) {
-                                               goto nomem;
-                                       }
-
-                                       g_hash_table_insert (mapping, key, value);
-                                       g_hash_table_insert (systemtzids, value, NULL);
-                                       key =
-                                               value = NULL;
-                               } else {
-                                       gint counter;
-
-                                       zonestr = icalcomponent_as_ical_string_r (subcomp);
-
-                                       /* check for collisions with existing timezones */
-                                       for (counter = 0;
-                                                counter < 100 /* sanity limit */;
-                                                counter++) {
-                                               icaltimezone *existing_zone;
-
-                                               if (counter) {
-                                                       g_free (value);
-                                                       value = g_strdup_printf ("%s %d", tzid, counter);
-                                               }
-                                               existing_zone = tzlookup (
-                                                       counter ? value : tzid,
-                                                       custom, error);
-                                               if (!existing_zone) {
-                                                       if (*error) {
-                                                               goto failed;
-                                                       } else {
-                                                               break;
-                                                       }
-                                               }
-                                               g_free (buffer);
-                                               buffer = icalcomponent_as_ical_string_r 
(icaltimezone_get_component (existing_zone));
-
-                                               if (counter) {
-                                                       gchar *fulltzid = g_strdup_printf ("TZID:%s", value);
-                                                       gsize baselen = strlen ("TZID:") + strlen (tzid);
-                                                       gsize fulllen = strlen (fulltzid);
-                                                       gchar *tzidprop;
-                                                       /*
-                                                        * Map TZID with counter suffix back to basename.
-                                                        */
-                                                       tzidprop = strstr (buffer, fulltzid);
-                                                       if (tzidprop) {
-                                                               memmove (
-                                                                       tzidprop + baselen,
-                                                                       tzidprop + fulllen,
-                                                                       strlen (tzidprop + fulllen) + 1);
-                                                       }
-                                                       g_free (fulltzid);
-                                               }
-
-                                               /*
-                                                * If the strings are identical, then the
-                                                * VTIMEZONE definitions are identical.  If
-                                                * they are not identical, then VTIMEZONE
-                                                * definitions might still be semantically
-                                                * correct and we waste some space by
-                                                * needlesly duplicating the VTIMEZONE. This
-                                                * is expected to occur rarely (if at all) in
-                                                * practice.
-                                                */
-                                               if (!strcmp (zonestr, buffer)) {
-                                                       break;
-                                               }
-                                       }
+               ICalComponent *zone_comp;
 
-                                       if (!counter) {
-                                               /* does not exist, nothing to do */
-                                       } else {
-                                               /* timezone renamed */
-                                               icalproperty *prop = icalcomponent_get_first_property (
-                                                       subcomp, ICAL_TZID_PROPERTY);
-                                               while (prop) {
-                                                       icalproperty_set_value_from_string (prop, value, 
"NO");
-                                                       prop = icalcomponent_get_next_property (
-                                                               subcomp, ICAL_ANY_PROPERTY);
-                                               }
-                                               g_free (key);
-                                               key = g_strdup (tzid);
-                                               g_hash_table_insert (mapping, key, value);
-                                               key = value = NULL;
-                                       }
-                               }
-                       }
+               zone_comp = i_cal_timezone_get_component (zone);
+               if (zone_comp) {
+                       i_cal_component_take_component (vcalendar, i_cal_component_new_clone (zone_comp));
+                       g_object_unref (zone_comp);
                }
-
-               subcomp = icalcomponent_get_next_component (
-                       comp, ICAL_VTIMEZONE_COMPONENT);
-       }
-
-       /*
-        * now replace all TZID parameters in place
-        */
-       subcomp = icalcomponent_get_first_component (
-               comp, ICAL_ANY_COMPONENT);
-       while (subcomp) {
-               /*
-                * Leave VTIMEZONE unchanged, iterate over properties of
-                * everything else.
-                *
-                * Note that no attempt is made to remove unused VTIMEZONE
-                * definitions. That would just make the code more complex for
-                * little additional gain. However, newly used time zones are
-                * added below.
-                */
-               patch_tzids (subcomp, mapping);
-               subcomp = icalcomponent_get_next_component (
-                       comp, ICAL_ANY_COMPONENT);
-       }
-
-       for (l = comps; l; l = l->next) {
-               patch_tzids (l->data, mapping);
-       }
-
-       /*
-        * add system time zones that we mapped to: adding them ensures
-        * that the VCALENDAR remains consistent
-        */
-       g_hash_table_foreach (systemtzids, addsystemtz, comp);
-
-       goto done;
- nomem:
-       /* set gerror for "out of memory" if possible, otherwise abort via g_error() */
-       *error = g_error_new(E_CALENDAR_ERROR, E_CALENDAR_STATUS_OTHER_ERROR, "out of memory");
-       if (!*error) {
-               g_error ("e_cal_check_timezones(): out of memory, cannot proceed - sorry!");
-       }
- failed:
-       /* gerror should have been set already */
-       success = FALSE;
- done:
-       if (mapping) {
-               g_hash_table_destroy (mapping);
-       }
-       if (systemtzids) {
-               g_hash_table_destroy (systemtzids);
-       }
-       if (zone) {
-               icaltimezone_free (zone, 1);
-       }
-       g_free (tzid);
-       g_free (zonestr);
-       g_free (buffer);
-       g_free (key);
-       g_free (value);
-
-       return success;
-}
-
-/**
- * e_cal_tzlookup_ecal:
- * @tzid: ID of the timezone to lookup
- * @custom: must be a valid #ECal pointer
- * @error: an error description in case of a failure
- *
- * An implementation of the tzlookup callback which clients
- * can use. Calls e_cal_get_timezone().
- *
- * Returns: A timezone object, or %NULL on failure. This object is owned
- *   by the @custom, thus do not free it.
- *
- * Since: 2.24
- *
- * Deprecated: 3.2: Use e_cal_client_tzlookup() instead.
- */
-icaltimezone *
-e_cal_tzlookup_ecal (const gchar *tzid,
-                     gconstpointer custom,
-                     GError **error)
-{
-       ECal *ecal = (ECal *) custom;
-       icaltimezone *zone = NULL;
-       GError *local_error = NULL;
-
-       g_return_val_if_fail (ecal != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL (ecal), NULL);
-
-       if (e_cal_get_timezone (ecal, tzid, &zone, &local_error)) {
-               g_warn_if_fail (local_error == NULL);
-               return zone;
        }
-
-       if (g_error_matches (local_error, E_CALENDAR_ERROR,
-               E_CALENDAR_STATUS_OBJECT_NOT_FOUND)) {
-               /* We had to trigger this error to check for the
-                * timezone existance, clear it and return NULL. */
-               g_clear_error (&local_error);
-       }
-
-       g_propagate_error (error, local_error);
-
-       return NULL;
 }
 
 /**
- * e_cal_tzlookup_icomp:
- * @tzid: ID of the timezone to lookup
- * @custom: must be a icalcomponent pointer which contains
- *          either a VCALENDAR with VTIMEZONEs or VTIMEZONES
- *          directly
- * @error: an error description in case of a failure
- *
- * An implementation of the tzlookup callback which backends
- * like the file backend can use. Searches for the timezone
- * in the component list.
- *
- * Returns: A timezone object, or %NULL if not found inside @custom. This object is owned
- *   by the @custom, thus do not free it.
- *
- * Since: 2.24
- *
- * Deprecated: 3.2: Use e_cal_client_tzlookup_icomp() instead.
- **/
-icaltimezone *
-e_cal_tzlookup_icomp (const gchar *tzid,
-                      gconstpointer custom,
-                      GError **error)
-{
-    icalcomponent *icomp = (icalcomponent *) custom;
-
-    return icalcomponent_get_timezone (icomp, (gchar *) tzid);
-}
-
-/**
- * e_cal_client_check_timezones:
- * @comp:     a VCALENDAR containing a list of
- *            VTIMEZONE and arbitrary other components, in
- *            arbitrary order: these other components are
- *            modified by this call
- * @comps: (element-type icalcomponent) (allow-none): a list of #icalcomponent
- * instances which also have to be patched; may be %NULL
- * @tzlookup: a callback function which is called to retrieve
- *            a calendar's VTIMEZONE definition; the returned
- *            definition is *not* freed by e_cal_client_check_timezones()
- *            (to be compatible with e_cal_get_timezone());
- *            NULL indicates that no such timezone exists
- *            or an error occurred
- * @ecalclient: an arbitrary pointer which is passed through to
- *            the @tzlookup function
+ * e_cal_client_check_timezones_sync:
+ * @vcalendar: a VCALENDAR containing a list of
+ *    VTIMEZONE and arbitrary other components, in
+ *    arbitrary order: these other components are
+ *    modified by this call
+ * @icalcomps: (element-type ICalComponent) (nullable): a list of #ICalComponent
+ *    instances which also have to be patched; may be %NULL
+ * @tzlookup: (scope call): a callback function which is called to retrieve
+ *    a calendar's VTIMEZONE definition; the returned
+ *    definition is *not* freed by e_cal_client_check_timezones()
+ *    NULL indicates that no such timezone exists
+ *    or an error occurred
+ * @tzlookup_data: (closure tzlookup): an arbitrary pointer which is passed
+ *    through to the @tzlookup function
  * @cancellable: a #GCancellable to use in @tzlookup function
- * @error:    an error description in case of a failure
+ * @error: an error description in case of a failure
  *
  * This function cleans up VEVENT, VJOURNAL, VTODO and VTIMEZONE
  * items which are to be imported into Evolution.
@@ -567,7 +238,7 @@ e_cal_tzlookup_icomp (const gchar *tzid,
  * Some programs generate broken meeting invitations with TZID, but
  * without including the corresponding VTIMEZONE. Importing such
  * invitations unchanged causes problems later on (meeting displayed
- * incorrectly, e_cal_get_component_as_string() fails). The situation
+ * incorrectly, e_cal_component_get_as_string() fails). The situation
  * where this occurred in the past (found by a SyncEvolution user) is
  * now handled via the location based mapping.
  *
@@ -578,34 +249,31 @@ e_cal_tzlookup_icomp (const gchar *tzid,
  * displaying of old events, whereas not replacing it breaks the new
  * events (the behavior in Evolution <= 2.22.1).
  *
- * The way this problem is resolved is by renaming the new VTIMEZONE
+ * The way this problem is resolved by renaming the new VTIMEZONE
  * definition until the TZID is unique. A running count is appended to
  * the TZID. All items referencing the renamed TZID are adapted
  * accordingly.
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
- * Since: 3.2
+ * Since: 3.36
  **/
 gboolean
-e_cal_client_check_timezones (icalcomponent *comp,
-                              GList *comps,
-                              icaltimezone *(*tzlookup) (const gchar *tzid,
-                                                         gconstpointer ecalclient,
-                                                         GCancellable *cancellable,
-                                                         GError **error),
-                              gconstpointer ecalclient,
-                              GCancellable *cancellable,
-                              GError **error)
+e_cal_client_check_timezones_sync (ICalComponent *vcalendar,
+                                  GSList *icalcomps,
+                                  ECalRecurResolveTimezoneCb tzlookup,
+                                  gpointer tzlookup_data,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
        gboolean success = TRUE;
-       icalcomponent *subcomp = NULL;
-       icaltimezone *zone = icaltimezone_new ();
+       ICalComponent *subcomp;
+       ICalTimezone *zone = i_cal_timezone_new ();
        gchar *key = NULL, *value = NULL;
        gchar *buffer = NULL;
        gchar *zonestr = NULL;
        gchar *tzid = NULL;
-       GList *l;
+       GSList *link;
 
        /* a hash from old to new tzid; strings dynamically allocated */
        GHashTable *mapping = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
@@ -613,18 +281,17 @@ e_cal_client_check_timezones (icalcomponent *comp,
        /* a hash of all system time zone IDs which have to be added; strings are shared with mapping hash */
        GHashTable *systemtzids = g_hash_table_new (g_str_hash, g_str_equal);
 
-       *error = NULL;
-
        if (!mapping || !zone) {
                goto nomem;
        }
 
        /* iterate over all VTIMEZONE definitions */
-       subcomp = icalcomponent_get_first_component (comp, ICAL_VTIMEZONE_COMPONENT);
-       while (subcomp) {
-               if (icaltimezone_set_component (zone, subcomp)) {
+       for (subcomp = i_cal_component_get_first_component (vcalendar, I_CAL_VTIMEZONE_COMPONENT);
+            subcomp;
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (vcalendar, 
I_CAL_VTIMEZONE_COMPONENT)) {
+               if (i_cal_timezone_set_component (zone, subcomp)) {
                        g_free (tzid);
-                       tzid = g_strdup (icaltimezone_get_tzid (zone));
+                       tzid = g_strdup (i_cal_timezone_get_tzid (zone));
                        if (tzid) {
                                const gchar *newtzid = e_cal_match_tzid (tzid);
                                if (newtzid) {
@@ -632,12 +299,14 @@ e_cal_client_check_timezones (icalcomponent *comp,
                                        g_free (key);
                                        key = g_strdup (tzid);
                                        if (!key) {
+                                               g_object_unref (subcomp);
                                                goto nomem;
                                        }
 
                                        g_free (value);
                                        value = g_strdup (newtzid);
                                        if (!value) {
+                                               g_object_unref (subcomp);
                                                goto nomem;
                                        }
 
@@ -647,28 +316,38 @@ e_cal_client_check_timezones (icalcomponent *comp,
                                } else {
                                        gint counter;
 
-                                       zonestr = icalcomponent_as_ical_string_r (subcomp);
+                                       zonestr = i_cal_component_as_ical_string_r (subcomp);
 
                                        /* check for collisions with existing timezones */
                                        for (counter = 0;
                                             counter < 100 /* sanity limit */;
                                             counter++) {
-                                               icaltimezone *existing_zone;
+                                               ICalTimezone *existing_zone;
+                                               ICalComponent *zone_comp;
+                                               GError *local_error = NULL;
 
                                                if (counter) {
                                                        g_free (value);
                                                        value = g_strdup_printf ("%s %d", tzid, counter);
                                                }
-                                               existing_zone = tzlookup (counter ? value : tzid, ecalclient, 
cancellable, error);
+                                               existing_zone = tzlookup (counter ? value : tzid, 
tzlookup_data, cancellable, &local_error);
                                                if (!existing_zone) {
-                                                       if (*error) {
+                                                       if (local_error) {
+                                                               g_propagate_error (error, local_error);
+                                                               g_object_unref (subcomp);
                                                                goto failed;
                                                        } else {
                                                                break;
                                                        }
                                                }
                                                g_free (buffer);
-                                               buffer = icalcomponent_as_ical_string_r 
(icaltimezone_get_component (existing_zone));
+                                               zone_comp = i_cal_timezone_get_component (existing_zone);
+                                               buffer = zone_comp ? i_cal_component_as_ical_string_r 
(zone_comp) : NULL;
+                                               g_clear_object (&zone_comp);
+                                               g_clear_object (&existing_zone);
+
+                                               if (!buffer)
+                                                       continue;
 
                                                if (counter) {
                                                        gchar *fulltzid = g_strdup_printf ("TZID:%s", value);
@@ -698,7 +377,7 @@ e_cal_client_check_timezones (icalcomponent *comp,
                                                 * is expected to occur rarely (if at all) in
                                                 * practice.
                                                 */
-                                               if (!strcmp (zonestr, buffer)) {
+                                               if (!g_strcmp0 (zonestr, buffer)) {
                                                        break;
                                                }
                                        }
@@ -707,10 +386,12 @@ e_cal_client_check_timezones (icalcomponent *comp,
                                                /* does not exist, nothing to do */
                                        } else {
                                                /* timezone renamed */
-                                               icalproperty *prop = icalcomponent_get_first_property 
(subcomp, ICAL_TZID_PROPERTY);
-                                               while (prop) {
-                                                       icalproperty_set_value_from_string (prop, value, 
"NO");
-                                                       prop = icalcomponent_get_next_property (subcomp, 
ICAL_ANY_PROPERTY);
+                                               ICalProperty *prop;
+
+                                               for (prop = i_cal_component_get_first_property (subcomp, 
I_CAL_TZID_PROPERTY);
+                                                    prop;
+                                                    g_object_unref (prop), prop = 
i_cal_component_get_next_property (subcomp, I_CAL_TZID_PROPERTY)) {
+                                                       i_cal_property_set_value_from_string (prop, value, 
"NO");
                                                }
                                                g_free (key);
                                                key = g_strdup (tzid);
@@ -720,15 +401,14 @@ e_cal_client_check_timezones (icalcomponent *comp,
                                }
                        }
                }
-
-               subcomp = icalcomponent_get_next_component (comp, ICAL_VTIMEZONE_COMPONENT);
        }
 
        /*
         * now replace all TZID parameters in place
         */
-       subcomp = icalcomponent_get_first_component (comp, ICAL_ANY_COMPONENT);
-       while (subcomp) {
+       for (subcomp = i_cal_component_get_first_component (vcalendar, ICAL_ANY_COMPONENT);
+            subcomp;
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (vcalendar, 
ICAL_ANY_COMPONENT)) {
                /*
                 * Leave VTIMEZONE unchanged, iterate over properties of
                 * everything else.
@@ -739,39 +419,37 @@ e_cal_client_check_timezones (icalcomponent *comp,
                 * added below.
                 */
                patch_tzids (subcomp, mapping);
-               subcomp = icalcomponent_get_next_component (comp, ICAL_ANY_COMPONENT);
        }
 
-       for (l = comps; l; l = l->next) {
-               patch_tzids (l->data, mapping);
+       for (link = icalcomps; link; link = g_slist_next (link)) {
+               ICalComponent *icalcomp = link->data;
+               patch_tzids (icalcomp, mapping);
        }
 
        /*
         * add system time zones that we mapped to: adding them ensures
         * that the VCALENDAR remains consistent
         */
-       g_hash_table_foreach (systemtzids, addsystemtz, comp);
+       g_hash_table_foreach (systemtzids, addsystemtz, vcalendar);
 
        goto done;
  nomem:
        /* set gerror for "out of memory" if possible, otherwise abort via g_error() */
-       *error = g_error_new (E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, "out of memory");
-       if (!*error) {
-               g_error ("e_cal_check_timezones(): out of memory, cannot proceed - sorry!");
+       g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, "out of memory");
+       if (error && !*error) {
+               g_error ("%s: out of memory, cannot proceed - sorry!", G_STRFUNC);
        }
  failed:
        /* gerror should have been set already */
        success = FALSE;
  done:
-       if (mapping) {
+       if (mapping)
                g_hash_table_destroy (mapping);
-       }
-       if (systemtzids) {
+
+       if (systemtzids)
                g_hash_table_destroy (systemtzids);
-       }
-       if (zone) {
-               icaltimezone_free (zone, 1);
-       }
+
+       g_clear_object (&zone);
        g_free (tzid);
        g_free (zonestr);
        g_free (buffer);
@@ -782,31 +460,33 @@ e_cal_client_check_timezones (icalcomponent *comp,
 }
 
 /**
- * e_cal_client_tzlookup:
+ * e_cal_client_tzlookup_cb:
  * @tzid: ID of the timezone to lookup
- * @ecalclient: must be a valid #ECalClient pointer
+ * @ecalclient: (type ECalClient): a valid #ECalClient pointer
  * @cancellable: an optional #GCancellable to use, or %NULL
  * @error: an error description in case of a failure
  *
- * An implementation of the tzlookup callback which clients
+ * An implementation of the #ECalRecurResolveTimezoneCb callback which clients
  * can use. Calls e_cal_client_get_timezone_sync().
  *
- * Returns: A timezone object, or %NULL on failure. This object is owned
- *   by the @ecalclient, thus do not free it.
+ * Free a non-NULL returned timezone object with g_object_unref(), when
+ * no longer needed.
  *
- * Since: 3.2
- */
-icaltimezone *
-e_cal_client_tzlookup (const gchar *tzid,
-                       gconstpointer ecalclient,
-                       GCancellable *cancellable,
-                       GError **error)
+ * Returns: (transfer full) (nullable): A timezone object, or %NULL on failure
+ *    or when not found.
+ *
+ * Since: 3.36
+ **/
+ICalTimezone *
+e_cal_client_tzlookup_cb (const gchar *tzid,
+                         gpointer ecalclient,
+                         GCancellable *cancellable,
+                         GError **error)
 {
-       ECalClient *cal_client = (ECalClient *) ecalclient;
-       icaltimezone *zone = NULL;
+       ECalClient *cal_client = ecalclient;
+       ICalTimezone *zone = NULL;
        GError *local_error = NULL;
 
-       g_return_val_if_fail (cal_client != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), NULL);
 
        if (e_cal_client_get_timezone_sync (cal_client, tzid, &zone, cancellable, &local_error)) {
@@ -827,30 +507,33 @@ e_cal_client_tzlookup (const gchar *tzid,
 }
 
 /**
- * e_cal_client_tzlookup_icomp:
+ * e_cal_client_tzlookup_icalcomp_cb:
  * @tzid: ID of the timezone to lookup
- * @custom: must be a icalcomponent pointer which contains
- *          either a VCALENDAR with VTIMEZONEs or VTIMEZONES
- *          directly
+ * @icalcomp: (type ICalComponent): an #ICalComponent pointer, which contains
+ *    either a VCALENDAR with VTIMEZONEs or VTIMEZONES directly
  * @cancellable: an optional #GCancellable to use, or %NULL
  * @error: an error description in case of a failure
  *
- * An implementation of the tzlookup callback which backends
- * like the file backend can use. Searches for the timezone
- * in the component list.
+ * An implementation of the #ECalRecurResolveTimezoneCb callback which
+ * backends can use. Searches for the timezone in the @icalcomp.
  *
- * Returns: A timezone object, or %NULL if not found inside @custom. This object is owned
- *   by the @custom, thus do not free it.
+ * Free a non-NULL returned timezone object with g_object_unref(), when
+ * no longer needed.
  *
- * Since: 3.2
- */
-icaltimezone *
-e_cal_client_tzlookup_icomp (const gchar *tzid,
-                             gconstpointer custom,
-                             GCancellable *cancellable,
-                             GError **error)
+ * Returns: (transfer full) (nullable): A timezone object, or %NULL, if
+ *    not found inside @icalcomp.
+ *
+ * Since: 3.36
+ **/
+ICalTimezone *
+e_cal_client_tzlookup_icalcomp_cb (const gchar *tzid,
+                                  gpointer icalcomp,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
-       icalcomponent *icomp = (icalcomponent *) custom;
+       ICalComponent *icomp = icalcomp;
+
+       g_return_val_if_fail (I_CAL_IS_COMPONENT (icalcomp), NULL);
 
-       return icalcomponent_get_timezone (icomp, (gchar *) tzid);
+       return i_cal_component_get_timezone (icomp, tzid);
 }
diff --git a/src/calendar/libecal/e-cal-check-timezones.h b/src/calendar/libecal/e-cal-check-timezones.h
index 299615c76..ec20f90f1 100644
--- a/src/calendar/libecal/e-cal-check-timezones.h
+++ b/src/calendar/libecal/e-cal-check-timezones.h
@@ -23,50 +23,35 @@
 #ifndef E_CAL_CHECK_TIMEZONES_H
 #define E_CAL_CHECK_TIMEZONES_H
 
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 #include <glib.h>
 #include <gio/gio.h>
 
+#include <libecal/e-cal-recur.h>
+
 G_BEGIN_DECLS
 
-gboolean       e_cal_client_check_timezones    (icalcomponent *comp,
-                                                GList *comps,
-                                                icaltimezone *(*tzlookup) (const gchar *tzid, gconstpointer 
ecalclient, GCancellable *cancellable, GError **error),
-                                                gconstpointer ecalclient,
+gboolean       e_cal_client_check_timezones_sync
+                                               (ICalComponent *vcalendar,
+                                                GSList *icalcomps, /* ICalComponent * */
+                                                ECalRecurResolveTimezoneCb tzlookup,
+                                                gpointer tzlookup_data,
                                                 GCancellable *cancellable,
                                                 GError **error);
 
-icaltimezone * e_cal_client_tzlookup           (const gchar *tzid,
-                                                gconstpointer ecalclient,
+ICalTimezone * e_cal_client_tzlookup_cb        (const gchar *tzid,
+                                                gpointer ecalclient, /* ECalClient * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 
-icaltimezone * e_cal_client_tzlookup_icomp
+ICalTimezone * e_cal_client_tzlookup_icalcomp_cb
                                                (const gchar *tzid,
-                                                gconstpointer custom,
+                                                gpointer icalcomp, /* ICalComponent * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 
 const gchar *  e_cal_match_tzid                (const gchar *tzid);
 
-#ifndef EDS_DISABLE_DEPRECATED
-
-gboolean       e_cal_check_timezones           (icalcomponent *comp,
-                                                GList *comps,
-                                                icaltimezone * (*tzlookup) (const gchar *tzid, gconstpointer 
custom, GError **error),
-                                                gconstpointer custom,
-                                                GError **error);
-
-icaltimezone * e_cal_tzlookup_ecal             (const gchar *tzid,
-                                                gconstpointer custom,
-                                                GError **error);
-
-icaltimezone * e_cal_tzlookup_icomp            (const gchar *tzid,
-                                                gconstpointer custom,
-                                                GError **error);
-
-#endif /* EDS_DISABLE_DEPRECATED */
-
 G_END_DECLS
 
 #endif /* E_CAL_CHECK_TIMEZONES_H */
diff --git a/src/calendar/libecal/e-cal-client-view.c b/src/calendar/libecal/e-cal-client-view.c
index fdac51a9d..e51286b4f 100644
--- a/src/calendar/libecal/e-cal-client-view.c
+++ b/src/calendar/libecal/e-cal-client-view.c
@@ -106,13 +106,8 @@ signal_closure_free (SignalClosure *signal_closure)
 {
        g_weak_ref_clear (&signal_closure->client_view);
 
-       g_slist_free_full (
-               signal_closure->component_list,
-               (GDestroyNotify) icalcomponent_free);
-
-       g_slist_free_full (
-               signal_closure->component_id_list,
-               (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (signal_closure->component_list, g_object_unref);
+       g_slist_free_full (signal_closure->component_id_list, e_cal_component_id_free);
 
        g_free (signal_closure->message);
 
@@ -154,7 +149,7 @@ cal_client_view_set_main_context (ECalClientView *client_view,
        g_mutex_unlock (&client_view->priv->main_context_lock);
 }
 
-static GSList *
+static GSList * /* ICalComponent * */
 build_object_list (const gchar * const *seq)
 {
        GSList *list;
@@ -162,9 +157,9 @@ build_object_list (const gchar * const *seq)
 
        list = NULL;
        for (i = 0; seq[i]; i++) {
-               icalcomponent *comp;
+               ICalComponent *comp;
 
-               comp = icalcomponent_new_from_string ((gchar *) seq[i]);
+               comp = i_cal_component_new_from_string (seq[i]);
                if (!comp)
                        continue;
 
@@ -174,7 +169,7 @@ build_object_list (const gchar * const *seq)
        return g_slist_reverse (list);
 }
 
-static GSList *
+static GSList * /* ECalComponentId * */
 build_id_list (const gchar * const *seq)
 {
        GSList *list;
@@ -184,17 +179,15 @@ build_id_list (const gchar * const *seq)
        list = NULL;
        for (i = 0; seq[i]; i++) {
                ECalComponentId *id;
-               id = g_new (ECalComponentId, 1);
 
                /* match encoding as in notify_remove()
                 * in e-data-cal-view.c: <uid>[\n<rid>] */
                eol = strchr (seq[i], '\n');
                if (eol) {
-                       id->uid = g_strndup (seq[i], eol - seq[i]);
-                       id->rid = g_strdup (eol + 1);
+                       id = e_cal_component_id_new_take (g_strndup (seq[i], eol - seq[i]),
+                                                         g_strdup (eol + 1));
                } else {
-                       id->uid = g_strdup (seq[i]);
-                       id->rid = NULL;
+                       id = e_cal_component_id_new (seq[i], NULL);
                }
 
                list = g_slist_prepend (list, id);
@@ -810,7 +803,8 @@ e_cal_client_view_class_init (ECalClientViewClass *class)
        /**
         * ECalClientView::objects-added:
         * @client_view: the #ECalClientView which emitted the signal
-        * @objects: (type GSList) (transfer none) (element-type long):
+        * @objects: (type GSList) (transfer none) (element-type ICalComponent): a #GSList
+        *    of added #ICalComponent objects into the @client_view.
         */
        signals[OBJECTS_ADDED] = g_signal_new (
                "objects-added",
@@ -824,7 +818,8 @@ e_cal_client_view_class_init (ECalClientViewClass *class)
        /**
         * ECalClientView::objects-modified:
         * @client_view: the #ECalClientView which emitted the signal
-        * @objects: (type GSList) (transfer none) (element-type long):
+        * @objects: (type GSList) (transfer none) (element-type ICalComponent): a #GSList
+        *    of modified #ICalComponent objects within the @client_view
         */
        signals[OBJECTS_MODIFIED] = g_signal_new (
                "objects-modified",
@@ -838,7 +833,8 @@ e_cal_client_view_class_init (ECalClientViewClass *class)
        /**
         * ECalClientView::objects-removed:
         * @client_view: the #ECalClientView which emitted the signal
-        * @objects: (type GSList) (transfer none) (element-type ECalComponentId):
+        * @uids: (type GSList) (transfer none) (element-type ECalComponentId): a #GSList
+        *    of removed objects, described by their UID and eventually RID, as an #ECalComponentId structure.
         */
        signals[OBJECTS_REMOVED] = g_signal_new (
                "objects-removed",
@@ -908,36 +904,6 @@ e_cal_client_view_ref_client (ECalClientView *client_view)
        return g_object_ref (client_view->priv->client);
 }
 
-/**
- * e_cal_client_view_get_client:
- * @client_view: an #ECalClientView
- *
- * Returns the #ECalClientView:client associated with @client_view.
- *
- * Returns: (transfer none): an #ECalClient
- *
- * Deprecated: 3.10: Use e_cal_client_view_ref_client() instead.
- *
- * Since: 3.2
- **/
-ECalClient *
-e_cal_client_view_get_client (ECalClientView *client_view)
-{
-       ECalClient *client;
-
-       g_return_val_if_fail (E_IS_CAL_CLIENT_VIEW (client_view), NULL);
-
-       client = e_cal_client_view_ref_client (client_view);
-
-       /* XXX Drop the ECalClient reference for backward-compatibility.
-        *     This is risky.  Without a reference, the ECalClient could
-        *     be finalized while the caller is still using it. */
-       if (client != NULL)
-               g_object_unref (client);
-
-       return client;
-}
-
 /**
  * e_cal_client_view_get_connection:
  * @client_view: an #ECalClientView
@@ -1057,7 +1023,7 @@ e_cal_client_view_stop (ECalClientView *client_view,
 /**
  * e_cal_client_view_set_fields_of_interest:
  * @client_view: an #ECalClientView
- * @fields_of_interest: (element-type utf8) (allow-none): List of field names
+ * @fields_of_interest: (element-type utf8) (nullable): List of field names
  *                      in which the client is interested, or %NULL to reset
  *                      the fields of interest
  * @error: return location for a #GError, or %NULL
diff --git a/src/calendar/libecal/e-cal-client-view.h b/src/calendar/libecal/e-cal-client-view.h
index 54cb70990..00cf318c2 100644
--- a/src/calendar/libecal/e-cal-client-view.h
+++ b/src/calendar/libecal/e-cal-client-view.h
@@ -102,11 +102,11 @@ struct _ECalClientViewClass {
        /*< public >*/
        /* Signals */
        void            (*objects_added)        (ECalClientView *client_view,
-                                                const GSList *objects);
+                                                const GSList *objects); /* ICalComponent * */
        void            (*objects_modified)     (ECalClientView *client_view,
-                                                const GSList *objects);
+                                                const GSList *objects); /* ICalComponent * */
        void            (*objects_removed)      (ECalClientView *client_view,
-                                                const GSList *uids);
+                                                const GSList *uids); /* ECalComponentId * */
        void            (*progress)             (ECalClientView *client_view,
                                                 guint percent,
                                                 const gchar *message);
@@ -125,7 +125,7 @@ const gchar *       e_cal_client_view_get_object_path
 gboolean       e_cal_client_view_is_running    (ECalClientView *client_view);
 void           e_cal_client_view_set_fields_of_interest
                                                (ECalClientView *client_view,
-                                                const GSList *fields_of_interest,
+                                                const GSList *fields_of_interest, /* gchar * */
                                                 GError **error);
 void           e_cal_client_view_start         (ECalClientView *client_view,
                                                 GError **error);
@@ -135,11 +135,6 @@ void               e_cal_client_view_set_flags     (ECalClientView *client_view,
                                                 ECalClientViewFlags flags,
                                                 GError **error);
 
-#ifndef EDS_DISABLE_DEPRECATED
-struct _ECalClient *
-               e_cal_client_view_get_client    (ECalClientView *client_view);
-#endif /* EDS_DISABLE_DEPRECATED */
-
 G_END_DECLS
 
 #endif /* E_CAL_CLIENT_VIEW_H */
diff --git a/src/calendar/libecal/e-cal-client.c b/src/calendar/libecal/e-cal-client.c
index f0994f6f6..998fddeda 100644
--- a/src/calendar/libecal/e-cal-client.c
+++ b/src/calendar/libecal/e-cal-client.c
@@ -42,7 +42,7 @@
 #include "e-cal-check-timezones.h"
 #include "e-cal-enumtypes.h"
 #include "e-cal-time-util.h"
-#include "e-cal-types.h"
+#include "e-cal-enums.h"
 #include "e-timezone-cache.h"
 
 #define E_CAL_CLIENT_GET_PRIVATE(obj) \
@@ -63,7 +63,7 @@ struct _ECalClientPrivate {
        guint name_watcher_id;
 
        ECalClientSourceType source_type;
-       icaltimezone *default_zone;
+       ICalTimezone *default_zone;
 
        GMutex zone_cache_lock;
        GHashTable *zone_cache;
@@ -75,12 +75,13 @@ struct _ECalClientPrivate {
 
 struct _AsyncContext {
        ECalClientView *client_view;
-       icalcomponent *in_comp;
-       icalcomponent *out_comp;
-       icaltimezone *zone;
+       ICalComponent *in_comp;
+       ICalComponent *out_comp;
+       ICalTimezone *zone;
        GSList *comp_list;
        GSList *object_list;
        GSList *string_list;
+       GSList *ids_list; /* ECalComponentId * */
        gchar *sexp;
        gchar *tzid;
        gchar *uid;
@@ -89,6 +90,7 @@ struct _AsyncContext {
        ECalObjModType mod;
        time_t start;
        time_t end;
+       guint32 opflags;
 };
 
 struct _SignalClosure {
@@ -96,7 +98,7 @@ struct _SignalClosure {
        gchar *property_name;
        gchar *error_message;
        gchar **free_busy_data;
-       icaltimezone *cached_zone;
+       ICalTimezone *cached_zone;
 };
 
 struct _ConnectClosure {
@@ -149,29 +151,15 @@ G_DEFINE_TYPE_WITH_CODE (
 static void
 async_context_free (AsyncContext *async_context)
 {
-       if (async_context->client_view != NULL)
-               g_object_unref (async_context->client_view);
+       g_clear_object (&async_context->client_view);
+       g_clear_object (&async_context->in_comp);
+       g_clear_object (&async_context->out_comp);
+       g_clear_object (&async_context->zone);
 
-       if (async_context->in_comp != NULL)
-               icalcomponent_free (async_context->in_comp);
-
-       if (async_context->out_comp != NULL)
-               icalcomponent_free (async_context->out_comp);
-
-       if (async_context->zone != NULL)
-               icaltimezone_free (async_context->zone, 1);
-
-       g_slist_free_full (
-               async_context->comp_list,
-               (GDestroyNotify) icalcomponent_free);
-
-       g_slist_free_full (
-               async_context->object_list,
-               (GDestroyNotify) g_object_unref);
-
-       g_slist_free_full (
-               async_context->string_list,
-               (GDestroyNotify) g_free);
+       g_slist_free_full (async_context->comp_list, g_object_unref);
+       g_slist_free_full (async_context->object_list, g_object_unref);
+       g_slist_free_full (async_context->string_list, g_free);
+       g_slist_free_full (async_context->ids_list, e_cal_component_id_free);
 
        g_free (async_context->sexp);
        g_free (async_context->tzid);
@@ -191,8 +179,9 @@ signal_closure_free (SignalClosure *signal_closure)
        g_free (signal_closure->error_message);
 
        g_strfreev (signal_closure->free_busy_data);
+       g_clear_object (&signal_closure->cached_zone);
 
-       /* The icaltimezone is cached in ECalClient's internal
+       /* The ICalTimezone is cached in ECalClient's internal
         * "zone_cache" hash table and must not be freed here. */
 
        g_slice_free (SignalClosure, signal_closure);
@@ -222,20 +211,14 @@ run_in_thread_closure_free (RunInThreadClosure *run_in_thread_closure)
        g_slice_free (RunInThreadClosure, run_in_thread_closure);
 }
 
-static void
-free_zone_cb (gpointer zone)
-{
-       icaltimezone_free (zone, 1);
-}
-
 /*
  * Well-known calendar backend properties:
- * @CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS: Contains default calendar's email
+ * @E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS: Contains default calendar's email
  *   address suggested by the backend.
- * @CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS: Contains default alarm email
+ * @E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS: Contains default alarm email
  *   address suggested by the backend.
- * @CAL_BACKEND_PROPERTY_DEFAULT_OBJECT: Contains iCal component string
- *   of an #icalcomponent with the default values for properties needed.
+ * @E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT: Contains iCal component string
+ *   of an #ICalComponent with the default values for properties needed.
  *   Preferred way of retrieving this property is by
  *   calling e_cal_client_get_default_object().
  *
@@ -280,29 +263,64 @@ e_cal_client_error_to_string (ECalClientError code)
 /**
  * e_cal_client_error_create:
  * @code: an #ECalClientError code to create
- * @custom_msg: custom message to use for the error; can be %NULL
- *
- * Returns: a new #GError containing an E_CAL_CLIENT_ERROR of the given
- * @code. If the @custom_msg is NULL, then the error message is
- * the one returned from e_cal_client_error_to_string() for the @code,
- * otherwise the given message is used.
+ * @custom_msg: (nullable): custom message to use for the error; can be %NULL
  *
- * Returned pointer should be freed with g_error_free().
+ * Returns: (transfer full): a new #GError containing an #E_CAL_CLIENT_ERROR of the given
+ *    @code. If the @custom_msg is NULL, then the error message is the one returned
+ *    from e_cal_client_error_to_string() for the @code, otherwise the given message is used.
+ *    Returned pointer should be freed with g_error_free().
  *
  * Since: 3.2
- *
- * Deprecated: 3.8: Just use the #GError API directly.
  **/
 GError *
 e_cal_client_error_create (ECalClientError code,
-                           const gchar *custom_msg)
+                          const gchar *custom_msg)
 {
-       if (custom_msg == NULL)
+       if (!custom_msg)
                custom_msg = e_cal_client_error_to_string (code);
 
        return g_error_new_literal (E_CAL_CLIENT_ERROR, code, custom_msg);
 }
 
+/**
+ * e_cal_client_error_create_fmt:
+ * @code: an #ECalClientError
+ * @format: (nullable): message format, or %NULL to use the default message for the @code
+ * @...: arguments for the format
+ *
+ * Similar as e_cal_client_error_create(), only here, instead of custom_msg,
+ * is used a printf() format to create a custom message for the error.
+ *
+ * Returns: (transfer full): a newly allocated #GError, which should be
+ *   freed with g_error_free(), when no longer needed.
+ *   The #GError has set the custom message, or the default message for
+ *   @code, when @format is %NULL.
+ *
+ * Since: 3.36
+ **/
+GError *
+e_cal_client_error_create_fmt (ECalClientError code,
+                              const gchar *format,
+                              ...)
+{
+       GError *error;
+       gchar *custom_msg;
+       va_list ap;
+
+       if (!format)
+               return e_cal_client_error_create (code, NULL);
+
+       va_start (ap, format);
+       custom_msg = g_strdup_vprintf (format, ap);
+       va_end (ap);
+
+       error = e_cal_client_error_create (code, custom_msg);
+
+       g_free (custom_msg);
+
+       return error;
+}
+
 static gpointer
 cal_client_dbus_thread (gpointer user_data)
 {
@@ -487,27 +505,22 @@ cal_client_emit_free_busy_data_idle_cb (gpointer user_data)
 
                for (ii = 0; strv[ii] != NULL; ii++) {
                        ECalComponent *comp;
-                       icalcomponent *icalcomp;
-                       icalcomponent_kind kind;
+                       ICalComponent *icalcomp;
+                       ICalComponentKind kind;
 
-                       icalcomp = icalcomponent_new_from_string (strv[ii]);
+                       icalcomp = i_cal_component_new_from_string (strv[ii]);
                        if (icalcomp == NULL)
                                continue;
 
-                       kind = icalcomponent_isa (icalcomp);
-                       if (kind != ICAL_VFREEBUSY_COMPONENT) {
-                               icalcomponent_free (icalcomp);
-                               continue;
-                       }
-
-                       comp = e_cal_component_new ();
-                       if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
-                               icalcomponent_free (icalcomp);
-                               g_object_unref (comp);
+                       kind = i_cal_component_isa (icalcomp);
+                       if (kind != I_CAL_VFREEBUSY_COMPONENT) {
+                               i_cal_component_free (icalcomp);
                                continue;
                        }
 
-                       list = g_slist_prepend (list, comp);
+                       comp = e_cal_component_new_from_icalcomponent (icalcomp);
+                       if (comp)
+                               list = g_slist_prepend (list, comp);
                }
 
                list = g_slist_reverse (list);
@@ -587,7 +600,7 @@ cal_client_dbus_proxy_property_changed (EClient *client,
        g_return_if_fail (property_name != NULL);
 
        if (g_str_equal (property_name, "alarm-email-address")) {
-               backend_prop_name = CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
+               backend_prop_name = E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
        }
 
        if (g_str_equal (property_name, "cache-dir")) {
@@ -595,7 +608,7 @@ cal_client_dbus_proxy_property_changed (EClient *client,
        }
 
        if (g_str_equal (property_name, "cal-email-address")) {
-               backend_prop_name = CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
+               backend_prop_name = E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
        }
 
        if (g_str_equal (property_name, "capabilities")) {
@@ -613,7 +626,7 @@ cal_client_dbus_proxy_property_changed (EClient *client,
        }
 
        if (g_str_equal (property_name, "default-object")) {
-               backend_prop_name = CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
+               backend_prop_name = E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
        }
 
        if (g_str_equal (property_name, "online")) {
@@ -810,7 +823,7 @@ cal_client_set_property (GObject *object,
                case PROP_DEFAULT_TIMEZONE:
                        e_cal_client_set_default_timezone (
                                E_CAL_CLIENT (object),
-                               g_value_get_pointer (value));
+                               g_value_get_object (value));
                        return;
 
                case PROP_SOURCE_TYPE:
@@ -831,7 +844,7 @@ cal_client_get_property (GObject *object,
 {
        switch (property_id) {
                case PROP_DEFAULT_TIMEZONE:
-                       g_value_set_pointer (
+                       g_value_set_object (
                                value,
                                e_cal_client_get_default_timezone (
                                E_CAL_CLIENT (object)));
@@ -900,8 +913,8 @@ cal_client_finalize (GObject *object)
        if (priv->name_watcher_id > 0)
                g_bus_unwatch_name (priv->name_watcher_id);
 
-       if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ())
-               icaltimezone_free (priv->default_zone, 1);
+       if (priv->default_zone && priv->default_zone != i_cal_timezone_get_utc_timezone ())
+               g_clear_object (&priv->default_zone);
 
        g_mutex_lock (&priv->zone_cache_lock);
        g_hash_table_destroy (priv->zone_cache);
@@ -1043,17 +1056,17 @@ cal_client_get_backend_property_sync (EClient *client,
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
                *prop_value = e_dbus_calendar_dup_alarm_email_address (dbus_proxy);
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
                *prop_value = e_dbus_calendar_dup_cal_email_address (dbus_proxy);
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
                *prop_value = e_dbus_calendar_dup_default_object (dbus_proxy);
                return TRUE;
        }
@@ -1386,7 +1399,7 @@ cal_client_initable_init_finish (GAsyncInitable *initable,
 
 static void
 cal_client_add_cached_timezone (ETimezoneCache *cache,
-                                icaltimezone *zone)
+                                ICalTimezone *zone)
 {
        ECalClientPrivate *priv;
        const gchar *tzid;
@@ -1395,39 +1408,34 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
 
        /* XXX Apparently this function can sometimes return NULL.
         *     I'm not sure when or why that happens, but we can't
-        *     cache the icaltimezone if it has no tzid string. */
-       tzid = icaltimezone_get_tzid (zone);
+        *     cache the ICalTimezone if it has no tzid string. */
+       tzid = i_cal_timezone_get_tzid (zone);
        if (tzid == NULL)
                return;
 
        g_mutex_lock (&priv->zone_cache_lock);
 
        /* Avoid replacing an existing cache entry.  We don't want to
-        * invalidate any icaltimezone pointers that may have already
+        * invalidate any ICalTimezone pointers that may have already
         * been returned through e_timezone_cache_get_timezone(). */
        if (!g_hash_table_contains (priv->zone_cache, tzid)) {
                GSource *idle_source;
                GMainContext *main_context;
                SignalClosure *signal_closure;
+               ICalTimezone *cached_zone;
 
-               icalcomponent *icalcomp;
-               icaltimezone *cached_zone;
-
-               cached_zone = icaltimezone_new ();
-               icalcomp = icaltimezone_get_component (zone);
-               icalcomp = icalcomponent_new_clone (icalcomp);
-               icaltimezone_set_component (cached_zone, icalcomp);
+               cached_zone = e_cal_util_copy_timezone (zone);
 
                g_hash_table_insert (
                        priv->zone_cache,
                        g_strdup (tzid), cached_zone);
 
                /* The closure's client reference will keep the
-                * internally cached icaltimezone alive for the
+                * internally cached ICalTimezone alive for the
                 * duration of the idle callback. */
                signal_closure = g_slice_new0 (SignalClosure);
                g_weak_ref_init (&signal_closure->client, cache);
-               signal_closure->cached_zone = cached_zone;
+               signal_closure->cached_zone = g_object_ref (cached_zone);
 
                main_context = e_client_ref_main_context (E_CLIENT (cache));
 
@@ -1446,21 +1454,21 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
        g_mutex_unlock (&priv->zone_cache_lock);
 }
 
-static icaltimezone *
+static ICalTimezone *
 cal_client_get_cached_timezone (ETimezoneCache *cache,
                                 const gchar *tzid)
 {
        ECalClientPrivate *priv;
-       icaltimezone *zone = NULL;
-       icaltimezone *builtin_zone = NULL;
-       icalcomponent *icalcomp;
-       icalproperty *prop;
+       ICalTimezone *zone = NULL;
+       ICalTimezone *builtin_zone = NULL;
+       ICalComponent *icalcomp, *clone;
+       ICalProperty *prop;
        const gchar *builtin_tzid;
 
        priv = E_CAL_CLIENT_GET_PRIVATE (cache);
 
        if (g_str_equal (tzid, "UTC"))
-               return icaltimezone_get_utc_timezone ();
+               return i_cal_timezone_get_utc_timezone ();
 
        g_mutex_lock (&priv->zone_cache_lock);
 
@@ -1473,52 +1481,46 @@ cal_client_get_cached_timezone (ETimezoneCache *cache,
        /* Try to replace the original time zone with a more complete
         * and/or potentially updated built-in time zone.  Note this also
         * applies to TZIDs which match built-in time zones exactly: they
-        * are extracted via icaltimezone_get_builtin_timezone_from_tzid()
+        * are extracted via i_cal_timezone_get_builtin_timezone_from_tzid()
         * below without a roundtrip to the backend. */
 
        builtin_tzid = e_cal_match_tzid (tzid);
 
        if (builtin_tzid != NULL)
-               builtin_zone = icaltimezone_get_builtin_timezone_from_tzid (
-                       builtin_tzid);
+               builtin_zone = i_cal_timezone_get_builtin_timezone_from_tzid (builtin_tzid);
 
        if (builtin_zone == NULL)
                goto exit;
 
        /* Use the built-in time zone *and* rename it.  Likely the caller
         * is asking for a specific TZID because it has an event with such
-        * a TZID.  Returning an icaltimezone with a different TZID would
+        * a TZID.  Returning an ICalTimezone with a different TZID would
         * lead to broken VCALENDARs in the caller. */
 
-       icalcomp = icaltimezone_get_component (builtin_zone);
-       icalcomp = icalcomponent_new_clone (icalcomp);
-
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_ANY_PROPERTY);
-
-       while (prop != NULL) {
-               if (icalproperty_isa (prop) == ICAL_TZID_PROPERTY) {
-                       icalproperty_set_value_from_string (prop, tzid, "NO");
+       icalcomp = i_cal_timezone_get_component (builtin_zone);
+       clone = i_cal_component_new_clone (icalcomp);
+       g_object_unref (icalcomp);
+       icalcomp = clone;
+
+       for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_ANY_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, I_CAL_ANY_PROPERTY)) {
+               if (i_cal_property_isa (prop) == I_CAL_TZID_PROPERTY) {
+                       i_cal_property_set_value_from_string (prop, tzid, "NO");
+                       g_object_unref (prop);
                        break;
                }
-
-               prop = icalcomponent_get_next_property (
-                       icalcomp, ICAL_ANY_PROPERTY);
        }
 
-       if (icalcomp != NULL) {
-               zone = icaltimezone_new ();
-               if (icaltimezone_set_component (zone, icalcomp)) {
-                       tzid = icaltimezone_get_tzid (zone);
-                       g_hash_table_insert (
-                               priv->zone_cache,
-                               g_strdup (tzid), zone);
-               } else {
-                       icalcomponent_free (icalcomp);
-                       icaltimezone_free (zone, 1);
-                       zone = NULL;
-               }
+       zone = i_cal_timezone_new ();
+       if (i_cal_timezone_set_component (zone, icalcomp)) {
+               tzid = i_cal_timezone_get_tzid (zone);
+               g_hash_table_insert (priv->zone_cache, g_strdup (tzid), zone);
+       } else {
+               g_object_unref (zone);
+               zone = NULL;
        }
+       g_object_unref (icalcomp);
 
 exit:
        g_mutex_unlock (&priv->zone_cache_lock);
@@ -1568,11 +1570,11 @@ e_cal_client_class_init (ECalClientClass *class)
        g_object_class_install_property (
                object_class,
                PROP_DEFAULT_TIMEZONE,
-               g_param_spec_pointer (
+               g_param_spec_object (
                        "default-timezone",
                        "Default Timezone",
-                       "Timezone used to resolve DATE "
-                       "and floating DATE-TIME values",
+                       "Timezone used to resolve DATE and floating DATE-TIME values",
+                       I_CAL_TYPE_TIMEZONE,
                        G_PARAM_READWRITE |
                        G_PARAM_EXPLICIT_NOTIFY |
                        G_PARAM_STATIC_STRINGS));
@@ -1626,15 +1628,11 @@ e_cal_client_init (ECalClient *client)
 {
        GHashTable *zone_cache;
 
-       zone_cache = g_hash_table_new_full (
-               (GHashFunc) g_str_hash,
-               (GEqualFunc) g_str_equal,
-               (GDestroyNotify) g_free,
-               (GDestroyNotify) free_zone_cb);
+       zone_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 
        client->priv = E_CAL_CLIENT_GET_PRIVATE (client);
        client->priv->source_type = E_CAL_CLIENT_SOURCE_TYPE_LAST;
-       client->priv->default_zone = icaltimezone_get_utc_timezone ();
+       client->priv->default_zone = i_cal_timezone_get_utc_timezone ();
        g_mutex_init (&client->priv->zone_cache_lock);
        client->priv->zone_cache = zone_cache;
 }
@@ -1959,42 +1957,6 @@ e_cal_client_connect_finish (GAsyncResult *result,
        return E_CLIENT (g_async_result_get_source_object (result));
 }
 
-/**
- * e_cal_client_new:
- * @source: An #ESource pointer
- * @source_type: source type of the calendar
- * @error: A #GError pointer
- *
- * Creates a new #ECalClient corresponding to the given source.  There are
- * only two operations that are valid on this calendar at this point:
- * e_client_open(), and e_client_remove().
- *
- * Returns: a new but unopened #ECalClient.
- *
- * Since: 3.2
- *
- * Deprecated: 3.8: It covertly makes synchronous D-Bus calls, with no
- *                  way to cancel.  Use e_cal_client_connect() instead,
- *                  which combines e_cal_client_new() and e_client_open()
- *                  into one step.
- **/
-ECalClient *
-e_cal_client_new (ESource *source,
-                  ECalClientSourceType source_type,
-                  GError **error)
-{
-       g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-       g_return_val_if_fail (
-               source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS ||
-               source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS ||
-               source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS, NULL);
-
-       return g_initable_new (
-               E_TYPE_CAL_CLIENT, NULL, error,
-               "source", source,
-               "source-type", source_type, NULL);
-}
-
 /**
  * e_cal_client_get_source_type:
  * @client: A calendar client.
@@ -2039,35 +2001,6 @@ e_cal_client_get_local_attachment_store (ECalClient *client)
        return e_dbus_calendar_get_cache_dir (client->priv->dbus_proxy);
 }
 
-/* icaltimezone_copy does a shallow copy while icaltimezone_free tries to
- * free the entire the contents inside the structure with libical 0.43.
- * Use this, till eds allows older libical.
- */
-static icaltimezone *
-copy_timezone (icaltimezone *ozone)
-{
-       icaltimezone *zone = NULL;
-       const gchar *tzid;
-
-       tzid = icaltimezone_get_tzid (ozone);
-
-       if (g_strcmp0 (tzid, "UTC") != 0) {
-               icalcomponent *comp;
-
-               comp = icaltimezone_get_component (ozone);
-               if (comp != NULL) {
-                       zone = icaltimezone_new ();
-                       icaltimezone_set_component (
-                               zone, icalcomponent_new_clone (comp));
-               }
-       }
-
-       if (zone == NULL)
-               zone = icaltimezone_get_utc_timezone ();
-
-       return zone;
-}
-
 /**
  * e_cal_client_set_default_timezone:
  * @client: A calendar client.
@@ -2081,7 +2014,7 @@ copy_timezone (icaltimezone *ozone)
  **/
 void
 e_cal_client_set_default_timezone (ECalClient *client,
-                                   icaltimezone *zone)
+                                   ICalTimezone *zone)
 {
        g_return_if_fail (E_IS_CAL_CLIENT (client));
        g_return_if_fail (zone != NULL);
@@ -2089,13 +2022,13 @@ e_cal_client_set_default_timezone (ECalClient *client,
        if (zone == client->priv->default_zone)
                return;
 
-       if (client->priv->default_zone != icaltimezone_get_utc_timezone ())
-               icaltimezone_free (client->priv->default_zone, 1);
+       if (client->priv->default_zone != i_cal_timezone_get_utc_timezone ())
+               g_clear_object (&client->priv->default_zone);
 
-       if (zone == icaltimezone_get_utc_timezone ())
+       if (zone == i_cal_timezone_get_utc_timezone ())
                client->priv->default_zone = zone;
        else
-               client->priv->default_zone = copy_timezone (zone);
+               client->priv->default_zone = e_cal_util_copy_timezone (zone);
 
        g_object_notify (G_OBJECT (client), "default-timezone");
 }
@@ -2108,11 +2041,11 @@ e_cal_client_set_default_timezone (ECalClient *client,
  * e_cal_client_set_default_timezone().  The returned pointer is owned by
  * the @client and should not be freed.
  *
- * Returns: an #icaltimezone
+ * Returns: (transfer none): an #ICalTimezone
  *
  * Since: 3.2
  **/
-icaltimezone *
+ICalTimezone *
 e_cal_client_get_default_timezone (ECalClient *client)
 {
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
@@ -2137,7 +2070,7 @@ e_cal_client_check_one_alarm_only (ECalClient *client)
 
        return e_client_check_capability (
                E_CLIENT (client),
-               CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY);
+               E_CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY);
 }
 
 /**
@@ -2157,7 +2090,7 @@ e_cal_client_check_save_schedules (ECalClient *client)
 
        return e_client_check_capability (
                E_CLIENT (client),
-               CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+               E_CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
 }
 
 /**
@@ -2178,7 +2111,7 @@ e_cal_client_check_organizer_must_attend (ECalClient *client)
 
        return e_client_check_capability (
                E_CLIENT (client),
-               CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND);
+               E_CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND);
 }
 
 /**
@@ -2200,7 +2133,7 @@ e_cal_client_check_organizer_must_accept (ECalClient *client)
 
        return e_client_check_capability (
                E_CLIENT (client),
-               CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT);
+               E_CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT);
 }
 
 /**
@@ -2221,221 +2154,83 @@ e_cal_client_check_recurrences_no_master (ECalClient *client)
 
        return e_client_check_capability (
                E_CLIENT (client),
-               CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
+               E_CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
 }
 
-/**
- * e_cal_client_free_icalcomp_slist:
- * @icalcomps: (element-type icalcomponent): list of icalcomponent objects
- *
- * Frees each element of the @icalcomps list and the list itself.
- * Each element is an object of type #icalcomponent.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_free_icalcomp_slist (GSList *icalcomps)
-{
-       g_slist_foreach (icalcomps, (GFunc) icalcomponent_free, NULL);
-       g_slist_free (icalcomps);
-}
-
-/**
- * e_cal_client_free_ecalcomp_slist:
- * @ecalcomps: (element-type ECalComponent): list of #ECalComponent objects
- *
- * Frees each element of the @ecalcomps list and the list itself.
- * Each element is an object of type #ECalComponent.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_free_ecalcomp_slist (GSList *ecalcomps)
-{
-       g_slist_foreach (ecalcomps, (GFunc) g_object_unref, NULL);
-       g_slist_free (ecalcomps);
-}
+struct comp_instance {
+       ECalComponent *comp;
+       ICalTime *start;
+       ICalTime *end;
+};
 
-/**
- * e_cal_client_resolve_tzid_cb:
- * @tzid: ID of the timezone to resolve.
- * @data: Closure data for the callback, in this case #ECalClient.
- *
- * Resolves TZIDs for the recurrence generator.
- *
- * Returns: The timezone identified by the @tzid argument, or %NULL if
- * it could not be found.
- *
- * Since: 3.2
- */
-icaltimezone *
-e_cal_client_resolve_tzid_cb (const gchar *tzid,
-                              gpointer data)
+static void
+comp_instance_free (gpointer ptr)
 {
-       ECalClient *client = data;
-       icaltimezone *zone = NULL;
-       GError *local_error = NULL;
-
-       g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
-
-       e_cal_client_get_timezone_sync (
-               client, tzid, &zone, NULL, &local_error);
+       struct comp_instance *ci = ptr;
 
-       if (local_error != NULL) {
-               g_debug (
-                       "%s: Failed to find '%s' timezone: %s",
-                       G_STRFUNC, tzid, local_error->message);
-               g_error_free (local_error);
+       if (ci) {
+               g_clear_object (&ci->comp);
+               g_clear_object (&ci->start);
+               g_clear_object (&ci->end);
+               g_free (ci);
        }
-
-       return zone;
 }
 
-/**
- * e_cal_client_resolve_tzid_sync:
- * @tzid: ID of the timezone to resolve.
- * @cal_client: User data for the callback, in this case #ECalClient.
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Resolves TZIDs for the recurrence generator.
- *
- * Returns: The timezone identified by the @tzid argument, or %NULL if
- * it could not be found.
- *
- * Since: 3.20
- */
-icaltimezone *
-e_cal_client_resolve_tzid_sync (const gchar *tzid,
-                               gpointer cal_client,
-                               GCancellable *cancellable,
-                               GError **error)
-{
-       icaltimezone *zone = NULL;
-
-       g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), NULL);
-
-       if (!e_cal_client_get_timezone_sync (cal_client, tzid, &zone, cancellable, error))
-               return NULL;
-
-       return zone;
-}
-
-struct comp_instance {
-       ECalComponent *comp;
-       time_t start;
-       time_t end;
-};
-
 struct instances_info {
        GSList **instances;
-       icaltimezone *start_zone;
-       icaltimezone *end_zone;
-       icaltimezone *default_zone;
 };
 
 /* Called from cal_recur_generate_instances(); adds an instance to the list */
 static gboolean
-add_instance (ECalComponent *comp,
-              time_t start,
-              time_t end,
-              gpointer data)
+add_instance_cb (ICalComponent *icomp,
+                ICalTime *start,
+                ICalTime *end,
+                gpointer user_data,
+                GCancellable *cancellable,
+                GError **error)
 {
        GSList **list;
        struct comp_instance *ci;
-       icalcomponent *icalcomp;
        struct instances_info *instances_hold;
 
-       instances_hold = data;
+       instances_hold = user_data;
        list = instances_hold->instances;
 
-       ci = g_new (struct comp_instance, 1);
-
-       icalcomp = icalcomponent_new_clone (
-               e_cal_component_get_icalcomponent (comp));
+       ci = g_new0 (struct comp_instance, 1);
 
        /* add the instance to the list */
-       ci->comp = e_cal_component_new ();
-       e_cal_component_set_icalcomponent (ci->comp, icalcomp);
+       ci->comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icomp));
+       if (!ci->comp) {
+               comp_instance_free (ci);
+               return FALSE;
+       }
 
        /* make sure we return an instance */
-       if (e_cal_util_component_has_recurrences (icalcomp) &&
-           !(icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY))) {
+       if (e_cal_component_has_recurrences (ci->comp) &&
+           !e_cal_component_is_instance (ci->comp)) {
+               ECalComponentDateTime *dtstart, *dtend;
                ECalComponentRange *range;
-               struct icaltimetype itt;
-               ECalComponentDateTime dtstart, dtend;
-
-               /* update DTSTART */
-               dtstart.value = NULL;
-               dtstart.tzid = NULL;
-
-               e_cal_component_get_dtstart (comp, &dtstart);
-
-               if (instances_hold->start_zone) {
-                       itt = icaltime_from_timet_with_zone (
-                               start, dtstart.value && dtstart.value->is_date,
-                               instances_hold->start_zone);
-                       g_free ((gchar *) dtstart.tzid);
-                       dtstart.tzid = g_strdup (icaltimezone_get_tzid (
-                               instances_hold->start_zone));
-               } else if (dtstart.value && dtstart.value->is_date && !dtstart.tzid && 
instances_hold->default_zone) {
-                       /* Floating date, set in the default zone */
-                       itt = icaltime_from_timet_with_zone (start, TRUE, instances_hold->default_zone);
-               } else {
-                       itt = icaltime_from_timet_with_zone (start, dtstart.value && dtstart.value->is_date, 
NULL);
-                       if (dtstart.tzid) {
-                               g_free ((gchar *) dtstart.tzid);
-                               dtstart.tzid = NULL;
-                       }
-               }
 
-               g_free (dtstart.value);
-               dtstart.value = &itt;
-               e_cal_component_set_dtstart (ci->comp, &dtstart);
+               /* Update DTSTART */
+               dtstart = e_cal_component_datetime_new (start, i_cal_time_get_tzid (start));
+               e_cal_component_set_dtstart (ci->comp, dtstart);
 
                /* set the RECUR-ID for the instance */
-               range = g_new0 (ECalComponentRange, 1);
-               range->type = E_CAL_COMPONENT_RANGE_SINGLE;
-               range->datetime = dtstart;
+               range = e_cal_component_range_new (E_CAL_COMPONENT_RANGE_SINGLE, dtstart);
 
                e_cal_component_set_recurid (ci->comp, range);
 
-               g_free (range);
-               g_free ((gchar *) dtstart.tzid);
+               e_cal_component_datetime_free (dtstart);
+               e_cal_component_range_free (range);
 
                /* Update DTEND */
-               dtend.value = NULL;
-               dtend.tzid = NULL;
-
-               e_cal_component_get_dtend (comp, &dtend);
-
-               if (instances_hold->end_zone) {
-                       itt = icaltime_from_timet_with_zone (
-                               end, dtend.value && dtend.value->is_date,
-                               instances_hold->end_zone);
-                       g_free ((gchar *) dtend.tzid);
-                       dtend.tzid = g_strdup (icaltimezone_get_tzid (
-                               instances_hold->end_zone));
-               } else if (dtend.value && dtend.value->is_date && !dtend.tzid && 
instances_hold->default_zone) {
-                       /* Floating date, set in the default zone */
-                       itt = icaltime_from_timet_with_zone (end, TRUE, instances_hold->default_zone);
-               } else {
-                       itt = icaltime_from_timet_with_zone (end, dtend.value && dtend.value->is_date, NULL);
-                       if (dtend.tzid) {
-                               g_free ((gchar *) dtend.tzid);
-                               dtend.tzid = NULL;
-                       }
-               }
-
-               g_free (dtend.value);
-               dtend.value = &itt;
-               e_cal_component_set_dtend (ci->comp, &dtend);
-
-               g_free ((gchar *) dtend.tzid);
+               dtend = e_cal_component_datetime_new (end, i_cal_time_get_tzid (end));
+               e_cal_component_set_dtend (ci->comp, dtend);
+               e_cal_component_datetime_free (dtend);
        }
 
-       ci->start = start;
-       ci->end = end;
+       ci->start = i_cal_time_new_clone (start);
+       ci->end = i_cal_time_new_clone (end);
 
        *list = g_slist_prepend (*list, ci);
 
@@ -2448,44 +2243,48 @@ compare_comp_instance (gconstpointer a,
                        gconstpointer b)
 {
        const struct comp_instance *cia, *cib;
-       time_t diff;
 
        cia = a;
        cib = b;
 
-       diff = cia->start - cib->start;
-       return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
+       return i_cal_time_compare (cia->start, cib->start);
 }
 
 static time_t
 convert_to_tt_with_zone (const ECalComponentDateTime *dt,
-                        ECalRecurResolveTimezoneFn tz_cb,
+                        ECalRecurResolveTimezoneCb tz_cb,
                         gpointer tz_cb_data,
-                        icaltimezone *default_timezone)
+                        ICalTimezone *default_timezone)
 {
-       icaltimezone *zone = default_timezone;
+       ICalTimezone *zone = NULL;
+       ICalTime *value;
+       time_t tt;
 
-       if (!dt || !dt->value)
-               return (time_t) 0;
+       value = dt ? e_cal_component_datetime_get_value (dt) : NULL;
 
-       if (icaltime_is_utc (*dt->value)) {
-               zone = icaltimezone_get_utc_timezone ();
-       } else if (tz_cb && !dt->value->is_date && dt->tzid) {
-               zone = (*tz_cb) (dt->tzid, tz_cb_data);
+       if (!dt || !value)
+               return (time_t) 0;
 
-               if (!zone)
-                       zone = default_timezone;
+       if (i_cal_time_is_utc (value)) {
+               zone = i_cal_timezone_get_utc_timezone ();
+       } else if (tz_cb && !i_cal_time_is_date (value) && e_cal_component_datetime_get_tzid (dt)) {
+               zone = (*tz_cb) (e_cal_component_datetime_get_tzid (dt), tz_cb_data, NULL, NULL);
        }
 
-       return icaltime_as_timet_with_zone (*dt->value, zone);
+       if (!zone)
+               zone = default_timezone;
+
+       tt = i_cal_time_as_timet_with_zone (value, zone);
+
+       return tt;
 }
 
 static GSList *
 process_detached_instances (GSList *instances,
                            GSList *detached_instances,
-                           ECalRecurResolveTimezoneFn tz_cb,
+                           ECalRecurResolveTimezoneCb tz_cb,
                            gpointer tz_cb_data,
-                           icaltimezone *default_timezone)
+                           ICalTimezone *default_timezone)
 {
        struct comp_instance *ci, *cid;
        GSList *dl, *unprocessed_instances = NULL;
@@ -2494,21 +2293,23 @@ process_detached_instances (GSList *instances,
                GSList *il;
                const gchar *uid;
                gboolean processed;
-               ECalComponentRange recur_id;
+               ECalComponentRange *recur_id;
                time_t d_rid, i_rid;
 
                processed = FALSE;
-               recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
-               recur_id.datetime.value = NULL;
 
                cid = dl->data;
-               e_cal_component_get_uid (cid->comp, &uid);
-               e_cal_component_get_recurid (cid->comp, &recur_id);
+               uid = e_cal_component_get_uid (cid->comp);
+               recur_id = e_cal_component_get_recurid (cid->comp);
 
-               if (!recur_id.datetime.value)
+               if (!recur_id ||
+                   !e_cal_component_range_get_datetime (recur_id) ||
+                   !e_cal_component_datetime_get_value (e_cal_component_range_get_datetime (recur_id))) {
+                       e_cal_component_range_free (recur_id);
                        continue;
+               }
 
-               d_rid = convert_to_tt_with_zone (&recur_id.datetime, tz_cb, tz_cb_data, default_timezone);
+               d_rid = convert_to_tt_with_zone (e_cal_component_range_get_datetime (recur_id), tz_cb, 
tz_cb_data, default_timezone);
 
                /* search for coincident instances already expanded */
                for (il = instances; il != NULL; il = il->next) {
@@ -2516,17 +2317,16 @@ process_detached_instances (GSList *instances,
                        gint cmp;
 
                        ci = il->data;
-                       e_cal_component_get_uid (ci->comp, &instance_uid);
+                       instance_uid = e_cal_component_get_uid (ci->comp);
 
-                       if (strcmp (uid, instance_uid) == 0) {
-                               ECalComponentRange instance_recur_id;
+                       if (g_strcmp0 (uid, instance_uid) == 0) {
+                               ECalComponentRange *instance_recur_id;
 
-                               instance_recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
-                               instance_recur_id.datetime.value = NULL;
+                               instance_recur_id = e_cal_component_get_recurid (ci->comp);
 
-                               e_cal_component_get_recurid (ci->comp, &instance_recur_id);
-
-                               if (!instance_recur_id.datetime.value) {
+                               if (!instance_recur_id ||
+                                   !e_cal_component_range_get_datetime (instance_recur_id) ||
+                                   !e_cal_component_datetime_get_value (e_cal_component_range_get_datetime 
(instance_recur_id))) {
                                        /*
                                         * Prevent obvious segfault by ignoring missing
                                         * recurrency ids. Real problem might be elsewhere,
@@ -2534,30 +2334,29 @@ process_detached_instances (GSList *instances,
                                         */
                                        g_warning ("UID %s: instance RECURRENCE-ID and detached instance 
RECURRENCE-ID cannot compare", uid);
 
-                                       e_cal_component_free_range (&instance_recur_id);
+                                       e_cal_component_range_free (instance_recur_id);
                                        continue;
                                }
 
-                               i_rid = convert_to_tt_with_zone (&instance_recur_id.datetime, tz_cb, 
tz_cb_data, default_timezone);
+                               i_rid = convert_to_tt_with_zone (e_cal_component_range_get_datetime 
(instance_recur_id), tz_cb, tz_cb_data, default_timezone);
 
-                               if (recur_id.type == E_CAL_COMPONENT_RANGE_SINGLE && i_rid == d_rid) {
+                               if (e_cal_component_range_get_kind (recur_id) == E_CAL_COMPONENT_RANGE_SINGLE 
&& i_rid == d_rid) {
                                        g_object_unref (ci->comp);
+                                       g_clear_object (&ci->start);
+                                       g_clear_object (&ci->end);
                                        ci->comp = g_object_ref (cid->comp);
-                                       ci->start = cid->start;
-                                       ci->end = cid->end;
+                                       ci->start = i_cal_time_new_clone (cid->start);
+                                       ci->end = i_cal_time_new_clone (cid->end);
 
                                        processed = TRUE;
                                } else {
                                        cmp = i_rid == d_rid ? 0 : i_rid < d_rid ? -1 : 1;
-                                       if ((recur_id.type == E_CAL_COMPONENT_RANGE_THISPRIOR && cmp <= 0) ||
-                                               (recur_id.type == E_CAL_COMPONENT_RANGE_THISFUTURE && cmp >= 
0)) {
+                                       if ((e_cal_component_range_get_kind (recur_id) == 
E_CAL_COMPONENT_RANGE_THISPRIOR && cmp <= 0) ||
+                                           (e_cal_component_range_get_kind (recur_id) == 
E_CAL_COMPONENT_RANGE_THISFUTURE && cmp >= 0)) {
                                                ECalComponent *comp;
 
-                                               comp = e_cal_component_new ();
-                                               e_cal_component_set_icalcomponent (
-                                                       comp,
-                                                       icalcomponent_new_clone 
(e_cal_component_get_icalcomponent (cid->comp)));
-                                               e_cal_component_set_recurid (comp, &instance_recur_id);
+                                               comp = e_cal_component_clone (cid->comp);
+                                               e_cal_component_set_recurid (comp, instance_recur_id);
 
                                                /* replace the generated instances */
                                                g_object_unref (ci->comp);
@@ -2565,11 +2364,11 @@ process_detached_instances (GSList *instances,
                                        }
                                }
 
-                               e_cal_component_free_range (&instance_recur_id);
+                               e_cal_component_range_free (instance_recur_id);
                        }
                }
 
-               e_cal_component_free_datetime (&recur_id.datetime);
+               e_cal_component_range_free (recur_id);
 
                if (!processed)
                        unprocessed_instances = g_slist_prepend (unprocessed_instances, cid);
@@ -2581,8 +2380,8 @@ process_detached_instances (GSList *instances,
                cid = unprocessed_instances->data;
                ci = g_new0 (struct comp_instance, 1);
                ci->comp = g_object_ref (cid->comp);
-               ci->start = cid->start;
-               ci->end = cid->end;
+               ci->start = i_cal_time_new_clone (cid->start);
+               ci->end = i_cal_time_new_clone (cid->end);
                instances = g_slist_append (instances, ci);
 
                unprocessed_instances = g_slist_remove (unprocessed_instances, cid);
@@ -2597,13 +2396,14 @@ generate_instances (ECalClient *client,
                     time_t end,
                     GSList *objects,
                     GCancellable *cancellable,
-                    ECalRecurInstanceFn cb,
+                    ECalRecurInstanceCb cb,
                     gpointer cb_data)
 {
        GSList *instances, *detached_instances = NULL;
        GSList *l;
        ECalClientPrivate *priv;
-       icaltimezone *default_zone;
+       ICalTimezone *default_zone;
+       ICalTime *starttt, *endtt;
 
        priv = client->priv;
 
@@ -2612,7 +2412,10 @@ generate_instances (ECalClient *client,
        if (priv->default_zone)
                default_zone = priv->default_zone;
        else
-               default_zone = icaltimezone_get_utc_timezone ();
+               default_zone = i_cal_timezone_get_utc_timezone ();
+
+       starttt = i_cal_time_from_timet_with_zone (start, FALSE, NULL);
+       endtt = i_cal_time_from_timet_with_zone (end, FALSE, NULL);
 
        for (l = objects; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
                ECalComponent *comp;
@@ -2620,123 +2423,68 @@ generate_instances (ECalClient *client,
                comp = l->data;
                if (e_cal_component_is_instance (comp)) {
                        struct comp_instance *ci;
-                       ECalComponentDateTime dtstart, dtend;
-                       icaltimezone *start_zone = NULL, *end_zone = NULL;
+                       ECalComponentDateTime *dtstart, *dtend;
 
                        /* keep the detached instances apart */
                        ci = g_new0 (struct comp_instance, 1);
                        ci->comp = g_object_ref (comp);
 
-                       e_cal_component_get_dtstart (comp, &dtstart);
-                       e_cal_component_get_dtend (comp, &dtend);
-
-                       /* For DATE-TIME values with a TZID, we use
-                        * e_cal_resolve_tzid_cb to resolve the TZID.
-                        * For DATE values and DATE-TIME values without a
-                        * TZID (i.e. floating times) we use the default
-                        * timezone. */
-                       if (dtstart.tzid && dtstart.value && !dtstart.value->is_date) {
-                               start_zone = e_cal_client_resolve_tzid_cb (
-                                       dtstart.tzid, client);
-                               if (!start_zone)
-                                       start_zone = default_zone;
-                       } else {
-                               start_zone = default_zone;
-                       }
-
-                       if (dtend.tzid && dtend.value && !dtend.value->is_date) {
-                               end_zone = e_cal_client_resolve_tzid_cb (
-                                       dtend.tzid, client);
-                               if (!end_zone)
-                                       end_zone = default_zone;
-                       } else {
-                               end_zone = default_zone;
-                       }
+                       dtstart = e_cal_component_get_dtstart (comp);
+                       dtend = e_cal_component_get_dtend (comp);
 
-                       if (!dtstart.value) {
+                       if (!dtstart || !e_cal_component_datetime_get_value (dtstart)) {
                                g_warn_if_reached ();
 
-                               e_cal_component_free_datetime (&dtstart);
-                               e_cal_component_free_datetime (&dtend);
-                               g_object_unref (G_OBJECT (ci->comp));
-                               g_free (ci);
+                               e_cal_component_datetime_free (dtstart);
+                               e_cal_component_datetime_free (dtend);
+                               comp_instance_free (ci);
 
                                continue;
                        }
 
-                       if (dtstart.value) {
-                               ci->start = icaltime_as_timet_with_zone (
-                                       *dtstart.value, start_zone);
-                       }
+                       ci->start = i_cal_time_new_clone (e_cal_component_datetime_get_value (dtstart));
+
+                       if (dtend && e_cal_component_datetime_get_value (dtend))
+                               ci->end = i_cal_time_new_clone (e_cal_component_datetime_get_value (dtend));
+                       else {
+                               ci->end = i_cal_time_new_clone (ci->start);
 
-                       if (dtend.value)
-                               ci->end = icaltime_as_timet_with_zone (
-                                       *dtend.value, end_zone);
-                       else if (dtstart.value && icaltime_is_date (*dtstart.value))
-                               ci->end = time_day_end (ci->start);
-                       else
-                               ci->end = ci->start;
+                               if (i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)))
+                                       i_cal_time_adjust (ci->end, 1, 0, 0, 0);
+                       }
 
-                       e_cal_component_free_datetime (&dtstart);
-                       e_cal_component_free_datetime (&dtend);
+                       e_cal_component_datetime_free (dtstart);
+                       e_cal_component_datetime_free (dtend);
 
-                       if (ci->start <= end && ci->end >= start) {
-                               detached_instances = g_slist_prepend (
-                                       detached_instances, ci);
+                       if (i_cal_time_compare (ci->start, endtt) <= 0 && i_cal_time_compare (ci->end, 
starttt) >= 0) {
+                               detached_instances = g_slist_prepend (detached_instances, ci);
                        } else {
                                /* it doesn't fit to our time range, thus skip it */
-                               g_object_unref (G_OBJECT (ci->comp));
-                               g_free (ci);
+                               comp_instance_free (ci);
                        }
                } else {
-                       ECalComponentDateTime datetime;
-                       icaltimezone *start_zone = NULL, *end_zone = NULL;
                        struct instances_info *instances_hold;
 
-                       /* Get the start timezone */
-                       e_cal_component_get_dtstart (comp, &datetime);
-                       if (datetime.tzid)
-                               e_cal_client_get_timezone_sync (
-                                       client, datetime.tzid,
-                                       &start_zone, cancellable, NULL);
-                       else
-                               start_zone = NULL;
-                       e_cal_component_free_datetime (&datetime);
-
-                       /* Get the end timezone */
-                       e_cal_component_get_dtend (comp, &datetime);
-                       if (datetime.tzid)
-                               e_cal_client_get_timezone_sync (
-                                       client, datetime.tzid,
-                                       &end_zone, cancellable, NULL);
-                       else
-                               end_zone = NULL;
-                       e_cal_component_free_datetime (&datetime);
-
                        instances_hold = g_new0 (struct instances_info, 1);
                        instances_hold->instances = &instances;
-                       instances_hold->start_zone = start_zone;
-                       instances_hold->end_zone = end_zone;
-                       instances_hold->default_zone = default_zone;
 
-                       e_cal_recur_generate_instances (
-                               comp, start, end, add_instance, instances_hold,
-                               e_cal_client_resolve_tzid_cb, client,
-                               default_zone);
+                       e_cal_recur_generate_instances_sync (
+                               e_cal_component_get_icalcomponent (comp), starttt, endtt, add_instance_cb, 
instances_hold,
+                               e_cal_client_tzlookup_cb, client,
+                               default_zone, cancellable, NULL);
 
                        g_free (instances_hold);
                }
        }
 
-       g_slist_foreach (objects, (GFunc) g_object_unref, NULL);
-       g_slist_free (objects);
+       g_slist_free_full (objects, g_object_unref);
 
        /* Generate instances and spew them out */
 
        if (!g_cancellable_is_cancelled (cancellable)) {
                instances = g_slist_sort (instances, compare_comp_instance);
                instances = process_detached_instances (instances, detached_instances,
-                       e_cal_client_resolve_tzid_cb, client, default_zone);
+                       e_cal_client_tzlookup_cb, client, default_zone);
        }
 
        for (l = instances; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
@@ -2745,7 +2493,7 @@ generate_instances (ECalClient *client,
 
                ci = l->data;
 
-               result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+               result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), ci->start, ci->end, cb_data, 
cancellable, NULL);
 
                if (!result)
                        break;
@@ -2753,25 +2501,10 @@ generate_instances (ECalClient *client,
 
        /* Clean up */
 
-       for (l = instances; l; l = l->next) {
-               struct comp_instance *ci;
-
-               ci = l->data;
-               g_object_unref (G_OBJECT (ci->comp));
-               g_free (ci);
-       }
-
-       g_slist_free (instances);
-
-       for (l = detached_instances; l; l = l->next) {
-               struct comp_instance *ci;
-
-               ci = l->data;
-               g_object_unref (G_OBJECT (ci->comp));
-               g_free (ci);
-       }
-
-       g_slist_free (detached_instances);
+       g_slist_free_full (instances, comp_instance_free);
+       g_slist_free_full (detached_instances, comp_instance_free);
+       g_clear_object (&starttt);
+       g_clear_object (&endtt);
 }
 
 static GSList *
@@ -2832,15 +2565,13 @@ struct get_objects_async_data {
        ECalClient *client;
        time_t start;
        time_t end;
-       ECalRecurInstanceFn cb;
+       ECalRecurInstanceCb cb;
        gpointer cb_data;
        GDestroyNotify destroy_cb_data;
        gchar *uid;
        gchar *query;
        guint tries;
        void (* ready_cb) (struct get_objects_async_data *goad, GSList *objects);
-       icaltimezone *start_zone;
-       icaltimezone *end_zone;
        ECalComponent *comp;
 };
 
@@ -3006,7 +2737,7 @@ generate_instances_got_objects_cb (struct get_objects_async_data *goad,
  *                   @cb_data; can be %NULL.
  *
  * Does a combination of e_cal_client_get_object_list() and
- * e_cal_recur_generate_instances(). Unlike
+ * e_cal_recur_generate_instances_sync(). Unlike
  * e_cal_client_generate_instances_sync(), this returns immediately and the
  * @cb callback is called asynchronously.
  *
@@ -3021,7 +2752,7 @@ e_cal_client_generate_instances (ECalClient *client,
                                  time_t start,
                                  time_t end,
                                  GCancellable *cancellable,
-                                 ECalRecurInstanceFn cb,
+                                 ECalRecurInstanceCb cb,
                                  gpointer cb_data,
                                  GDestroyNotify destroy_cb_data)
 {
@@ -3058,11 +2789,12 @@ e_cal_client_generate_instances (ECalClient *client,
  * @client: A calendar client
  * @start: Start time for query
  * @end: End time for query
+ * @cancellable: a #GCancellable; can be %NULL
  * @cb: (closure cb_data) (scope call): Callback for each generated instance
  * @cb_data: (closure): Closure data for the callback
  *
  * Does a combination of e_cal_client_get_object_list() and
- * e_cal_recur_generate_instances().
+ * e_cal_recur_generate_instances_sync().
  *
  * The callback function should do a g_object_ref() of the calendar component
  * it gets passed if it intends to keep it around, since it will be unreffed
@@ -3074,7 +2806,8 @@ void
 e_cal_client_generate_instances_sync (ECalClient *client,
                                       time_t start,
                                       time_t end,
-                                      ECalRecurInstanceFn cb,
+                                     GCancellable *cancellable,
+                                      ECalRecurInstanceCb cb,
                                       gpointer cb_data)
 {
        GSList *objects = NULL;
@@ -3090,25 +2823,27 @@ e_cal_client_generate_instances_sync (ECalClient *client,
                return;
 
        /* generate_instaces frees 'objects' slist */
-       generate_instances (client, start, end, objects, NULL, cb, cb_data);
+       generate_instances (client, start, end, objects, cancellable, cb, cb_data);
 }
 
 /* also frees 'instances' GSList */
 static void
-process_instances (ECalComponent *comp,
+process_instances (ECalClient *client,
+                  ECalComponent *comp,
                    GSList *instances,
-                   ECalRecurInstanceFn cb,
+                   ECalRecurInstanceCb cb,
                    gpointer cb_data)
 {
        gchar *rid;
        gboolean result;
 
+       g_return_if_fail (E_IS_CAL_CLIENT (client));
        g_return_if_fail (comp != NULL);
        g_return_if_fail (cb != NULL);
 
        rid = e_cal_component_get_recurid_as_string (comp);
 
-       /* Reverse the instances list because the add_instance() function
+       /* Reverse the instances list because the add_instance_cb() function
         * is prepending. */
        instances = g_slist_reverse (instances);
 
@@ -3124,16 +2859,17 @@ process_instances (ECalComponent *comp,
                        instance_rid = e_cal_component_get_recurid_as_string (ci->comp);
 
                        if (rid && *rid) {
-                               if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0)
-                                       result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
-                       } else
-                               result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+                               if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0) {
+                                       result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), 
ci->start, ci->end, cb_data, NULL, NULL);
+                               }
+                       } else {
+                               result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), ci->start, 
ci->end, cb_data, NULL, NULL);
+                       }
                }
 
                /* remove instance from list */
                instances = g_slist_remove (instances, ci);
-               g_object_unref (ci->comp);
-               g_free (ci);
+               comp_instance_free (ci);
                g_free (instance_rid);
        }
 
@@ -3152,18 +2888,15 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
 
        instances_hold = g_new0 (struct instances_info, 1);
        instances_hold->instances = &instances;
-       instances_hold->start_zone = goad->start_zone;
-       instances_hold->end_zone = goad->end_zone;
-       instances_hold->default_zone = e_cal_client_get_default_timezone (goad->client);
 
        /* generate all instances in the given time range */
        generate_instances (
                goad->client, goad->start, goad->end, objects,
-               goad->cancellable, add_instance, instances_hold);
+               goad->cancellable, add_instance_cb, instances_hold);
 
        /* it also frees 'instances' GSList */
        process_instances (
-               goad->comp, *(instances_hold->instances),
+               goad->client, goad->comp, *(instances_hold->instances),
                goad->cb, goad->cb_data);
 
        /* clean up */
@@ -3184,7 +2917,7 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
  *                   free @cb_data; can be %NULL.
  *
  * Does a combination of e_cal_client_get_object_list() and
- * e_cal_recur_generate_instances(), like
+ * e_cal_recur_generate_instances_sync(), like
  * e_cal_client_generate_instances(), but for a single object. Unlike
  * e_cal_client_generate_instances_for_object_sync(), this returns immediately
  * and the @cb callback is called asynchronously.
@@ -3197,19 +2930,16 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
  **/
 void
 e_cal_client_generate_instances_for_object (ECalClient *client,
-                                            icalcomponent *icalcomp,
+                                            ICalComponent *icalcomp,
                                             time_t start,
                                             time_t end,
                                             GCancellable *cancellable,
-                                            ECalRecurInstanceFn cb,
+                                            ECalRecurInstanceCb cb,
                                             gpointer cb_data,
                                             GDestroyNotify destroy_cb_data)
 {
        ECalComponent *comp;
        const gchar *uid;
-       ECalComponentDateTime datetime;
-       icaltimezone *start_zone = NULL, *end_zone = NULL;
-       gboolean is_single_instance = FALSE;
        struct get_objects_async_data *goad;
        GCancellable *use_cancellable;
 
@@ -3219,50 +2949,29 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
        g_return_if_fail (end >= 0);
        g_return_if_fail (cb != NULL);
 
-       comp = e_cal_component_new ();
-       e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
-
-       if (!e_cal_component_has_recurrences (comp))
-               is_single_instance = TRUE;
-
        /* If the backend stores it as individual instances and does not
         * have a master object - do not expand */
-       if (is_single_instance || e_client_check_capability (E_CLIENT (client), 
CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+       if (!e_cal_util_component_has_recurrences (icalcomp) || e_client_check_capability (E_CLIENT (client), 
E_CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+               ICalTime *dtstart, *dtend;
+
+               dtstart = i_cal_component_get_dtstart (icalcomp);
+               dtend = i_cal_component_get_dtend (icalcomp);
+
                /* return the same instance */
-               (* cb)  (comp,
-                       icaltime_as_timet_with_zone (
-                               icalcomponent_get_dtstart (icalcomp),
-                               client->priv->default_zone),
-                       icaltime_as_timet_with_zone (
-                               icalcomponent_get_dtend (icalcomp),
-                               client->priv->default_zone),
-                       cb_data);
-               g_object_unref (comp);
+               (* cb)  (icalcomp, dtstart, dtend, cb_data, NULL, NULL);
+
+               g_clear_object (&dtstart);
+               g_clear_object (&dtend);
 
                if (destroy_cb_data)
                        destroy_cb_data (cb_data);
                return;
        }
 
-       e_cal_component_get_uid (comp, &uid);
+       comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icalcomp));
+       g_return_if_fail (comp != NULL);
 
-       /* Get the start timezone */
-       e_cal_component_get_dtstart (comp, &datetime);
-       if (datetime.tzid)
-               e_cal_client_get_timezone_sync (
-                       client, datetime.tzid, &start_zone, NULL, NULL);
-       else
-               start_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
-
-       /* Get the end timezone */
-       e_cal_component_get_dtend (comp, &datetime);
-       if (datetime.tzid)
-               e_cal_client_get_timezone_sync (
-                       client, datetime.tzid, &end_zone, NULL, NULL);
-       else
-               end_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
+       uid = e_cal_component_get_uid (comp);
 
        use_cancellable = cancellable;
        if (!use_cancellable)
@@ -3276,8 +2985,6 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
        goad->cb = cb;
        goad->cb_data = cb_data;
        goad->destroy_cb_data = destroy_cb_data;
-       goad->start_zone = start_zone;
-       goad->end_zone = end_zone;
        goad->comp = comp;
        goad->uid = g_strdup (uid);
 
@@ -3293,11 +3000,12 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
  * @icalcomp: Object to generate instances from
  * @start: Start time for query
  * @end: End time for query
+ * @cancellable: a #GCancellable; can be %NULL
  * @cb: (closure cb_data) (scope call): Callback for each generated instance
  * @cb_data: (closure): Closure data for the callback
  *
  * Does a combination of e_cal_client_get_object_list() and
- * e_cal_recur_generate_instances(), like
+ * e_cal_recur_generate_instances_sync(), like
  * e_cal_client_generate_instances_sync(), but for a single object.
  *
  * The callback function should do a g_object_ref() of the calendar component
@@ -3308,19 +3016,17 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
  **/
 void
 e_cal_client_generate_instances_for_object_sync (ECalClient *client,
-                                                 icalcomponent *icalcomp,
+                                                 ICalComponent *icalcomp,
                                                  time_t start,
                                                  time_t end,
-                                                 ECalRecurInstanceFn cb,
+                                                GCancellable *cancellable,
+                                                 ECalRecurInstanceCb cb,
                                                  gpointer cb_data)
 {
        ECalComponent *comp;
        const gchar *uid;
        GSList *instances = NULL;
-       ECalComponentDateTime datetime;
-       icaltimezone *start_zone = NULL, *end_zone = NULL;
        struct instances_info *instances_hold;
-       gboolean is_single_instance = FALSE;
 
        g_return_if_fail (E_IS_CAL_CLIENT (client));
 
@@ -3328,62 +3034,39 @@ e_cal_client_generate_instances_for_object_sync (ECalClient *client,
        g_return_if_fail (end >= 0);
        g_return_if_fail (cb != NULL);
 
-       comp = e_cal_component_new ();
-       e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
-
-       if (!e_cal_component_has_recurrences (comp))
-               is_single_instance = TRUE;
-
        /* If the backend stores it as individual instances and does not
         * have a master object - do not expand */
-       if (is_single_instance || e_client_check_capability (E_CLIENT (client), 
CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+       if (!e_cal_util_component_has_recurrences (icalcomp) || e_client_check_capability (E_CLIENT (client), 
E_CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+               ICalTime *dtstart, *dtend;
+
+               dtstart = i_cal_component_get_dtstart (icalcomp);
+               dtend = i_cal_component_get_dtend (icalcomp);
+
                /* return the same instance */
-               (* cb)  (comp,
-                       icaltime_as_timet_with_zone (
-                               icalcomponent_get_dtstart (icalcomp),
-                               client->priv->default_zone),
-                       icaltime_as_timet_with_zone (
-                               icalcomponent_get_dtend (icalcomp),
-                               client->priv->default_zone),
-                       cb_data);
-               g_object_unref (comp);
+               (* cb)  (icalcomp, dtstart, dtend, cb_data, cancellable, NULL);
+
+               g_clear_object (&dtstart);
+               g_clear_object (&dtend);
+
                return;
        }
 
-       e_cal_component_get_uid (comp, &uid);
+       comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icalcomp));
+       g_return_if_fail (comp != NULL);
 
-       /* Get the start timezone */
-       e_cal_component_get_dtstart (comp, &datetime);
-       if (datetime.tzid)
-               e_cal_client_get_timezone_sync (
-                       client, datetime.tzid, &start_zone, NULL, NULL);
-       else
-               start_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
-
-       /* Get the end timezone */
-       e_cal_component_get_dtend (comp, &datetime);
-       if (datetime.tzid)
-               e_cal_client_get_timezone_sync (
-                       client, datetime.tzid, &end_zone, NULL, NULL);
-       else
-               end_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
+       uid = e_cal_component_get_uid (comp);
 
        instances_hold = g_new0 (struct instances_info, 1);
        instances_hold->instances = &instances;
-       instances_hold->start_zone = start_zone;
-       instances_hold->end_zone = end_zone;
-       instances_hold->default_zone = e_cal_client_get_default_timezone (client);
 
        /* generate all instances in the given time range */
        generate_instances (
                client, start, end,
                get_objects_sync (client, start, end, uid),
-               NULL, add_instance, instances_hold);
+               cancellable, add_instance_cb, instances_hold);
 
        /* it also frees 'instances' GSList */
-       process_instances (comp, *(instances_hold->instances), cb, cb_data);
+       process_instances (client, comp, *(instances_hold->instances), cb, cb_data);
 
        /* clean up */
        g_object_unref (comp);
@@ -3400,17 +3083,17 @@ struct _ForeachTZIDCallbackData {
 /* This adds the VTIMEZONE given by the TZID parameter to the GHashTable in
  * data. */
 static void
-foreach_tzid_callback (icalparameter *param,
+foreach_tzid_callback (ICalParameter *param,
                        gpointer cbdata)
 {
        ForeachTZIDCallbackData *data = cbdata;
        const gchar *tzid;
-       icaltimezone *zone = NULL;
-       icalcomponent *vtimezone_comp;
+       ICalTimezone *zone = NULL;
+       ICalComponent *vtimezone_comp;
        gchar *vtimezone_as_string;
 
        /* Get the TZID string from the parameter. */
-       tzid = icalparameter_get_tzid (param);
+       tzid = i_cal_parameter_get_tzid (param);
        if (!tzid)
                return;
 
@@ -3424,11 +3107,11 @@ foreach_tzid_callback (icalparameter *param,
        }
 
        /* Convert it to a string and add it to the hash. */
-       vtimezone_comp = icaltimezone_get_component (zone);
+       vtimezone_comp = i_cal_timezone_get_component (zone);
        if (!vtimezone_comp)
                return;
 
-       vtimezone_as_string = icalcomponent_as_ical_string_r (vtimezone_comp);
+       vtimezone_as_string = i_cal_component_as_ical_string_r (vtimezone_comp);
 
        g_hash_table_insert (data->timezone_hash, (gchar *) tzid, vtimezone_as_string);
 }
@@ -3469,7 +3152,7 @@ free_timezone_string (gpointer key,
  **/
 gchar *
 e_cal_client_get_component_as_string (ECalClient *client,
-                                      icalcomponent *icalcomp)
+                                      ICalComponent *icalcomp)
 {
        GHashTable *timezone_hash;
        GString *vcal_string;
@@ -3486,7 +3169,7 @@ e_cal_client_get_component_as_string (ECalClient *client,
        cbdata.client = client;
        cbdata.timezone_hash = timezone_hash;
        cbdata.success = TRUE;
-       icalcomponent_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata);
+       i_cal_component_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata);
        if (!cbdata.success) {
                g_hash_table_foreach (timezone_hash, free_timezone_string, NULL);
                return NULL;
@@ -3507,7 +3190,7 @@ e_cal_client_get_component_as_string (ECalClient *client,
        g_hash_table_foreach (timezone_hash, append_timezone_string, vcal_string);
 
        /* Get the string for the VEVENT/VTODO. */
-       obj_string = icalcomponent_as_ical_string_r (icalcomp);
+       obj_string = i_cal_component_as_ical_string_r (icalcomp);
 
        /* If there were any timezones to send, create a complete VCALENDAR,
         * else just send the VEVENT/VTODO string. */
@@ -3556,7 +3239,7 @@ cal_client_get_default_object_thread (GSimpleAsyncResult *simple,
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
  *
- * Retrives an #icalcomponent from the backend that contains the default
+ * Retrives an #ICalComponent from the backend that contains the default
  * values for properties needed. The call is finished
  * by e_cal_client_get_default_object_finish() from the @callback.
  *
@@ -3595,13 +3278,13 @@ e_cal_client_get_default_object (ECalClient *client,
  * e_cal_client_get_default_object_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_icalcomp: (out): Return value for the default calendar object.
+ * @out_icalcomp: (out) (transfer full): Return value for the default calendar object.
  * @error: (out): a #GError to set an error, if any
  *
  * Finishes previous call of e_cal_client_get_default_object() and
- * sets @out_icalcomp to an #icalcomponent from the backend that contains
+ * sets @out_icalcomp to an #ICalComponent from the backend that contains
  * the default values for properties needed. This @out_icalcomp should be
- * freed with icalcomponent_free().
+ * freed with g_object_unref(), when no longer needed.
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -3610,7 +3293,7 @@ e_cal_client_get_default_object (ECalClient *client,
 gboolean
 e_cal_client_get_default_object_finish (ECalClient *client,
                                         GAsyncResult *result,
-                                        icalcomponent **out_icalcomp,
+                                        ICalComponent **out_icalcomp,
                                         GError **error)
 {
        GSimpleAsyncResult *simple;
@@ -3640,13 +3323,13 @@ e_cal_client_get_default_object_finish (ECalClient *client,
 /**
  * e_cal_client_get_default_object_sync:
  * @client: an #ECalClient
- * @out_icalcomp: (out): Return value for the default calendar object.
+ * @out_icalcomp: (out) (transfer full): Return value for the default calendar object.
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
- * Retrives an #icalcomponent from the backend that contains the default
+ * Retrives an #ICalComponent from the backend that contains the default
  * values for properties needed. This @out_icalcomp should be freed with
- * icalcomponent_free().
+ * g_object_unref(), when no longer needed.
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -3654,11 +3337,11 @@ e_cal_client_get_default_object_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_get_default_object_sync (ECalClient *client,
-                                      icalcomponent **out_icalcomp,
+                                      ICalComponent **out_icalcomp,
                                       GCancellable *cancellable,
                                       GError **error)
 {
-       icalcomponent *icalcomp = NULL;
+       ICalComponent *icalcomp = NULL;
        gchar *string;
 
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
@@ -3666,7 +3349,7 @@ e_cal_client_get_default_object_sync (ECalClient *client,
 
        string = e_dbus_calendar_dup_default_object (client->priv->dbus_proxy);
        if (string != NULL) {
-               icalcomp = icalparser_parse_string (string);
+               icalcomp = i_cal_parser_parse_string (string);
                g_free (string);
        }
 
@@ -3679,12 +3362,12 @@ e_cal_client_get_default_object_sync (ECalClient *client,
                return FALSE;
        }
 
-       if (icalcomponent_get_uid (icalcomp) != NULL) {
+       if (i_cal_component_get_uid (icalcomp) != NULL) {
                gchar *new_uid;
 
                /* Make sure the UID is always unique. */
                new_uid = e_util_generate_uid ();
-               icalcomponent_set_uid (icalcomp, new_uid);
+               i_cal_component_set_uid (icalcomp, new_uid);
                g_free (new_uid);
        }
 
@@ -3780,13 +3463,13 @@ e_cal_client_get_object (ECalClient *client,
  * e_cal_client_get_object_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_icalcomp: (out): Return value for the calendar component object.
+ * @out_icalcomp: (out) (transfer full): Return value for the calendar component object.
  * @error: (out): a #GError to set an error, if any
  *
  * Finishes previous call of e_cal_client_get_object() and
  * sets @out_icalcomp to queried component. This function always returns
  * master object for a case of @rid being NULL or an empty string.
- * This component should be freed with icalcomponent_free().
+ * This component should be freed with g_object_unref(), when no longer needed.
  *
  * Use e_cal_client_get_objects_for_uid() to get list of all
  * objects for the given uid, which includes master object and
@@ -3799,7 +3482,7 @@ e_cal_client_get_object (ECalClient *client,
 gboolean
 e_cal_client_get_object_finish (ECalClient *client,
                                 GAsyncResult *result,
-                                icalcomponent **out_icalcomp,
+                                ICalComponent **out_icalcomp,
                                 GError **error)
 {
        GSimpleAsyncResult *simple;
@@ -3831,14 +3514,15 @@ e_cal_client_get_object_finish (ECalClient *client,
  * @client: an #ECalClient
  * @uid: Unique identifier for a calendar component.
  * @rid: Recurrence identifier.
- * @out_icalcomp: (out): Return value for the calendar component object.
+ * @out_icalcomp: (out) (transfer full): Return value for the calendar component object.
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
  * Queries a calendar for a calendar component object based
  * on its unique identifier. This function always returns
  * master object for a case of @rid being NULL or an empty string.
- * This component should be freed with icalcomponent_free().
+ * This component should be freed with g_object_unref(),
+ * when no longer needed.
  *
  * Use e_cal_client_get_objects_for_uid_sync() to get list of all
  * objects for the given uid, which includes master object and
@@ -3852,12 +3536,12 @@ gboolean
 e_cal_client_get_object_sync (ECalClient *client,
                               const gchar *uid,
                               const gchar *rid,
-                              icalcomponent **out_icalcomp,
+                              ICalComponent **out_icalcomp,
                               GCancellable *cancellable,
                               GError **error)
 {
-       icalcomponent *icalcomp = NULL;
-       icalcomponent_kind kind;
+       ICalComponent *icalcomp = NULL;
+       ICalComponentKind kind;
        gchar *utf8_uid;
        gchar *utf8_rid;
        gchar *string = NULL;
@@ -3867,6 +3551,8 @@ e_cal_client_get_object_sync (ECalClient *client,
        g_return_val_if_fail (uid != NULL, FALSE);
        g_return_val_if_fail (out_icalcomp != NULL, FALSE);
 
+       *out_icalcomp = NULL;
+
        if (rid == NULL)
                rid = "";
 
@@ -3891,7 +3577,7 @@ e_cal_client_get_object_sync (ECalClient *client,
                return FALSE;
        }
 
-       icalcomp = icalparser_parse_string (string);
+       icalcomp = i_cal_parser_parse_string (string);
 
        g_free (string);
 
@@ -3906,55 +3592,61 @@ e_cal_client_get_object_sync (ECalClient *client,
 
        switch (e_cal_client_get_source_type (client)) {
                case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-                       kind = ICAL_VEVENT_COMPONENT;
+                       kind = I_CAL_VEVENT_COMPONENT;
                        break;
                case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-                       kind = ICAL_VTODO_COMPONENT;
+                       kind = I_CAL_VTODO_COMPONENT;
                        break;
                case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-                       kind = ICAL_VJOURNAL_COMPONENT;
+                       kind = I_CAL_VJOURNAL_COMPONENT;
                        break;
                default:
                        g_warn_if_reached ();
-                       kind = ICAL_VEVENT_COMPONENT;
+                       kind = I_CAL_VEVENT_COMPONENT;
                        break;
        }
 
-       if (icalcomponent_isa (icalcomp) == kind) {
+       if (i_cal_component_isa (icalcomp) == kind) {
                *out_icalcomp = icalcomp;
+               icalcomp = NULL;
 
-       } else if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT) {
-               icalcomponent *subcomponent;
+       } else if (i_cal_component_isa (icalcomp) == I_CAL_VCALENDAR_COMPONENT) {
+               ICalComponent *subcomponent;
 
-               for (subcomponent = icalcomponent_get_first_component (icalcomp, kind);
-                       subcomponent != NULL;
-                       subcomponent = icalcomponent_get_next_component (icalcomp, kind)) {
-                       struct icaltimetype recurrenceid;
+               for (subcomponent = i_cal_component_get_first_component (icalcomp, kind);
+                    subcomponent != NULL;
+                    g_object_unref (subcomponent), subcomponent = i_cal_component_get_next_component 
(icalcomp, kind)) {
+                       ICalTime *recurrenceid;
 
-                       if (icalcomponent_get_uid (subcomponent) == NULL)
+                       if (i_cal_component_get_uid (subcomponent) == NULL)
                                continue;
 
-                       recurrenceid =
-                               icalcomponent_get_recurrenceid (subcomponent);
+                       recurrenceid = i_cal_component_get_recurrenceid (subcomponent);
 
-                       if (icaltime_is_null_time (recurrenceid))
-                               break;
-
-                       if (!icaltime_is_valid_time (recurrenceid))
+                       if (!recurrenceid ||
+                           i_cal_time_is_null_time (recurrenceid) ||
+                           !i_cal_time_is_valid_time (recurrenceid)) {
+                               g_clear_object (&recurrenceid);
                                break;
+                       }
                }
 
                if (subcomponent == NULL)
-                       subcomponent = icalcomponent_get_first_component (icalcomp, kind);
-               if (subcomponent != NULL)
-                       subcomponent = icalcomponent_new_clone (subcomponent);
+                       subcomponent = i_cal_component_get_first_component (icalcomp, kind);
+               if (subcomponent != NULL) {
+                       ICalComponent *clone;
 
-               /* XXX Shouldn't we set an error is this is still NULL? */
-               *out_icalcomp = subcomponent;
+                       clone = i_cal_component_new_clone (subcomponent);
+                       g_object_unref (subcomponent);
+                       subcomponent = clone;
+               }
 
-               icalcomponent_free (icalcomp);
+               /* XXX Shouldn't we set an error if this is still NULL? */
+               *out_icalcomp = subcomponent;
        }
 
+       g_clear_object (&icalcomp);
+
        return TRUE;
 }
 
@@ -4046,7 +3738,7 @@ e_cal_client_get_objects_for_uid (ECalClient *client,
  * Finishes previous call of e_cal_client_get_objects_for_uid() and
  * sets @out_ecalcomps to a list of #ECalComponent<!-- -->s corresponding to
  * found components for a given uid of the same type as this client.
- * This list should be freed with e_cal_client_free_ecalcomp_slist().
+ * This list should be freed with e_client_util_free_object_slist().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -4093,7 +3785,7 @@ e_cal_client_get_objects_for_uid_finish (ECalClient *client,
  * Queries a calendar for all calendar components with the given unique
  * ID. This will return any recurring event and all its detached recurrences.
  * For non-recurring events, it will just return the object with that ID.
- * This list should be freed with e_cal_client_free_ecalcomp_slist().
+ * This list should be freed with e_client_util_free_object_slist().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -4106,8 +3798,8 @@ e_cal_client_get_objects_for_uid_sync (ECalClient *client,
                                        GCancellable *cancellable,
                                        GError **error)
 {
-       icalcomponent *icalcomp;
-       icalcomponent_kind kind;
+       ICalComponent *icalcomp;
+       ICalComponentKind kind;
        gchar *utf8_uid;
        gchar *string = NULL;
        GError *local_error = NULL;
@@ -4116,6 +3808,8 @@ e_cal_client_get_objects_for_uid_sync (ECalClient *client,
        g_return_val_if_fail (uid != NULL, FALSE);
        g_return_val_if_fail (out_ecalcomps != NULL, FALSE);
 
+       *out_ecalcomps = NULL;
+
        utf8_uid = e_util_utf8_make_valid (uid);
 
        e_dbus_calendar_call_get_object_sync (
@@ -4135,7 +3829,7 @@ e_cal_client_get_objects_for_uid_sync (ECalClient *client,
                return FALSE;
        }
 
-       icalcomp = icalparser_parse_string (string);
+       icalcomp = i_cal_parser_parse_string (string);
 
        g_free (string);
 
@@ -4150,52 +3844,47 @@ e_cal_client_get_objects_for_uid_sync (ECalClient *client,
 
        switch (e_cal_client_get_source_type (client)) {
                case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-                       kind = ICAL_VEVENT_COMPONENT;
+                       kind = I_CAL_VEVENT_COMPONENT;
                        break;
                case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-                       kind = ICAL_VTODO_COMPONENT;
+                       kind = I_CAL_VTODO_COMPONENT;
                        break;
                case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-                       kind = ICAL_VJOURNAL_COMPONENT;
+                       kind = I_CAL_VJOURNAL_COMPONENT;
                        break;
                default:
                        g_warn_if_reached ();
-                       kind = ICAL_VEVENT_COMPONENT;
+                       kind = I_CAL_VEVENT_COMPONENT;
                        break;
        }
 
-       if (icalcomponent_isa (icalcomp) == kind) {
+       if (i_cal_component_isa (icalcomp) == kind) {
                ECalComponent *comp;
 
-               comp = e_cal_component_new ();
-               e_cal_component_set_icalcomponent (comp, icalcomp);
+               comp = e_cal_component_new_from_icalcomponent (icalcomp);
+               icalcomp = NULL;
+
                *out_ecalcomps = g_slist_append (NULL, comp);
 
-       } else if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT) {
+       } else if (i_cal_component_isa (icalcomp) == I_CAL_VCALENDAR_COMPONENT) {
                GSList *tmp = NULL;
-               icalcomponent *subcomponent;
-
-               subcomponent = icalcomponent_get_first_component (
-                       icalcomp, kind);
+               ICalComponent *subcomponent;
 
-               while (subcomponent != NULL) {
+               for (subcomponent = i_cal_component_get_first_component (icalcomp, kind);
+                    subcomponent;
+                    g_object_unref (subcomponent), subcomponent = i_cal_component_get_next_component 
(icalcomp, kind)) {
                        ECalComponent *comp;
-                       icalcomponent *clone;
-
-                       comp = e_cal_component_new ();
-                       clone = icalcomponent_new_clone (subcomponent);
-                       e_cal_component_set_icalcomponent (comp, clone);
-                       tmp = g_slist_prepend (tmp, comp);
 
-                       subcomponent = icalcomponent_get_next_component (
-                               icalcomp, kind);
+                       comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone 
(subcomponent));
+                       if (comp)
+                               tmp = g_slist_prepend (tmp, comp);
                }
 
                *out_ecalcomps = g_slist_reverse (tmp);
-
-               icalcomponent_free (icalcomp);
        }
 
+       g_clear_object (&icalcomp);
+
        return TRUE;
 }
 
@@ -4236,7 +3925,7 @@ cal_client_get_object_list_thread (GSimpleAsyncResult *simple,
  * @user_data: user data for the @callback
  *
  * Gets a list of objects from the calendar that match the query specified
- * by the @sexp argument, returning matching objects as a list of #icalcomponent-s.
+ * by the @sexp argument, returning matching objects as a list of #ICalComponent-s.
  * The call is finished by e_cal_client_get_object_list_finish() from
  * the @callback.
  *
@@ -4278,13 +3967,13 @@ e_cal_client_get_object_list (ECalClient *client,
  * e_cal_client_get_object_list_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_icalcomps: (out) (element-type icalcomponent): list of matching
- *                 #icalcomponent<!-- -->s
+ * @out_icalcomps: (out) (element-type ICalComponent): list of matching
+ *                 #ICalComponent<!-- -->s
  * @error: (out): a #GError to set an error, if any
  *
  * Finishes previous call of e_cal_client_get_object_list() and
- * sets @out_icalcomps to a matching list of #icalcomponent-s.
- * This list should be freed with e_cal_client_free_icalcomp_slist().
+ * sets @out_icalcomps to a matching list of #ICalComponent-s.
+ * This list should be freed with e_client_util_free_object_slist().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -4322,15 +4011,15 @@ e_cal_client_get_object_list_finish (ECalClient *client,
  * e_cal_client_get_object_list_sync:
  * @client: an #ECalClient
  * @sexp: an S-expression representing the query
- * @out_icalcomps: (out) (element-type icalcomponent): list of matching
- *                 #icalcomponent<!-- -->s
+ * @out_icalcomps: (out) (element-type ICalComponent): list of matching
+ *                 #ICalComponent<!-- -->s
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
  * Gets a list of objects from the calendar that match the query specified
  * by the @sexp argument. The objects will be returned in the @out_icalcomps
- * argument, which is a list of #icalcomponent.
- * This list should be freed with e_cal_client_free_icalcomp_slist().
+ * argument, which is a list of #ICalComponent.
+ * This list should be freed with e_client_util_free_object_slist().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -4353,6 +4042,8 @@ e_cal_client_get_object_list_sync (ECalClient *client,
        g_return_val_if_fail (sexp != NULL, FALSE);
        g_return_val_if_fail (out_icalcomps != NULL, FALSE);
 
+       *out_icalcomps = NULL;
+
        utf8_sexp = e_util_utf8_make_valid (sexp);
 
        e_dbus_calendar_call_get_object_list_sync (
@@ -4373,9 +4064,9 @@ e_cal_client_get_object_list_sync (ECalClient *client,
        }
 
        for (ii = 0; strv[ii] != NULL; ii++) {
-               icalcomponent *icalcomp;
+               ICalComponent *icalcomp;
 
-               icalcomp = icalcomponent_new_from_string (strv[ii]);
+               icalcomp = i_cal_component_new_from_string (strv[ii]);
                if (icalcomp == NULL)
                        continue;
 
@@ -4474,7 +4165,7 @@ e_cal_client_get_object_list_as_comps (ECalClient *client,
  *
  * Finishes previous call of e_cal_client_get_object_list_as_comps() and
  * sets @out_ecalcomps to a matching list of #ECalComponent-s.
- * This list should be freed with e_cal_client_free_ecalcomp_slist().
+ * This list should be freed with e_client_util_free_object_slist().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -4520,7 +4211,7 @@ e_cal_client_get_object_list_as_comps_finish (ECalClient *client,
  * Gets a list of objects from the calendar that match the query specified
  * by the @sexp argument. The objects will be returned in the @out_ecalcomps
  * argument, which is a list of #ECalComponent.
- * This list should be freed with e_cal_client_free_ecalcomp_slist().
+ * This list should be freed with e_client_util_free_object_slist().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -4535,13 +4226,14 @@ e_cal_client_get_object_list_as_comps_sync (ECalClient *client,
 {
        GSList *list = NULL;
        GSList *link;
-       GQueue trash = G_QUEUE_INIT;
        gboolean success;
 
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
        g_return_val_if_fail (sexp != NULL, FALSE);
        g_return_val_if_fail (out_ecalcomps != NULL, FALSE);
 
+       *out_ecalcomps = NULL;
+
        success = e_cal_client_get_object_list_sync (
                client, sexp, &list, cancellable, error);
 
@@ -4550,32 +4242,21 @@ e_cal_client_get_object_list_as_comps_sync (ECalClient *client,
                return FALSE;
        }
 
-       /* Convert the icalcomponent list to an ECalComponent list. */
+       /* Convert the ICalComponent list to an ECalComponent list. */
        for (link = list; link != NULL; link = g_slist_next (link)) {
                ECalComponent *comp;
-               icalcomponent *icalcomp = link->data;
+               ICalComponent *icalcomp = link->data;
 
-               comp = e_cal_component_new ();
-
-               /* This takes ownership of the icalcomponent, if it works. */
-               if (e_cal_component_set_icalcomponent (comp, icalcomp)) {
-                       link->data = g_object_ref (comp);
-               } else {
-                       /* On failure, free resources and add
-                        * the GSList link to the trash queue. */
-                       icalcomponent_free (icalcomp);
-                       g_queue_push_tail (&trash, link);
-                       link->data = NULL;
-               }
+               /* This takes ownership of the ICalComponent. */
+               comp = e_cal_component_new_from_icalcomponent (icalcomp);
+               if (comp)
+                       *out_ecalcomps = g_slist_prepend (*out_ecalcomps, comp);
 
-               g_object_unref (comp);
        }
 
-       /* Delete GSList links we failed to convert. */
-       while ((link = g_queue_pop_head (&trash)) != NULL)
-               list = g_slist_delete_link (list, link);
+       g_slist_free (list);
 
-       *out_ecalcomps = list;
+       *out_ecalcomps = g_slist_reverse (*out_ecalcomps);
 
        return TRUE;
 }
@@ -4777,10 +4458,8 @@ e_cal_client_get_free_busy_sync (ECalClient *client,
                        ECalComponent *comp;
 
                        comp = e_cal_component_new_from_string (freebusy_strv[ii]);
-                       if (!comp)
-                               continue;
-
-                       *out_freebusy = g_slist_prepend (*out_freebusy, comp);
+                       if (comp)
+                               *out_freebusy = g_slist_prepend (*out_freebusy, comp);
                }
 
                *out_freebusy = g_slist_reverse (*out_freebusy);
@@ -4805,6 +4484,7 @@ cal_client_create_object_thread (GSimpleAsyncResult *simple,
        if (!e_cal_client_create_object_sync (
                E_CAL_CLIENT (source_object),
                async_context->in_comp,
+               async_context->opflags,
                &async_context->uid,
                cancellable, &local_error)) {
 
@@ -4823,6 +4503,7 @@ cal_client_create_object_thread (GSimpleAsyncResult *simple,
  * e_cal_client_create_object:
  * @client: an #ECalClient
  * @icalcomp: The component to create
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -4837,7 +4518,8 @@ cal_client_create_object_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_cal_client_create_object (ECalClient *client,
-                            icalcomponent *icalcomp,
+                            ICalComponent *icalcomp,
+                           guint32 opflags,
                             GCancellable *cancellable,
                             GAsyncReadyCallback callback,
                             gpointer user_data)
@@ -4849,7 +4531,8 @@ e_cal_client_create_object (ECalClient *client,
        g_return_if_fail (icalcomp != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->in_comp = icalcomponent_new_clone (icalcomp);
+       async_context->in_comp = i_cal_component_new_clone (icalcomp);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -4869,7 +4552,7 @@ e_cal_client_create_object (ECalClient *client,
  * e_cal_client_create_object_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_uid: (out): Return value for the UID assigned to the new component
+ * @out_uid: (out) (nullable): Return value for the UID assigned to the new component
  *           by the calendar backend
  * @error: (out): a #GError to set an error, if any
  *
@@ -4915,7 +4598,8 @@ e_cal_client_create_object_finish (ECalClient *client,
  * e_cal_client_create_object_sync:
  * @client: an #ECalClient
  * @icalcomp: The component to create
- * @out_uid: (out): Return value for the UID assigned to the new component
+ * @opflags: bit-or of #ECalOperationFlags
+ * @out_uid: (out) (nullable): Return value for the UID assigned to the new component
  *           by the calendar backend
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
@@ -4932,7 +4616,8 @@ e_cal_client_create_object_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_create_object_sync (ECalClient *client,
-                                 icalcomponent *icalcomp,
+                                 ICalComponent *icalcomp,
+                                guint32 opflags,
                                  gchar **out_uid,
                                  GCancellable *cancellable,
                                  GError **error)
@@ -4945,7 +4630,7 @@ e_cal_client_create_object_sync (ECalClient *client,
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
        success = e_cal_client_create_objects_sync (
-               client, &link, &string_list, cancellable, error);
+               client, &link, opflags, &string_list, cancellable, error);
 
        /* Sanity check. */
        g_return_val_if_fail (
@@ -4954,6 +4639,8 @@ e_cal_client_create_object_sync (ECalClient *client,
 
        if (out_uid != NULL && string_list != NULL)
                *out_uid = g_strdup (string_list->data);
+       else if (out_uid)
+               *out_uid = NULL;
 
        g_slist_free_full (string_list, (GDestroyNotify) g_free);
 
@@ -4974,6 +4661,7 @@ cal_client_create_objects_thread (GSimpleAsyncResult *simple,
        if (!e_cal_client_create_objects_sync (
                E_CAL_CLIENT (source_object),
                async_context->comp_list,
+               async_context->opflags,
                &async_context->string_list,
                cancellable, &local_error)) {
 
@@ -4991,7 +4679,8 @@ cal_client_create_objects_thread (GSimpleAsyncResult *simple,
 /**
  * e_cal_client_create_objects:
  * @client: an #ECalClient
- * @icalcomps: (element-type icalcomponent): The components to create
+ * @icalcomps: (element-type ICalComponent): The components to create
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -5007,6 +4696,7 @@ cal_client_create_objects_thread (GSimpleAsyncResult *simple,
 void
 e_cal_client_create_objects (ECalClient *client,
                              GSList *icalcomps,
+                            guint32 opflags,
                              GCancellable *cancellable,
                              GAsyncReadyCallback callback,
                              gpointer user_data)
@@ -5019,7 +4709,8 @@ e_cal_client_create_objects (ECalClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->comp_list = g_slist_copy_deep (
-               icalcomps, (GCopyFunc) icalcomponent_new_clone, NULL);
+               icalcomps, (GCopyFunc) i_cal_component_new_clone, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -5041,7 +4732,7 @@ e_cal_client_create_objects (ECalClient *client,
  * e_cal_client_create_objects_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_uids: (out) (element-type utf8): Return value for the UIDs assigned
+ * @out_uids: (out) (nullable) (element-type utf8): Return value for the UIDs assigned
  *            to the new components by the calendar backend
  * @error: (out): a #GError to set an error, if any
  *
@@ -5084,8 +4775,9 @@ e_cal_client_create_objects_finish (ECalClient *client,
 /**
  * e_cal_client_create_objects_sync:
  * @client: an #ECalClient
- * @icalcomps: (element-type icalcomponent): The components to create
- * @out_uids: (out) (element-type utf8): Return value for the UIDs assigned
+ * @icalcomps: (element-type ICalComponent): The components to create
+ * @opflags: bit-or of #ECalOperationFlags
+ * @out_uids: (out) (nullable) (element-type utf8): Return value for the UIDs assigned
  *            to the new components by the calendar backend
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
@@ -5104,6 +4796,7 @@ e_cal_client_create_objects_finish (ECalClient *client,
 gboolean
 e_cal_client_create_objects_sync (ECalClient *client,
                                   GSList *icalcomps,
+                                 guint32 opflags,
                                   GSList **out_uids,
                                   GCancellable *cancellable,
                                   GError **error)
@@ -5121,7 +4814,7 @@ e_cal_client_create_objects_sync (ECalClient *client,
        while (icalcomps != NULL) {
                gchar *ical_string;
 
-               ical_string = icalcomponent_as_ical_string_r (icalcomps->data);
+               ical_string = i_cal_component_as_ical_string_r (icalcomps->data);
                strv[ii++] = e_util_utf8_make_valid (ical_string);
                g_free (ical_string);
 
@@ -5131,7 +4824,7 @@ e_cal_client_create_objects_sync (ECalClient *client,
        e_dbus_calendar_call_create_objects_sync (
                client->priv->dbus_proxy,
                (const gchar * const *) strv,
-               &uids, cancellable, &local_error);
+               opflags, &uids, cancellable, &local_error);
 
        g_strfreev (strv);
 
@@ -5140,7 +4833,7 @@ e_cal_client_create_objects_sync (ECalClient *client,
                ((uids != NULL) && (local_error == NULL)) ||
                ((uids == NULL) && (local_error != NULL)), FALSE);
 
-       if (uids != NULL) {
+       if (uids && out_uids) {
                GSList *tmp = NULL;
 
                /* Steal the string array elements. */
@@ -5150,6 +4843,8 @@ e_cal_client_create_objects_sync (ECalClient *client,
                }
 
                *out_uids = g_slist_reverse (tmp);
+       } else if (out_uids) {
+               *out_uids = NULL;
        }
 
        g_strfreev (uids);
@@ -5178,6 +4873,7 @@ cal_client_modify_object_thread (GSimpleAsyncResult *simple,
                E_CAL_CLIENT (source_object),
                async_context->in_comp,
                async_context->mod,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -5196,6 +4892,7 @@ cal_client_modify_object_thread (GSimpleAsyncResult *simple,
  * @client: an #ECalClient
  * @icalcomp: Component to modify
  * @mod: Type of modification
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -5215,8 +4912,9 @@ cal_client_modify_object_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_cal_client_modify_object (ECalClient *client,
-                            icalcomponent *icalcomp,
+                            ICalComponent *icalcomp,
                             ECalObjModType mod,
+                           guint32 opflags,
                             GCancellable *cancellable,
                             GAsyncReadyCallback callback,
                             gpointer user_data)
@@ -5228,8 +4926,9 @@ e_cal_client_modify_object (ECalClient *client,
        g_return_if_fail (icalcomp != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->in_comp = icalcomponent_new_clone (icalcomp);
+       async_context->in_comp = i_cal_component_new_clone (icalcomp);
        async_context->mod = mod;
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -5282,6 +4981,7 @@ e_cal_client_modify_object_finish (ECalClient *client,
  * @client: an #ECalClient
  * @icalcomp: Component to modify
  * @mod: Type of modification
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -5299,8 +4999,9 @@ e_cal_client_modify_object_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_modify_object_sync (ECalClient *client,
-                                 icalcomponent *icalcomp,
+                                 ICalComponent *icalcomp,
                                  ECalObjModType mod,
+                                guint32 opflags,
                                  GCancellable *cancellable,
                                  GError **error)
 {
@@ -5310,7 +5011,7 @@ e_cal_client_modify_object_sync (ECalClient *client,
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
        return e_cal_client_modify_objects_sync (
-               client, &link, mod, cancellable, error);
+               client, &link, mod, opflags, cancellable, error);
 }
 
 /* Helper for e_cal_client_modify_objects() */
@@ -5328,6 +5029,7 @@ cal_client_modify_objects_thread (GSimpleAsyncResult *simple,
                E_CAL_CLIENT (source_object),
                async_context->comp_list,
                async_context->mod,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -5344,8 +5046,9 @@ cal_client_modify_objects_thread (GSimpleAsyncResult *simple,
 /**
  * e_cal_client_modify_objects:
  * @client: an #ECalClient
- * @comps: (element-type icalcomponent): Components to modify
+ * @icalcomps: (element-type ICalComponent): Components to modify
  * @mod: Type of modification
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -5365,8 +5068,9 @@ cal_client_modify_objects_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_cal_client_modify_objects (ECalClient *client,
-                             GSList *comps,
+                             GSList *icalcomps,
                              ECalObjModType mod,
+                            guint32 opflags,
                              GCancellable *cancellable,
                              GAsyncReadyCallback callback,
                              gpointer user_data)
@@ -5375,12 +5079,13 @@ e_cal_client_modify_objects (ECalClient *client,
        AsyncContext *async_context;
 
        g_return_if_fail (E_IS_CAL_CLIENT (client));
-       g_return_if_fail (comps != NULL);
+       g_return_if_fail (icalcomps != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->comp_list = g_slist_copy_deep (
-               comps, (GCopyFunc) icalcomponent_new_clone, NULL);
+               icalcomps, (GCopyFunc) i_cal_component_new_clone, NULL);
        async_context->mod = mod;
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -5431,8 +5136,9 @@ e_cal_client_modify_objects_finish (ECalClient *client,
 /**
  * e_cal_client_modify_objects_sync:
  * @client: an #ECalClient
- * @comps: (element-type icalcomponent): Components to modify
+ * @icalcomps: (element-type ICalComponent): Components to modify
  * @mod: Type of modification
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -5450,52 +5156,53 @@ e_cal_client_modify_objects_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_modify_objects_sync (ECalClient *client,
-                                  GSList *comps,
+                                  GSList *icalcomps,
                                   ECalObjModType mod,
+                                 guint32 opflags,
                                   GCancellable *cancellable,
                                   GError **error)
 {
        GFlagsClass *flags_class;
        GFlagsValue *flags_value;
-       GString *flags;
+       GString *mod_flags;
        gchar **strv;
        gint ii = 0;
        GError *local_error = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-       g_return_val_if_fail (comps != NULL, FALSE);
+       g_return_val_if_fail (icalcomps != NULL, FALSE);
 
-       flags = g_string_new (NULL);
+       mod_flags = g_string_new (NULL);
        flags_class = g_type_class_ref (E_TYPE_CAL_OBJ_MOD_TYPE);
        flags_value = g_flags_get_first_value (flags_class, mod);
        while (flags_value != NULL) {
-               if (flags->len > 0)
-                       g_string_append_c (flags, ':');
-               g_string_append (flags, flags_value->value_nick);
+               if (mod_flags->len > 0)
+                       g_string_append_c (mod_flags, ':');
+               g_string_append (mod_flags, flags_value->value_nick);
                mod &= ~flags_value->value;
                flags_value = g_flags_get_first_value (flags_class, mod);
        }
 
-       strv = g_new0 (gchar *, g_slist_length (comps) + 1);
-       while (comps != NULL) {
+       strv = g_new0 (gchar *, g_slist_length (icalcomps) + 1);
+       while (icalcomps != NULL) {
                gchar *ical_string;
 
-               ical_string = icalcomponent_as_ical_string_r (comps->data);
+               ical_string = i_cal_component_as_ical_string_r (icalcomps->data);
                strv[ii++] = e_util_utf8_make_valid (ical_string);
                g_free (ical_string);
 
-               comps = g_slist_next (comps);
+               icalcomps = g_slist_next (icalcomps);
        }
 
        e_dbus_calendar_call_modify_objects_sync (
                client->priv->dbus_proxy,
                (const gchar * const *) strv,
-               flags->str, cancellable, &local_error);
+               mod_flags->str, opflags, cancellable, &local_error);
 
        g_strfreev (strv);
 
        g_type_class_unref (flags_class);
-       g_string_free (flags, TRUE);
+       g_string_free (mod_flags, TRUE);
 
        if (local_error != NULL) {
                g_dbus_error_strip_remote_error (local_error);
@@ -5522,6 +5229,7 @@ cal_client_remove_object_thread (GSimpleAsyncResult *simple,
                async_context->uid,
                async_context->rid,
                async_context->mod,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -5541,6 +5249,7 @@ cal_client_remove_object_thread (GSimpleAsyncResult *simple,
  * @uid: UID of the object to remove
  * @rid: Recurrence ID of the specific recurrence to remove
  * @mod: Type of the removal
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -5561,6 +5270,7 @@ e_cal_client_remove_object (ECalClient *client,
                             const gchar *uid,
                             const gchar *rid,
                             ECalObjModType mod,
+                           guint32 opflags,
                             GCancellable *cancellable,
                             GAsyncReadyCallback callback,
                             gpointer user_data)
@@ -5576,6 +5286,7 @@ e_cal_client_remove_object (ECalClient *client,
        async_context->uid = g_strdup (uid);
        async_context->rid = g_strdup (rid);
        async_context->mod = mod;
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -5629,6 +5340,7 @@ e_cal_client_remove_object_finish (ECalClient *client,
  * @uid: UID of the object to remove
  * @rid: Recurrence ID of the specific recurrence to remove
  * @mod: Type of the removal
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -5647,17 +5359,25 @@ e_cal_client_remove_object_sync (ECalClient *client,
                                  const gchar *uid,
                                  const gchar *rid,
                                  ECalObjModType mod,
+                                guint32 opflags,
                                  GCancellable *cancellable,
                                  GError **error)
 {
-       ECalComponentId id = { (gchar *) uid, (gchar *) rid };
-       GSList link = { &id, NULL };
+       ECalComponentId *id;
+       GSList *link;
+       gboolean success;
 
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
        g_return_val_if_fail (uid != NULL, FALSE);
 
-       return e_cal_client_remove_objects_sync (
-               client, &link, mod, cancellable, error);
+       id = e_cal_component_id_new (uid, rid);
+       link = g_slist_prepend (NULL, id);
+
+       success = e_cal_client_remove_objects_sync (client, link, mod, opflags, cancellable, error);
+
+       g_slist_free_full (link, e_cal_component_id_free);
+
+       return success;
 }
 
 /* Helper for e_cal_client_remove_objects() */
@@ -5673,8 +5393,9 @@ cal_client_remove_objects_thread (GSimpleAsyncResult *simple,
 
        if (!e_cal_client_remove_objects_sync (
                E_CAL_CLIENT (source_object),
-               async_context->string_list,
+               async_context->ids_list,
                async_context->mod,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -5694,6 +5415,7 @@ cal_client_remove_objects_thread (GSimpleAsyncResult *simple,
  * @ids: (element-type ECalComponentId): A list of #ECalComponentId objects
  * identifying the objects to remove
  * @mod: Type of the removal
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -5712,6 +5434,7 @@ void
 e_cal_client_remove_objects (ECalClient *client,
                              const GSList *ids,
                              ECalObjModType mod,
+                            guint32 opflags,
                              GCancellable *cancellable,
                              GAsyncReadyCallback callback,
                              gpointer user_data)
@@ -5723,9 +5446,10 @@ e_cal_client_remove_objects (ECalClient *client,
        g_return_if_fail (ids != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->string_list = g_slist_copy_deep (
-               (GSList *) ids, (GCopyFunc) g_strdup, NULL);
+       async_context->ids_list = g_slist_copy_deep (
+               (GSList *) ids, (GCopyFunc) e_cal_component_id_copy, NULL);
        async_context->mod = mod;
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -5779,6 +5503,7 @@ e_cal_client_remove_objects_finish (ECalClient *client,
  * @ids: (element-type ECalComponentId): a list of #ECalComponentId objects
  *       identifying the objects to remove
  * @mod: Type of the removal
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -5795,26 +5520,27 @@ gboolean
 e_cal_client_remove_objects_sync (ECalClient *client,
                                   const GSList *ids,
                                   ECalObjModType mod,
+                                 guint32 opflags,
                                   GCancellable *cancellable,
                                   GError **error)
 {
        GVariantBuilder builder;
        GFlagsClass *flags_class;
        GFlagsValue *flags_value;
-       GString *flags;
+       GString *mod_flags;
        guint n_valid_uids = 0;
        GError *local_error = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
        g_return_val_if_fail (ids != NULL, FALSE);
 
-       flags = g_string_new (NULL);
+       mod_flags = g_string_new (NULL);
        flags_class = g_type_class_ref (E_TYPE_CAL_OBJ_MOD_TYPE);
        flags_value = g_flags_get_first_value (flags_class, mod);
        while (flags_value != NULL) {
-               if (flags->len > 0)
-                       g_string_append_c (flags, ':');
-               g_string_append (flags, flags_value->value_nick);
+               if (mod_flags->len > 0)
+                       g_string_append_c (mod_flags, ':');
+               g_string_append (mod_flags, flags_value->value_nick);
                mod &= ~flags_value->value;
                flags_value = g_flags_get_first_value (flags_class, mod);
        }
@@ -5822,18 +5548,22 @@ e_cal_client_remove_objects_sync (ECalClient *client,
        g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
        while (ids != NULL) {
                ECalComponentId *id = ids->data;
+               const gchar *uid, *rid;
                gchar *utf8_uid;
                gchar *utf8_rid;
 
                ids = g_slist_next (ids);
 
-               if (id->uid == NULL)
+               uid = e_cal_component_id_get_uid (id);
+               rid = e_cal_component_id_get_rid (id);
+
+               if (!uid)
                        continue;
 
                /* Reject empty UIDs with an OBJECT_NOT_FOUND error for
                 * backward-compatibility, even though INVALID_ARG might
                 * be more appropriate. */
-               if (*id->uid == '\0') {
+               if (!*uid) {
                        local_error = g_error_new_literal (
                                E_CAL_CLIENT_ERROR,
                                E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND,
@@ -5843,9 +5573,9 @@ e_cal_client_remove_objects_sync (ECalClient *client,
                        break;
                }
 
-               utf8_uid = e_util_utf8_make_valid (id->uid);
-               if (id->rid != NULL)
-                       utf8_rid = e_util_utf8_make_valid (id->rid);
+               utf8_uid = e_util_utf8_make_valid (uid);
+               if (rid)
+                       utf8_rid = e_util_utf8_make_valid (rid);
                else
                        utf8_rid = g_strdup ("");
 
@@ -5861,13 +5591,13 @@ e_cal_client_remove_objects_sync (ECalClient *client,
                e_dbus_calendar_call_remove_objects_sync (
                        client->priv->dbus_proxy,
                        g_variant_builder_end (&builder),
-                       flags->str, cancellable, &local_error);
+                       mod_flags->str, opflags, cancellable, &local_error);
        } else {
                g_variant_builder_clear (&builder);
        }
 
        g_type_class_unref (flags_class);
-       g_string_free (flags, TRUE);
+       g_string_free (mod_flags, TRUE);
 
        if (local_error != NULL) {
                g_dbus_error_strip_remote_error (local_error);
@@ -5892,6 +5622,7 @@ cal_client_receive_objects_thread (GSimpleAsyncResult *simple,
        if (!e_cal_client_receive_objects_sync (
                E_CAL_CLIENT (source_object),
                async_context->in_comp,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -5908,7 +5639,8 @@ cal_client_receive_objects_thread (GSimpleAsyncResult *simple,
 /**
  * e_cal_client_receive_objects:
  * @client: an #ECalClient
- * @icalcomp: An #icalcomponent
+ * @icalcomp: An #ICalComponent
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -5924,7 +5656,8 @@ cal_client_receive_objects_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_cal_client_receive_objects (ECalClient *client,
-                              icalcomponent *icalcomp,
+                              ICalComponent *icalcomp,
+                             guint32 opflags,
                               GCancellable *cancellable,
                               GAsyncReadyCallback callback,
                               gpointer user_data)
@@ -5936,7 +5669,8 @@ e_cal_client_receive_objects (ECalClient *client,
        g_return_if_fail (icalcomp != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->in_comp = icalcomponent_new_clone (icalcomp);
+       async_context->in_comp = i_cal_component_new_clone (icalcomp);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -5987,7 +5721,8 @@ e_cal_client_receive_objects_finish (ECalClient *client,
 /**
  * e_cal_client_receive_objects_sync:
  * @client: an #ECalClient
- * @icalcomp: An #icalcomponent
+ * @icalcomp: An #ICalComponent
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -6001,7 +5736,8 @@ e_cal_client_receive_objects_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_receive_objects_sync (ECalClient *client,
-                                   icalcomponent *icalcomp,
+                                   ICalComponent *icalcomp,
+                                  guint32 opflags,
                                    GCancellable *cancellable,
                                    GError **error)
 {
@@ -6011,11 +5747,11 @@ e_cal_client_receive_objects_sync (ECalClient *client,
 
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
 
-       ical_string = icalcomponent_as_ical_string_r (icalcomp);
+       ical_string = i_cal_component_as_ical_string_r (icalcomp);
        utf8_ical_string = e_util_utf8_make_valid (ical_string);
 
        e_dbus_calendar_call_receive_objects_sync (
-               client->priv->dbus_proxy, utf8_ical_string,
+               client->priv->dbus_proxy, utf8_ical_string, opflags,
                cancellable, &local_error);
 
        g_free (utf8_ical_string);
@@ -6044,6 +5780,7 @@ cal_client_send_objects_thread (GSimpleAsyncResult *simple,
        if (!e_cal_client_send_objects_sync (
                E_CAL_CLIENT (source_object),
                async_context->in_comp,
+               async_context->opflags,
                &async_context->string_list,
                &async_context->out_comp,
                cancellable, &local_error)) {
@@ -6062,7 +5799,8 @@ cal_client_send_objects_thread (GSimpleAsyncResult *simple,
 /**
  * e_cal_client_send_objects:
  * @client: an #ECalClient
- * @icalcomp: An icalcomponent to be sent
+ * @icalcomp: An #ICalComponent to be sent
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -6076,7 +5814,8 @@ cal_client_send_objects_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_cal_client_send_objects (ECalClient *client,
-                           icalcomponent *icalcomp,
+                           ICalComponent *icalcomp,
+                          guint32 opflags,
                            GCancellable *cancellable,
                            GAsyncReadyCallback callback,
                            gpointer user_data)
@@ -6088,7 +5827,8 @@ e_cal_client_send_objects (ECalClient *client,
        g_return_if_fail (icalcomp != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->in_comp = icalcomponent_new_clone (icalcomp);
+       async_context->in_comp = i_cal_component_new_clone (icalcomp);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -6110,16 +5850,16 @@ e_cal_client_send_objects (ECalClient *client,
  * e_cal_client_send_objects_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_users: (out) (element-type utf8): List of users to send
+ * @out_users: (out) (transfer full) (element-type utf8): List of users to send
  *             the @out_modified_icalcomp to
- * @out_modified_icalcomp: (out): Return value for the icalcomponent to be sent
+ * @out_modified_icalcomp: (out) (transfer full): Return value for the #ICalComponent to be sent
  * @error: (out): a #GError to set an error, if any
  *
  * Finishes previous call of e_cal_client_send_objects() and
  * populates @out_users with a list of users to send @out_modified_icalcomp to.
  *
  * The @out_users list should be freed with e_client_util_free_string_slist()
- * and the @out_modified_icalcomp should be freed with icalcomponent_free().
+ * and the @out_modified_icalcomp should be freed with g_object_unref().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -6129,7 +5869,7 @@ gboolean
 e_cal_client_send_objects_finish (ECalClient *client,
                                   GAsyncResult *result,
                                   GSList **out_users,
-                                  icalcomponent **out_modified_icalcomp,
+                                  ICalComponent **out_modified_icalcomp,
                                   GError **error)
 {
        GSimpleAsyncResult *simple;
@@ -6164,10 +5904,11 @@ e_cal_client_send_objects_finish (ECalClient *client,
 /**
  * e_cal_client_send_objects_sync:
  * @client: an #ECalClient
- * @icalcomp: An icalcomponent to be sent
- * @out_users: (out) (element-type utf8): List of users to send the
+ * @icalcomp: An #ICalComponent to be sent
+ * @opflags: bit-or of #ECalOperationFlags
+ * @out_users: (out) (transfer full) (element-type utf8): List of users to send the
  *             @out_modified_icalcomp to
- * @out_modified_icalcomp: (out): Return value for the icalcomponent to be sent
+ * @out_modified_icalcomp: (out) (transfer full): Return value for the #ICalComponent to be sent
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -6176,7 +5917,7 @@ e_cal_client_send_objects_finish (ECalClient *client,
  * @out_users list.
  *
  * The @out_users list should be freed with e_client_util_free_string_slist()
- * and the @out_modified_icalcomp should be freed with icalcomponent_free().
+ * and the @out_modified_icalcomp should be freed with g_object_unref().
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -6184,9 +5925,10 @@ e_cal_client_send_objects_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_send_objects_sync (ECalClient *client,
-                                icalcomponent *icalcomp,
+                                ICalComponent *icalcomp,
+                               guint32 opflags,
                                 GSList **out_users,
-                                icalcomponent **out_modified_icalcomp,
+                                ICalComponent **out_modified_icalcomp,
                                 GCancellable *cancellable,
                                 GError **error)
 {
@@ -6201,12 +5943,12 @@ e_cal_client_send_objects_sync (ECalClient *client,
        g_return_val_if_fail (out_users != NULL, FALSE);
        g_return_val_if_fail (out_modified_icalcomp != NULL, FALSE);
 
-       ical_string = icalcomponent_as_ical_string_r (icalcomp);
+       ical_string = i_cal_component_as_ical_string_r (icalcomp);
        utf8_ical_string = e_util_utf8_make_valid (ical_string);
 
        e_dbus_calendar_call_send_objects_sync (
-               client->priv->dbus_proxy, utf8_ical_string, &users,
-               &out_ical_string, cancellable, &local_error);
+               client->priv->dbus_proxy, utf8_ical_string, opflags,
+               &users, &out_ical_string, cancellable, &local_error);
 
        g_free (utf8_ical_string);
        g_free (ical_string);
@@ -6223,7 +5965,7 @@ e_cal_client_send_objects_sync (ECalClient *client,
                return FALSE;
        }
 
-       icalcomp = icalparser_parse_string (out_ical_string);
+       icalcomp = i_cal_parser_parse_string (out_ical_string);
 
        g_free (out_ical_string);
 
@@ -6441,6 +6183,8 @@ e_cal_client_get_attachment_uris_sync (ECalClient *client,
                }
 
                *out_attachment_uris = g_slist_reverse (tmp);
+
+               g_free (uris);
        }
 
        if (local_error != NULL) {
@@ -6468,6 +6212,7 @@ cal_client_discard_alarm_thread (GSimpleAsyncResult *simple,
                async_context->uid,
                async_context->rid,
                async_context->auid,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -6486,12 +6231,13 @@ cal_client_discard_alarm_thread (GSimpleAsyncResult *simple,
  * @client: an #ECalClient
  * @uid: Unique identifier for a calendar component
  * @rid: Recurrence identifier
- * @auid: Alarm identifier to remove
+ * @auid: Alarm identifier to discard
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
  *
- * Removes alarm @auid from a given component identified by @uid and @rid.
+ * Discards alarm @auid from a given component identified by @uid and @rid.
  * The call is finished by e_cal_client_discard_alarm_finish() from
  * the @callback.
  *
@@ -6502,6 +6248,7 @@ e_cal_client_discard_alarm (ECalClient *client,
                             const gchar *uid,
                             const gchar *rid,
                             const gchar *auid,
+                           guint32 opflags,
                             GCancellable *cancellable,
                             GAsyncReadyCallback callback,
                             gpointer user_data)
@@ -6516,8 +6263,9 @@ e_cal_client_discard_alarm (ECalClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->uid = g_strdup (uid);
-       async_context->rid = NULL;
+       async_context->rid = g_strdup (rid);
        async_context->auid = g_strdup (auid);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -6570,11 +6318,12 @@ e_cal_client_discard_alarm_finish (ECalClient *client,
  * @client: an #ECalClient
  * @uid: Unique identifier for a calendar component
  * @rid: Recurrence identifier
- * @auid: Alarm identifier to remove
+ * @auid: Alarm identifier to discard
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
- * Removes alarm @auid from a given component identified by @uid and @rid.
+ * Discards alarm @auid from a given component identified by @uid and @rid.
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
@@ -6585,6 +6334,7 @@ e_cal_client_discard_alarm_sync (ECalClient *client,
                                  const gchar *uid,
                                  const gchar *rid,
                                  const gchar *auid,
+                                guint32 opflags,
                                  GCancellable *cancellable,
                                  GError **error)
 {
@@ -6606,7 +6356,7 @@ e_cal_client_discard_alarm_sync (ECalClient *client,
 
        e_dbus_calendar_call_discard_alarm_sync (
                client->priv->dbus_proxy,
-               utf8_uid, utf8_rid, utf8_auid,
+               utf8_uid, utf8_rid, utf8_auid, opflags,
                cancellable, &local_error);
 
        g_free (utf8_uid);
@@ -6894,7 +6644,7 @@ e_cal_client_get_timezone (ECalClient *client,
  * e_cal_client_get_timezone_finish:
  * @client: an #ECalClient
  * @result: a #GAsyncResult
- * @out_zone: (out): Return value for the timezone
+ * @out_zone: (out) (transfer none): Return value for the timezone
  * @error: (out): a #GError to set an error, if any
  *
  * Finishes previous call of e_cal_client_get_timezone() and
@@ -6908,7 +6658,7 @@ e_cal_client_get_timezone (ECalClient *client,
 gboolean
 e_cal_client_get_timezone_finish (ECalClient *client,
                                   GAsyncResult *result,
-                                  icaltimezone **out_zone,
+                                  ICalTimezone **out_zone,
                                   GError **error)
 {
        GSimpleAsyncResult *simple;
@@ -6939,7 +6689,7 @@ e_cal_client_get_timezone_finish (ECalClient *client,
  * e_cal_client_get_timezone_sync:
  * @client: an #ECalClient
  * @tzid: ID of the timezone to retrieve
- * @out_zone: (out): Return value for the timezone
+ * @out_zone: (out) (transfer none): Return value for the timezone
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -6953,12 +6703,12 @@ e_cal_client_get_timezone_finish (ECalClient *client,
 gboolean
 e_cal_client_get_timezone_sync (ECalClient *client,
                                 const gchar *tzid,
-                                icaltimezone **out_zone,
+                                ICalTimezone **out_zone,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       icalcomponent *icalcomp;
-       icaltimezone *zone;
+       ICalComponent *icalcomp;
+       ICalTimezone *zone;
        gchar *utf8_tzid;
        gchar *string = NULL;
        GError *local_error = NULL;
@@ -6993,7 +6743,7 @@ e_cal_client_get_timezone_sync (ECalClient *client,
                return FALSE;
        }
 
-       icalcomp = icalparser_parse_string (string);
+       icalcomp = i_cal_parser_parse_string (string);
 
        g_free (string);
 
@@ -7006,15 +6756,15 @@ e_cal_client_get_timezone_sync (ECalClient *client,
                return FALSE;
        }
 
-       zone = icaltimezone_new ();
-       if (!icaltimezone_set_component (zone, icalcomp)) {
+       zone = i_cal_timezone_new ();
+       if (!i_cal_timezone_set_component (zone, icalcomp)) {
                g_set_error_literal (
                        error, E_CAL_CLIENT_ERROR,
                        E_CAL_CLIENT_ERROR_INVALID_OBJECT,
                        e_cal_client_error_to_string (
                        E_CAL_CLIENT_ERROR_INVALID_OBJECT));
-               icalcomponent_free (icalcomp);
-               icaltimezone_free (zone, 1);
+               g_object_unref (icalcomp);
+               g_object_unref (zone);
                return FALSE;
        }
 
@@ -7026,7 +6776,7 @@ e_cal_client_get_timezone_sync (ECalClient *client,
                /* It can be that another thread already filled the zone into the cache,
                   thus deal with it properly, because that other zone can be used by that
                   other thread. */
-               icaltimezone_free (zone, 1);
+               g_object_unref (zone);
                zone = g_hash_table_lookup (client->priv->zone_cache, tzid);
        } else {
                g_hash_table_insert (
@@ -7034,6 +6784,8 @@ e_cal_client_get_timezone_sync (ECalClient *client,
        }
        g_mutex_unlock (&client->priv->zone_cache_lock);
 
+       g_object_unref (icalcomp);
+
        *out_zone = zone;
 
        return TRUE;
@@ -7082,26 +6834,28 @@ cal_client_add_timezone_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_cal_client_add_timezone (ECalClient *client,
-                           icaltimezone *zone,
+                           ICalTimezone *zone,
                            GCancellable *cancellable,
                            GAsyncReadyCallback callback,
                            gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
-       icalcomponent *icalcomp;
+       ICalComponent *icalcomp, *clone;
 
        g_return_if_fail (E_IS_CAL_CLIENT (client));
        g_return_if_fail (zone != NULL);
 
-       icalcomp = icaltimezone_get_component (zone);
+       icalcomp = i_cal_timezone_get_component (zone);
        g_return_if_fail (icalcomp != NULL);
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->zone = icaltimezone_new ();
+       async_context->zone = i_cal_timezone_new ();
 
-       icalcomp = icalcomponent_new_clone (icalcomp);
-       icaltimezone_set_component (async_context->zone, icalcomp);
+       clone = i_cal_component_new_clone (icalcomp);
+       i_cal_timezone_set_component (async_context->zone, clone);
+       g_object_unref (icalcomp);
+       g_object_unref (clone);
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -7112,7 +6866,7 @@ e_cal_client_add_timezone (ECalClient *client,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (zone == icaltimezone_get_utc_timezone ())
+       if (zone == i_cal_timezone_get_utc_timezone ())
                g_simple_async_result_complete_in_idle (simple);
        else
                g_simple_async_result_run_in_thread (
@@ -7167,11 +6921,11 @@ e_cal_client_add_timezone_finish (ECalClient *client,
  **/
 gboolean
 e_cal_client_add_timezone_sync (ECalClient *client,
-                                icaltimezone *zone,
+                                ICalTimezone *zone,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icalcomp;
        gchar *zone_str;
        gchar *utf8_zone_str;
        GError *local_error = NULL;
@@ -7179,10 +6933,10 @@ e_cal_client_add_timezone_sync (ECalClient *client,
        g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
        g_return_val_if_fail (zone != NULL, FALSE);
 
-       if (zone == icaltimezone_get_utc_timezone ())
+       if (zone == i_cal_timezone_get_utc_timezone ())
                return TRUE;
 
-       icalcomp = icaltimezone_get_component (zone);
+       icalcomp = i_cal_timezone_get_component (zone);
        if (icalcomp == NULL) {
                g_propagate_error (
                        error, e_client_error_create (
@@ -7190,7 +6944,7 @@ e_cal_client_add_timezone_sync (ECalClient *client,
                return FALSE;
        }
 
-       zone_str = icalcomponent_as_ical_string_r (icalcomp);
+       zone_str = i_cal_component_as_ical_string_r (icalcomp);
        utf8_zone_str = e_util_utf8_make_valid (zone_str);
 
        e_dbus_calendar_call_add_timezone_sync (
@@ -7199,6 +6953,7 @@ e_cal_client_add_timezone_sync (ECalClient *client,
 
        g_free (zone_str);
        g_free (utf8_zone_str);
+       g_object_unref (icalcomp);
 
        if (local_error != NULL) {
                g_dbus_error_strip_remote_error (local_error);
diff --git a/src/calendar/libecal/e-cal-client.h b/src/calendar/libecal/e-cal-client.h
index 5e04986bb..d6498f322 100644
--- a/src/calendar/libecal/e-cal-client.h
+++ b/src/calendar/libecal/e-cal-client.h
@@ -27,8 +27,8 @@
 #include <libedataserver/libedataserver.h>
 
 #include <libecal/e-cal-client-view.h>
+#include <libecal/e-cal-enums.h>
 #include <libecal/e-cal-recur.h>
-#include <libecal/e-cal-types.h>
 #include <libecal/e-cal-util.h>
 
 /* Standard GObject macros */
@@ -51,35 +51,35 @@
        ((obj), E_TYPE_CAL_CLIENT, ECalClientClass))
 
 /**
- * CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS:
+ * E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS:
  *
  * An email address associated with the calendar.
  *
  * Since: 3.2
  **/
-#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS         "cal-email-address"
+#define E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS       "cal-email-address"
 
 /**
- * CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS:
+ * E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS:
  *
  * An email address preferred for e-mail reminders by the calendar.
  *
  * Since: 3.2
  **/
-#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS       "alarm-email-address"
+#define E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS     "alarm-email-address"
 
 /**
- * CAL_BACKEND_PROPERTY_DEFAULT_OBJECT:
+ * E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT:
  *
  * A default object for the calendar. Calendars use VEVENT, memo lists VJOURNAL
  * and task lists VTODO, which can have prefilled values by the backend.
  *
  * Since: 3.2
  **/
-#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT            "default-object"
+#define E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT          "default-object"
 
 /**
- * CAL_BACKEND_PROPERTY_REVISION:
+ * E_CAL_BACKEND_PROPERTY_REVISION:
  *
  * The current overall revision string, this can be used as
  * a quick check to see if data has changed at all since the
@@ -87,7 +87,7 @@
  *
  * Since: 3.4
  **/
-#define CAL_BACKEND_PROPERTY_REVISION                  "revision"
+#define E_CAL_BACKEND_PROPERTY_REVISION                        "revision"
 
 /**
  * E_CAL_CLIENT_ERROR:
@@ -121,6 +121,14 @@ typedef enum {
        E_CAL_CLIENT_ERROR_INVALID_RANGE
 } ECalClientError;
 
+GQuark         e_cal_client_error_quark        (void) G_GNUC_CONST;
+const gchar *  e_cal_client_error_to_string    (ECalClientError code);
+GError *       e_cal_client_error_create       (ECalClientError code,
+                                                const gchar *custom_msg);
+GError *       e_cal_client_error_create_fmt   (ECalClientError code,
+                                                const gchar *format,
+                                                ...) G_GNUC_PRINTF (2, 3);
+
 typedef struct _ECalClient ECalClient;
 typedef struct _ECalClientClass ECalClientClass;
 typedef struct _ECalClientPrivate ECalClientPrivate;
@@ -153,12 +161,9 @@ struct _ECalClientClass {
        /*< public >*/
        /* Signals */
        void            (*free_busy_data)       (ECalClient *client,
-                                                const GSList *free_busy_ecalcomps);
+                                                const GSList *free_busy_ecalcomps); /* ECalComponent * */
 };
 
-GQuark         e_cal_client_error_quark        (void) G_GNUC_CONST;
-const gchar *  e_cal_client_error_to_string    (ECalClientError code);
-
 GType          e_cal_client_get_type           (void) G_GNUC_CONST;
 EClient *      e_cal_client_connect_sync       (ESource *source,
                                                 ECalClientSourceType source_type,
@@ -179,8 +184,8 @@ const gchar *       e_cal_client_get_local_attachment_store
                                                (ECalClient *client);
 void           e_cal_client_set_default_timezone
                                                (ECalClient *client,
-                                                icaltimezone *zone);
-icaltimezone * e_cal_client_get_default_timezone
+                                                ICalTimezone *zone);
+ICalTimezone * e_cal_client_get_default_timezone
                                                (ECalClient *client);
 gboolean       e_cal_client_check_one_alarm_only
                                                (ECalClient *client);
@@ -192,49 +197,41 @@ gboolean  e_cal_client_check_organizer_must_accept
                                                (ECalClient *client);
 gboolean       e_cal_client_check_recurrences_no_master
                                                (ECalClient *client);
-void           e_cal_client_free_icalcomp_slist
-                                               (GSList *icalcomps);
-void           e_cal_client_free_ecalcomp_slist
-                                               (GSList *ecalcomps);
 
-icaltimezone * e_cal_client_resolve_tzid_cb    (const gchar *tzid,
-                                                gpointer data);
-icaltimezone * e_cal_client_resolve_tzid_sync  (const gchar *tzid,
-                                                gpointer cal_client,
-                                                GCancellable *cancellable,
-                                                GError **error);
 void           e_cal_client_generate_instances (ECalClient *client,
                                                 time_t start,
                                                 time_t end,
                                                 GCancellable *cancellable,
-                                                ECalRecurInstanceFn cb,
+                                                ECalRecurInstanceCb cb,
                                                 gpointer cb_data,
                                                 GDestroyNotify destroy_cb_data);
 void           e_cal_client_generate_instances_sync
                                                (ECalClient *client,
                                                 time_t start,
                                                 time_t end,
-                                                ECalRecurInstanceFn cb,
+                                                GCancellable *cancellable,
+                                                ECalRecurInstanceCb cb,
                                                 gpointer cb_data);
 void           e_cal_client_generate_instances_for_object
                                                (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
                                                 time_t start,
                                                 time_t end,
                                                 GCancellable *cancellable,
-                                                ECalRecurInstanceFn cb,
+                                                ECalRecurInstanceCb cb,
                                                 gpointer cb_data,
                                                 GDestroyNotify destroy_cb_data);
 void           e_cal_client_generate_instances_for_object_sync
                                                (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
                                                 time_t start,
                                                 time_t end,
-                                                ECalRecurInstanceFn cb,
+                                                GCancellable *cancellable,
+                                                ECalRecurInstanceCb cb,
                                                 gpointer cb_data);
 gchar *                e_cal_client_get_component_as_string
                                                (ECalClient *client,
-                                                icalcomponent *icalcomp);
+                                                ICalComponent *icalcomp);
 void           e_cal_client_get_default_object (ECalClient *client,
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
@@ -242,11 +239,11 @@ void              e_cal_client_get_default_object (ECalClient *client,
 gboolean       e_cal_client_get_default_object_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                icalcomponent **out_icalcomp,
+                                                ICalComponent **out_icalcomp,
                                                 GError **error);
 gboolean       e_cal_client_get_default_object_sync
                                                (ECalClient *client,
-                                                icalcomponent **out_icalcomp,
+                                                ICalComponent **out_icalcomp,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_object         (ECalClient *client,
@@ -257,12 +254,12 @@ void              e_cal_client_get_object         (ECalClient *client,
                                                 gpointer user_data);
 gboolean       e_cal_client_get_object_finish  (ECalClient *client,
                                                 GAsyncResult *result,
-                                                icalcomponent **out_icalcomp,
+                                                ICalComponent **out_icalcomp,
                                                 GError **error);
 gboolean       e_cal_client_get_object_sync    (ECalClient *client,
                                                 const gchar *uid,
                                                 const gchar *rid,
-                                                icalcomponent **out_icalcomp,
+                                                ICalComponent **out_icalcomp,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_objects_for_uid
@@ -274,12 +271,12 @@ void              e_cal_client_get_objects_for_uid
 gboolean       e_cal_client_get_objects_for_uid_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_ecalcomps,
+                                                GSList **out_ecalcomps, /* ECalComponent * */
                                                 GError **error);
 gboolean       e_cal_client_get_objects_for_uid_sync
                                                (ECalClient *client,
                                                 const gchar *uid,
-                                                GSList **out_ecalcomps,
+                                                GSList **out_ecalcomps, /* ECalComponent * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_object_list    (ECalClient *client,
@@ -290,12 +287,12 @@ void              e_cal_client_get_object_list    (ECalClient *client,
 gboolean       e_cal_client_get_object_list_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_icalcomps,
+                                                GSList **out_icalcomps, /* ICalComponent * */
                                                 GError **error);
 gboolean       e_cal_client_get_object_list_sync
                                                (ECalClient *client,
                                                 const gchar *sexp,
-                                                GSList **out_icalcomps,
+                                                GSList **out_icalcomps, /* ICalComponent * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_object_list_as_comps
@@ -307,35 +304,36 @@ void              e_cal_client_get_object_list_as_comps
 gboolean       e_cal_client_get_object_list_as_comps_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_ecalcomps,
+                                                GSList **out_ecalcomps, /* ECalComponent * */
                                                 GError **error);
 gboolean       e_cal_client_get_object_list_as_comps_sync
                                                (ECalClient *client,
                                                 const gchar *sexp,
-                                                GSList **out_ecalcomps,
+                                                GSList **out_ecalcomps, /* ECalComponent * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_free_busy      (ECalClient *client,
                                                 time_t start,
                                                 time_t end,
-                                                const GSList *users,
+                                                const GSList *users, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
 gboolean       e_cal_client_get_free_busy_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_freebusy,
+                                                GSList **out_freebusy, /* ECalComponent * */
                                                 GError **error);
 gboolean       e_cal_client_get_free_busy_sync (ECalClient *client,
                                                 time_t start,
                                                 time_t end,
-                                                const GSList *users,
-                                                GSList **out_freebusy,
+                                                const GSList *users, /* gchar * */
+                                                GSList **out_freebusy, /* ECalComponent * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_create_object      (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -345,29 +343,33 @@ gboolean  e_cal_client_create_object_finish
                                                 gchar **out_uid,
                                                 GError **error);
 gboolean       e_cal_client_create_object_sync (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 gchar **out_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_create_objects     (ECalClient *client,
-                                                GSList *icalcomps,
+                                                GSList *icalcomps, /* ICalComponent * */
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
 gboolean       e_cal_client_create_objects_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_uids,
+                                                GSList **out_uids, /* gchar * */
                                                 GError **error);
 gboolean       e_cal_client_create_objects_sync
                                                (ECalClient *client,
-                                                GSList *icalcomps,
-                                                GSList **out_uids,
+                                                GSList *icalcomps, /* ICalComponent * */
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
+                                                GSList **out_uids, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_modify_object      (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -376,13 +378,15 @@ gboolean  e_cal_client_modify_object_finish
                                                 GAsyncResult *result,
                                                 GError **error);
 gboolean       e_cal_client_modify_object_sync (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_modify_objects     (ECalClient *client,
-                                                GSList *comps,
+                                                GSList *icalcomps, /* ICalComponent * */
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -392,14 +396,16 @@ gboolean  e_cal_client_modify_objects_finish
                                                 GError **error);
 gboolean       e_cal_client_modify_objects_sync
                                                (ECalClient *client,
-                                                GSList *comps,
+                                                GSList *icalcomps, /* ICalComponent * */
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_remove_object      (ECalClient *client,
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -411,11 +417,13 @@ gboolean  e_cal_client_remove_object_sync (ECalClient *client,
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_remove_objects     (ECalClient *client,
-                                                const GSList *ids,
+                                                const GSList *ids, /* ECalComponentId * */
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -425,12 +433,14 @@ gboolean  e_cal_client_remove_objects_finish
                                                 GError **error);
 gboolean       e_cal_client_remove_objects_sync
                                                (ECalClient *client,
-                                                const GSList *ids,
+                                                const GSList *ids, /* ECalComponentId * */
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_receive_objects    (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -440,24 +450,27 @@ gboolean  e_cal_client_receive_objects_finish
                                                 GError **error);
 gboolean       e_cal_client_receive_objects_sync
                                                (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_send_objects       (ECalClient *client,
-                                                icalcomponent *icalcomp,
+                                                ICalComponent *icalcomp,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
 gboolean       e_cal_client_send_objects_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_users,
-                                                icalcomponent **out_modified_icalcomp,
+                                                GSList **out_users, /* gchar * */
+                                                ICalComponent **out_modified_icalcomp,
                                                 GError **error);
 gboolean       e_cal_client_send_objects_sync  (ECalClient *client,
-                                                icalcomponent *icalcomp,
-                                                GSList **out_users,
-                                                icalcomponent **out_modified_icalcomp,
+                                                ICalComponent *icalcomp,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
+                                                GSList **out_users, /* gchar * */
+                                                ICalComponent **out_modified_icalcomp,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_attachment_uris
@@ -470,19 +483,20 @@ void              e_cal_client_get_attachment_uris
 gboolean       e_cal_client_get_attachment_uris_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                GSList **out_attachment_uris,
+                                                GSList **out_attachment_uris, /* gchar * */
                                                 GError **error);
 gboolean       e_cal_client_get_attachment_uris_sync
                                                (ECalClient *client,
                                                 const gchar *uid,
                                                 const gchar *rid,
-                                                GSList **out_attachment_uris,
+                                                GSList **out_attachment_uris, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_discard_alarm      (ECalClient *client,
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 const gchar *auid,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -494,6 +508,7 @@ gboolean    e_cal_client_discard_alarm_sync (ECalClient *client,
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 const gchar *auid,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_get_view           (ECalClient *client,
@@ -518,15 +533,15 @@ void              e_cal_client_get_timezone       (ECalClient *client,
 gboolean       e_cal_client_get_timezone_finish
                                                (ECalClient *client,
                                                 GAsyncResult *result,
-                                                icaltimezone **out_zone,
+                                                ICalTimezone **out_zone,
                                                 GError **error);
 gboolean       e_cal_client_get_timezone_sync  (ECalClient *client,
                                                 const gchar *tzid,
-                                                icaltimezone **out_zone,
+                                                ICalTimezone **out_zone,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_client_add_timezone       (ECalClient *client,
-                                                icaltimezone *zone,
+                                                ICalTimezone *zone,
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -535,18 +550,10 @@ gboolean  e_cal_client_add_timezone_finish
                                                 GAsyncResult *result,
                                                 GError **error);
 gboolean       e_cal_client_add_timezone_sync  (ECalClient *client,
-                                                icaltimezone *zone,
+                                                ICalTimezone *zone,
                                                 GCancellable *cancellable,
                                                 GError **error);
 
-#ifndef EDS_DISABLE_DEPRECATED
-ECalClient *   e_cal_client_new                (ESource *source,
-                                                ECalClientSourceType source_type,
-                                                GError **error);
-GError *       e_cal_client_error_create       (ECalClientError code,
-                                                const gchar *custom_msg);
-#endif /* EDS_DISABLE_DEPRECATED */
-
 G_END_DECLS
 
 #endif /* E_CAL_CLIENT_H */
diff --git a/src/calendar/libecal/e-cal-component-alarm-instance.c 
b/src/calendar/libecal/e-cal-component-alarm-instance.c
new file mode 100644
index 000000000..377ed1aa6
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm-instance.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-alarm-instance
+ * @short_description: An ECalComponentAlarmInstance structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentAlarmInstance structure.
+ **/
+
+#include "e-cal-component-alarm-instance.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentAlarmInstance, e_cal_component_alarm_instance, 
e_cal_component_alarm_instance_copy, e_cal_component_alarm_instance_free)
+
+struct _ECalComponentAlarmInstance {
+       /* UID of the alarm that instanceed */
+       gchar *uid;
+
+       /* Instance time, i.e. "5 minutes before the appointment" */
+       time_t instance_time;
+
+       /* Actual event occurrence to which this instance corresponds */
+       time_t occur_start;
+       time_t occur_end;
+};
+
+/**
+ * e_cal_component_alarm_instance_new_relative:
+ * @uid: (not nullable): UID of the alarm
+ * @instance_time: instance time, i.e. "5 minutes before the appointment"
+ * @occur_start: actual event occurrence start to which this instance corresponds
+ * @occur_end: actual event occurrence end to which this instance corresponds
+ *
+ * Creates a new #ECalComponentAlarmInstance structure, filled with the given values.
+ * Free the instance with e_cal_component_alarm_instance_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarmInstance
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmInstance *
+e_cal_component_alarm_instance_new (const gchar *uid,
+                                   time_t instance_time,
+                                   time_t occur_start,
+                                   time_t occur_end)
+{
+       ECalComponentAlarmInstance *instance;
+
+       g_return_val_if_fail (uid != NULL, NULL);
+
+       instance = g_new0 (ECalComponentAlarmInstance, 1);
+       instance->uid = g_strdup (uid);
+       instance->instance_time = instance_time;
+       instance->occur_start = occur_start;
+       instance->occur_end = occur_end;
+
+       return instance;
+}
+
+/**
+ * e_cal_component_alarm_instance_copy:
+ * @instance: (not nullable): an #ECalComponentAlarmInstance
+ *
+ * Returns a newly allocated copy of @instance, which should be freed with
+ * e_cal_component_alarm_instance_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @instance
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmInstance *
+e_cal_component_alarm_instance_copy (const ECalComponentAlarmInstance *instance)
+{
+       g_return_val_if_fail (instance != NULL, NULL);
+
+       return e_cal_component_alarm_instance_new (instance->uid,
+               instance->instance_time,
+               instance->occur_start,
+               instance->occur_end);
+}
+
+/**
+ * e_cal_component_alarm_instance_free: (skip)
+ * @instance: (type ECalComponentAlarmInstance) (nullable): an #ECalComponentAlarmInstance to free
+ *
+ * Free @instance, previously created by e_cal_component_alarm_instance_new()
+ * or e_cal_component_alarm_instance_copy(). The function does nothing, if @instance
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_instance_free (gpointer instance)
+{
+       ECalComponentAlarmInstance *instnc = instance;
+
+       if (instnc) {
+               g_free (instnc->uid);
+               g_free (instnc);
+       }
+}
+
+/**
+ * e_cal_component_alarm_instance_get_uid:
+ * @instance: an #ECalComponentAlarmInstance
+ *
+ * Returns: alarm UID, to which this @instance corresponds
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_alarm_instance_get_uid (const ECalComponentAlarmInstance *instance)
+{
+       g_return_val_if_fail (instance != NULL, NULL);
+
+       return instance->uid;
+}
+
+/**
+ * e_cal_component_alarm_instance_set_uid:
+ * @instance: an ECalComponentAlarmInstance
+ * @uid: (not nullable): alarm UID to set
+ *
+ * Set the alarm UID.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_instance_set_uid (ECalComponentAlarmInstance *instance,
+                                       const gchar *uid)
+{
+       g_return_if_fail (instance != NULL);
+       g_return_if_fail (uid != NULL);
+
+       if (g_strcmp0 (instance->uid, uid) != 0) {
+               g_free (instance->uid);
+               instance->uid = g_strdup (uid);
+       }
+}
+
+/**
+ * e_cal_component_alarm_instance_get_time:
+ * @instance: an #ECalComponentAlarmInstance
+ *
+ * Returns: alarm instance time, i.e. "5 minutes before the appointment"
+ *
+ * Since: 3.36
+ **/
+time_t
+e_cal_component_alarm_instance_get_time (const ECalComponentAlarmInstance *instance)
+{
+       g_return_val_if_fail (instance != NULL, (time_t) 0);
+
+       return instance->instance_time;
+}
+
+/**
+ * e_cal_component_alarm_instance_set_time:
+ * @instance: an ECalComponentAlarmInstance
+ * @instance_time: instance time to set
+ *
+ * Set the instance time, i.e. "5 minutes before the appointment".
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_instance_set_time (ECalComponentAlarmInstance *instance,
+                                        time_t instance_time)
+{
+       g_return_if_fail (instance != NULL);
+
+       if (instance->instance_time != instance_time) {
+               instance->instance_time = instance_time;
+       }
+}
+
+/**
+ * e_cal_component_alarm_instance_get_occur_start:
+ * @instance: an #ECalComponentAlarmInstance
+ *
+ * Returns: actual event occurrence start to which this @instance corresponds
+ *
+ * Since: 3.36
+ **/
+time_t
+e_cal_component_alarm_instance_get_occur_start (const ECalComponentAlarmInstance *instance)
+{
+       g_return_val_if_fail (instance != NULL, (time_t) 0);
+
+       return instance->occur_start;
+}
+
+/**
+ * e_cal_component_alarm_instance_set_occur_start:
+ * @instance: an ECalComponentAlarmInstance
+ * @occur_start: event occurence start to set
+ *
+ * Set the actual event occurrence start to which this @instance corresponds.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_instance_set_occur_start (ECalComponentAlarmInstance *instance,
+                                               time_t occur_start)
+{
+       g_return_if_fail (instance != NULL);
+
+       if (instance->occur_start != occur_start) {
+               instance->occur_start = occur_start;
+       }
+}
+
+/**
+ * e_cal_component_alarm_instance_get_occur_end:
+ * @instance: an #ECalComponentAlarmInstance
+ *
+ * Returns: actual event occurrence end to which this @instance corresponds
+ *
+ * Since: 3.36
+ **/
+time_t
+e_cal_component_alarm_instance_get_occur_end (const ECalComponentAlarmInstance *instance)
+{
+       g_return_val_if_fail (instance != NULL, (time_t) 0);
+
+       return instance->occur_end;
+}
+
+/**
+ * e_cal_component_alarm_instance_set_occur_end:
+ * @instance: an ECalComponentAlarmInstance
+ * @occur_end: event occurence end to set
+ *
+ * Set the actual event occurrence end to which this @instance corresponds.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_instance_set_occur_end (ECalComponentAlarmInstance *instance,
+                                             time_t occur_end)
+{
+       g_return_if_fail (instance != NULL);
+
+       if (instance->occur_end != occur_end) {
+               instance->occur_end = occur_end;
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-alarm-instance.h 
b/src/calendar/libecal/e-cal-component-alarm-instance.h
new file mode 100644
index 000000000..15fa56e8a
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm-instance.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ALARM_INSTANCE_H
+#define E_CAL_COMPONENT_ALARM_INSTANCE_H
+
+#include <glib-object.h>
+#include <time.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentAlarmInstance:
+ *
+ * Opaque structure, which represents an alarm occurrence, i.e. a instance instance.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentAlarmInstance ECalComponentAlarmInstance;
+
+GType          e_cal_component_alarm_instance_get_type
+                                               (void);
+ECalComponentAlarmInstance *
+               e_cal_component_alarm_instance_new
+                                               (const gchar *uid,
+                                                time_t instance_time,
+                                                time_t occur_start,
+                                                time_t occur_end);
+ECalComponentAlarmInstance *
+               e_cal_component_alarm_instance_copy
+                                               (const ECalComponentAlarmInstance *instance);
+void           e_cal_component_alarm_instance_free
+                                               (gpointer instance); /* ECalComponentAlarmInstance * */
+const gchar *  e_cal_component_alarm_instance_get_uid
+                                               (const ECalComponentAlarmInstance *instance);
+void           e_cal_component_alarm_instance_set_uid
+                                               (ECalComponentAlarmInstance *instance,
+                                                const gchar *uid);
+time_t         e_cal_component_alarm_instance_get_time
+                                               (const ECalComponentAlarmInstance *instance);
+void           e_cal_component_alarm_instance_set_time
+                                               (ECalComponentAlarmInstance *instance,
+                                                time_t instance_time);
+time_t         e_cal_component_alarm_instance_get_occur_start
+                                               (const ECalComponentAlarmInstance *instance);
+void           e_cal_component_alarm_instance_set_occur_start
+                                               (ECalComponentAlarmInstance *instance,
+                                                time_t occur_start);
+time_t         e_cal_component_alarm_instance_get_occur_end
+                                               (const ECalComponentAlarmInstance *instance);
+void           e_cal_component_alarm_instance_set_occur_end
+                                               (ECalComponentAlarmInstance *instance,
+                                                time_t occur_end);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ALARM_INSTANCE_H */
diff --git a/src/calendar/libecal/e-cal-component-alarm-repeat.c 
b/src/calendar/libecal/e-cal-component-alarm-repeat.c
new file mode 100644
index 000000000..6c04c5e05
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm-repeat.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-alarm-repeat
+ * @short_description: An ECalComponentAlarmRepeat structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentAlarmRepeat structure.
+ **/
+
+#include "e-cal-component-alarm-repeat.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentAlarmRepeat, e_cal_component_alarm_repeat, 
e_cal_component_alarm_repeat_copy, e_cal_component_alarm_repeat_free)
+
+struct _ECalComponentAlarmRepeat {
+       gint repetitions;
+       ICalDuration *interval;
+};
+
+/**
+ * e_cal_component_alarm_repeat_new:
+ * @repetitions: number of extra repetitions, zero for none
+ * @interval: (not nullable): interval between repetitions
+ *
+ * Creates a new #ECalComponentAlarmRepeat describing alarm repetitions.
+ * The returned structure should be freed with e_cal_component_alarm_repeat_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarmRepeat
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmRepeat *
+e_cal_component_alarm_repeat_new (gint repetitions,
+                                 const ICalDuration *interval)
+{
+       g_return_val_if_fail (I_CAL_IS_DURATION (interval), NULL);
+
+       return e_cal_component_alarm_repeat_new_seconds (repetitions,
+               i_cal_duration_as_int ((ICalDuration *) interval));
+}
+
+/**
+ * e_cal_component_alarm_repeat_new_seconds:
+ * @repetitions: number of extra repetitions, zero for none
+ * @interval_seconds: interval between repetitions, in seconds
+ *
+ * Creates a new #ECalComponentAlarmRepeat describing alarm repetitions.
+ * The returned structure should be freed with e_cal_component_alarm_repeat_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarmRepeat
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmRepeat *
+e_cal_component_alarm_repeat_new_seconds (gint repetitions,
+                                         gint interval_seconds)
+{
+       ECalComponentAlarmRepeat *repeat;
+
+       repeat = g_new0 (ECalComponentAlarmRepeat, 1);
+       repeat->repetitions = repetitions;
+       repeat->interval = i_cal_duration_from_int (interval_seconds);
+
+       return repeat;
+}
+
+/**
+ * e_cal_component_alarm_repeat_copy:
+ * @repeat: (not nullable): an #ECalComponentAlarmRepeat to copy
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarmRepeat, copy of @repeat.
+ *    The returned structure should be freed with e_cal_component_alarm_repeat_free(),
+ *    when no longer needed.
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmRepeat *
+e_cal_component_alarm_repeat_copy (const ECalComponentAlarmRepeat *repeat)
+{
+       g_return_val_if_fail (repeat != NULL, NULL);
+
+       return e_cal_component_alarm_repeat_new_seconds (repeat->repetitions,
+               i_cal_duration_as_int (repeat->interval));
+}
+
+/**
+ * e_cal_component_alarm_repeat_free: (skip)
+ * @repeat: (type ECalComponentAlarmRepeat) (nullable): an #ECalComponentAlarmRepeat to free
+ *
+ * Free the @repeat, previously allocated by e_cal_component_alarm_repeat_new(),
+ * e_cal_component_alarm_repeat_new_seconds() or e_cal_component_alarm_repeat_copy().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_repeat_free (gpointer repeat)
+{
+       ECalComponentAlarmRepeat *rpt = repeat;
+
+       if (rpt) {
+               g_clear_object (&rpt->interval);
+               g_free (rpt);
+       }
+}
+
+/**
+ * e_cal_component_alarm_repeat_get_repetitions:
+ * @repeat: an #ECalComponentAlarmRepeat
+ *
+ * Returns: the repetitions count of the @repeat
+ *
+ * Since: 3.36
+ **/
+gint
+e_cal_component_alarm_repeat_get_repetitions (const ECalComponentAlarmRepeat *repeat)
+{
+       g_return_val_if_fail (repeat != NULL, 0);
+
+       return repeat->repetitions;
+}
+
+/**
+ * e_cal_component_alarm_repeat_set_repetitions:
+ * @repeat: an #ECalComponentAlarmRepeat
+ * @repetitions: number of repetitions, zero for none
+ *
+ * Set the @repetitions count of the @repeat.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_repeat_set_repetitions (ECalComponentAlarmRepeat *repeat,
+                                             gint repetitions)
+{
+       g_return_if_fail (repeat != NULL);
+
+       if (repeat->repetitions != repetitions) {
+               repeat->repetitions = repetitions;
+       }
+}
+
+/**
+ * e_cal_component_alarm_repeat_get_interval:
+ * @repeat: an #ECalComponentAlarmRepeat
+ *
+ * Returns the interval between repetitions of the @repeat, as an #ICalDuration
+ * object. This object is owned by @repeat and should not be freed. It's valid until
+ * the @repeat is not freed or its interval changed with either e_cal_component_alarm_repeat_set_interval()
+ * or e_cal_component_alarm_repeat_set_interval_seconds().
+ *
+ * Returns: (transfer none): the interval between repetitions of the @repeat
+ *
+ * Since: 3.36
+ **/
+ICalDuration *
+e_cal_component_alarm_repeat_get_interval (const ECalComponentAlarmRepeat *repeat)
+{
+       g_return_val_if_fail (repeat != NULL, NULL);
+
+       return repeat->interval;
+}
+
+/**
+ * e_cal_component_alarm_repeat_set_interval:
+ * @repeat: an #ECalComponentAlarmRepeat
+ * @interval: (not nullable): interval between repetitions, as an #ICalDuration
+ *
+ * Set the @interval between repetitions of the @repeat.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_repeat_set_interval (ECalComponentAlarmRepeat *repeat,
+                                          const ICalDuration *interval)
+{
+       g_return_if_fail (repeat != NULL);
+       g_return_if_fail (interval != NULL);
+
+       if (repeat->interval != interval) {
+               e_cal_component_alarm_repeat_set_interval_seconds (repeat,
+                       i_cal_duration_as_int ((ICalDuration *) interval));
+       }
+}
+
+/**
+ * e_cal_component_alarm_repeat_get_interval_seconds:
+ * @repeat: an #ECalComponentAlarmRepeat
+ *
+ * Returns the interval between repetitions of the @repeat in seconds.
+ *
+ * Returns: the interval between repetitions of the @repeat
+ *
+ * Since: 3.36
+ **/
+gint
+e_cal_component_alarm_repeat_get_interval_seconds (const ECalComponentAlarmRepeat *repeat)
+{
+       g_return_val_if_fail (repeat != NULL, 0);
+
+       return i_cal_duration_as_int (repeat->interval);
+}
+
+/**
+ * e_cal_component_alarm_repeat_set_interval_seconds:
+ * @repeat: an #ECalComponentAlarmRepeat
+ * @interval_seconds: interval between repetitions, in seconds
+ *
+ * Set the @interval_seconds between repetitions of the @repeat.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_repeat_set_interval_seconds (ECalComponentAlarmRepeat *repeat,
+                                                  gint interval_seconds)
+{
+       g_return_if_fail (repeat != NULL);
+
+       if (i_cal_duration_as_int (repeat->interval) != interval_seconds) {
+               g_clear_object (&repeat->interval);
+               repeat->interval = i_cal_duration_from_int (interval_seconds);
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-alarm-repeat.h 
b/src/calendar/libecal/e-cal-component-alarm-repeat.h
new file mode 100644
index 000000000..8ce892795
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm-repeat.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ALARM_REPEAT_H
+#define E_CAL_COMPONENT_ALARM_REPEAT_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentAlarmRepeat:
+ *
+ * A structure holding whether and how an alarm repeats.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentAlarmRepeat ECalComponentAlarmRepeat;
+
+GType          e_cal_component_alarm_repeat_get_type
+                                               (void);
+ECalComponentAlarmRepeat *
+               e_cal_component_alarm_repeat_new(gint repetitions,
+                                                const ICalDuration *interval);
+ECalComponentAlarmRepeat *
+               e_cal_component_alarm_repeat_new_seconds
+                                               (gint repetitions,
+                                                gint interval_seconds);
+ECalComponentAlarmRepeat *
+               e_cal_component_alarm_repeat_copy
+                                               (const ECalComponentAlarmRepeat *repeat);
+void           e_cal_component_alarm_repeat_free
+                                               (gpointer repeat); /* ECalComponentAlarmRepeat * */
+gint           e_cal_component_alarm_repeat_get_repetitions
+                                               (const ECalComponentAlarmRepeat *repeat);
+void           e_cal_component_alarm_repeat_set_repetitions
+                                               (ECalComponentAlarmRepeat *repeat,
+                                                gint repetitions);
+ICalDuration * e_cal_component_alarm_repeat_get_interval
+                                               (const ECalComponentAlarmRepeat *repeat);
+void           e_cal_component_alarm_repeat_set_interval
+                                               (ECalComponentAlarmRepeat *repeat,
+                                                const ICalDuration *interval);
+gint           e_cal_component_alarm_repeat_get_interval_seconds
+                                               (const ECalComponentAlarmRepeat *repeat);
+void           e_cal_component_alarm_repeat_set_interval_seconds
+                                               (ECalComponentAlarmRepeat *repeat,
+                                                gint interval_seconds);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ALARM_REPEAT_H */
diff --git a/src/calendar/libecal/e-cal-component-alarm-trigger.c 
b/src/calendar/libecal/e-cal-component-alarm-trigger.c
new file mode 100644
index 000000000..372bca94f
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm-trigger.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-alarm-trigger
+ * @short_description: An ECalComponentAlarmTrigger structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentAlarmTrigger structure.
+ **/
+
+#include "e-cal-component-parameter-bag.h"
+
+#include "e-cal-component-alarm-trigger.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentAlarmTrigger, e_cal_component_alarm_trigger, 
e_cal_component_alarm_trigger_copy, e_cal_component_alarm_trigger_free)
+
+struct _ECalComponentAlarmTrigger {
+       ECalComponentAlarmTriggerKind kind;
+
+       /* Only one of the below can be set, depending on the 'kind' */
+       ICalDuration *rel_duration;
+       ICalTime *abs_time;
+
+       ECalComponentParameterBag *parameter_bag;
+};
+
+/**
+ * e_cal_component_alarm_trigger_new_relative:
+ * @kind: an #ECalComponentAlarmTriggerKind, any but the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE
+ * @duration: (not nullable): the duration relative to @kind, as an #ICalDuration
+ *
+ * Creates a new #ECalComponentAlarmTrigger structure, set with the given @kind
+ * and @duration. The @kind can be any but the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE.
+ * To create an absolute trigger use e_cal_component_alarm_trigger_new_absolute().
+ * Free the trigger with e_cal_component_alarm_trigger_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarmTrigger
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTrigger *
+e_cal_component_alarm_trigger_new_relative (ECalComponentAlarmTriggerKind kind,
+                                           const ICalDuration *duration)
+{
+       ECalComponentAlarmTrigger *trigger;
+
+       g_return_val_if_fail (kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE, NULL);
+       g_return_val_if_fail (I_CAL_IS_DURATION (duration), NULL);
+
+       trigger = g_new0 (ECalComponentAlarmTrigger, 1);
+       trigger->parameter_bag = e_cal_component_parameter_bag_new ();
+
+       e_cal_component_alarm_trigger_set_relative (trigger, kind, duration);
+
+       return trigger;
+}
+
+/**
+ * e_cal_component_alarm_trigger_new_absolute:
+ * @absolute_time: (not nullable): the absolute time when to trigger the alarm, as an #ICalTime
+ *
+ * Creates a new #ECalComponentAlarmTrigger structure, set with
+ * the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE kind and the @absolute_time as
+ * the time of the trigger. The @absolute_time should be date/time (not date) in UTC.
+ *
+ * To create a relative trigger use e_cal_component_alarm_trigger_new_relative().
+ * Free the trigger with e_cal_component_alarm_trigger_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarmTrigger
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTrigger *
+e_cal_component_alarm_trigger_new_absolute (const ICalTime *absolute_time)
+{
+       ECalComponentAlarmTrigger *trigger;
+
+       g_return_val_if_fail (I_CAL_IS_TIME (absolute_time), NULL);
+
+       trigger = g_new0 (ECalComponentAlarmTrigger, 1);
+       trigger->parameter_bag = e_cal_component_parameter_bag_new ();
+
+       e_cal_component_alarm_trigger_set_absolute (trigger, absolute_time);
+
+       return trigger;
+}
+
+/**
+ * e_cal_component_alarm_trigger_new_from_property:
+ * @property: an #ICalProperty of kind %I_CAL_TRIGGER_PROPERTY
+ *
+ * Creates a new #ECalComponentAlarmTrigger, filled with values from @property,
+ * which should be of kind %I_CAL_TRIGGER_PROPERTY. The function returns
+ * %NULL when it is not of the expected kind. Free the structure
+ * with e_cal_component_alarm_trigger_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly allocated #ECalComponentAlarmTrigger
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTrigger *
+e_cal_component_alarm_trigger_new_from_property (const ICalProperty *property)
+{
+       ECalComponentAlarmTrigger *trigger;
+
+       g_return_val_if_fail (I_CAL_IS_PROPERTY (property), NULL);
+
+       if (i_cal_property_isa ((ICalProperty *) property) != I_CAL_TRIGGER_PROPERTY)
+               return NULL;
+
+       trigger = g_new0 (ECalComponentAlarmTrigger, 1);
+       trigger->parameter_bag = e_cal_component_parameter_bag_new ();
+
+       e_cal_component_alarm_trigger_set_from_property (trigger, property);
+
+       return trigger;
+}
+
+/**
+ * e_cal_component_alarm_trigger_copy:
+ * @trigger: (not nullable): an #ECalComponentAlarmTrigger
+ *
+ * Returns a newly allocated copy of @trigger, which should be freed with
+ * e_cal_component_alarm_trigger_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @trigger
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTrigger *
+e_cal_component_alarm_trigger_copy (const ECalComponentAlarmTrigger *trigger)
+{
+       ECalComponentAlarmTrigger *copy;
+
+       g_return_val_if_fail (trigger != NULL, NULL);
+
+       if (trigger->kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE)
+               copy = e_cal_component_alarm_trigger_new_absolute (trigger->abs_time);
+       else
+               copy = e_cal_component_alarm_trigger_new_relative (trigger->kind, trigger->rel_duration);
+
+       e_cal_component_parameter_bag_assign (copy->parameter_bag, trigger->parameter_bag);
+
+       return copy;
+}
+
+/**
+ * e_cal_component_alarm_trigger_free: (skip)
+ * @trigger: (type ECalComponentAlarmTrigger) (nullable): an #ECalComponentAlarmTrigger to free
+ *
+ * Free @trigger, previously created by e_cal_component_alarm_trigger_new_relative(),
+ * e_cal_component_alarm_trigger_new_absolute(), e_cal_component_alarm_trigger_new_from_property()
+ * or e_cal_component_alarm_trigger_copy(). The function does nothing, if @trigger
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_free (gpointer trigger)
+{
+       ECalComponentAlarmTrigger *trg = trigger;
+
+       if (trg) {
+               e_cal_component_parameter_bag_free (trg->parameter_bag);
+               g_clear_object (&trg->rel_duration);
+               g_clear_object (&trg->abs_time);
+               g_free (trg);
+       }
+}
+
+static gboolean
+e_cal_component_alarm_trigger_bag_filter_params_cb (ICalParameter *param,
+                                                   gpointer user_data)
+{
+       ICalParameterKind kind;
+
+       kind = i_cal_parameter_isa (param);
+
+       return kind != I_CAL_VALUE_PARAMETER &&
+              kind != I_CAL_RELATED_PARAMETER;
+}
+
+/**
+ * e_cal_component_alarm_trigger_set_from_property:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @property: an #ICalProperty
+ *
+ * Fill the @trigger structure with the information from
+ * the @property, which should be of %I_CAL_TRIGGER_PROPERTY kind.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_set_from_property (ECalComponentAlarmTrigger *trigger,
+                                                const ICalProperty *property)
+{
+       ICalProperty *prop = (ICalProperty *) property;
+       ICalParameter *param;
+       ICalTrigger *trg;
+       gboolean relative;
+
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+       g_return_if_fail (i_cal_property_isa (prop) == I_CAL_TRIGGER_PROPERTY);
+
+       g_clear_object (&trigger->rel_duration);
+       g_clear_object (&trigger->abs_time);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_VALUE_PARAMETER);
+       if (param) {
+               switch (i_cal_parameter_get_value (param)) {
+               case I_CAL_VALUE_DURATION:
+                       relative = TRUE;
+                       break;
+
+               case I_CAL_VALUE_DATETIME:
+                       relative = FALSE;
+                       break;
+
+               default:
+                       relative = TRUE;
+                       break;
+               }
+
+               g_clear_object (&param);
+       } else {
+               relative = TRUE;
+       }
+
+       trg = i_cal_property_get_trigger (prop);
+
+       if (relative) {
+               ECalComponentAlarmTriggerKind kind;
+               ICalDuration *duration;
+               ICalParameter *param;
+
+               param = i_cal_property_get_first_parameter (prop, I_CAL_RELATED_PARAMETER);
+               if (param) {
+                       switch (i_cal_parameter_get_related (param)) {
+                       case I_CAL_RELATED_START:
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
+                               break;
+
+                       case ICAL_RELATED_END:
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END;
+                               break;
+
+                       default:
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_NONE;
+                               break;
+                       }
+               } else {
+                       kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
+               }
+
+               duration = i_cal_trigger_get_duration (trg);
+
+               e_cal_component_alarm_trigger_set_relative (trigger, kind, duration);
+
+               g_clear_object (&duration);
+               g_clear_object (&param);
+       } else {
+               ICalTime *abs_time;
+
+               abs_time = i_cal_trigger_get_time (trg);
+               e_cal_component_alarm_trigger_set_absolute (trigger, abs_time);
+               g_clear_object (&abs_time);
+       }
+
+       g_clear_object (&trg);
+
+       e_cal_component_parameter_bag_set_from_property (trigger->parameter_bag, prop, 
e_cal_component_alarm_trigger_bag_filter_params_cb, NULL);
+}
+
+/**
+ * e_cal_component_alarm_trigger_get_as_property:
+ * @trigger: an #ECalComponentAlarmTrigger
+ *
+ * Converts information stored in @trigger into an #ICalProperty
+ * of %I_CAL_TRIGGER_PROPERTY kind. The caller is responsible to free
+ * the returned object with g_object_unref(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly created #ICalProperty, containing
+ *    information from the @trigger.
+ *
+ * Since: 3.36
+ **/
+ICalProperty *
+e_cal_component_alarm_trigger_get_as_property (const ECalComponentAlarmTrigger *trigger)
+{
+       ICalProperty *prop;
+
+       g_return_val_if_fail (trigger != NULL, NULL);
+
+       prop = i_cal_property_new (I_CAL_TRIGGER_PROPERTY);
+       g_return_val_if_fail (prop != NULL, NULL);
+
+       e_cal_component_alarm_trigger_fill_property (trigger, prop);
+
+       return prop;
+}
+
+/**
+ * e_cal_component_alarm_trigger_fill_property:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @property: (inout) (not nullable): an #ICalProperty
+ *
+ * Fill @property with information from @trigger. The @property
+ * should be of kind %I_CAL_TRIGGER_PROPERTY.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_fill_property (const ECalComponentAlarmTrigger *trigger,
+                                            ICalProperty *property)
+{
+       ICalParameter *param;
+       ICalParameterValue value_type = I_CAL_VALUE_DATETIME;
+       ICalParameterRelated related;
+       ICalTrigger *trg;
+
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+       g_return_if_fail (i_cal_property_isa (property) == I_CAL_TRIGGER_PROPERTY);
+
+       related = I_CAL_RELATED_START;
+       trg = i_cal_trigger_from_int (0);
+
+       switch (trigger->kind) {
+       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
+               i_cal_trigger_set_duration (trg, trigger->rel_duration);
+               value_type = I_CAL_VALUE_DURATION;
+               related = I_CAL_RELATED_START;
+               break;
+
+       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
+               i_cal_trigger_set_duration (trg, trigger->rel_duration);
+               value_type = I_CAL_VALUE_DURATION;
+               related = I_CAL_RELATED_END;
+               break;
+
+       case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
+               i_cal_trigger_set_time (trg, trigger->abs_time);
+               value_type = I_CAL_VALUE_DATETIME;
+               break;
+
+       case E_CAL_COMPONENT_ALARM_TRIGGER_NONE:
+               g_object_unref (trg);
+               return;
+       }
+
+       i_cal_property_set_trigger (property, trg);
+
+       g_object_unref (trg);
+
+       param = i_cal_property_get_first_parameter (property, I_CAL_VALUE_PARAMETER);
+       if (param) {
+               i_cal_parameter_set_value (param, value_type);
+       } else {
+               param = i_cal_parameter_new_value (value_type);
+               i_cal_property_set_parameter (property, param);
+       }
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (property, I_CAL_RELATED_PARAMETER);
+       if (trigger->kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+               if (param) {
+                       i_cal_parameter_set_related (param, related);
+               } else {
+                       param = i_cal_parameter_new_related (related);
+                       i_cal_property_add_parameter (property, param);
+               }
+       } else if (param) {
+               i_cal_property_remove_parameter_by_kind (property, I_CAL_RELATED_PARAMETER);
+       }
+       g_clear_object (&param);
+
+       e_cal_component_parameter_bag_fill_property (trigger->parameter_bag, property);
+}
+
+/**
+ * e_cal_component_alarm_trigger_set_relative:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @kind: an #ECalComponentAlarmTriggerKind, any but the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE
+ * @duration: (not nullable): the duration relative to @kind, as an #ICalDuration
+ *
+ * Set the @trigegr with the given @kind and @duration. The @kind can be any but
+ * the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE.
+ * To set an absolute trigger use e_cal_component_alarm_trigger_set_absolute().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_set_relative (ECalComponentAlarmTrigger *trigger,
+                                           ECalComponentAlarmTriggerKind kind,
+                                           const ICalDuration *duration)
+{
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE);
+       g_return_if_fail (I_CAL_IS_DURATION (duration));
+
+       g_clear_object (&trigger->rel_duration);
+       g_clear_object (&trigger->abs_time);
+
+       trigger->kind = kind;
+       trigger->rel_duration = i_cal_duration_from_int (
+               i_cal_duration_as_int ((ICalDuration *) duration));
+}
+
+/**
+ * e_cal_component_alarm_trigger_set_absolute:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @absolute_time: (not nullable): the absolute time when to trigger the alarm, as an #ICalTime
+ *
+ * Set the @trigegr with the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE kind and
+ * the @absolute_time as the time of the trigger. The @absolute_time
+ * should be date/time (not date) in UTC.
+ *
+ * To set a relative trigger use e_cal_component_alarm_trigger_set_relative().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_set_absolute (ECalComponentAlarmTrigger *trigger,
+                                           const ICalTime *absolute_time)
+{
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (absolute_time));
+
+       g_clear_object (&trigger->rel_duration);
+       g_clear_object (&trigger->abs_time);
+
+       trigger->kind = E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE;
+       trigger->abs_time = i_cal_time_new_clone (absolute_time);
+}
+
+/**
+ * e_cal_component_alarm_trigger_get_kind:
+ * @trigger: an #ECalComponentAlarmTrigger
+ *
+ * Returns: the @trigger kind, one of #ECalComponentAlarmTriggerKind
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTriggerKind
+e_cal_component_alarm_trigger_get_kind (const ECalComponentAlarmTrigger *trigger)
+{
+       g_return_val_if_fail (trigger != NULL, E_CAL_COMPONENT_ALARM_TRIGGER_NONE);
+
+       return trigger->kind;
+}
+
+/**
+ * e_cal_component_alarm_trigger_set_kind:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @kind: the kind to set, one of #ECalComponentAlarmTriggerKind
+ *
+ * Set the @trigger kind to @kind. This works only for other than
+ * the %E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE. To change the kind
+ * from absolute to relative, or vice versa, use either
+ * e_cal_component_alarm_trigger_set_relative() or
+ * e_cal_component_alarm_trigger_set_absolute().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_set_kind (ECalComponentAlarmTrigger *trigger,
+                                       ECalComponentAlarmTriggerKind kind)
+{
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (trigger->kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE);
+       g_return_if_fail (kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE);
+
+       if (trigger->kind != kind) {
+               trigger->kind = kind;
+       }
+}
+
+/**
+ * e_cal_component_alarm_trigger_get_duration:
+ * @trigger: an #ECalComponentAlarmTrigger
+ *
+ * Returns the @trigger duration for a relative @trigger, or %NULL, when
+ * the @trigger is an absolute trigger.
+ *
+ * Returns: (transfer none) (nullable): the @trigger duration, as an #ICalDuration, or %NULL
+ *
+ * Since: 3.36
+ **/
+ICalDuration *
+e_cal_component_alarm_trigger_get_duration (const ECalComponentAlarmTrigger *trigger)
+{
+       g_return_val_if_fail (trigger != NULL, NULL);
+
+       if (trigger->kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE)
+               return NULL;
+
+       return trigger->rel_duration;
+}
+
+/**
+ * e_cal_component_alarm_trigger_set_duration:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @duration: duration for a relative trigger, as an #ICalDuration
+ *
+ * Sets the @trigger duration for a relative trigger. The function does nothing, when
+ * the @trigger is an absolute trigger. The object is owned by @trigger and it's
+ * valid until the @trigger is freed or its relative duration changed.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_set_duration (ECalComponentAlarmTrigger *trigger,
+                                           const ICalDuration *duration)
+{
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (I_CAL_IS_DURATION (duration));
+
+       if (trigger->kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE)
+               return;
+
+       if (trigger->rel_duration != duration &&
+           i_cal_duration_as_int (trigger->rel_duration) != i_cal_duration_as_int ((ICalDuration *) 
duration)) {
+               g_clear_object (&trigger->rel_duration);
+               trigger->rel_duration = i_cal_duration_from_int (
+                       i_cal_duration_as_int ((ICalDuration *) duration));
+       }
+}
+
+/**
+ * e_cal_component_alarm_trigger_get_absolute_time:
+ * @trigger: an #ECalComponentAlarmTrigger
+ *
+ * Returns the @trigger absolute time for an absolute trigger, or %NULL, when
+ * the @trigger is a relative trigger. The object is owned by @trigger and it's
+ * valid until the @trigger is freed or its absolute time changed.
+ *
+ * Returns: (transfer none) (nullable): the @trigger absolute time, as an #ICalTime, or %NULL
+ *
+ * Since: 3.36
+ **/
+ICalTime *
+e_cal_component_alarm_trigger_get_absolute_time (const ECalComponentAlarmTrigger *trigger)
+{
+       g_return_val_if_fail (trigger != NULL, NULL);
+
+       if (trigger->kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE)
+               return NULL;
+
+       return trigger->abs_time;
+}
+
+/**
+ * e_cal_component_alarm_trigger_set_absolute_time:
+ * @trigger: an #ECalComponentAlarmTrigger
+ * @absolute_time: absolute time for an absolute trigger, as an #ICalTime
+ *
+ * Sets the @trigger absolute time for an absolute trigger. The @absolute_time
+ * should be date/time (not date) in UTC.
+ *
+ * The function does nothing, when the @trigger is a relative trigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_trigger_set_absolute_time (ECalComponentAlarmTrigger *trigger,
+                                                const ICalTime *absolute_time)
+{
+       g_return_if_fail (trigger != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (absolute_time));
+
+       if (trigger->kind != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE)
+               return;
+
+       if (trigger->abs_time != absolute_time) {
+               g_clear_object (&trigger->abs_time);
+               trigger->abs_time = i_cal_time_new_clone ((ICalTime *) absolute_time);
+       }
+}
+
+/**
+ * e_cal_component_alarm_trigger_get_parameter_bag:
+ * @trigger: an #ECalComponentAlarmTrigger
+ *
+ * Returns: (transfer none): an #ECalComponentParameterBag with additional
+ *    parameters stored with the trigger property, other than those accessible
+ *    with the other functions of the @trigger.
+ *
+ * Since: 3.36
+ **/
+ECalComponentParameterBag *
+e_cal_component_alarm_trigger_get_parameter_bag (const ECalComponentAlarmTrigger *trigger)
+{
+       g_return_val_if_fail (trigger != NULL, NULL);
+
+       return trigger->parameter_bag;
+}
diff --git a/src/calendar/libecal/e-cal-component-alarm-trigger.h 
b/src/calendar/libecal/e-cal-component-alarm-trigger.h
new file mode 100644
index 000000000..552611fb4
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm-trigger.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ALARM_TRIGGER_H
+#define E_CAL_COMPONENT_ALARM_TRIGGER_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+#include <libecal/e-cal-component-parameter-bag.h>
+#include <libecal/e-cal-enums.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentAlarmTrigger:
+ *
+ * Opaque structure, which represents when an alarm is supposed to be triggered.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentAlarmTrigger ECalComponentAlarmTrigger;
+
+GType          e_cal_component_alarm_trigger_get_type
+                                               (void);
+ECalComponentAlarmTrigger *
+               e_cal_component_alarm_trigger_new_relative
+                                               (ECalComponentAlarmTriggerKind kind,
+                                                const ICalDuration *duration);
+ECalComponentAlarmTrigger *
+               e_cal_component_alarm_trigger_new_absolute
+                                               (const ICalTime *absolute_time);
+ECalComponentAlarmTrigger *
+               e_cal_component_alarm_trigger_new_from_property
+                                               (const ICalProperty *property);
+ECalComponentAlarmTrigger *
+               e_cal_component_alarm_trigger_copy
+                                               (const ECalComponentAlarmTrigger *trigger);
+void           e_cal_component_alarm_trigger_free
+                                               (gpointer trigger); /* ECalComponentAlarmTrigger * */
+void           e_cal_component_alarm_trigger_set_from_property
+                                               (ECalComponentAlarmTrigger *trigger,
+                                                const ICalProperty *property);
+ICalProperty * e_cal_component_alarm_trigger_get_as_property
+                                               (const ECalComponentAlarmTrigger *trigger);
+void           e_cal_component_alarm_trigger_fill_property
+                                               (const ECalComponentAlarmTrigger *trigger,
+                                                ICalProperty *property);
+void           e_cal_component_alarm_trigger_set_relative
+                                               (ECalComponentAlarmTrigger *trigger,
+                                                ECalComponentAlarmTriggerKind kind,
+                                                const ICalDuration *duration);
+void           e_cal_component_alarm_trigger_set_absolute
+                                               (ECalComponentAlarmTrigger *trigger,
+                                                const ICalTime *absolute_time);
+ECalComponentAlarmTriggerKind
+               e_cal_component_alarm_trigger_get_kind
+                                               (const ECalComponentAlarmTrigger *trigger);
+void           e_cal_component_alarm_trigger_set_kind
+                                               (ECalComponentAlarmTrigger *trigger,
+                                                ECalComponentAlarmTriggerKind kind);
+ICalDuration * e_cal_component_alarm_trigger_get_duration
+                                               (const ECalComponentAlarmTrigger *trigger);
+void           e_cal_component_alarm_trigger_set_duration
+                                               (ECalComponentAlarmTrigger *trigger,
+                                                const ICalDuration *duration);
+ICalTime *     e_cal_component_alarm_trigger_get_absolute_time
+                                               (const ECalComponentAlarmTrigger *trigger);
+void           e_cal_component_alarm_trigger_set_absolute_time
+                                               (ECalComponentAlarmTrigger *trigger,
+                                                const ICalTime *absolute_time);
+ECalComponentParameterBag *
+               e_cal_component_alarm_trigger_get_parameter_bag
+                                               (const ECalComponentAlarmTrigger *trigger);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ALARM_TRIGGER_H */
diff --git a/src/calendar/libecal/e-cal-component-alarm.c b/src/calendar/libecal/e-cal-component-alarm.c
new file mode 100644
index 000000000..3cd875535
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm.c
@@ -0,0 +1,1121 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-alarm
+ * @short_description: An ECalComponentAlarm structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentAlarm structure.
+ **/
+
+#include <libedataserver/libedataserver.h>
+
+#include "e-cal-component-alarm-repeat.h"
+#include "e-cal-component-alarm-trigger.h"
+#include "e-cal-component-attendee.h"
+#include "e-cal-component-property-bag.h"
+#include "e-cal-component-text.h"
+#include "e-cal-enums.h"
+
+#include "e-cal-component-alarm.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentAlarm, e_cal_component_alarm, e_cal_component_alarm_copy, 
e_cal_component_alarm_free)
+
+struct _ECalComponentAlarm {
+       gchar *uid;
+       ECalComponentAlarmAction action;
+       ECalComponentText *summary;
+       ECalComponentText *description;
+       ECalComponentAlarmRepeat *repeat;
+       ECalComponentAlarmTrigger *trigger;
+       GSList *attendees; /* ECalComponentAttendee * */
+       GSList *attachments; /* ICalAttach * */
+       ECalComponentPropertyBag *property_bag;
+};
+
+/**
+ * e_cal_component_alarm_new:
+ *
+ * Creates a new empty #ECalComponentAlarm structure. Free it
+ * with e_cal_component_alarm_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarm
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarm *
+e_cal_component_alarm_new (void)
+{
+       ECalComponentAlarm *alarm;
+
+       alarm = g_new0 (ECalComponentAlarm, 1);
+       alarm->uid = e_util_generate_uid ();
+       alarm->action = E_CAL_COMPONENT_ALARM_UNKNOWN;
+       alarm->property_bag = e_cal_component_property_bag_new ();
+
+       return alarm;
+}
+
+/**
+ * e_cal_component_alarm_new_from_component:
+ * @component: an #ICalComponent of kind %I_CAL_VALARM_COMPONENT
+ *
+ * Creates a new #ECalComponentAlarm, filled with values from @component,
+ * which should be of kind %I_CAL_VALARM_COMPONENT. The function returns
+ * %NULL when it is not of the expected kind. Free the structure
+ * with e_cal_component_alarm_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly allocated #ECalComponentAlarm
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarm *
+e_cal_component_alarm_new_from_component (const ICalComponent *component)
+{
+       ECalComponentAlarm *alarm;
+
+       g_return_val_if_fail (I_CAL_IS_COMPONENT (component), NULL);
+
+       if (i_cal_component_isa ((ICalComponent *) component) != I_CAL_VALARM_COMPONENT)
+               return NULL;
+
+       alarm = e_cal_component_alarm_new ();
+
+       e_cal_component_alarm_set_from_component (alarm, component);
+
+       return alarm;
+}
+
+/**
+ * e_cal_component_alarm_copy:
+ * @alarm: (not nullable): an #ECalComponentAlarm
+ *
+ * Returns a newly allocated copy of @alarm, which should be freed with
+ * e_cal_component_alarm_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @alarm
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarm *
+e_cal_component_alarm_copy (const ECalComponentAlarm *alarm)
+{
+       ECalComponentAlarm *alrm;
+
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       alrm = e_cal_component_alarm_new ();
+
+       g_free (alrm->uid);
+       alrm->uid = g_strdup (alarm->uid);
+       alrm->action = alarm->action;
+
+       if (alarm->summary)
+               alrm->summary = e_cal_component_text_copy (alarm->summary);
+
+       if (alarm->description)
+               alrm->description = e_cal_component_text_copy (alarm->description);
+
+       if (alarm->repeat)
+               alrm->repeat = e_cal_component_alarm_repeat_copy (alarm->repeat);
+
+       if (alarm->trigger)
+               alrm->trigger = e_cal_component_alarm_trigger_copy (alarm->trigger);
+
+       if (alarm->attendees) {
+               GSList *link;
+
+               for (link = alarm->attendees; link; link = g_slist_next (link)) {
+                       ECalComponentAttendee *attendee = link->data;
+
+                       if (!attendee)
+                               continue;
+
+                       alrm->attendees = g_slist_prepend (alrm->attendees, e_cal_component_attendee_copy 
(attendee));
+               }
+
+               alrm->attendees = g_slist_reverse (alrm->attendees);
+       }
+
+       if (alarm->attachments) {
+               GSList *link;
+
+               for (link = alarm->attachments; link; link = g_slist_next (link)) {
+                       ICalAttach *src_attach = link->data, *attach = NULL;
+
+                       if (!src_attach)
+                               continue;
+
+                       if (i_cal_attach_get_is_url (src_attach)) {
+                               const gchar *url;
+
+                               url = i_cal_attach_get_url (src_attach);
+                               if (url)
+                                       attach = i_cal_attach_new_from_url (url);
+                       } else {
+                               const gchar *data;
+
+                               data = i_cal_attach_get_data (src_attach);
+                               if (data)
+                                       attach = i_cal_attach_new_from_data (data, NULL, NULL);
+                       }
+
+                       if (attach)
+                               alrm->attachments = g_slist_prepend (alrm->attachments, attach);
+               }
+
+               alrm->attachments = g_slist_reverse (alrm->attachments);
+       }
+
+       e_cal_component_property_bag_assign (alrm->property_bag, alarm->property_bag);
+
+       return alrm;
+}
+
+/**
+ * e_cal_component_alarm_free: (skip)
+ * @alarm: (type ECalComponentAlarm) (nullable): an #ECalComponentAlarm to free
+ *
+ * Free @alarm, previously created by e_cal_component_alarm_new(),
+ * e_cal_component_alarm_new_from_component()
+ * or e_cal_component_alarm_copy(). The function does nothing, if @alarm
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_free (gpointer alarm)
+{
+       ECalComponentAlarm *alrm = alarm;
+
+       if (alrm) {
+               g_free (alrm->uid);
+               e_cal_component_text_free (alrm->summary);
+               e_cal_component_text_free (alrm->description);
+               e_cal_component_alarm_repeat_free (alrm->repeat);
+               e_cal_component_alarm_trigger_free (alrm->trigger);
+               e_cal_component_property_bag_free (alrm->property_bag);
+               g_slist_free_full (alrm->attendees, e_cal_component_attendee_free);
+               g_slist_free_full (alrm->attachments, g_object_unref);
+               g_free (alrm);
+       }
+}
+
+/**
+ * e_cal_component_alarm_set_from_component:
+ * @alarm: an #ECalComponentAlarm
+ * @component: an #ICalComponent
+ *
+ * Fill the @alarm structure with the information from
+ * the @component, which should be of %I_CAL_VALARM_COMPONENT kind.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_from_component (ECalComponentAlarm *alarm,
+                                         const ICalComponent *component)
+{
+       ICalComponent *comp = (ICalComponent *) component;
+       ICalDuration *duration = NULL;
+       ICalProperty *prop, *repeat = NULL;
+
+       g_return_if_fail (alarm != NULL);
+       g_return_if_fail (I_CAL_IS_COMPONENT (component));
+       g_return_if_fail (i_cal_component_isa ((ICalComponent *) component) == I_CAL_VALARM_COMPONENT);
+
+       g_free (alarm->uid);
+       e_cal_component_text_free (alarm->summary);
+       e_cal_component_text_free (alarm->description);
+       e_cal_component_alarm_repeat_free (alarm->repeat);
+       e_cal_component_alarm_trigger_free (alarm->trigger);
+       g_slist_free_full (alarm->attendees, e_cal_component_attendee_free);
+       g_slist_free_full (alarm->attachments, g_object_unref);
+
+       alarm->uid = NULL;
+       alarm->action = E_CAL_COMPONENT_ALARM_NONE;
+       alarm->summary = NULL;
+       alarm->description = NULL;
+       alarm->repeat = NULL;
+       alarm->trigger = NULL;
+       alarm->attendees = NULL;
+       alarm->attachments = NULL;
+
+       e_cal_component_property_bag_clear (alarm->property_bag);
+
+       for (prop = i_cal_component_get_first_property (comp, I_CAL_ANY_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (comp, I_CAL_ANY_PROPERTY)) {
+               ECalComponentAttendee *attendee;
+               ICalAttach *attach;
+               const gchar *xname;
+
+               switch (i_cal_property_isa (prop)) {
+               case I_CAL_ACTION_PROPERTY:
+                       switch (i_cal_property_get_action (prop)) {
+                       case I_CAL_ACTION_AUDIO:
+                               alarm->action = E_CAL_COMPONENT_ALARM_AUDIO;
+                               break;
+
+                       case I_CAL_ACTION_DISPLAY:
+                               alarm->action = E_CAL_COMPONENT_ALARM_DISPLAY;
+                               break;
+
+                       case I_CAL_ACTION_EMAIL:
+                               alarm->action = E_CAL_COMPONENT_ALARM_EMAIL;
+                               break;
+
+                       case I_CAL_ACTION_PROCEDURE:
+                               alarm->action = E_CAL_COMPONENT_ALARM_PROCEDURE;
+                               break;
+
+                       case I_CAL_ACTION_NONE:
+                               alarm->action = E_CAL_COMPONENT_ALARM_NONE;
+                               break;
+
+                       default:
+                               alarm->action = E_CAL_COMPONENT_ALARM_UNKNOWN;
+                               break;
+                       }
+                       break;
+
+               case I_CAL_ATTACH_PROPERTY:
+                       attach = i_cal_property_get_attach (prop);
+                       if (attach)
+                               alarm->attachments = g_slist_prepend (alarm->attachments, attach);
+                       break;
+
+               case I_CAL_SUMMARY_PROPERTY:
+                       if (i_cal_property_get_summary (prop)) {
+                               ICalParameter *param;
+
+                               param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
+                               e_cal_component_alarm_take_summary (alarm,
+                                       e_cal_component_text_new (i_cal_property_get_summary (prop),
+                                       param ? i_cal_parameter_get_altrep (param) : NULL));
+                               g_clear_object (&param);
+                       }
+                       break;
+
+               case I_CAL_DESCRIPTION_PROPERTY:
+                       if (i_cal_property_get_description (prop)) {
+                               ICalParameter *param;
+
+                               param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
+                               e_cal_component_alarm_take_description (alarm,
+                                       e_cal_component_text_new (i_cal_property_get_description (prop),
+                                       param ? i_cal_parameter_get_altrep (param) : NULL));
+                               g_clear_object (&param);
+                       }
+                       break;
+
+               case I_CAL_DURATION_PROPERTY:
+                       g_clear_object (&duration);
+                       duration = i_cal_property_get_duration (prop);
+                       break;
+
+               case I_CAL_REPEAT_PROPERTY:
+                       g_clear_object (&repeat);
+                       repeat = g_object_ref (prop);
+                       break;
+
+               case I_CAL_TRIGGER_PROPERTY:
+                       alarm->trigger = e_cal_component_alarm_trigger_new_from_property (prop);
+                       break;
+
+               case I_CAL_ATTENDEE_PROPERTY:
+                       attendee = e_cal_component_attendee_new_from_property (prop);
+                       if (attendee)
+                               alarm->attendees = g_slist_prepend (alarm->attendees, attendee);
+                       break;
+
+               case I_CAL_X_PROPERTY:
+                       xname = i_cal_property_get_x_name (prop);
+                       if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
+                               g_free (alarm->uid);
+                               alarm->uid = g_strdup (i_cal_property_get_x (prop));
+                       } else {
+                               e_cal_component_property_bag_add (alarm->property_bag, prop);
+                       }
+                       break;
+
+               default:
+                       e_cal_component_property_bag_add (alarm->property_bag, prop);
+                       break;
+               }
+       }
+
+       alarm->attendees = g_slist_reverse (alarm->attendees);
+       alarm->attachments = g_slist_reverse (alarm->attachments);
+
+       if (duration && repeat) {
+               alarm->repeat = e_cal_component_alarm_repeat_new (
+                       i_cal_property_get_repeat (repeat),
+                       duration);
+       }
+
+       g_clear_object (&duration);
+       g_clear_object (&repeat);
+
+       /* Ensure mandatory property */
+       if (!alarm->uid)
+               alarm->uid = e_util_generate_uid ();
+}
+
+/**
+ * e_cal_component_alarm_get_as_component:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Creates a VALARM #ICalComponent filled with data from the @alarm.
+ * In case the @alarm doesn't have set 'uid', a new is assigned.
+ * Free the returned component with g_object_unref(), when no longer
+ * needed.
+ *
+ * Returns: (transfer full): a newly created #ICalComponent
+ *    of %I_CAL_VALARM_COMPONENT kind
+ *
+ * Since: 3.36
+ **/
+ICalComponent *
+e_cal_component_alarm_get_as_component (ECalComponentAlarm *alarm)
+{
+       ICalComponent *valarm;
+
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       valarm = i_cal_component_new_valarm ();
+
+       e_cal_component_alarm_fill_component (alarm, valarm);
+
+       return valarm;
+}
+
+/**
+ * e_cal_component_alarm_fill_component:
+ * @alarm: an #ECalComponentAlarm
+ * @component: an #ICalComponent of %I_CAL_VALARM_COMPONENT kind
+ *
+ * Fills @component with data from @alarm. The @component should
+ * be of %I_CAL_VALARM_COMPONENT kind - the function does nothing,
+ * if it's not. In case the @alarm doesn't have set 'uid', a new
+ * is assigned.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_fill_component (ECalComponentAlarm *alarm,
+                                     ICalComponent *component)
+{
+       ICalPropertyKind remove_props[] = {
+               I_CAL_ACTION_PROPERTY,
+               I_CAL_ATTACH_PROPERTY,
+               I_CAL_SUMMARY_PROPERTY,
+               I_CAL_DESCRIPTION_PROPERTY,
+               I_CAL_DURATION_PROPERTY,
+               I_CAL_REPEAT_PROPERTY,
+               I_CAL_TRIGGER_PROPERTY,
+               I_CAL_ATTENDEE_PROPERTY };
+       ICalProperty *prop;
+       GSList *link;
+       gint ii;
+
+       g_return_if_fail (alarm != NULL);
+       g_return_if_fail (I_CAL_IS_COMPONENT (component));
+
+       if (i_cal_component_isa (component) != I_CAL_VALARM_COMPONENT)
+               return;
+
+       /* Remove used properties first */
+
+       for (ii = 0; ii < G_N_ELEMENTS (remove_props); ii++) {
+               if (remove_props[ii] == I_CAL_ACTION_PROPERTY &&
+                   alarm->action == E_CAL_COMPONENT_ALARM_UNKNOWN)
+                       continue;
+
+               while (prop = i_cal_component_get_first_property (component, remove_props[ii]), prop) {
+                       i_cal_component_remove_property (component, prop);
+                       g_object_unref (prop);
+               }
+       }
+
+       if (!alarm->uid)
+               alarm->uid = e_util_generate_uid ();
+
+       for (prop = i_cal_component_get_first_property (component, I_CAL_X_PROPERTY);
+            prop;
+            g_object_unref (prop), i_cal_component_get_first_property (component, I_CAL_X_PROPERTY)) {
+               const gchar *xname;
+
+               xname = i_cal_property_get_x_name (prop);
+               if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
+                       i_cal_property_set_x (prop, alarm->uid);
+                       /* Do not set to NULL, it's used below as a sentinel */
+                       g_object_unref (prop);
+                       break;
+               }
+       }
+
+       /* Tried all existing and none was the E_CAL_EVOLUTION_ALARM_UID_PROPERTY, thus add it */
+       if (!prop) {
+               prop = i_cal_property_new_x (alarm->uid);
+               i_cal_property_set_x_name (prop, E_CAL_EVOLUTION_ALARM_UID_PROPERTY);
+               i_cal_component_take_property (component, prop);
+       }
+
+       prop = NULL;
+
+       switch (alarm->action) {
+       case E_CAL_COMPONENT_ALARM_AUDIO:
+               prop = i_cal_property_new_action (I_CAL_ACTION_AUDIO);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_DISPLAY:
+               prop = i_cal_property_new_action (I_CAL_ACTION_DISPLAY);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_EMAIL:
+               prop = i_cal_property_new_action (I_CAL_ACTION_EMAIL);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_PROCEDURE:
+               prop = i_cal_property_new_action (I_CAL_ACTION_PROCEDURE);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_NONE:
+               prop = i_cal_property_new_action (I_CAL_ACTION_NONE);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_UNKNOWN:
+               break;
+       }
+
+       if (prop)
+               i_cal_component_take_property (component, prop);
+
+       if (alarm->summary && e_cal_component_text_get_value (alarm->summary)) {
+               prop = i_cal_property_new_summary (e_cal_component_text_get_value (alarm->summary));
+
+               if (prop) {
+                       const gchar *altrep = e_cal_component_text_get_altrep (alarm->summary);
+
+                       if (altrep && *altrep) {
+                               ICalParameter *param;
+
+                               param = i_cal_parameter_new_altrep (altrep);
+                               if (param)
+                                       i_cal_property_take_parameter (prop, param);
+                       }
+
+                       i_cal_component_take_property (component, prop);
+               }
+       }
+
+       if (alarm->description && e_cal_component_text_get_value (alarm->description)) {
+               prop = i_cal_property_new_description (e_cal_component_text_get_value (alarm->description));
+
+               if (prop) {
+                       const gchar *altrep = e_cal_component_text_get_altrep (alarm->description);
+
+                       if (altrep && *altrep) {
+                               ICalParameter *param;
+
+                               param = i_cal_parameter_new_altrep (altrep);
+                               if (param)
+                                       i_cal_property_take_parameter (prop, param);
+                       }
+
+                       i_cal_component_take_property (component, prop);
+               }
+       }
+
+       if (alarm->trigger) {
+               prop = e_cal_component_alarm_trigger_get_as_property (alarm->trigger);
+               if (prop)
+                       i_cal_component_take_property (component, prop);
+       }
+
+       if (alarm->repeat) {
+               ICalDuration *interval;
+
+               interval = e_cal_component_alarm_repeat_get_interval (alarm->repeat);
+               if (interval) {
+                       prop = i_cal_property_new_repeat (e_cal_component_alarm_repeat_get_repetitions 
(alarm->repeat));
+                       i_cal_component_take_property (component, prop);
+
+                       prop = i_cal_property_new_duration (interval);
+                       i_cal_component_take_property (component, prop);
+               }
+       }
+
+       for (link = alarm->attendees; link; link = g_slist_next (link)) {
+               ECalComponentAttendee *attendee = link->data;
+
+               if (!attendee)
+                       continue;
+
+               prop = e_cal_component_attendee_get_as_property (attendee);
+               if (prop)
+                       i_cal_component_take_property (component, prop);
+       }
+
+       for (link = alarm->attachments; link; link = g_slist_next (link)) {
+               ICalAttach *attach = link->data;
+
+               if (!attach)
+                       continue;
+
+               prop = i_cal_property_new_attach (attach);
+               if (prop)
+                       i_cal_component_take_property (component, prop);
+       }
+
+       e_cal_component_property_bag_fill_component (alarm->property_bag, component);
+}
+
+/**
+ * e_cal_component_alarm_get_uid:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm UID.
+ *
+ * Returns: (nullable): the @alarm UID, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_alarm_get_uid (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->uid;
+}
+
+/**
+ * e_cal_component_alarm_set_uid:
+ * @alarm: an #ECalComponentAlarm
+ * @uid: (nullable): a UID to set, or %NULL or emptry string to generate new
+ *
+ * Set the @alarm UID, or generates a new UID, if @uid is %NULL or an empty string.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_uid (ECalComponentAlarm *alarm,
+                              const gchar *uid)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (!uid || !*uid) {
+               g_free (alarm->uid);
+               alarm->uid = e_util_generate_uid ();
+       } else if (g_strcmp0 (alarm->uid, uid) != 0) {
+               g_free (alarm->uid);
+               alarm->uid = g_strdup (uid);
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_action:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm action, as an #ECalComponentAlarmAction.
+ *
+ * Returns: the @alarm action, or %E_CAL_COMPONENT_ALARM_NONE, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmAction
+e_cal_component_alarm_get_action (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, E_CAL_COMPONENT_ALARM_NONE);
+
+       return alarm->action;
+}
+
+/**
+ * e_cal_component_alarm_set_action:
+ * @alarm: an #ECalComponentAlarm
+ * @action: an #ECalComponentAlarmAction
+ *
+ * Set the @alarm action, as an #ECalComponentAlarmAction.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_action (ECalComponentAlarm *alarm,
+                                 ECalComponentAlarmAction action)
+{
+       g_return_if_fail (alarm != NULL);
+
+       alarm->action = action;
+}
+
+/**
+ * e_cal_component_alarm_get_summary:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm summary, as an #ECalComponentText.
+ *
+ * Returns: (transfer none) (nullable): the @alarm summary, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentText *
+e_cal_component_alarm_get_summary (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->summary;
+}
+
+/**
+ * e_cal_component_alarm_set_summary:
+ * @alarm: an #ECalComponentAlarm
+ * @summary: (transfer none) (nullable): a summary to set, or %NULL to unset
+ *
+ * Set the @alarm summary, as an #ECalComponentText.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_summary (ECalComponentAlarm *alarm,
+                                  const ECalComponentText *summary)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (summary != alarm->summary) {
+               e_cal_component_text_free (alarm->summary);
+
+               alarm->summary = summary ? e_cal_component_text_copy (summary) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_summary: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @summary: (transfer full) (nullable): a summary to set, or %NULL to unset
+ *
+ * Set the @alarm summary, as an #ECalComponentText, and assumes
+ * ownership of the @summary.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_summary (ECalComponentAlarm *alarm,
+                                   ECalComponentText *summary)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (summary != alarm->summary) {
+               e_cal_component_text_free (alarm->summary);
+               alarm->summary = summary;
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_description:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm description, as an #ECalComponentText.
+ *
+ * Returns: (transfer none) (nullable): the @alarm description, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentText *
+e_cal_component_alarm_get_description (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->description;
+}
+
+/**
+ * e_cal_component_alarm_set_description:
+ * @alarm: an #ECalComponentAlarm
+ * @description: (transfer none) (nullable): a description to set, or %NULL to unset
+ *
+ * Set the @alarm description, as an #ECalComponentText.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_description (ECalComponentAlarm *alarm,
+                                      const ECalComponentText *description)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (description != alarm->description) {
+               e_cal_component_text_free (alarm->description);
+
+               alarm->description = description ? e_cal_component_text_copy (description) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_description: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @description: (transfer full) (nullable): a description to set, or %NULL to unset
+ *
+ * Set the @alarm description, as an #ECalComponentText, and assumes
+ * ownership of the @description.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_description (ECalComponentAlarm *alarm,
+                                       ECalComponentText *description)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (description != alarm->description) {
+               e_cal_component_text_free (alarm->description);
+               alarm->description = description;
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_repeat:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm repeat information, as an ECalComponentAlarmRepeat.
+ *
+ * Returns: (transfer none) (nullable): the @alarm repeat information,
+ *    or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmRepeat *
+e_cal_component_alarm_get_repeat (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->repeat;
+}
+
+/**
+ * e_cal_component_alarm_set_repeat:
+ * @alarm: an #ECalComponentAlarm
+ * @repeat: (transfer none) (nullable): a repeat information to set, or %NULL to unset
+ *
+ * Set the @alarm repeat information, as an #ECalComponentAlarmRepeat.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_repeat (ECalComponentAlarm *alarm,
+                                 const ECalComponentAlarmRepeat *repeat)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (repeat != alarm->repeat) {
+               e_cal_component_alarm_repeat_free (alarm->repeat);
+
+               alarm->repeat = repeat ? e_cal_component_alarm_repeat_copy (repeat) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_repeat: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @repeat: (transfer none) (nullable): a repeat information to set, or %NULL to unset
+ *
+ * Set the @alarm repeat information, as an #ECalComponentAlarmRepeat and assumes
+ * ownership of the @trigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_repeat (ECalComponentAlarm *alarm,
+                                  ECalComponentAlarmRepeat *repeat)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (repeat != alarm->repeat) {
+               e_cal_component_alarm_repeat_free (alarm->repeat);
+               alarm->repeat = repeat;
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_trigger:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm trigger, as an #ECalComponentAlarmTrigger.
+ *
+ * Returns: (transfer none) (nullable): the @alarm trigger, or %NULL when, none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTrigger *
+e_cal_component_alarm_get_trigger (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->trigger;
+}
+
+/**
+ * e_cal_component_alarm_set_trigger:
+ * @alarm: an #ECalComponentAlarm
+ * @trigger: (transfer none) (nullable): a trigger to set, or %NULL to unset
+ *
+ * Set the @alarm trigger, as an #ECalComponentAlarmTrigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_trigger (ECalComponentAlarm *alarm,
+                                  const ECalComponentAlarmTrigger *trigger)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (trigger != alarm->trigger) {
+               e_cal_component_alarm_trigger_free (alarm->trigger);
+
+               alarm->trigger = trigger ? e_cal_component_alarm_trigger_copy (trigger) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_trigger: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @trigger: (transfer full) (nullable): a trigger to set, or %NULL to unset
+ *
+ * Set the @alarm trigger, as an #ECalComponentAlarmTrigger and assumes
+ * ownership of the @trigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_trigger (ECalComponentAlarm *alarm,
+                                   ECalComponentAlarmTrigger *trigger)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (trigger != alarm->trigger) {
+               e_cal_component_alarm_trigger_free (alarm->trigger);
+               alarm->trigger = trigger;
+       }
+}
+
+/**
+ * e_cal_component_alarm_has_attendees:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Returns: whether the @alarm has any attendees
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_alarm_has_attendees (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, FALSE);
+
+       return alarm->attendees != NULL;
+}
+
+/**
+ * e_cal_component_alarm_get_attendees:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the list of attendees, as #ECalComponentAttendee.
+ * The returned #GSList is owned by @alarm and should not be modified,
+ * neither its content.
+ *
+ * Returns: (transfer none) (nullable) (element-type ECalComponentAttendee): the @alarm attendees,
+ *    as a #GSList of an #ECalComponentAttendee, or %NULL when, none are set
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_alarm_get_attendees (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->attendees;
+}
+
+/**
+ * e_cal_component_alarm_set_attendees:
+ * @alarm: an #ECalComponentAlarm
+ * @attendees: (transfer none) (nullable) (element-type ECalComponentAttendee): a #GSList
+ *    of an #ECalComponentAttendee objects to set as attendees, or %NULL to unset
+ *
+ * Set the list of attendees, as a #GSList of an #ECalComponentAttendee.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_attendees (ECalComponentAlarm *alarm,
+                                    const GSList *attendees)
+{
+       GSList *to_take = NULL, *link;
+
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attendees == attendees)
+               return;
+
+       for (link = (GSList *) attendees; link; link = g_slist_next (link)) {
+               ECalComponentAttendee *attendee = link->data;
+
+               if (attendee)
+                       to_take = g_slist_prepend (to_take, e_cal_component_attendee_copy (attendee));
+       }
+
+       to_take = g_slist_reverse (to_take);
+
+       e_cal_component_alarm_take_attendees (alarm, to_take);
+}
+
+/**
+ * e_cal_component_alarm_take_attendees: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @attendees: (transfer full) (nullable) (element-type ECalComponentAttendee): a #GSList
+ *    of an #ECalComponentAttendee objects to set as attendees, or %NULL to unset
+ *
+ * Sets the list of attendees, as a #GSList of an #ECalComponentAttendee and assumes
+ * ownership of the @attendees and its content.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_attendees (ECalComponentAlarm *alarm,
+                                     GSList *attendees)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attendees != attendees) {
+               g_slist_free_full (alarm->attendees, e_cal_component_attendee_free);
+               alarm->attendees = attendees;
+       }
+}
+
+/**
+ * e_cal_component_alarm_has_attachments:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Returns: whether the @alarm has any attachments
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_alarm_has_attachments (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, FALSE);
+
+       return alarm->attachments != NULL;
+}
+
+/**
+ * e_cal_component_alarm_get_attachments:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the list of attachments, as #ICalAttach.
+ * The returned #GSList is owned by @alarm and should not be modified,
+ * neither its content.
+ *
+ * Returns: (transfer none) (nullable) (element-type ICalAttach): the @alarm attachments,
+ *    as a #GSList of an #ICalAttach, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_alarm_get_attachments (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->attachments;
+}
+
+/**
+ * e_cal_component_alarm_set_attachments:
+ * @alarm: an #ECalComponentAlarm
+ * @attachments: (transfer none) (nullable) (element-type ICalAttach): a #GSList
+ *    of an #ICalAttach objects to set as attachments, or %NULL to unset
+ *
+ * Set the list of attachments, as a #GSList of an #ICalAttach.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_attachments (ECalComponentAlarm *alarm,
+                                      const GSList *attachments)
+{
+       GSList *to_take = NULL, *link;
+
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attachments == attachments)
+               return;
+
+       for (link = (GSList *) attachments; link; link = g_slist_next (link)) {
+               ICalAttach *attach = link->data;
+
+               if (attach)
+                       to_take = g_slist_prepend (to_take, g_object_ref (attach));
+       }
+
+       to_take = g_slist_reverse (to_take);
+
+       e_cal_component_alarm_take_attachments (alarm, to_take);
+}
+
+/**
+ * e_cal_component_alarm_take_attachments: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @attachments: (transfer full) (nullable) (element-type ICalAttach): a #GSList
+ *    of an #ICalAttach objects to set as attachments, or %NULL to unset
+ *
+ * Sets the list of attachments, as a #GSList of an #ICalAttach and assumes
+ * ownership of the @attachments and its content.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_attachments (ECalComponentAlarm *alarm,
+                                       GSList *attachments)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attachments != attachments) {
+               g_slist_free_full (alarm->attachments, g_object_unref);
+               alarm->attachments = attachments;
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_property_bag:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Returns: (transfer none): an #ECalComponentPropertyBag with additional
+ *    properties stored with an alarm component, other than those accessible
+ *    with the other functions of the @alarm.
+ *
+ * Since: 3.36
+ **/
+ECalComponentPropertyBag *
+e_cal_component_alarm_get_property_bag (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->property_bag;
+}
diff --git a/src/calendar/libecal/e-cal-component-alarm.h b/src/calendar/libecal/e-cal-component-alarm.h
new file mode 100644
index 000000000..696ee38d8
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarm.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ALARM_H
+#define E_CAL_COMPONENT_ALARM_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+#include <libecal/e-cal-component-alarm-repeat.h>
+#include <libecal/e-cal-component-alarm-trigger.h>
+#include <libecal/e-cal-component-attendee.h>
+#include <libecal/e-cal-component-property-bag.h>
+#include <libecal/e-cal-component-text.h>
+#include <libecal/e-cal-enums.h>
+
+/**
+ * E_CAL_EVOLUTION_ALARM_UID_PROPERTY:
+ *
+ * Extension property for alarm components so that we can reference them by UID.
+ *
+ * Since: 3.36
+ **/
+#define E_CAL_EVOLUTION_ALARM_UID_PROPERTY "X-EVOLUTION-ALARM-UID"
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentAlarm:
+ *
+ * Opaque structure, which represents alarm subcomponents.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentAlarm ECalComponentAlarm;
+
+GType          e_cal_component_alarm_get_type  (void);
+ECalComponentAlarm *
+               e_cal_component_alarm_new       (void);
+ECalComponentAlarm *
+               e_cal_component_alarm_new_from_component
+                                               (const ICalComponent *component);
+ECalComponentAlarm *
+               e_cal_component_alarm_copy      (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_free      (gpointer alarm); /* ECalComponentAlarm * */
+void           e_cal_component_alarm_set_from_component
+                                               (ECalComponentAlarm *alarm,
+                                                const ICalComponent *component);
+ICalComponent *        e_cal_component_alarm_get_as_component
+                                               (ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_fill_component
+                                               (ECalComponentAlarm *alarm,
+                                                ICalComponent *component);
+const gchar *  e_cal_component_alarm_get_uid   (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_uid   (ECalComponentAlarm *alarm,
+                                                const gchar *uid);
+ECalComponentAlarmAction
+               e_cal_component_alarm_get_action(const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_action(ECalComponentAlarm *alarm,
+                                                ECalComponentAlarmAction action);
+ECalComponentText *
+               e_cal_component_alarm_get_summary
+                                               (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_summary
+                                               (ECalComponentAlarm *alarm,
+                                                const ECalComponentText *summary);
+void           e_cal_component_alarm_take_summary
+                                               (ECalComponentAlarm *alarm,
+                                                ECalComponentText *summary);
+ECalComponentText *
+               e_cal_component_alarm_get_description
+                                               (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_description
+                                               (ECalComponentAlarm *alarm,
+                                                const ECalComponentText *description);
+void           e_cal_component_alarm_take_description
+                                               (ECalComponentAlarm *alarm,
+                                                ECalComponentText *description);
+ECalComponentAlarmRepeat *
+               e_cal_component_alarm_get_repeat(const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_repeat(ECalComponentAlarm *alarm,
+                                                const ECalComponentAlarmRepeat *repeat);
+void           e_cal_component_alarm_take_repeat
+                                               (ECalComponentAlarm *alarm,
+                                                ECalComponentAlarmRepeat *repeat);
+ECalComponentAlarmTrigger *
+               e_cal_component_alarm_get_trigger
+                                               (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_trigger
+                                               (ECalComponentAlarm *alarm,
+                                                const ECalComponentAlarmTrigger *trigger);
+void           e_cal_component_alarm_take_trigger
+                                               (ECalComponentAlarm *alarm,
+                                                ECalComponentAlarmTrigger *trigger);
+gboolean       e_cal_component_alarm_has_attendees
+                                               (const ECalComponentAlarm *alarm);
+GSList *       e_cal_component_alarm_get_attendees /* ECalComponentAttendee * */
+                                               (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_attendees
+                                               (ECalComponentAlarm *alarm,
+                                                const GSList *attendees); /* ECalComponentAttendee * */
+void           e_cal_component_alarm_take_attendees
+                                               (ECalComponentAlarm *alarm,
+                                                GSList *attendees); /* ECalComponentAttendee * */
+gboolean       e_cal_component_alarm_has_attachments
+                                               (const ECalComponentAlarm *alarm);
+GSList *       e_cal_component_alarm_get_attachments /* ICalAttach * */
+                                               (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_attachments
+                                               (ECalComponentAlarm *alarm,
+                                                const GSList *attachments); /* ICalAttach * */
+void           e_cal_component_alarm_take_attachments
+                                               (ECalComponentAlarm *alarm,
+                                                GSList *attachments); /* ICalAttach * */
+ECalComponentPropertyBag *
+               e_cal_component_alarm_get_property_bag
+                                               (const ECalComponentAlarm *alarm);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ALARM_H */
diff --git a/src/calendar/libecal/e-cal-component-alarms.c b/src/calendar/libecal/e-cal-component-alarms.c
new file mode 100644
index 000000000..0a6c25666
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarms.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-alarms
+ * @short_description: An ECalComponentAlarms structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentAlarms structure.
+ **/
+
+#include "e-cal-component.h"
+
+#include "e-cal-component-alarms.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentAlarms, e_cal_component_alarms, e_cal_component_alarms_copy, 
e_cal_component_alarms_free)
+
+struct _ECalComponentAlarms {
+       /* The actual component */
+       ECalComponent *comp;
+
+       /* List of ECalComponentAlarmInstance structures */
+       GSList *instances;
+};
+
+/**
+ * e_cal_component_alarms_new:
+ * @comp: (not nullable): the actual alarm component, as #ECalComponent
+ *
+ * Creates a new #ECalComponentAlarms structure, associated with @comp.
+ * Free the alarms with e_cal_component_alarms_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAlarms
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarms *
+e_cal_component_alarms_new (ECalComponent *comp)
+{
+       ECalComponentAlarms *alarms;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+
+       alarms = g_new0 (ECalComponentAlarms, 1);
+       alarms->comp = g_object_ref (comp);
+
+       return alarms;
+}
+
+/**
+ * e_cal_component_alarms_copy:
+ * @alarms: (not nullable): an #ECalComponentAlarms
+ *
+ * Returns a newly allocated copy of @alarms, which should be freed with
+ * e_cal_component_alarms_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @alarms
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarms *
+e_cal_component_alarms_copy (const ECalComponentAlarms *alarms)
+{
+       ECalComponentAlarms *alrms;
+
+       g_return_val_if_fail (alarms != NULL, NULL);
+
+       alrms = e_cal_component_alarms_new (alarms->comp);
+       alrms->instances = g_slist_copy_deep (alarms->instances, (GCopyFunc) 
e_cal_component_alarm_instance_copy, NULL);
+
+       return alrms;
+}
+
+/**
+ * e_cal_component_alarms_free: (skip)
+ * @alarms: (type ECalComponentAlarms) (nullable): an #ECalComponentAlarms to free
+ *
+ * Free @alarms, previously created by e_cal_component_alarms_new()
+ * or e_cal_component_alarms_copy(). The function does nothing, if @alarms
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarms_free (gpointer alarms)
+{
+       ECalComponentAlarms *alrms = alarms;
+
+       if (alrms) {
+               g_clear_object (&alrms->comp);
+               g_slist_free_full (alrms->instances, e_cal_component_alarm_instance_free);
+               g_free (alrms);
+       }
+}
+
+/**
+ * e_cal_component_alarms_get_component:
+ * @alarms: an #ECalComponentAlarms
+ *
+ * The returned component is valid until the @alarms is freed.
+ *
+ * Returns: (transfer none): an #ECalComponent associated with the @alarms structure
+ *
+ * Since: 3.36
+ **/
+ECalComponent *
+e_cal_component_alarms_get_component (const ECalComponentAlarms *alarms)
+{
+       g_return_val_if_fail (alarms != NULL, NULL);
+
+       return alarms->comp;
+}
+
+/**
+ * e_cal_component_alarms_get_instances:
+ * @alarms: an #ECalComponentAlarms
+ *
+ * The returned #GSList is owned by @alarms and should not be modified.
+ * It's valid until the @alarms is freed or the list of instances is not
+ * modified by other functions. The items are of type #ECalComponentAlarmInstance.
+ *
+ * Returns: (transfer none) (element-type ECalComponentAlarmInstance) (nullable): instances
+ *    of the @alarms structure; can be %NULL, when none had been added yet
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_alarms_get_instances (const ECalComponentAlarms *alarms)
+{
+       g_return_val_if_fail (alarms != NULL, NULL);
+
+       return alarms->instances;
+}
+
+/**
+ * e_cal_component_alarms_set_instances:
+ * @alarms: an #ECalComponentAlarms
+ * @instances: (nullable) (element-type ECalComponentAlarmInstance): #ECalComponentAlarmInstance objects to 
set
+ *
+ * Modifies the list of instances to copy of the given @instances.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarms_set_instances (ECalComponentAlarms *alarms,
+                                     const GSList *instances)
+{
+       GSList *copy;
+
+       g_return_if_fail (alarms != NULL);
+
+       copy = g_slist_copy_deep ((GSList *) instances, (GCopyFunc) e_cal_component_alarm_instance_copy, 
NULL);
+       g_slist_free_full (alarms->instances, e_cal_component_alarm_instance_free);
+       alarms->instances = copy;
+}
+
+/**
+ * e_cal_component_alarms_take_instances:
+ * @alarms: an #ECalComponentAlarms
+ * @instances: (nullable) (transfer full) (element-type ECalComponentAlarmInstance): 
#ECalComponentAlarmInstance objects to take
+ *
+ * Replaces the list of instances with the given @instances and
+ * assumes ownership of it. Neither the #GSList, nor its items, should
+ * contain the same structures.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarms_take_instances (ECalComponentAlarms *alarms,
+                                      GSList *instances)
+{
+       g_return_if_fail (alarms != NULL);
+
+       g_slist_free_full (alarms->instances, e_cal_component_alarm_instance_free);
+       alarms->instances = instances;
+}
+
+/**
+ * e_cal_component_alarms_add_instance:
+ * @alarms: an #ECalComponentAlarms
+ * @instance: (not nullable): an #ECalComponentAlarmInstance
+ *
+ * Add a copy of @instance into the list of instances. It is added
+ * in no particular order.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarms_add_instance (ECalComponentAlarms *alarms,
+                                    const ECalComponentAlarmInstance *instance)
+{
+       g_return_if_fail (alarms != NULL);
+       g_return_if_fail (instance != NULL);
+
+       alarms->instances = g_slist_prepend (alarms->instances,
+               e_cal_component_alarm_instance_copy (instance));
+}
+
+/**
+ * e_cal_component_alarms_take_instance:
+ * @alarms: an #ECalComponentAlarms
+ * @instance: (not nullable) (transfer full): an #ECalComponentAlarmInstance
+ *
+ * Add the @instance into the list of instances and assume ownership of it.
+ * It is added in no particular order.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarms_take_instance (ECalComponentAlarms *alarms,
+                                     ECalComponentAlarmInstance *instance)
+{
+       g_return_if_fail (alarms != NULL);
+       g_return_if_fail (instance != NULL);
+
+       alarms->instances = g_slist_prepend (alarms->instances, instance);
+}
+
+/**
+ * e_cal_component_alarms_remove_instance:
+ * @alarms: an #ECalComponentAlarms
+ * @instance: (not nullable): an #ECalComponentAlarmInstance
+ *
+ * Remove the @instance from the list of instances. If found, the @instance
+ * is also freed.
+ *
+ * Returns: whether the @instance had been found and freed
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_alarms_remove_instance (ECalComponentAlarms *alarms,
+                                       const ECalComponentAlarmInstance *instance)
+{
+       GSList *found;
+
+       g_return_val_if_fail (alarms != NULL, FALSE);
+       g_return_val_if_fail (instance != NULL, FALSE);
+
+       found = g_slist_find (alarms->instances, instance);
+       if (found) {
+               alarms->instances = g_slist_remove (alarms->instances, instance);
+               e_cal_component_alarm_instance_free ((ECalComponentAlarmInstance *) instance);
+       }
+
+       return found != NULL;
+}
diff --git a/src/calendar/libecal/e-cal-component-alarms.h b/src/calendar/libecal/e-cal-component-alarms.h
new file mode 100644
index 000000000..7c98389b0
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-alarms.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ALARMS_H
+#define E_CAL_COMPONENT_ALARMS_H
+
+#include <glib-object.h>
+#include <libecal/e-cal-component-alarm-instance.h>
+
+G_BEGIN_DECLS
+
+/* Forward declaration */
+struct _ECalComponent;
+
+/**
+ * ECalComponentAlarms:
+ *
+ * Opaque structure, which represents alarm trigger instances for a particular component.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentAlarms ECalComponentAlarms;
+
+GType          e_cal_component_alarms_get_type (void);
+ECalComponentAlarms *
+               e_cal_component_alarms_new      (struct _ECalComponent *comp);
+ECalComponentAlarms *
+               e_cal_component_alarms_copy     (const ECalComponentAlarms *alarms);
+void           e_cal_component_alarms_free     (gpointer alarms); /* ECalComponentAlarms * */
+struct _ECalComponent *
+               e_cal_component_alarms_get_component
+                                               (const ECalComponentAlarms *alarms);
+GSList *       e_cal_component_alarms_get_instances /* ECalComponentAlarmInstance * */
+                                               (const ECalComponentAlarms *alarms);
+void           e_cal_component_alarms_set_instances
+                                               (ECalComponentAlarms *alarms,
+                                                const GSList *instances); /* ECalComponentAlarmInstance * */
+void           e_cal_component_alarms_take_instances
+                                               (ECalComponentAlarms *alarms,
+                                                GSList *instances); /* ECalComponentAlarmInstance * */
+void           e_cal_component_alarms_add_instance
+                                               (ECalComponentAlarms *alarms,
+                                                const ECalComponentAlarmInstance *instance);
+void           e_cal_component_alarms_take_instance
+                                               (ECalComponentAlarms *alarms,
+                                                ECalComponentAlarmInstance *instance);
+gboolean       e_cal_component_alarms_remove_instance
+                                               (ECalComponentAlarms *alarms,
+                                                const ECalComponentAlarmInstance *instance);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ALARMS_H */
diff --git a/src/calendar/libecal/e-cal-component-attendee.c b/src/calendar/libecal/e-cal-component-attendee.c
new file mode 100644
index 000000000..beb31f66d
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-attendee.c
@@ -0,0 +1,848 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-attendee
+ * @short_description: An ECalComponentAttendee structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentAttendee structure.
+ **/
+
+#include "e-cal-component-parameter-bag.h"
+
+#include "e-cal-component-attendee.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentAttendee, e_cal_component_attendee, e_cal_component_attendee_copy, 
e_cal_component_attendee_free)
+
+struct _ECalComponentAttendee {
+       gchar *value;
+
+       gchar *member;
+       ICalParameterCutype cutype;
+       ICalParameterRole role;
+       ICalParameterPartstat partstat;
+       gboolean rsvp;
+
+       gchar *delegatedfrom;
+       gchar *delegatedto;
+       gchar *sentby;
+       gchar *cn;
+       gchar *language;
+
+       ECalComponentParameterBag *parameter_bag;
+};
+
+/**
+ * e_cal_component_attendee_new:
+ *
+ * Creates a new empty #ECalComponentAttendee structure. Free it
+ * with e_cal_component_attendee_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAttendee
+ *
+ * Since: 3.36
+ **/
+ECalComponentAttendee *
+e_cal_component_attendee_new (void)
+{
+       ECalComponentAttendee *attendee;
+
+       attendee = g_new0 (ECalComponentAttendee, 1);
+       attendee->cutype = I_CAL_CUTYPE_NONE;
+       attendee->role = I_CAL_ROLE_REQPARTICIPANT;
+       attendee->partstat = I_CAL_PARTSTAT_NEEDSACTION;
+       attendee->parameter_bag = e_cal_component_parameter_bag_new ();
+
+       return attendee;
+}
+
+/**
+ * e_cal_component_attendee_new_full:
+ * @value: (nullable): usually a "mailto:email"; of the attendee
+ * @member: (nullable): member parameter
+ * @cutype: type of the attendee, an #ICalParameterCutype
+ * @role: role of the attendee, an #ICalParameterRole
+ * @partstat: current status of the attendee, an #ICalParameterPartstat
+ * @rsvp: whether requires RSVP
+ * @delegatedfrom: (nullable): delegated from
+ * @delegatedto: (nullable): delegated to
+ * @sentby: (nullable): sent by
+ * @cn: (nullable): common name
+ * @language: (nullable): language
+ *
+ * Creates a new #ECalComponentAttendee structure, with all members filled
+ * with given values from the parameters. The %NULL and empty strings are
+ * treated as unset the value. Free the structure
+ * with e_cal_component_attendee_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentAttendee
+ *
+ * Since: 3.36
+ **/
+ECalComponentAttendee *
+e_cal_component_attendee_new_full (const gchar *value,
+                                  const gchar *member,
+                                  ICalParameterCutype cutype,
+                                  ICalParameterRole role,
+                                  ICalParameterPartstat partstat,
+                                  gboolean rsvp,
+                                  const gchar *delegatedfrom,
+                                  const gchar *delegatedto,
+                                  const gchar *sentby,
+                                  const gchar *cn,
+                                  const gchar *language)
+{
+       ECalComponentAttendee *attendee;
+
+       attendee = e_cal_component_attendee_new ();
+       attendee->value = value && *value ? g_strdup (value) : NULL;
+       attendee->member = member && *member ? g_strdup (member) : NULL;
+       attendee->cutype = cutype;
+       attendee->role = role;
+       attendee->partstat = partstat;
+       attendee->rsvp = rsvp;
+       attendee->delegatedfrom = delegatedfrom && *delegatedfrom ? g_strdup (delegatedfrom) : NULL;
+       attendee->delegatedto = delegatedto && *delegatedto ? g_strdup (delegatedto) : NULL;
+       attendee->sentby = sentby && *sentby ? g_strdup (sentby) : NULL;
+       attendee->cn = cn && *cn ? g_strdup (cn) : NULL;
+       attendee->language = language && *language ? g_strdup (language) : NULL;
+
+       return attendee;
+}
+
+/**
+ * e_cal_component_attendee_new_from_property:
+ * @property: an #ICalProperty of kind %I_CAL_ATTENDEE_PROPERTY
+ *
+ * Creates a new #ECalComponentAttendee, filled with values from @property,
+ * which should be of kind %I_CAL_ATTENDEE_PROPERTY. The function returns
+ * %NULL when it is not of the expected kind. Free the structure
+ * with e_cal_component_attendee_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly allocated #ECalComponentAttendee
+ *
+ * Since: 3.36
+ **/
+ECalComponentAttendee *
+e_cal_component_attendee_new_from_property (const ICalProperty *property)
+{
+       ECalComponentAttendee *attendee;
+
+       g_return_val_if_fail (I_CAL_IS_PROPERTY (property), NULL);
+
+       if (i_cal_property_isa ((ICalProperty *) property) != I_CAL_ATTENDEE_PROPERTY)
+               return NULL;
+
+       attendee = e_cal_component_attendee_new ();
+
+       e_cal_component_attendee_set_from_property (attendee, property);
+
+       return attendee;
+}
+
+/**
+ * e_cal_component_attendee_copy:
+ * @attendee: (not nullable): an #ECalComponentAttendee
+ *
+ * Returns a newly allocated copy of @attendee, which should be freed with
+ * e_cal_component_attendee_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @attendee
+ *
+ * Since: 3.36
+ **/
+ECalComponentAttendee *
+e_cal_component_attendee_copy (const ECalComponentAttendee *attendee)
+{
+       ECalComponentAttendee *copy;
+
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       copy = e_cal_component_attendee_new_full (attendee->value,
+               attendee->member,
+               attendee->cutype,
+               attendee->role,
+               attendee->partstat,
+               attendee->rsvp,
+               attendee->delegatedfrom,
+               attendee->delegatedto,
+               attendee->sentby,
+               attendee->cn,
+               attendee->language);
+
+       e_cal_component_parameter_bag_assign (copy->parameter_bag, attendee->parameter_bag);
+
+       return copy;
+}
+
+/**
+ * e_cal_component_attendee_free: (skip)
+ * @attendee: (type ECalComponentAttendee) (nullable): an #ECalComponentAttendee to free
+ *
+ * Free @attendee, previously created by e_cal_component_attendee_new(),
+ * e_cal_component_attendee_new_full(), e_cal_component_attendee_new_from_property()
+ * or e_cal_component_attendee_copy(). The function does nothing, if @attendee
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_free (gpointer attendee)
+{
+       ECalComponentAttendee *att = attendee;
+
+       if (att) {
+               e_cal_component_parameter_bag_free (att->parameter_bag);
+               g_free (att->value);
+               g_free (att->member);
+               g_free (att->delegatedfrom);
+               g_free (att->delegatedto);
+               g_free (att->sentby);
+               g_free (att->cn);
+               g_free (att->language);
+               g_free (att);
+       }
+}
+
+static gboolean
+e_cal_component_attendee_filter_params_cb (ICalParameter *param,
+                                          gpointer user_data)
+{
+       ICalParameterKind kind;
+
+       kind = i_cal_parameter_isa (param);
+
+       return kind != I_CAL_MEMBER_PARAMETER &&
+              kind != I_CAL_CUTYPE_PARAMETER &&
+              kind != I_CAL_ROLE_PARAMETER &&
+              kind != I_CAL_PARTSTAT_PARAMETER &&
+              kind != I_CAL_RSVP_PARAMETER &&
+              kind != I_CAL_DELEGATEDFROM_PARAMETER &&
+              kind != I_CAL_DELEGATEDTO_PARAMETER &&
+              kind != I_CAL_SENTBY_PARAMETER &&
+              kind != I_CAL_CN_PARAMETER &&
+              kind != I_CAL_LANGUAGE_PARAMETER;
+}
+
+/**
+ * e_cal_component_attendee_set_from_property:
+ * @attendee: an #ECalComponentAttendee
+ * @property: an #ICalProperty
+ *
+ * Fill the @attendee structure with the information from
+ * the @property, which should be of %I_CAL_ATTENDEE_PROPERTY kind.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_from_property (ECalComponentAttendee *attendee,
+                                           const ICalProperty *property)
+{
+       ICalProperty *prop = (ICalProperty *) property;
+       ICalParameter *param;
+
+       g_return_if_fail (attendee != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+       g_return_if_fail (i_cal_property_isa (prop) == I_CAL_ATTENDEE_PROPERTY);
+
+       e_cal_component_attendee_set_value (attendee, i_cal_property_get_attendee (prop));
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_MEMBER_PARAMETER);
+       e_cal_component_attendee_set_member (attendee, param ? i_cal_parameter_get_member (param) : NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_CUTYPE_PARAMETER);
+       e_cal_component_attendee_set_cutype (attendee, param ? i_cal_parameter_get_cutype (param) : 
I_CAL_CUTYPE_NONE);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_ROLE_PARAMETER);
+       e_cal_component_attendee_set_role (attendee, param ? i_cal_parameter_get_role (param) : 
I_CAL_ROLE_REQPARTICIPANT);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_PARTSTAT_PARAMETER);
+       e_cal_component_attendee_set_partstat (attendee, param ? i_cal_parameter_get_partstat (param) : 
I_CAL_PARTSTAT_NEEDSACTION);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_RSVP_PARAMETER);
+       e_cal_component_attendee_set_rsvp (attendee, param && i_cal_parameter_get_rsvp (param) == 
I_CAL_RSVP_TRUE);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_DELEGATEDFROM_PARAMETER);
+       e_cal_component_attendee_set_delegatedfrom (attendee, param ? i_cal_parameter_get_delegatedfrom 
(param) : NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_DELEGATEDTO_PARAMETER);
+       e_cal_component_attendee_set_delegatedto (attendee, param ? i_cal_parameter_get_delegatedto (param) : 
NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_SENTBY_PARAMETER);
+       e_cal_component_attendee_set_sentby (attendee, param ? i_cal_parameter_get_sentby (param) : NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_CN_PARAMETER);
+       e_cal_component_attendee_set_cn (attendee, param ? i_cal_parameter_get_cn (param) : NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_LANGUAGE_PARAMETER);
+       e_cal_component_attendee_set_language (attendee, param ? i_cal_parameter_get_language (param) : NULL);
+       g_clear_object (&param);
+
+       e_cal_component_parameter_bag_set_from_property (attendee->parameter_bag, prop, 
e_cal_component_attendee_filter_params_cb, NULL);
+}
+
+/**
+ * e_cal_component_attendee_get_as_property:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Converts information stored in @attendee into an #ICalProperty
+ * of %I_CAL_ATTENDEE_PROPERTY kind. The caller is responsible to free
+ * the returned object with g_object_unref(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly created #ICalProperty, containing
+ *    information from the @attendee.
+ *
+ * Since: 3.36
+ **/
+ICalProperty *
+e_cal_component_attendee_get_as_property (const ECalComponentAttendee *attendee)
+{
+       ICalProperty *prop;
+
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       prop = i_cal_property_new (I_CAL_ATTENDEE_PROPERTY);
+       g_return_val_if_fail (prop != NULL, NULL);
+
+       e_cal_component_attendee_fill_property (attendee, prop);
+
+       return prop;
+}
+
+/**
+ * e_cal_component_attendee_fill_property:
+ * @attendee: an #ECalComponentAttendee
+ * @property: (inout) (not nullable): an #ICalProperty
+ *
+ * Fill @property with information from @attendee. The @property
+ * should be of kind %I_CAL_ATTENDEE_PROPERTY.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_fill_property (const ECalComponentAttendee *attendee,
+                                       ICalProperty *property)
+{
+       ICalParameter *param;
+
+       g_return_if_fail (attendee != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+       g_return_if_fail (i_cal_property_isa (property) == I_CAL_ATTENDEE_PROPERTY);
+
+       i_cal_property_set_attendee (property, attendee->value ? attendee->value : "mailto:";);
+
+       #define fill_param(_param, _val, _filled) \
+               param = i_cal_property_get_first_parameter (property, _param); \
+               if (_filled) { \
+                       if (!param) { \
+                               param = i_cal_parameter_new (_param); \
+                               i_cal_property_add_parameter (property, param); \
+                       } \
+                       i_cal_parameter_set_ ## _val (param, attendee-> _val); \
+                       g_clear_object (&param); \
+               } else if (param) { \
+                       i_cal_property_remove_parameter_by_kind (property, _param); \
+                       g_clear_object (&param); \
+               }
+
+       fill_param (I_CAL_MEMBER_PARAMETER, member, attendee->member && *attendee->member);
+       fill_param (I_CAL_CUTYPE_PARAMETER, cutype, attendee->cutype != I_CAL_CUTYPE_NONE);
+       fill_param (I_CAL_ROLE_PARAMETER, role, attendee->role != I_CAL_ROLE_NONE);
+       fill_param (I_CAL_PARTSTAT_PARAMETER, partstat, attendee->partstat != I_CAL_PARTSTAT_NONE);
+
+       param = i_cal_property_get_first_parameter (property, I_CAL_RSVP_PARAMETER);
+       if (param) {
+               i_cal_parameter_set_rsvp (param, attendee->rsvp ? I_CAL_RSVP_TRUE : I_CAL_RSVP_FALSE);
+               g_clear_object (&param);
+       } else {
+               param = i_cal_parameter_new (I_CAL_RSVP_PARAMETER);
+               i_cal_parameter_set_rsvp (param, attendee->rsvp ? I_CAL_RSVP_TRUE : I_CAL_RSVP_FALSE);
+               i_cal_property_take_parameter (property, param);
+       }
+
+       fill_param (I_CAL_DELEGATEDFROM_PARAMETER, delegatedfrom, attendee->delegatedfrom && 
*attendee->delegatedfrom);
+       fill_param (I_CAL_DELEGATEDTO_PARAMETER, delegatedto, attendee->delegatedto && 
*attendee->delegatedto);
+       fill_param (I_CAL_SENTBY_PARAMETER, sentby, attendee->sentby && *attendee->sentby);
+       fill_param (I_CAL_CN_PARAMETER, cn, attendee->cn && *attendee->cn);
+       fill_param (I_CAL_LANGUAGE_PARAMETER, language, attendee->language && *attendee->language);
+
+       #undef fill_param
+
+       e_cal_component_parameter_bag_fill_property (attendee->parameter_bag, property);
+}
+
+/**
+ * e_cal_component_attendee_get_value:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee URI, usually of "mailto:email"; form
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_value (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->value;
+}
+
+/**
+ * e_cal_component_attendee_set_value:
+ * @attendee: an #ECalComponentAttendee
+ * @value: (nullable): the value to set
+ *
+ * Set the @attendee URI, usually of "mailto:email"; form. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_value (ECalComponentAttendee *attendee,
+                                   const gchar *value)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (value && !*value)
+               value = NULL;
+
+       if (g_strcmp0 (attendee->value, value) != 0) {
+               g_free (attendee->value);
+               attendee->value = g_strdup (value);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_member:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee member property
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_member (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->member;
+}
+
+/**
+ * e_cal_component_attendee_set_member:
+ * @attendee: an #ECalComponentAttendee
+ * @member: (nullable): the value to set
+ *
+ * Set the @attendee member parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_member (ECalComponentAttendee *attendee,
+                                    const gchar *member)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (member && !*member)
+               member = NULL;
+
+       if (g_strcmp0 (attendee->member, member) != 0) {
+               g_free (attendee->member);
+               attendee->member = g_strdup (member);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_cutype:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: the @attendee type, as an #ICalParameterCutype
+ *
+ * Since: 3.36
+ **/
+ICalParameterCutype
+e_cal_component_attendee_get_cutype (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, I_CAL_CUTYPE_NONE);
+
+       return attendee->cutype;
+}
+
+/**
+ * e_cal_component_attendee_set_cutype:
+ * @attendee: an #ECalComponentAttendee
+ * @cutype: the value to set, as an #ICalParameterCutype
+ *
+ * Set the @attendee type, as an #ICalParameterCutype.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_cutype (ECalComponentAttendee *attendee,
+                                    ICalParameterCutype cutype)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (attendee->cutype != cutype) {
+               attendee->cutype = cutype;
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_role:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: the @attendee role, as an #ICalParameterRole
+ *
+ * Since: 3.36
+ **/
+ICalParameterRole
+e_cal_component_attendee_get_role (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, I_CAL_ROLE_NONE);
+
+       return attendee->role;
+}
+
+/**
+ * e_cal_component_attendee_set_role:
+ * @attendee: an #ECalComponentAttendee
+ * @role: the value to set, as an #ICalParameterRole
+ *
+ * Set the @attendee role, as an #ICalParameterRole.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_role (ECalComponentAttendee *attendee,
+                                  ICalParameterRole role)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (attendee->role != role) {
+               attendee->role = role;
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_partstat:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: the @attendee status, as an #ICalParameterPartstat
+ *
+ * Since: 3.36
+ **/
+ICalParameterPartstat
+e_cal_component_attendee_get_partstat (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, I_CAL_PARTSTAT_NONE);
+
+       return attendee->partstat;
+}
+
+/**
+ * e_cal_component_attendee_set_partstat:
+ * @attendee: an #ECalComponentAttendee
+ * @partstat: the value to set, as an #ICalParameterPartstat
+ *
+ * Set the @attendee status, as an #ICalParameterPartstat.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_partstat (ECalComponentAttendee *attendee,
+                                      ICalParameterPartstat partstat)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (attendee->partstat != partstat) {
+               attendee->partstat = partstat;
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_rsvp:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: whether the @attendee requires RSVP
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_attendee_get_rsvp (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, FALSE);
+
+       return attendee->rsvp;
+}
+
+/**
+ * e_cal_component_attendee_set_rsvp:
+ * @attendee: an #ECalComponentAttendee
+ * @rsvp: the value to set
+ *
+ * Set the @attendee RSVP.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_rsvp (ECalComponentAttendee *attendee,
+                                  gboolean rsvp)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if ((attendee->rsvp ? 1 : 0) != (rsvp ? 1 : 0)) {
+               attendee->rsvp = rsvp;
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_delegatedfrom:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee delegatedfrom parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_delegatedfrom (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->delegatedfrom;
+}
+
+/**
+ * e_cal_component_attendee_set_delegatedfrom:
+ * @attendee: an #ECalComponentAttendee
+ * @delegatedfrom: (nullable): the value to set
+ *
+ * Set the @attendee delegatedfrom parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_delegatedfrom (ECalComponentAttendee *attendee,
+                                           const gchar *delegatedfrom)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (delegatedfrom && !*delegatedfrom)
+               delegatedfrom = NULL;
+
+       if (g_strcmp0 (attendee->delegatedfrom, delegatedfrom) != 0) {
+               g_free (attendee->delegatedfrom);
+               attendee->delegatedfrom = g_strdup (delegatedfrom);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_delegatedto:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee delegatedto parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_delegatedto (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->delegatedto;
+}
+
+/**
+ * e_cal_component_attendee_set_delegatedto:
+ * @attendee: an #ECalComponentAttendee
+ * @delegatedto: (nullable): the value to set
+ *
+ * Set the @attendee delegatedto parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_delegatedto (ECalComponentAttendee *attendee,
+                                         const gchar *delegatedto)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (delegatedto && !*delegatedto)
+               delegatedto = NULL;
+
+       if (g_strcmp0 (attendee->delegatedto, delegatedto) != 0) {
+               g_free (attendee->delegatedto);
+               attendee->delegatedto = g_strdup (delegatedto);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_sentby:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee sentby parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_sentby (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->sentby;
+}
+
+/**
+ * e_cal_component_attendee_set_sentby:
+ * @attendee: an #ECalComponentAttendee
+ * @sentby: (nullable): the value to set
+ *
+ * Set the @attendee sentby parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_sentby (ECalComponentAttendee *attendee,
+                                    const gchar *sentby)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (sentby && !*sentby)
+               sentby = NULL;
+
+       if (g_strcmp0 (attendee->sentby, sentby) != 0) {
+               g_free (attendee->sentby);
+               attendee->sentby = g_strdup (sentby);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_cn:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee common name (cn) parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_cn (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->cn;
+}
+
+/**
+ * e_cal_component_attendee_set_cn:
+ * @attendee: an #ECalComponentAttendee
+ * @cn: (nullable): the value to set
+ *
+ * Set the @attendee common name (cn) parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_cn (ECalComponentAttendee *attendee,
+                                const gchar *cn)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (cn && !*cn)
+               cn = NULL;
+
+       if (g_strcmp0 (attendee->cn, cn) != 0) {
+               g_free (attendee->cn);
+               attendee->cn = g_strdup (cn);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_language:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (nullable): the @attendee language parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_attendee_get_language (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->language;
+}
+
+/**
+ * e_cal_component_attendee_set_language:
+ * @attendee: an #ECalComponentAttendee
+ * @language: (nullable): the value to set
+ *
+ * Set the @attendee language parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_attendee_set_language (ECalComponentAttendee *attendee,
+                                      const gchar *language)
+{
+       g_return_if_fail (attendee != NULL);
+
+       if (language && !*language)
+               language = NULL;
+
+       if (g_strcmp0 (attendee->language, language) != 0) {
+               g_free (attendee->language);
+               attendee->language = g_strdup (language);
+       }
+}
+
+/**
+ * e_cal_component_attendee_get_parameter_bag:
+ * @attendee: an #ECalComponentAttendee
+ *
+ * Returns: (transfer none): an #ECalComponentParameterBag with additional
+ *    parameters stored with the attendee property, other than those accessible
+ *    with the other functions of the @attendee.
+ *
+ * Since: 3.36
+ **/
+ECalComponentParameterBag *
+e_cal_component_attendee_get_parameter_bag (const ECalComponentAttendee *attendee)
+{
+       g_return_val_if_fail (attendee != NULL, NULL);
+
+       return attendee->parameter_bag;
+}
diff --git a/src/calendar/libecal/e-cal-component-attendee.h b/src/calendar/libecal/e-cal-component-attendee.h
new file mode 100644
index 000000000..71015ddd8
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-attendee.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ATTENDEE_H
+#define E_CAL_COMPONENT_ATTENDEE_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+#include <libecal/e-cal-component-parameter-bag.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentAttendee:
+ *
+ * Describes an attendee. Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentAttendee ECalComponentAttendee;
+
+GType          e_cal_component_attendee_get_type
+                                               (void);
+ECalComponentAttendee *
+               e_cal_component_attendee_new    (void);
+ECalComponentAttendee *
+               e_cal_component_attendee_new_full
+                                               (const gchar *value,
+                                                const gchar *member,
+                                                ICalParameterCutype cutype,
+                                                ICalParameterRole role,
+                                                ICalParameterPartstat partstat,
+                                                gboolean rsvp,
+                                                const gchar *delegatedfrom,
+                                                const gchar *delegatedto,
+                                                const gchar *sentby,
+                                                const gchar *cn,
+                                                const gchar *language);
+ECalComponentAttendee *
+               e_cal_component_attendee_new_from_property
+                                               (const ICalProperty *property);
+ECalComponentAttendee *
+               e_cal_component_attendee_copy   (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_free   (gpointer attendee); /* ECalComponentAttendee * */
+void           e_cal_component_attendee_set_from_property
+                                               (ECalComponentAttendee *attendee,
+                                                const ICalProperty *property);
+ICalProperty * e_cal_component_attendee_get_as_property
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_fill_property
+                                               (const ECalComponentAttendee *attendee,
+                                                ICalProperty *property);
+const gchar *  e_cal_component_attendee_get_value
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_value
+                                               (ECalComponentAttendee *attendee,
+                                                const gchar *value);
+const gchar *  e_cal_component_attendee_get_member
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_member
+                                               (ECalComponentAttendee *attendee,
+                                                const gchar *member);
+ICalParameterCutype
+               e_cal_component_attendee_get_cutype
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_cutype
+                                               (ECalComponentAttendee *attendee,
+                                                ICalParameterCutype cutype);
+ICalParameterRole
+               e_cal_component_attendee_get_role
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_role
+                                               (ECalComponentAttendee *attendee,
+                                                ICalParameterRole role);
+ICalParameterPartstat
+               e_cal_component_attendee_get_partstat
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_partstat
+                                               (ECalComponentAttendee *attendee,
+                                                ICalParameterPartstat partstat);
+gboolean       e_cal_component_attendee_get_rsvp
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_rsvp
+                                               (ECalComponentAttendee *attendee,
+                                                gboolean rsvp);
+const gchar *  e_cal_component_attendee_get_delegatedfrom
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_delegatedfrom
+                                               (ECalComponentAttendee *attendee,
+                                                const gchar *delegatedfrom);
+const gchar *  e_cal_component_attendee_get_delegatedto
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_delegatedto
+                                               (ECalComponentAttendee *attendee,
+                                                const gchar *delegatedto);
+const gchar *  e_cal_component_attendee_get_sentby
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_sentby
+                                               (ECalComponentAttendee *attendee,
+                                                const gchar *sentby);
+const gchar *  e_cal_component_attendee_get_cn (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_cn (ECalComponentAttendee *attendee,
+                                                const gchar *cn);
+const gchar *  e_cal_component_attendee_get_language
+                                               (const ECalComponentAttendee *attendee);
+void           e_cal_component_attendee_set_language
+                                               (ECalComponentAttendee *attendee,
+                                                const gchar *language);
+ECalComponentParameterBag *
+               e_cal_component_attendee_get_parameter_bag
+                                               (const ECalComponentAttendee *attendee);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ATTENDEE_H */
diff --git a/src/calendar/libecal/e-cal-component-datetime.c b/src/calendar/libecal/e-cal-component-datetime.c
new file mode 100644
index 000000000..ee26ab8b8
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-datetime.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-datetime
+ * @short_description: An ECalComponentDateTime structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentDateTime structure.
+ **/
+
+#include "e-cal-component-datetime.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentDateTime, e_cal_component_datetime, e_cal_component_datetime_copy, 
e_cal_component_datetime_free)
+
+struct _ECalComponentDateTime {
+       /* Actual date/time value */
+       ICalTime *value;
+
+       /* Timezone ID */
+       gchar *tzid;
+};
+
+/**
+ * e_cal_component_datetime_new:
+ * @value: (not nullable): an #ICalTime as a value
+ * @tzid: (nullable): timezone ID for the @value, or %NULL
+ *
+ * Creates a new #ECalComponentDateTime instance, which holds
+ * the @value and @tzid. The returned structure should be freed
+ * with e_cal_component_datetime_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a new #ECalComponentDateTime
+ *
+ * Since: 3.36
+ **/
+ECalComponentDateTime *
+e_cal_component_datetime_new (const ICalTime *value,
+                             const gchar *tzid)
+{
+       ECalComponentDateTime *dt;
+
+       g_return_val_if_fail (I_CAL_IS_TIME (value), NULL);
+
+       dt = g_new0 (ECalComponentDateTime, 1);
+       e_cal_component_datetime_set (dt, value, tzid);
+
+       return dt;
+}
+
+/**
+ * e_cal_component_datetime_new_take:
+ * @value: (transfer full) (not nullable): an #ICalTime as a value
+ * @tzid: (transfer full) (nullable): timezone ID for the @value, or %NULL
+ *
+ * Creates a new #ECalComponentDateTime instance, which holds
+ * the @value and @tzid. It is similar to e_cal_component_datetime_new(),
+ * except this function assumes ownership of the @value and @tzid.
+ * The returned structure should be freed with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a new #ECalComponentDateTime
+ *
+ * Since: 3.36
+ **/
+ECalComponentDateTime *
+e_cal_component_datetime_new_take (ICalTime *value,
+                                  gchar *tzid)
+{
+       ECalComponentDateTime *dt;
+
+       g_return_val_if_fail (I_CAL_IS_TIME (value), NULL);
+
+       dt = g_new0 (ECalComponentDateTime, 1);
+       dt->value = value;
+       dt->tzid = tzid;
+
+       return dt;
+}
+
+/**
+ * e_cal_component_datetime_copy:
+ * @dt: (not nullable): an #ECalComponentDateTime
+ *
+ * Creates a new copy of @dt. The returned structure should be freed
+ * with e_cal_component_datetime_free() when no longer needed.
+ *
+ * Returns: (transfer full): a new #ECalComponentDateTime, copy of @dt
+ *
+ * Since: 3.36
+ **/
+ECalComponentDateTime *
+e_cal_component_datetime_copy (const ECalComponentDateTime *dt)
+{
+       g_return_val_if_fail (dt != NULL, NULL);
+
+       return e_cal_component_datetime_new (
+               e_cal_component_datetime_get_value (dt),
+               e_cal_component_datetime_get_tzid (dt));
+}
+
+/**
+ * e_cal_component_datetime_free: (skip)
+ * @dt: (type ECalComponentDateTime) (nullable): an #ECalComponentDateTime to free
+ *
+ * Free @dt, previously created by e_cal_component_datetime_new(),
+ * e_cal_component_datetime_new_take() or e_cal_component_datetime_copy().
+ * The function does nothing, if @dt is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_datetime_free (gpointer dt)
+{
+       ECalComponentDateTime *pdt = dt;
+
+       if (pdt) {
+               g_clear_object (&pdt->value);
+               g_free (pdt->tzid);
+               g_free (pdt);
+       }
+}
+
+/**
+ * e_cal_component_datetime_set:
+ * @dt: an #ECalComponentDateTime
+ * @value: (not nullable): an #ICalTime as a value
+ * @tzid: (nullable): timezone ID for the @value, or %NULL
+ *
+ * Sets both @value and @tzid in one call. Use e_cal_component_datetime_set_value()
+ * and e_cal_component_datetime_set_tzid() to set them separately.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_datetime_set (ECalComponentDateTime *dt,
+                             const ICalTime *value,
+                             const gchar *tzid)
+{
+       g_return_if_fail (dt != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (value));
+
+       e_cal_component_datetime_set_value (dt, value);
+       e_cal_component_datetime_set_tzid (dt, tzid);
+}
+
+/**
+ * e_cal_component_datetime_get_value:
+ * @dt: an #ECalComponentDateTime
+ *
+ * Returns the value stored with the @dt. The object is owned by @dt and
+ * it's valid until the @dt is freed or its value overwritten.
+ *
+ * Returns: (transfer none): a value of @dt, as an #ICalTime
+ *
+ * Since: 3.36
+ **/
+ICalTime *
+e_cal_component_datetime_get_value (const ECalComponentDateTime *dt)
+{
+       g_return_val_if_fail (dt != NULL, NULL);
+
+       return dt->value;
+}
+
+/**
+ * e_cal_component_datetime_set_value:
+ * @dt: an #ECalComponentDateTime
+ * @value: (not nullable): the value to set, as an #ICalTime
+ *
+ * Sets the @value of the @dt. Any previously set value is freed.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_datetime_set_value (ECalComponentDateTime *dt,
+                                   const ICalTime *value)
+{
+       g_return_if_fail (dt != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (value));
+
+       if (dt->value != value) {
+               g_clear_object (&dt->value);
+               dt->value = i_cal_time_new_clone (value);
+       }
+}
+
+/**
+ * e_cal_component_datetime_take_value:
+ * @dt: an #ECalComponentDateTime
+ * @value: (not nullable) (transfer full): the value to take, as an #ICalTime
+ *
+ * Sets the @value of the @dt and assumes ownership of the @value.
+ * Any previously set value is freed.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_datetime_take_value (ECalComponentDateTime *dt,
+                                    ICalTime *value)
+{
+       g_return_if_fail (dt != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (value));
+
+       if (dt->value != value) {
+               g_clear_object (&dt->value);
+               dt->value = value;
+       }
+}
+
+/**
+ * e_cal_component_datetime_get_tzid:
+ * @dt: an #ECalComponentDateTime
+ *
+ * Returns the TZID stored with the @dt. The string is owned by @dt and
+ * it's valid until the @dt is freed or its TZID overwritten. It never
+ * returns an empty string, it returns either set TZID parameter value
+ * or %NULL, when none is set.
+ *
+ * Returns: (transfer none) (nullable): a TZID of @dt, or %NULL
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_datetime_get_tzid (const ECalComponentDateTime *dt)
+{
+       g_return_val_if_fail (dt != NULL, NULL);
+
+       return dt->tzid;
+}
+
+/**
+ * e_cal_component_datetime_set_tzid:
+ * @dt: an #ECalComponentDateTime
+ * @tzid: (nullable): the TZID to set, or %NULL
+ *
+ * Sets the @tzid of the @dt. Any previously set TZID is freed.
+ * An empty string or a %NULL as @tzid is treated as none TZID.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_datetime_set_tzid (ECalComponentDateTime *dt,
+                                  const gchar *tzid)
+{
+       g_return_if_fail (dt != NULL);
+
+       if (tzid && !*tzid)
+               tzid = NULL;
+
+       if (tzid != dt->tzid) {
+               g_free (dt->tzid);
+               dt->tzid = g_strdup (tzid);
+       }
+}
+
+/**
+ * e_cal_component_datetime_take_tzid:
+ * @dt: an #ECalComponentDateTime
+ * @tzid: (nullable) (transfer full): the TZID to take, or %NULL
+ *
+ * Sets the @tzid of the @dt and assumes ownership of @tzid. Any previously
+ * set TZID is freed. An empty string or a %NULL as @tzid is treated as none TZID.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_datetime_take_tzid (ECalComponentDateTime *dt,
+                                   gchar *tzid)
+{
+       g_return_if_fail (dt != NULL);
+
+       if (tzid && !*tzid) {
+               g_free (tzid);
+               tzid = NULL;
+       }
+
+       if (tzid != dt->tzid) {
+               g_free (dt->tzid);
+               dt->tzid = tzid;
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-datetime.h b/src/calendar/libecal/e-cal-component-datetime.h
new file mode 100644
index 000000000..ff7eb968c
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-datetime.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_DATETIME_H
+#define E_CAL_COMPONENT_DATETIME_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentDateTime:
+ *
+ * An opaque structure containing an #ICalTime describing
+ * the date/time value and also its TZID parameter. Use the functions
+ * below to work with it.
+ **/
+typedef struct _ECalComponentDateTime ECalComponentDateTime;
+
+GType          e_cal_component_datetime_get_type
+                                               (void);
+ECalComponentDateTime *
+               e_cal_component_datetime_new    (const ICalTime *value,
+                                                const gchar *tzid);
+ECalComponentDateTime *
+               e_cal_component_datetime_new_take
+                                               (ICalTime *value,
+                                                gchar *tzid);
+ECalComponentDateTime *
+               e_cal_component_datetime_copy   (const ECalComponentDateTime *dt);
+void           e_cal_component_datetime_free   (gpointer dt); /* ECalComponentDateTime * */
+void           e_cal_component_datetime_set    (ECalComponentDateTime *dt,
+                                                const ICalTime *value,
+                                                const gchar *tzid);
+ICalTime *     e_cal_component_datetime_get_value
+                                               (const ECalComponentDateTime *dt);
+void           e_cal_component_datetime_set_value
+                                               (ECalComponentDateTime *dt,
+                                                const ICalTime *value);
+void           e_cal_component_datetime_take_value
+                                               (ECalComponentDateTime *dt,
+                                                ICalTime *value);
+const gchar *  e_cal_component_datetime_get_tzid
+                                               (const ECalComponentDateTime *dt);
+void           e_cal_component_datetime_set_tzid
+                                               (ECalComponentDateTime *dt,
+                                                const gchar *tzid);
+void           e_cal_component_datetime_take_tzid
+                                               (ECalComponentDateTime *dt,
+                                                gchar *tzid);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_DATETIME_H */
diff --git a/src/calendar/libecal/e-cal-component-id.c b/src/calendar/libecal/e-cal-component-id.c
new file mode 100644
index 000000000..d80b40262
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-id.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-id
+ * @short_description: An ECalComponentId structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentId structure.
+ **/
+
+#include "e-cal-component-id.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentId, e_cal_component_id, e_cal_component_id_copy, e_cal_component_id_free)
+
+struct _ECalComponentId {
+       gchar *uid;
+       gchar *rid;
+};
+
+/**
+ * e_cal_component_id_new:
+ * @uid: a unique ID string
+ * @rid: (nullable): an optional recurrence ID string
+ *
+ * Creates a new #ECalComponentId from @uid and @rid, which should be
+ * freed with e_cal_component_id_free().
+ *
+ * Returns: (transfer full): an #ECalComponentId
+ *
+ * Since: 3.10
+ **/
+ECalComponentId *
+e_cal_component_id_new (const gchar *uid,
+                        const gchar *rid)
+{
+       g_return_val_if_fail (uid != NULL, NULL);
+
+       /* Normalize an empty recurrence ID to NULL. */
+       if (rid && !*rid)
+               rid = NULL;
+
+       return e_cal_component_id_new_take (g_strdup (uid), g_strdup (rid));
+}
+
+/**
+ * e_cal_component_id_new_take:
+ * @uid: (transfer full): a unique ID string
+ * @rid: (transfer full) (nullable): an optional recurrence ID string
+ *
+ * Creates a new #ECalComponentId from @uid and @rid, which should be
+ * freed with e_cal_component_id_free(). The function assumes ownership
+ * of @uid and @rid parameters.
+ *
+ * Returns: (transfer full): an #ECalComponentId
+ *
+ * Since: 3.36
+ **/
+ECalComponentId *
+e_cal_component_id_new_take (gchar *uid,
+                            gchar *rid)
+{
+       ECalComponentId *id;
+
+       g_return_val_if_fail (uid != NULL, NULL);
+
+       /* Normalize an empty recurrence ID to NULL. */
+       if (rid && !*rid) {
+               g_free (rid);
+               rid = NULL;
+       }
+
+       id = g_new0 (ECalComponentId, 1);
+       id->uid = uid;
+       id->rid = rid;
+
+       return id;
+}
+
+/**
+ * e_cal_component_id_copy:
+ * @id: (not nullable): an #ECalComponentId
+ *
+ * Returns a newly allocated copy of @id, which should be freed with
+ * e_cal_component_id_free().
+ *
+ * Returns: (transfer full): a newly allocated copy of @id
+ *
+ * Since: 3.10
+ **/
+ECalComponentId *
+e_cal_component_id_copy (const ECalComponentId *id)
+{
+       g_return_val_if_fail (id != NULL, NULL);
+
+       return e_cal_component_id_new (id->uid, id->rid);
+}
+
+/**
+ * e_cal_component_id_free: (skip)
+ * @id: (type ECalComponentId) (transfer full) (nullable): an #ECalComponentId
+ *
+ * Free the @id, previously created by e_cal_component_id_new(),
+ * e_cal_component_id_new_take() or e_cal_component_id_copy().
+ **/
+void
+e_cal_component_id_free (gpointer id)
+{
+       ECalComponentId *eid = id;
+
+       if (eid) {
+               g_free (eid->uid);
+               g_free (eid->rid);
+               g_free (eid);
+       }
+}
+
+/**
+ * e_cal_component_id_hash:
+ * @id: (type ECalComponentId): an #ECalComponentId
+ *
+ * Generates a hash value for @id.
+ *
+ * Returns: a hash value for @id
+ *
+ * Since: 3.10
+ **/
+guint
+e_cal_component_id_hash (gconstpointer id)
+{
+       const ECalComponentId *eid = id;
+       guint uid_hash;
+       guint rid_hash;
+
+       g_return_val_if_fail (id != NULL, 0);
+
+       uid_hash = g_str_hash (eid->uid);
+       rid_hash = eid->rid ? g_str_hash (eid->rid) : 0;
+
+       return uid_hash ^ rid_hash;
+}
+
+/**
+ * e_cal_component_id_equal:
+ * @id1: (type ECalComponentId): the first #ECalComponentId
+ * @id2: (type ECalComponentId): the second #ECalComponentId
+ *
+ * Compares two #ECalComponentId structs for equality.
+ *
+ * Returns: %TRUE if @id1 and @id2 are equal
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_component_id_equal (gconstpointer id1,
+                          gconstpointer id2)
+{
+       const ECalComponentId *eid1 = id1, *eid2 = id2;
+       gboolean uids_equal;
+       gboolean rids_equal;
+
+       if (id1 == id2)
+               return TRUE;
+
+       /* Safety check before we dereference. */
+       g_return_val_if_fail (id1 != NULL, FALSE);
+       g_return_val_if_fail (id2 != NULL, FALSE);
+
+       uids_equal = (g_strcmp0 (eid1->uid, eid2->uid) == 0);
+       rids_equal = (g_strcmp0 (eid1->rid, eid2->rid) == 0);
+
+       return uids_equal && rids_equal;
+}
+
+/**
+ * e_cal_component_id_get_uid:
+ * @id: an #ECalComponentId
+ *
+ * Returns: (transfer none): The UID part of the @id. The returned
+ *    string is owned by @id and it's valid until it's changed
+ *    with e_cal_component_id_set_uid() or until the @id is freed.
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_id_get_uid (const ECalComponentId *id)
+{
+       g_return_val_if_fail (id != NULL, NULL);
+
+       return id->uid;
+}
+
+/**
+ * e_cal_component_id_set_uid:
+ * @id: an #ECalComponentId
+ * @uid: (not nullable): the UID to set
+ *
+ * Sets the UID part of the @id.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_id_set_uid (ECalComponentId *id,
+                           const gchar *uid)
+{
+       g_return_if_fail (id != NULL);
+       g_return_if_fail (uid != NULL);
+
+       if (g_strcmp0 (id->uid, uid) != 0) {
+               g_free (id->uid);
+               id->uid = g_strdup (uid);
+       }
+}
+
+/**
+ * e_cal_component_id_get_rid:
+ * @id: an #ECalComponentId
+ *
+ * Returns: (transfer none) (nullable): The RECURRENCE-ID part of the @id.
+ *    The returned string is owned by @id and it's valid until it's
+ *    changed with e_cal_component_id_set_rid() or until the @id is freed.
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_id_get_rid (const ECalComponentId *id)
+{
+       g_return_val_if_fail (id != NULL, NULL);
+
+       return id->rid;
+}
+
+/**
+ * e_cal_component_id_set_rid:
+ * @id: an #ECalComponentId
+ * @rid: (nullable): the RECURRENCE-ID to set
+ *
+ * Sets the RECURRENCE-ID part of the @id. The @rid can be %NULL
+ * or an empty string, where both are treated as %NULL, which
+ * means the @id has not RECURRENCE-ID.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_id_set_rid (ECalComponentId *id,
+                           const gchar *rid)
+{
+       g_return_if_fail (id != NULL);
+
+       if (g_strcmp0 (id->rid, rid) != 0) {
+               g_free (id->rid);
+               id->rid = (rid && *rid) ? g_strdup (rid) : NULL;
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-id.h b/src/calendar/libecal/e-cal-component-id.h
new file mode 100644
index 000000000..bf03cd4fd
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-id.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ID_H
+#define E_CAL_COMPONENT_ID_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentId:
+ *
+ * An opaque structure containing UID of a component and
+ * its recurrence ID (which can be %NULL). Use the functions
+ * below to work with it.
+ **/
+typedef struct _ECalComponentId ECalComponentId;
+
+GType          e_cal_component_id_get_type     (void);
+ECalComponentId *
+               e_cal_component_id_new          (const gchar *uid,
+                                                const gchar *rid);
+ECalComponentId *
+               e_cal_component_id_new_take     (gchar *uid,
+                                                gchar *rid);
+ECalComponentId *
+               e_cal_component_id_copy         (const ECalComponentId *id);
+void           e_cal_component_id_free         (gpointer id); /* ECalComponentId * */
+guint          e_cal_component_id_hash         (gconstpointer id); /* ECalComponentId * */
+gboolean       e_cal_component_id_equal        (gconstpointer id1, /* ECalComponentId * */
+                                                gconstpointer id2); /* ECalComponentId * */
+const gchar *  e_cal_component_id_get_uid      (const ECalComponentId *id);
+void           e_cal_component_id_set_uid      (ECalComponentId *id,
+                                                const gchar *uid);
+const gchar *  e_cal_component_id_get_rid      (const ECalComponentId *id);
+void           e_cal_component_id_set_rid      (ECalComponentId *id,
+                                                const gchar *rid);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ID_H */
diff --git a/src/calendar/libecal/e-cal-component-organizer.c 
b/src/calendar/libecal/e-cal-component-organizer.c
new file mode 100644
index 000000000..3a2478261
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-organizer.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-organizer
+ * @short_description: An ECalComponentOrganizer structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentOrganizer structure.
+ **/
+
+#include "e-cal-component-parameter-bag.h"
+
+#include "e-cal-component-organizer.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentOrganizer, e_cal_component_organizer, e_cal_component_organizer_copy, 
e_cal_component_organizer_free)
+
+struct _ECalComponentOrganizer {
+       gchar *value;
+       gchar *sentby;
+       gchar *cn;
+       gchar *language;
+
+       ECalComponentParameterBag *parameter_bag;
+};
+
+/**
+ * e_cal_component_organizer_new:
+ *
+ * Creates a new empty #ECalComponentOrganizer structure. Free it
+ * with e_cal_component_organizer_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentOrganizer
+ *
+ * Since: 3.36
+ **/
+ECalComponentOrganizer *
+e_cal_component_organizer_new (void)
+{
+       ECalComponentOrganizer *organizer;
+
+       organizer = g_new0 (ECalComponentOrganizer, 1);
+       organizer->parameter_bag = e_cal_component_parameter_bag_new ();
+
+       return organizer;
+}
+
+/**
+ * e_cal_component_organizer_new_full:
+ * @value: (nullable): usually a "mailto:email"; of the organizer
+ * @sentby: (nullable): sent by
+ * @cn: (nullable): common name
+ * @language: (nullable): language
+ *
+ * Creates a new #ECalComponentOrganizer structure, with all members filled
+ * with given values from the parameters. The %NULL and empty strings are
+ * treated as unset the value. Free the structure
+ * with e_cal_component_organizer_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentOrganizer
+ *
+ * Since: 3.36
+ **/
+ECalComponentOrganizer *
+e_cal_component_organizer_new_full (const gchar *value,
+                                   const gchar *sentby,
+                                   const gchar *cn,
+                                   const gchar *language)
+{
+       ECalComponentOrganizer *organizer;
+
+       organizer = e_cal_component_organizer_new ();
+       organizer->value = value && *value ? g_strdup (value) : NULL;
+       organizer->sentby = sentby && *sentby ? g_strdup (sentby) : NULL;
+       organizer->cn = cn && *cn ? g_strdup (cn) : NULL;
+       organizer->language = language && *language ? g_strdup (language) : NULL;
+
+       return organizer;
+}
+
+/**
+ * e_cal_component_organizer_new_from_property:
+ * @property: an #ICalProperty of kind %I_CAL_ORGANIZER_PROPERTY
+ *
+ * Creates a new #ECalComponentOrganizer, filled with values from @property,
+ * which should be of kind %I_CAL_ORGANIZER_PROPERTY. The function returns
+ * %NULL when it is not of the expected kind. Free the structure
+ * with e_cal_component_organizer_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly allocated #ECalComponentOrganizer
+ *
+ * Since: 3.36
+ **/
+ECalComponentOrganizer *
+e_cal_component_organizer_new_from_property (const ICalProperty *property)
+{
+       ECalComponentOrganizer *organizer;
+
+       g_return_val_if_fail (I_CAL_IS_PROPERTY (property), NULL);
+
+       if (i_cal_property_isa ((ICalProperty *) property) != I_CAL_ORGANIZER_PROPERTY)
+               return NULL;
+
+       organizer = e_cal_component_organizer_new ();
+
+       e_cal_component_organizer_set_from_property (organizer, property);
+
+       return organizer;
+}
+
+/**
+ * e_cal_component_organizer_copy:
+ * @organizer: (not nullable): an #ECalComponentOrganizer
+ *
+ * Returns a newly allocated copy of @organizer, which should be freed with
+ * e_cal_component_organizer_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @organizer
+ *
+ * Since: 3.36
+ **/
+ECalComponentOrganizer *
+e_cal_component_organizer_copy (const ECalComponentOrganizer *organizer)
+{
+       ECalComponentOrganizer *copy;
+
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       copy = e_cal_component_organizer_new_full (organizer->value,
+               organizer->sentby,
+               organizer->cn,
+               organizer->language);
+
+       e_cal_component_parameter_bag_assign (copy->parameter_bag, organizer->parameter_bag);
+
+       return copy;
+}
+
+/**
+ * e_cal_component_organizer_free: (skip)
+ * @organizer: (type ECalComponentOrganizer) (nullable): an #ECalComponentOrganizer to free
+ *
+ * Free @organizer, previously created by e_cal_component_organizer_new(),
+ * e_cal_component_organizer_new_full(), e_cal_component_organizer_new_from_property()
+ * or e_cal_component_organizer_copy(). The function does nothing, if @organizer
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_free (gpointer organizer)
+{
+       ECalComponentOrganizer *org = organizer;
+
+       if (org) {
+               e_cal_component_parameter_bag_free (org->parameter_bag);
+               g_free (org->value);
+               g_free (org->sentby);
+               g_free (org->cn);
+               g_free (org->language);
+               g_free (org);
+       }
+}
+
+static gboolean
+e_cal_component_organizer_filter_params_cb (ICalParameter *param,
+                                           gpointer user_data)
+{
+       ICalParameterKind kind;
+
+       kind = i_cal_parameter_isa (param);
+
+       return kind != I_CAL_SENTBY_PARAMETER &&
+              kind != I_CAL_CN_PARAMETER &&
+              kind != I_CAL_LANGUAGE_PARAMETER;
+}
+
+/**
+ * e_cal_component_organizer_set_from_property:
+ * @organizer: an #ECalComponentOrganizer
+ * @property: an #ICalProperty
+ *
+ * Fill the @organizer structure with the information from
+ * the @property, which should be of %I_CAL_ORGANIZER_PROPERTY kind.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_set_from_property (ECalComponentOrganizer *organizer,
+                                            const ICalProperty *property)
+{
+       ICalProperty *prop = (ICalProperty *) property;
+       ICalParameter *param;
+
+       g_return_if_fail (organizer != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+       g_return_if_fail (i_cal_property_isa (prop) == I_CAL_ORGANIZER_PROPERTY);
+
+       e_cal_component_organizer_set_value (organizer, i_cal_property_get_organizer (prop));
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_SENTBY_PARAMETER);
+       e_cal_component_organizer_set_sentby (organizer, param ? i_cal_parameter_get_sentby (param) : NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_CN_PARAMETER);
+       e_cal_component_organizer_set_cn (organizer, param ? i_cal_parameter_get_cn (param) : NULL);
+       g_clear_object (&param);
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_LANGUAGE_PARAMETER);
+       e_cal_component_organizer_set_language (organizer, param ? i_cal_parameter_get_language (param) : 
NULL);
+       g_clear_object (&param);
+
+       e_cal_component_parameter_bag_set_from_property (organizer->parameter_bag, prop, 
e_cal_component_organizer_filter_params_cb, NULL);
+}
+
+/**
+ * e_cal_component_organizer_get_as_property:
+ * @organizer: an #ECalComponentOrganizer
+ *
+ * Converts information stored in @organizer into an #ICalProperty
+ * of %I_CAL_ORGANIZER_PROPERTY kind. The caller is responsible to free
+ * the returned object with g_object_unref(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly created #ICalProperty, containing
+ *    information from the @organizer.
+ *
+ * Since: 3.36
+ **/
+ICalProperty *
+e_cal_component_organizer_get_as_property (const ECalComponentOrganizer *organizer)
+{
+       ICalProperty *prop;
+
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       prop = i_cal_property_new (I_CAL_ORGANIZER_PROPERTY);
+       g_return_val_if_fail (prop != NULL, NULL);
+
+       e_cal_component_organizer_fill_property (organizer, prop);
+
+       return prop;
+}
+
+/**
+ * e_cal_component_organizer_fill_property:
+ * @organizer: an #ECalComponentOrganizer
+ * @property: (inout) (not nullable): an #ICalProperty
+ *
+ * Fill @property with information from @organizer. The @property
+ * should be of kind %I_CAL_ORGANIZER_PROPERTY.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_fill_property (const ECalComponentOrganizer *organizer,
+                                        ICalProperty *property)
+{
+       ICalParameter *param;
+
+       g_return_if_fail (organizer != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+       g_return_if_fail (i_cal_property_isa (property) == I_CAL_ORGANIZER_PROPERTY);
+
+       i_cal_property_set_organizer (property, organizer->value ? organizer->value : "mailto:";);
+
+       #define fill_param(_param, _val, _filled) \
+               param = i_cal_property_get_first_parameter (property, _param); \
+               if (_filled) { \
+                       if (!param) { \
+                               param = i_cal_parameter_new (_param); \
+                               i_cal_property_add_parameter (property, param); \
+                       } \
+                       i_cal_parameter_set_ ## _val (param, organizer-> _val); \
+                       g_clear_object (&param); \
+               } else if (param) { \
+                       i_cal_property_remove_parameter_by_kind (property, _param); \
+                       g_clear_object (&param); \
+               }
+
+       fill_param (I_CAL_SENTBY_PARAMETER, sentby, organizer->sentby && *organizer->sentby);
+       fill_param (I_CAL_CN_PARAMETER, cn, organizer->cn && *organizer->cn);
+       fill_param (I_CAL_LANGUAGE_PARAMETER, language, organizer->language && *organizer->language);
+
+       #undef fill_param
+
+       e_cal_component_parameter_bag_fill_property (organizer->parameter_bag, property);
+}
+
+/**
+ * e_cal_component_organizer_get_value:
+ * @organizer: an #ECalComponentOrganizer
+ *
+ * Returns: (nullable): the @organizer URI, usually of "mailto:email"; form
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_organizer_get_value (const ECalComponentOrganizer *organizer)
+{
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       return organizer->value;
+}
+
+/**
+ * e_cal_component_organizer_set_value:
+ * @organizer: an #ECalComponentOrganizer
+ * @value: (nullable): the value to set
+ *
+ * Set the @organizer URI, usually of "mailto:email"; form. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_set_value (ECalComponentOrganizer *organizer,
+                                    const gchar *value)
+{
+       g_return_if_fail (organizer != NULL);
+
+       if (value && !*value)
+               value = NULL;
+
+       if (g_strcmp0 (organizer->value, value) != 0) {
+               g_free (organizer->value);
+               organizer->value = g_strdup (value);
+       }
+}
+
+/**
+ * e_cal_component_organizer_get_sentby:
+ * @organizer: an #ECalComponentOrganizer
+ *
+ * Returns: (nullable): the @organizer sentby parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_organizer_get_sentby (const ECalComponentOrganizer *organizer)
+{
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       return organizer->sentby;
+}
+
+/**
+ * e_cal_component_organizer_set_sentby:
+ * @organizer: an #ECalComponentOrganizer
+ * @sentby: (nullable): the value to set
+ *
+ * Set the @organizer sentby parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_set_sentby (ECalComponentOrganizer *organizer,
+                                     const gchar *sentby)
+{
+       g_return_if_fail (organizer != NULL);
+
+       if (sentby && !*sentby)
+               sentby = NULL;
+
+       if (g_strcmp0 (organizer->sentby, sentby) != 0) {
+               g_free (organizer->sentby);
+               organizer->sentby = g_strdup (sentby);
+       }
+}
+
+/**
+ * e_cal_component_organizer_get_cn:
+ * @organizer: an #ECalComponentOrganizer
+ *
+ * Returns: (nullable): the @organizer common name (cn) parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_organizer_get_cn (const ECalComponentOrganizer *organizer)
+{
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       return organizer->cn;
+}
+
+/**
+ * e_cal_component_organizer_set_cn:
+ * @organizer: an #ECalComponentOrganizer
+ * @cn: (nullable): the value to set
+ *
+ * Set the @organizer common name (cn) parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_set_cn (ECalComponentOrganizer *organizer,
+                                 const gchar *cn)
+{
+       g_return_if_fail (organizer != NULL);
+
+       if (cn && !*cn)
+               cn = NULL;
+
+       if (g_strcmp0 (organizer->cn, cn) != 0) {
+               g_free (organizer->cn);
+               organizer->cn = g_strdup (cn);
+       }
+}
+
+/**
+ * e_cal_component_organizer_get_language:
+ * @organizer: an #ECalComponentOrganizer
+ *
+ * Returns: (nullable): the @organizer language parameter
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_organizer_get_language (const ECalComponentOrganizer *organizer)
+{
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       return organizer->language;
+}
+
+/**
+ * e_cal_component_organizer_set_language:
+ * @organizer: an #ECalComponentOrganizer
+ * @language: (nullable): the value to set
+ *
+ * Set the @organizer language parameter. The %NULL
+ * and empty strings are treated as unset the value.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_organizer_set_language (ECalComponentOrganizer *organizer,
+                                       const gchar *language)
+{
+       g_return_if_fail (organizer != NULL);
+
+       if (language && !*language)
+               language = NULL;
+
+       if (g_strcmp0 (organizer->language, language) != 0) {
+               g_free (organizer->language);
+               organizer->language = g_strdup (language);
+       }
+}
+
+/**
+ * e_cal_component_organizer_get_parameter_bag:
+ * @organizer: an #ECalComponentOrganizer
+ *
+ * Returns: (transfer none): an #ECalComponentParameterBag with additional
+ *    parameters stored with the organizer property, other than those accessible
+ *    with the other functions of the @organizer.
+ *
+ * Since: 3.36
+ **/
+ECalComponentParameterBag *
+e_cal_component_organizer_get_parameter_bag (const ECalComponentOrganizer *organizer)
+{
+       g_return_val_if_fail (organizer != NULL, NULL);
+
+       return organizer->parameter_bag;
+}
diff --git a/src/calendar/libecal/e-cal-component-organizer.h 
b/src/calendar/libecal/e-cal-component-organizer.h
new file mode 100644
index 000000000..20a3db73d
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-organizer.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_ORGANIZER_H
+#define E_CAL_COMPONENT_ORGANIZER_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+#include <libecal/e-cal-component-parameter-bag.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentOrganizer:
+ *
+ * Describes an organizer. Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentOrganizer ECalComponentOrganizer;
+
+GType          e_cal_component_organizer_get_type
+                                               (void);
+ECalComponentOrganizer *
+               e_cal_component_organizer_new   (void);
+ECalComponentOrganizer *
+               e_cal_component_organizer_new_full
+                                               (const gchar *value,
+                                                const gchar *sentby,
+                                                const gchar *cn,
+                                                const gchar *language);
+ECalComponentOrganizer *
+               e_cal_component_organizer_new_from_property
+                                               (const ICalProperty *property);
+ECalComponentOrganizer *
+               e_cal_component_organizer_copy  (const ECalComponentOrganizer *organizer);
+void           e_cal_component_organizer_free  (gpointer organizer); /* ECalComponentOrganizer * */
+void           e_cal_component_organizer_set_from_property
+                                               (ECalComponentOrganizer *organizer,
+                                                const ICalProperty *property);
+ICalProperty * e_cal_component_organizer_get_as_property
+                                               (const ECalComponentOrganizer *organizer);
+void           e_cal_component_organizer_fill_property
+                                               (const ECalComponentOrganizer *organizer,
+                                                ICalProperty *property);
+const gchar *  e_cal_component_organizer_get_value
+                                               (const ECalComponentOrganizer *organizer);
+void           e_cal_component_organizer_set_value
+                                               (ECalComponentOrganizer *organizer,
+                                                const gchar *value);
+const gchar *  e_cal_component_organizer_get_sentby
+                                               (const ECalComponentOrganizer *organizer);
+void           e_cal_component_organizer_set_sentby
+                                               (ECalComponentOrganizer *organizer,
+                                                const gchar *sentby);
+const gchar *  e_cal_component_organizer_get_cn(const ECalComponentOrganizer *organizer);
+void           e_cal_component_organizer_set_cn(ECalComponentOrganizer *organizer,
+                                                const gchar *cn);
+const gchar *  e_cal_component_organizer_get_language
+                                               (const ECalComponentOrganizer *organizer);
+void           e_cal_component_organizer_set_language
+                                               (ECalComponentOrganizer *organizer,
+                                                const gchar *language);
+ECalComponentParameterBag *
+               e_cal_component_organizer_get_parameter_bag
+                                               (const ECalComponentOrganizer *organizer);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_ORGANIZER_H */
diff --git a/src/calendar/libecal/e-cal-component-parameter-bag.c 
b/src/calendar/libecal/e-cal-component-parameter-bag.c
new file mode 100644
index 000000000..8afeb5f16
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-parameter-bag.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-parameter-bag
+ * @short_description: An ECalComponentParameterBag structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentParameterBag structure.
+ **/
+
+#include "e-cal-component-parameter-bag.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentParameterBag, e_cal_component_parameter_bag, 
e_cal_component_parameter_bag_copy, e_cal_component_parameter_bag_free)
+
+struct _ECalComponentParameterBag {
+       GPtrArray *parameters; /* ICalParameter * */
+};
+
+/**
+ * e_cal_component_parameter_bag_new:
+ *
+ * Creates a new #ECalComponentParameterBag. Free the structure
+ * with e_cal_component_parameter_bag_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentParameterBag
+ *
+ * Since: 3.36
+ **/
+ECalComponentParameterBag *
+e_cal_component_parameter_bag_new (void)
+{
+       ECalComponentParameterBag *bag;
+
+       bag = g_new0 (ECalComponentParameterBag, 1);
+       bag->parameters = g_ptr_array_new_with_free_func (g_object_unref);
+
+       return bag;
+}
+
+/**
+ * e_cal_component_parameter_bag_new_from_property:
+ * @property: an #ICalProperty containing the parameters to fill the bag with
+ * @func: (nullable) (scope call): an optional %ECalComponentParameterBagFilterFunc callback
+ * @user_data: (closure func): user data for the @func
+ *
+ * Creates a new #ECalComponentParameterBag, filled with parameters
+ * from the @property, for which the @func returned %TRUE. When
+ * the @func is %NULL, all the parameters are included.
+ *
+ * Free the structure with e_cal_component_parameter_bag_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentParameterBag
+ *
+ * Since: 3.36
+ **/
+ECalComponentParameterBag *
+e_cal_component_parameter_bag_new_from_property (const ICalProperty *property,
+                                                ECalComponentParameterBagFilterFunc func,
+                                                gpointer user_data)
+{
+       ECalComponentParameterBag *bag;
+
+       bag = e_cal_component_parameter_bag_new ();
+
+       e_cal_component_parameter_bag_set_from_property (bag, property, func, user_data);
+
+       return bag;
+}
+
+/**
+ * e_cal_component_parameter_bag_copy:
+ * @bag: (not nullable): an #ECalComponentParameterBag
+ *
+ * Returns a newly allocated copy of @bag, which should be freed with
+ * e_cal_component_parameter_bag_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @bag
+ *
+ * Since: 3.36
+ **/
+ECalComponentParameterBag *
+e_cal_component_parameter_bag_copy (const ECalComponentParameterBag *bag)
+{
+       ECalComponentParameterBag *copy;
+
+       g_return_val_if_fail (bag != NULL, NULL);
+
+       copy = e_cal_component_parameter_bag_new ();
+
+       e_cal_component_parameter_bag_assign (copy, bag);
+
+       return copy;
+}
+
+/**
+ * e_cal_component_parameter_bag_free: (skip)
+ * @bag: (type ECalComponentParameterBag) (nullable): an #ECalComponentParameterBag to free
+ *
+ * Free @bag, previously created by e_cal_component_parameter_bag_new(),
+ * e_cal_component_parameter_bag_new_from_component() or
+ * e_cal_component_parameter_bag_copy(). The function does nothing, if @bag
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_free (gpointer bag)
+{
+       ECalComponentParameterBag *bg = bag;
+
+       if (bg) {
+               g_ptr_array_unref (bg->parameters);
+               g_free (bg);
+       }
+}
+
+/**
+ * e_cal_component_parameter_bag_set_from_property:
+ * @bag: an #ECalComponentParameterBag
+ * @property: an #ICalProperty containing the parameters to fill the @bag with
+ * @func: (nullable) (scope call): an optional %ECalComponentParameterBagFilterFunc callback
+ * @user_data: (closure func): user data for the @func
+ *
+ * Fills the @bag with parameters from the @property, for which the @func
+ * returned %TRUE. When the @func is %NULL, all the parameters are included.
+ * The @bag content is cleared before any parameter is added.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_set_from_property (ECalComponentParameterBag *bag,
+                                                const ICalProperty *property,
+                                                ECalComponentParameterBagFilterFunc func,
+                                                gpointer user_data)
+{
+       ICalProperty *prop = (ICalProperty *) property;
+       ICalParameter *param;
+
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+
+       e_cal_component_parameter_bag_clear (bag);
+
+       for (param = i_cal_property_get_first_parameter (prop, I_CAL_ANY_PARAMETER);
+            param;
+            g_object_unref (param), param = i_cal_property_get_next_parameter (prop, I_CAL_ANY_PARAMETER)) {
+               if (!func || func (param, user_data)) {
+                       e_cal_component_parameter_bag_add (bag, param);
+               }
+       }
+}
+
+/**
+ * e_cal_component_parameter_bag_fill_property:
+ * @bag: an #ECalComponentParameterBag
+ * @property: an #ICalProperty
+ *
+ * Adds all the stored parameters in the @bag to the @property.
+ * The function replaces any existing parameter with the new value,
+ * if any such exists. Otherwise the parameter is added.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_fill_property (const ECalComponentParameterBag *bag,
+                                            ICalProperty *property)
+{
+       guint ii;
+
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (property));
+
+       for (ii = 0; ii < bag->parameters->len; ii++) {
+               ICalParameter *param = g_ptr_array_index (bag->parameters, ii);
+
+               if (param)
+                       i_cal_property_take_parameter (property, i_cal_parameter_new_clone (param));
+       }
+}
+
+/**
+ * e_cal_component_parameter_bag_assign:
+ * @bag: a destination #ECalComponentParameterBag
+ * @src_bag: a source #ECalComponentParameterBag
+ *
+ * Assigns content of the @src_bag into the @bag.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_assign (ECalComponentParameterBag *bag,
+                                    const ECalComponentParameterBag *src_bag)
+{
+       guint count, ii;
+
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (src_bag != NULL);
+
+       e_cal_component_parameter_bag_clear (bag);
+       count = e_cal_component_parameter_bag_get_count (src_bag);
+
+       if (count) {
+               for (ii = 0; ii < count; ii++) {
+                       ICalParameter *param;
+
+                       param = e_cal_component_parameter_bag_get (src_bag, ii);
+
+                       e_cal_component_parameter_bag_add (bag, param);
+               }
+       }
+}
+
+/**
+ * e_cal_component_parameter_bag_add:
+ * @bag: an #ECalComponentParameterBag
+ * @param: an #ICalParameter
+ *
+ * Adds a copy of the @param into the @bag.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_add (ECalComponentParameterBag *bag,
+                                 const ICalParameter *param)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_PARAMETER (param));
+
+       e_cal_component_parameter_bag_take (bag,
+               i_cal_parameter_new_clone ((ICalParameter *) param));
+}
+
+/**
+ * e_cal_component_parameter_bag_take:
+ * @bag: an #ECalComponentParameterBag
+ * @param: an #ICalParameter
+ *
+ * Adds the @param into the @bag and assumes ownership of the @param.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_take (ECalComponentParameterBag *bag,
+                                  ICalParameter *param)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_PARAMETER (param));
+
+       g_ptr_array_add (bag->parameters, param);
+}
+
+/**
+ * e_cal_component_parameter_bag_get_count:
+ * @bag: an #ECalComponentParameterBag
+ *
+ * Returns: how many parameters are stored in the @bag
+ *
+ * Since: 3.36
+ **/
+guint
+e_cal_component_parameter_bag_get_count (const ECalComponentParameterBag *bag)
+{
+       g_return_val_if_fail (bag != NULL, 0);
+       g_return_val_if_fail (bag->parameters != NULL, 0);
+
+       return bag->parameters->len;
+}
+
+/**
+ * e_cal_component_parameter_bag_get:
+ * @bag: an #ECalComponentParameterBag
+ * @index: an index of the parameter to get
+ *
+ * Returns the #ICalParameter at the given @index. If the @index is
+ * out of bounds (not lower than e_cal_component_parameter_bag_get_count()),
+ * then %NULL is returned.
+ *
+ * The returned parameter is owned by the @bag and should not be freed
+ * by the caller.
+ *
+ * Returns: (transfer none) (nullable): the #ICalParameter at the given @index,
+ *    or %NULL on error
+ *
+ * Since: 3.36
+ **/
+ICalParameter *
+e_cal_component_parameter_bag_get (const ECalComponentParameterBag *bag,
+                                 guint index)
+{
+       g_return_val_if_fail (bag != NULL, NULL);
+       g_return_val_if_fail (bag->parameters != NULL, NULL);
+
+       if (index >= bag->parameters->len)
+               return NULL;
+
+       return g_ptr_array_index (bag->parameters, index);
+}
+
+/**
+ * e_cal_component_parameter_bag_get_first_by_kind:
+ * @bag: an #ECalComponentParameterBag
+ * @kind: an #ICalParameterKind to search for
+ *
+ * Returns: the index of the first parameter of the given @kind, or value
+ *    out of bounds, if such parameter cannot be found
+ *
+ * Since: 3.36
+ **/
+guint
+e_cal_component_parameter_bag_get_first_by_kind (const ECalComponentParameterBag *bag,
+                                                ICalParameterKind kind)
+{
+       guint index;
+
+       g_return_val_if_fail (bag != NULL, ~0);
+       g_return_val_if_fail (bag->parameters != NULL, ~0);
+
+       for (index = 0; index < bag->parameters->len; index++) {
+               ICalParameter *param;
+
+               param = g_ptr_array_index (bag->parameters, index);
+               if (param && i_cal_parameter_isa (param) == kind)
+                       return index;
+       }
+
+       return ~0;
+}
+
+/**
+ * e_cal_component_parameter_bag_remove:
+ * @bag: an #ECalComponentParameterBag
+ * @index: an index of the parameter to remove
+ *
+ * Removes the #ICalParameter at the given @index. If the @index is
+ * out of bounds (not lower than e_cal_component_parameter_bag_get_count()),
+ * then the function does nothing.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_remove (ECalComponentParameterBag *bag,
+                                    guint index)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (bag->parameters != NULL);
+
+       if (index < bag->parameters->len)
+               g_ptr_array_remove_index (bag->parameters, index);
+}
+
+/**
+ * e_cal_component_parameter_bag_remove_by_kind:
+ * @bag: an #ECalComponentParameterBag
+ * @kind: an #ICalParameterKind to remove
+ * @all: %TRUE to remove all parameters of the @kind, or %FALSE to only the first
+ *
+ * Removes the first or all (depending on the @all) parameters of the given @kind.
+ *
+ * Returns: how many parameters had been removed
+ *
+ * Since: 3.36
+ **/
+guint
+e_cal_component_parameter_bag_remove_by_kind (ECalComponentParameterBag *bag,
+                                             ICalParameterKind kind,
+                                             gboolean all)
+{
+       guint index, count = 0;
+
+       g_return_val_if_fail (bag != NULL, 0);
+       g_return_val_if_fail (bag->parameters != NULL, 0);
+
+       index = 0;
+       while (index < bag->parameters->len) {
+               ICalParameter *param;
+
+               param = g_ptr_array_index (bag->parameters, index);
+               if (param && i_cal_parameter_isa (param) == kind) {
+                       g_ptr_array_remove_index (bag->parameters, index);
+                       count++;
+
+                       if (!all)
+                               break;
+               } else {
+                       index++;
+               }
+       }
+
+       return count;
+}
+
+/**
+ * e_cal_component_parameter_bag_clear:
+ * @bag: an #ECalComponentParameterBag
+ *
+ * Removes all parameters from the @bag, thus it doesn't contain any
+ * parameter after this function returns.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_parameter_bag_clear (ECalComponentParameterBag *bag)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (bag->parameters != NULL);
+
+       g_ptr_array_set_size (bag->parameters, 0);
+}
diff --git a/src/calendar/libecal/e-cal-component-parameter-bag.h 
b/src/calendar/libecal/e-cal-component-parameter-bag.h
new file mode 100644
index 000000000..ca2b77fd7
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-parameter-bag.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_PARAMETER_BAG_H
+#define E_CAL_COMPONENT_PARAMETER_BAG_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentParameterBag:
+ *
+ * Opaque structure, which represents a bad (list) of #ICalParameter objects.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentParameterBag ECalComponentParameterBag;
+
+/**
+ * ECalComponentParameterBagFilterFunc:
+ * @parameter: an #ICalParameter
+ * @user_data: user data for the callback
+ *
+ * A function used to filter which parameters should be added to the bag,
+ * when filling it with e_cal_component_parameter_bag_new_from_property()
+ * and e_cal_component_parameter_bag_set_from_property().
+ *
+ * Returns: %TRUE, to add the parameter to the bag; %FALSE, to not add it to the bag
+ *
+ * Since: 3.36
+ **/
+typedef gboolean (* ECalComponentParameterBagFilterFunc)
+                                               (ICalParameter *parameter,
+                                                gpointer user_data);
+
+GType          e_cal_component_parameter_bag_get_type
+                                               (void);
+ECalComponentParameterBag *
+               e_cal_component_parameter_bag_new
+                                               (void);
+ECalComponentParameterBag *
+               e_cal_component_parameter_bag_new_from_property
+                                               (const ICalProperty *property,
+                                                ECalComponentParameterBagFilterFunc func,
+                                                gpointer user_data);
+ECalComponentParameterBag *
+               e_cal_component_parameter_bag_copy
+                                               (const ECalComponentParameterBag *bag);
+void           e_cal_component_parameter_bag_free
+                                               (gpointer bag); /* ECalComponentParameterBag * */
+void           e_cal_component_parameter_bag_set_from_property
+                                               (ECalComponentParameterBag *bag,
+                                                const ICalProperty *property,
+                                                ECalComponentParameterBagFilterFunc func,
+                                                gpointer user_data);
+void           e_cal_component_parameter_bag_fill_property
+                                               (const ECalComponentParameterBag *bag,
+                                                ICalProperty *property);
+void           e_cal_component_parameter_bag_assign
+                                               (ECalComponentParameterBag *bag,
+                                                const ECalComponentParameterBag *src_bag);
+void           e_cal_component_parameter_bag_add(ECalComponentParameterBag *bag,
+                                                const ICalParameter *param);
+void           e_cal_component_parameter_bag_take
+                                               (ECalComponentParameterBag *bag,
+                                                ICalParameter *param);
+guint          e_cal_component_parameter_bag_get_count
+                                               (const ECalComponentParameterBag *bag);
+ICalParameter *        e_cal_component_parameter_bag_get(const ECalComponentParameterBag *bag,
+                                                guint index);
+guint          e_cal_component_parameter_bag_get_first_by_kind
+                                               (const ECalComponentParameterBag *bag,
+                                                ICalParameterKind kind);
+void           e_cal_component_parameter_bag_remove
+                                               (ECalComponentParameterBag *bag,
+                                                guint index);
+guint          e_cal_component_parameter_bag_remove_by_kind
+                                               (ECalComponentParameterBag *bag,
+                                                ICalParameterKind kind,
+                                                gboolean all);
+void           e_cal_component_parameter_bag_clear
+                                               (ECalComponentParameterBag *bag);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_PARAMETER_BAG_H */
diff --git a/src/calendar/libecal/e-cal-component-period.c b/src/calendar/libecal/e-cal-component-period.c
new file mode 100644
index 000000000..dca2e3068
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-period.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-period
+ * @short_description: An ECalComponentPeriod structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentPeriod structure.
+ **/
+
+#include "e-cal-component-period.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentPeriod, e_cal_component_period, e_cal_component_period_copy, 
e_cal_component_period_free)
+
+struct _ECalComponentPeriod {
+       ECalComponentPeriodKind kind;
+
+       ICalTime *start;
+
+       /* Only one of 'end' and 'duration' can be set, depending on the kind */
+       ICalTime *end;
+       ICalDuration *duration;
+};
+
+/**
+ * e_cal_component_period_new_datetime:
+ * @start: (not nullable): an #ICalTime, the start of the period
+ * @end: (nullable): an #ICalTime, the end of the period
+ *
+ * Creates a new #ECalComponentPeriod of kind %E_CAL_COMPONENT_PERIOD_DATETIME.
+ * The returned structure should be freed with e_cal_component_period_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentPeriod
+ *
+ * Since: 3.36
+ **/
+ECalComponentPeriod *
+e_cal_component_period_new_datetime (const ICalTime *start,
+                                    const ICalTime *end)
+{
+       ECalComponentPeriod *period;
+
+       g_return_val_if_fail (I_CAL_IS_TIME (start), NULL);
+
+       period = g_new0 (ECalComponentPeriod, 1);
+       period->kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+
+       e_cal_component_period_set_datetime_full (period, start, end);
+
+       return period;
+}
+
+/**
+ * e_cal_component_period_new_duration:
+ * @start: (not nullable): an #ICalTime, the start of the period
+ * @duration: (not nullable): an #ICalDuration, the duration of the period
+ *
+ * Creates a new #ECalComponentPeriod of kind %E_CAL_COMPONENT_PERIOD_DURATION.
+ * The returned structure should be freed with e_cal_component_period_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentPeriod
+ *
+ * Since: 3.36
+ **/
+ECalComponentPeriod *
+e_cal_component_period_new_duration (const ICalTime *start,
+                                    const ICalDuration *duration)
+{
+       ECalComponentPeriod *period;
+
+       g_return_val_if_fail (I_CAL_IS_TIME (start), NULL);
+       g_return_val_if_fail (I_CAL_IS_DURATION (duration), NULL);
+
+       period = g_new0 (ECalComponentPeriod, 1);
+       period->kind = E_CAL_COMPONENT_PERIOD_DURATION;
+
+       e_cal_component_period_set_duration_full (period, start, duration);
+
+       return period;
+}
+
+/**
+ * e_cal_component_period_copy:
+ * @period: (not nullable): an #ECalComponentPeriod to copy
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentPeriod, copy of @period.
+ *    The returned structure should be freed with e_cal_component_period_free(),
+ *    when no longer needed.
+ *
+ * Since: 3.36
+ **/
+ECalComponentPeriod *
+e_cal_component_period_copy (const ECalComponentPeriod *period)
+{
+       ECalComponentPeriod *copy = NULL;
+
+       g_return_val_if_fail (period != NULL, NULL);
+
+       switch (e_cal_component_period_get_kind (period)) {
+       case E_CAL_COMPONENT_PERIOD_DATETIME:
+               copy = e_cal_component_period_new_datetime (
+                       e_cal_component_period_get_start (period),
+                       e_cal_component_period_get_end (period));
+               break;
+       case E_CAL_COMPONENT_PERIOD_DURATION:
+               copy = e_cal_component_period_new_duration (
+                       e_cal_component_period_get_start (period),
+                       e_cal_component_period_get_duration (period));
+               break;
+       }
+
+       return copy;
+}
+
+/**
+ * e_cal_component_period_free: (skip)
+ * @period: (type ECalComponentPeriod) (nullable): an #ECalComponentPeriod to free
+ *
+ * Free the @period, previously allocated by e_cal_component_period_new_datetime(),
+ * e_cal_component_period_new_duration() or e_cal_component_period_copy().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_period_free (gpointer period)
+{
+       ECalComponentPeriod *pd = period;
+
+       if (pd) {
+               g_clear_object (&pd->start);
+               g_clear_object (&pd->end);
+               g_clear_object (&pd->duration);
+               g_free (pd);
+       }
+}
+
+/**
+ * e_cal_component_period_get_kind:
+ * @period: an #ECalComponentPeriod
+ *
+ * Returns kind of the @period, one of #ECalComponentPeriodKind. Depending
+ * on it either e_cal_component_period_get_end()/e_cal_component_period_set_end()
+ * or e_cal_component_period_get_duration()/e_cal_component_period_set_duration()
+ * can be used. The kind of an existing @period canbe changed with
+ * e_cal_component_period_set_datetime_full() and e_cal_component_period_set_duration_full().
+ *
+ * Returns: kind of the period, one of #ECalComponentPeriodKind
+ *
+ * Since: 3.36
+ **/
+ECalComponentPeriodKind
+e_cal_component_period_get_kind        (const ECalComponentPeriod *period)
+{
+       g_return_val_if_fail (period != NULL, E_CAL_COMPONENT_PERIOD_DATETIME);
+
+       return period->kind;
+}
+
+/**
+ * e_cal_component_period_set_datetime_full:
+ * @period: an #ECalComponentPeriod
+ * @start: (not nullable): an #ICalTime, the start of the @period
+ * @end: (nullable): an #ICalTime, the end of the @period
+ *
+ * Set the kind of @period to be %E_CAL_COMPONENT_PERIOD_DATETIME
+ * and fills the content with @start and @end.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_period_set_datetime_full (ECalComponentPeriod *period,
+                                         const ICalTime *start,
+                                         const ICalTime *end)
+{
+       g_return_if_fail (period != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (start));
+
+       g_clear_object (&period->duration);
+
+       period->kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+
+       e_cal_component_period_set_start (period, start);
+       e_cal_component_period_set_end (period, end);
+}
+
+/**
+ * e_cal_component_period_set_duration_full:
+ * @period: an #ECalComponentPeriod
+ * @start: (not nullable): an #ICalTime, the start of the @period
+ * @duration: (not nullable): an #ICalDuration, the duration of the @period
+ *
+ * Set the kind of @period to be %E_CAL_COMPONENT_PERIOD_DURATION
+ * and fills the content with @start and @duration.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_period_set_duration_full (ECalComponentPeriod *period,
+                                         const ICalTime *start,
+                                         const ICalDuration *duration)
+{
+       g_return_if_fail (period != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (start));
+       g_return_if_fail (I_CAL_IS_DURATION (duration));
+
+       g_clear_object (&period->end);
+
+       period->kind = E_CAL_COMPONENT_PERIOD_DURATION;
+
+       e_cal_component_period_set_start (period, start);
+       e_cal_component_period_set_duration (period, duration);
+}
+
+/**
+ * e_cal_component_period_get_start:
+ * @period: an #ECalComponentPeriod
+ *
+ * Returns the start of the @period. The returned #ICalTime object
+ * is owned by @period and should not be freed. It's valid until the @period
+ * is freed or its start time changed.
+ *
+ * Returns: (transfer none): the start of the @period, as an #ICalTime
+ *
+ * Since: 3.36
+ **/
+ICalTime *
+e_cal_component_period_get_start (const ECalComponentPeriod *period)
+{
+       g_return_val_if_fail (period != NULL, NULL);
+
+       return period->start;
+}
+
+/**
+ * e_cal_component_period_set_start:
+ * @period: an #ECalComponentPeriod
+ * @start: (not nullable): an #ICalTime, the start of the @period
+ *
+ * Set the @start of the @period. This can be called on any kind of the @period.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_period_set_start (ECalComponentPeriod *period,
+                                 const ICalTime *start)
+{
+       g_return_if_fail (period != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (start));
+
+       if (period->start != start) {
+               g_clear_object (&period->start);
+               period->start = i_cal_time_new_clone (start);
+       }
+}
+
+/**
+ * e_cal_component_period_get_end:
+ * @period: an #ECalComponentPeriod
+ *
+ * Returns the end of the @period. This can be called only on @period
+ * objects of kind %E_CAL_COMPONENT_PERIOD_DATETIME. The end time can
+ * be a null-time, in which case the @period corresponds to a single
+ * date/date-time value, not to a period.
+ *
+ * The returned #ICalTime object is owned by @period and should not
+ * be freed. It's valid until the @period is freed or its end time changed.
+ *
+ * Returns: (transfer none) (nullable): the end of the period, as an #ICalTime
+ *
+ * Since: 3.36
+ **/
+ICalTime *
+e_cal_component_period_get_end (const ECalComponentPeriod *period)
+{
+       g_return_val_if_fail (period != NULL, NULL);
+       g_return_val_if_fail (period->kind == E_CAL_COMPONENT_PERIOD_DATETIME, NULL);
+
+       return period->end;
+}
+
+/**
+ * e_cal_component_period_set_end:
+ * @period: an #ECalComponentPeriod
+ * @end: (nullable): an #ICalTime, the end of the @period
+ *
+ * Set the end of the @period. This can be called only on @period
+ * objects of kind %E_CAL_COMPONENT_PERIOD_DATETIME.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_period_set_end (ECalComponentPeriod *period,
+                               const ICalTime *end)
+{
+       g_return_if_fail (period != NULL);
+       g_return_if_fail (period->kind == E_CAL_COMPONENT_PERIOD_DATETIME);
+
+       if (period->end != end) {
+               g_clear_object (&period->end);
+               if (end)
+                       period->end = i_cal_time_new_clone (end);
+       }
+}
+
+/**
+ * e_cal_component_period_get_duration:
+ * @period: an #ECalComponentPeriod
+ *
+ * Returns the duration of the @period. This can be called only on @period
+ * objects of kind %E_CAL_COMPONENT_PERIOD_DURATION.
+ * The returned #ICalDuration object is owned by @period and should not
+ * be freed. It's valid until the @period is freed or its duration changed.
+ *
+ * Returns: (transfer none): the duration of the period, as an #ICalDuration
+ *
+ * Since: 3.36
+ **/
+ICalDuration *
+e_cal_component_period_get_duration (const ECalComponentPeriod *period)
+{
+       g_return_val_if_fail (period != NULL, NULL);
+       g_return_val_if_fail (period->kind == E_CAL_COMPONENT_PERIOD_DURATION, NULL);
+
+       return period->duration;
+}
+
+/**
+ * e_cal_component_period_set_duration:
+ * @period: an #ECalComponentPeriod
+ * @duration: (not nullable): an #ICalDuration, the duration of the @period
+ *
+ * Set the duration of the @period. This can be called only on @period
+ * objects of kind %E_CAL_COMPONENT_PERIOD_DURATION.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_period_set_duration (ECalComponentPeriod *period,
+                                    const ICalDuration *duration)
+{
+       g_return_if_fail (period != NULL);
+       g_return_if_fail (period->kind == E_CAL_COMPONENT_PERIOD_DURATION);
+       g_return_if_fail (I_CAL_IS_DURATION (duration));
+
+       if (period->duration != duration) {
+               g_clear_object (&period->duration);
+               period->duration = i_cal_duration_from_int (i_cal_duration_as_int ((ICalDuration *) 
duration));
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-period.h b/src/calendar/libecal/e-cal-component-period.h
new file mode 100644
index 000000000..3ee42e47c
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-period.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_PERIOD_H
+#define E_CAL_COMPONENT_PERIOD_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+#include <libecal/e-cal-enums.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentPeriod:
+ *
+ * Period of time, can have explicit start/end times or start/duration instead.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentPeriod ECalComponentPeriod;
+
+GType          e_cal_component_period_get_type (void);
+ECalComponentPeriod *
+               e_cal_component_period_new_datetime
+                                               (const ICalTime *start,
+                                                const ICalTime *end);
+ECalComponentPeriod *
+               e_cal_component_period_new_duration
+                                               (const ICalTime *start,
+                                                const ICalDuration *duration);
+ECalComponentPeriod *
+               e_cal_component_period_copy     (const ECalComponentPeriod *period);
+void           e_cal_component_period_free     (gpointer period); /* ECalComponentPeriod * */
+ECalComponentPeriodKind
+               e_cal_component_period_get_kind (const ECalComponentPeriod *period);
+void           e_cal_component_period_set_datetime_full
+                                               (ECalComponentPeriod *period,
+                                                const ICalTime *start,
+                                                const ICalTime *end);
+void           e_cal_component_period_set_duration_full
+                                               (ECalComponentPeriod *period,
+                                                const ICalTime *start,
+                                                const ICalDuration *duration);
+ICalTime *     e_cal_component_period_get_start(const ECalComponentPeriod *period);
+void           e_cal_component_period_set_start(ECalComponentPeriod *period,
+                                                const ICalTime *start);
+ICalTime *     e_cal_component_period_get_end  (const ECalComponentPeriod *period);
+void           e_cal_component_period_set_end  (ECalComponentPeriod *period,
+                                                const ICalTime *end);
+ICalDuration * e_cal_component_period_get_duration
+                                               (const ECalComponentPeriod *period);
+void           e_cal_component_period_set_duration
+                                               (ECalComponentPeriod *period,
+                                                const ICalDuration *duration);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_PERIOD_H */
diff --git a/src/calendar/libecal/e-cal-component-property-bag.c 
b/src/calendar/libecal/e-cal-component-property-bag.c
new file mode 100644
index 000000000..7ff36af5d
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-property-bag.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-property-bag
+ * @short_description: An ECalComponentPropertyBag structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentPropertyBag structure.
+ **/
+
+#include "e-cal-component-property-bag.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentPropertyBag, e_cal_component_property_bag, 
e_cal_component_property_bag_copy, e_cal_component_property_bag_free)
+
+struct _ECalComponentPropertyBag {
+       GPtrArray *properties; /* ICalProperty * */
+};
+
+/**
+ * e_cal_component_property_bag_new:
+ *
+ * Creates a new #ECalComponentPropertyBag. Free the structure
+ * with e_cal_component_property_bag_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentPropertyBag
+ *
+ * Since: 3.36
+ **/
+ECalComponentPropertyBag *
+e_cal_component_property_bag_new (void)
+{
+       ECalComponentPropertyBag *bag;
+
+       bag = g_new0 (ECalComponentPropertyBag, 1);
+       bag->properties = g_ptr_array_new_with_free_func (g_object_unref);
+
+       return bag;
+}
+
+/**
+ * e_cal_component_property_bag_new_from_component:
+ * @component: an #ICalComponent containing the properties to fill the bag with
+ * @func: (nullable) (scope call): an optional %ECalComponentPropertyBagFilterFunc callback
+ * @user_data: (closure func): user data for the @func
+ *
+ * Creates a new #ECalComponentPropertyBag, filled with properties
+ * from the @component, for which the @func returned %TRUE. When
+ * the @func is %NULL, all the properties are included.
+ *
+ * Free the structure with e_cal_component_property_bag_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentPropertyBag
+ *
+ * Since: 3.36
+ **/
+ECalComponentPropertyBag *
+e_cal_component_property_bag_new_from_component (const ICalComponent *component,
+                                                ECalComponentPropertyBagFilterFunc func,
+                                                gpointer user_data)
+{
+       ECalComponentPropertyBag *bag;
+
+       bag = e_cal_component_property_bag_new ();
+
+       e_cal_component_property_bag_set_from_component (bag, component, func, user_data);
+
+       return bag;
+}
+
+/**
+ * e_cal_component_property_bag_copy:
+ * @bag: (not nullable): an #ECalComponentPropertyBag
+ *
+ * Returns a newly allocated copy of @bag, which should be freed with
+ * e_cal_component_property_bag_free(), when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated copy of @bag
+ *
+ * Since: 3.36
+ **/
+ECalComponentPropertyBag *
+e_cal_component_property_bag_copy (const ECalComponentPropertyBag *bag)
+{
+       ECalComponentPropertyBag *copy;
+
+       g_return_val_if_fail (bag != NULL, NULL);
+
+       copy = e_cal_component_property_bag_new ();
+
+       e_cal_component_property_bag_assign (copy, bag);
+
+       return copy;
+}
+
+/**
+ * e_cal_component_property_bag_free: (skip)
+ * @bag: (type ECalComponentPropertyBag) (nullable): an #ECalComponentPropertyBag to free
+ *
+ * Free @bag, previously created by e_cal_component_property_bag_new(),
+ * e_cal_component_property_bag_new_from_component() or
+ * e_cal_component_property_bag_copy(). The function does nothing, if @bag
+ * is %NULL.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_free (gpointer bag)
+{
+       ECalComponentPropertyBag *bg = bag;
+
+       if (bg) {
+               g_ptr_array_unref (bg->properties);
+               g_free (bg);
+       }
+}
+
+/**
+ * e_cal_component_property_bag_set_from_component:
+ * @bag: an #ECalComponentPropertyBag
+ * @component: an #ICalComponent containing the properties to fill the @bag with
+ * @func: (nullable) (scope call): an optional %ECalComponentPropertyBagFilterFunc callback
+ * @user_data: (closure func): user data for the @func
+ *
+ * Fills the @bag with properties from the @component, for which the @func
+ * returned %TRUE. When the @func is %NULL, all the properties are included.
+ * The @bag content is cleared before any property is added.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_set_from_component (ECalComponentPropertyBag *bag,
+                                                const ICalComponent *component,
+                                                ECalComponentPropertyBagFilterFunc func,
+                                                gpointer user_data)
+{
+       ICalComponent *comp = (ICalComponent *) component;
+       ICalProperty *prop;
+
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_COMPONENT (component));
+
+       e_cal_component_property_bag_clear (bag);
+
+       for (prop = i_cal_component_get_first_property (comp, I_CAL_ANY_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (comp, I_CAL_ANY_PROPERTY)) {
+               if (!func || func (prop, user_data)) {
+                       e_cal_component_property_bag_add (bag, prop);
+               }
+       }
+}
+
+/**
+ * e_cal_component_property_bag_fill_component:
+ * @bag: an #ECalComponentPropertyBag
+ * @component: an #ICalComponent
+ *
+ * Adds all the stored properties in the @bag to the @component.
+ * The function doesn't verify whether the @component contains
+ * the same property already.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_fill_component (const ECalComponentPropertyBag *bag,
+                                            ICalComponent *component)
+{
+       guint ii;
+
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_COMPONENT (component));
+
+       for (ii = 0; ii < bag->properties->len; ii++) {
+               ICalProperty *prop = g_ptr_array_index (bag->properties, ii);
+
+               if (prop)
+                       i_cal_component_take_property (component, i_cal_property_new_clone (prop));
+       }
+}
+
+/**
+ * e_cal_component_property_bag_assign:
+ * @bag: a destination #ECalComponentPropertyBag
+ * @src_bag: a source #ECalComponentPropertyBag
+ *
+ * Assigns content of the @src_bag into the @bag.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_assign (ECalComponentPropertyBag *bag,
+                                    const ECalComponentPropertyBag *src_bag)
+{
+       guint count, ii;
+
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (src_bag != NULL);
+
+       e_cal_component_property_bag_clear (bag);
+       count = e_cal_component_property_bag_get_count (src_bag);
+
+       if (count) {
+               for (ii = 0; ii < count; ii++) {
+                       ICalProperty *prop;
+
+                       prop = e_cal_component_property_bag_get (src_bag, ii);
+
+                       e_cal_component_property_bag_add (bag, prop);
+               }
+       }
+}
+
+/**
+ * e_cal_component_property_bag_add:
+ * @bag: an #ECalComponentPropertyBag
+ * @prop: an #ICalProperty
+ *
+ * Adds a copy of the @prop into the @bag.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_add (ECalComponentPropertyBag *bag,
+                                 const ICalProperty *prop)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (prop));
+
+       e_cal_component_property_bag_take (bag,
+               i_cal_property_new_clone ((ICalProperty *) prop));
+}
+
+/**
+ * e_cal_component_property_bag_take:
+ * @bag: an #ECalComponentPropertyBag
+ * @prop: an #ICalProperty
+ *
+ * Adds the @prop into the @bag and assumes ownership of the @prop.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_take (ECalComponentPropertyBag *bag,
+                                  ICalProperty *prop)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (I_CAL_IS_PROPERTY (prop));
+
+       g_ptr_array_add (bag->properties, prop);
+}
+
+/**
+ * e_cal_component_property_bag_get_count:
+ * @bag: an #ECalComponentPropertyBag
+ *
+ * Returns: how many properties are stored in the @bag
+ *
+ * Since: 3.36
+ **/
+guint
+e_cal_component_property_bag_get_count (const ECalComponentPropertyBag *bag)
+{
+       g_return_val_if_fail (bag != NULL, 0);
+       g_return_val_if_fail (bag->properties != NULL, 0);
+
+       return bag->properties->len;
+}
+
+/**
+ * e_cal_component_property_bag_get:
+ * @bag: an #ECalComponentPropertyBag
+ * @index: an index of the property to get
+ *
+ * Returns the #ICalProperty at the given @index. If the @index is
+ * out of bounds (not lower than e_cal_component_property_bag_get_count()),
+ * then %NULL is returned.
+ *
+ * The returned property is owned by the @bag and should not be freed
+ * by the caller.
+ *
+ * Returns: (transfer none) (nullable): the #ICalProperty at the given @index,
+ *    or %NULL on error
+ *
+ * Since: 3.36
+ **/
+ICalProperty *
+e_cal_component_property_bag_get (const ECalComponentPropertyBag *bag,
+                                 guint index)
+{
+       g_return_val_if_fail (bag != NULL, NULL);
+       g_return_val_if_fail (bag->properties != NULL, NULL);
+
+       if (index >= bag->properties->len)
+               return NULL;
+
+       return g_ptr_array_index (bag->properties, index);
+}
+
+/**
+ * e_cal_component_property_bag_get_first_by_kind:
+ * @bag: an #ECalComponentPropertyBag
+ * @kind: an #ICalPropertyKind to search for
+ *
+ * Returns: the index of the first property of the given @kind, or value
+ *    out of bounds, if such property cannot be found
+ *
+ * Since: 3.36
+ **/
+guint
+e_cal_component_property_bag_get_first_by_kind (const ECalComponentPropertyBag *bag,
+                                               ICalPropertyKind kind)
+{
+       guint index;
+
+       g_return_val_if_fail (bag != NULL, ~0);
+       g_return_val_if_fail (bag->properties != NULL, ~0);
+
+       for (index = 0; index < bag->properties->len; index++) {
+               ICalProperty *prop;
+
+               prop = g_ptr_array_index (bag->properties, index);
+               if (prop && i_cal_property_isa (prop) == kind)
+                       return index;
+       }
+
+       return ~0;
+}
+
+/**
+ * e_cal_component_property_bag_remove:
+ * @bag: an #ECalComponentPropertyBag
+ * @index: an index of the property to remove
+ *
+ * Removes the #ICalProperty at the given @index. If the @index is
+ * out of bounds (not lower than e_cal_component_property_bag_get_count()),
+ * then the function does nothing.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_remove (ECalComponentPropertyBag *bag,
+                                    guint index)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (bag->properties != NULL);
+
+       if (index < bag->properties->len)
+               g_ptr_array_remove_index (bag->properties, index);
+}
+
+/**
+ * e_cal_component_property_bag_remove_by_kind:
+ * @bag: an #ECalComponentPropertyBag
+ * @kind: an #ICalPropertyKind to remove
+ * @all: %TRUE to remove all properties of the @kind, or %FALSE to only the first
+ *
+ * Removes the first or all (depending on the @all) properties of the given @kind.
+ *
+ * Returns: how many properties had been removed
+ *
+ * Since: 3.36
+ **/
+guint
+e_cal_component_property_bag_remove_by_kind (ECalComponentPropertyBag *bag,
+                                            ICalPropertyKind kind,
+                                            gboolean all)
+{
+       guint index, count = 0;
+
+       g_return_val_if_fail (bag != NULL, 0);
+       g_return_val_if_fail (bag->properties != NULL, 0);
+
+       index = 0;
+       while (index < bag->properties->len) {
+               ICalProperty *prop;
+
+               prop = g_ptr_array_index (bag->properties, index);
+               if (prop && i_cal_property_isa (prop) == kind) {
+                       g_ptr_array_remove_index (bag->properties, index);
+                       count++;
+
+                       if (!all)
+                               break;
+               } else {
+                       index++;
+               }
+       }
+
+       return count;
+}
+
+/**
+ * e_cal_component_property_bag_clear:
+ * @bag: an #ECalComponentPropertyBag
+ *
+ * Removes all properties from the @bag, thus it doesn't contain any
+ * property after this function returns.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_property_bag_clear (ECalComponentPropertyBag *bag)
+{
+       g_return_if_fail (bag != NULL);
+       g_return_if_fail (bag->properties != NULL);
+
+       g_ptr_array_set_size (bag->properties, 0);
+}
diff --git a/src/calendar/libecal/e-cal-component-property-bag.h 
b/src/calendar/libecal/e-cal-component-property-bag.h
new file mode 100644
index 000000000..537c2c6ae
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-property-bag.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_PROPERTY_BAG_H
+#define E_CAL_COMPONENT_PROPERTY_BAG_H
+
+#include <glib-object.h>
+#include <libical-glib/libical-glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentPropertyBag:
+ *
+ * Opaque structure, which represents a bad (list) of #ICalProperty objects.
+ * Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentPropertyBag ECalComponentPropertyBag;
+
+/**
+ * ECalComponentPropertyBagFilterFunc:
+ * @property: an #ICalProperty
+ * @user_data: user data for the callback
+ *
+ * A function used to filter which properties should be added to the bag,
+ * when filling it with e_cal_component_property_bag_new_from_component()
+ * and e_cal_component_property_bag_set_from_component().
+ *
+ * Returns: %TRUE, to add the property to the bag; %FALSE, to not add it to the bag
+ *
+ * Since: 3.36
+ **/
+typedef gboolean (* ECalComponentPropertyBagFilterFunc)
+                                               (ICalProperty *property,
+                                                gpointer user_data);
+
+GType          e_cal_component_property_bag_get_type
+                                               (void);
+ECalComponentPropertyBag *
+               e_cal_component_property_bag_new(void);
+ECalComponentPropertyBag *
+               e_cal_component_property_bag_new_from_component
+                                               (const ICalComponent *component,
+                                                ECalComponentPropertyBagFilterFunc func,
+                                                gpointer user_data);
+ECalComponentPropertyBag *
+               e_cal_component_property_bag_copy
+                                               (const ECalComponentPropertyBag *bag);
+void           e_cal_component_property_bag_free
+                                               (gpointer bag); /* ECalComponentPropertyBag * */
+void           e_cal_component_property_bag_set_from_component
+                                               (ECalComponentPropertyBag *bag,
+                                                const ICalComponent *component,
+                                                ECalComponentPropertyBagFilterFunc func,
+                                                gpointer user_data);
+void           e_cal_component_property_bag_fill_component
+                                               (const ECalComponentPropertyBag *bag,
+                                                ICalComponent *component);
+void           e_cal_component_property_bag_assign
+                                               (ECalComponentPropertyBag *bag,
+                                                const ECalComponentPropertyBag *src_bag);
+void           e_cal_component_property_bag_add(ECalComponentPropertyBag *bag,
+                                                const ICalProperty *prop);
+void           e_cal_component_property_bag_take
+                                               (ECalComponentPropertyBag *bag,
+                                                ICalProperty *prop);
+guint          e_cal_component_property_bag_get_count
+                                               (const ECalComponentPropertyBag *bag);
+ICalProperty * e_cal_component_property_bag_get(const ECalComponentPropertyBag *bag,
+                                                guint index);
+guint          e_cal_component_property_bag_get_first_by_kind
+                                               (const ECalComponentPropertyBag *bag,
+                                                ICalPropertyKind kind);
+void           e_cal_component_property_bag_remove
+                                               (ECalComponentPropertyBag *bag,
+                                                guint index);
+guint          e_cal_component_property_bag_remove_by_kind
+                                               (ECalComponentPropertyBag *bag,
+                                                ICalPropertyKind kind,
+                                                gboolean all);
+void           e_cal_component_property_bag_clear
+                                               (ECalComponentPropertyBag *bag);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_PROPERTY_BAG_H */
diff --git a/src/calendar/libecal/e-cal-component-range.c b/src/calendar/libecal/e-cal-component-range.c
new file mode 100644
index 000000000..7003b1fa2
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-range.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-range
+ * @short_description: An ECalComponentRange structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentRange structure.
+ **/
+
+#include "e-cal-component-range.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentRange, e_cal_component_range, e_cal_component_range_copy, 
e_cal_component_range_free)
+
+struct _ECalComponentRange {
+       ECalComponentRangeKind kind;
+       ECalComponentDateTime *datetime;
+};
+
+/**
+ * e_cal_component_range_new:
+ * @kind: an #ECalComponentRangeKind
+ * @datetime: (not nullable): an #ECalComponentDateTime
+ *
+ * Creates a new #ECalComponentRange describing a range.
+ * The returned structure should be freed with e_cal_component_range_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentRange
+ *
+ * Since: 3.36
+ **/
+ECalComponentRange *
+e_cal_component_range_new (ECalComponentRangeKind kind,
+                          const ECalComponentDateTime *datetime)
+{
+       ECalComponentDateTime *dt;
+
+       g_return_val_if_fail (datetime != NULL, NULL);
+
+       dt = e_cal_component_datetime_copy (datetime);
+       g_return_val_if_fail (dt != NULL, NULL);
+
+       return e_cal_component_range_new_take (kind, dt);
+}
+
+/**
+ * e_cal_component_range_new_take: (skip)
+ * @kind: an #ECalComponentRangeKind
+ * @datetime: (not nullable) (transfer full): an #ECalComponentDateTime
+ *
+ * Creates a new #ECalComponentRange describing a range, similar to
+ * e_cal_component_range_new() except is assumes ownership of @datetime.
+ * The returned structure should be freed with e_cal_component_range_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentRange
+ *
+ * Since: 3.36
+ **/
+ECalComponentRange *
+e_cal_component_range_new_take (ECalComponentRangeKind kind,
+                               ECalComponentDateTime *datetime)
+{
+       ECalComponentRange *range;
+
+       g_return_val_if_fail (datetime != NULL, NULL);
+
+       range = g_new0 (ECalComponentRange, 1);
+       range->kind = kind;
+       range->datetime = datetime;
+
+       return range;
+}
+
+/**
+ * e_cal_component_range_copy:
+ * @range: (not nullable): an #ECalComponentRange to copy
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentRange, copy of @range.
+ *    The returned structure should be freed with e_cal_component_range_free(),
+ *    when no longer needed.
+ *
+ * Since: 3.36
+ **/
+ECalComponentRange *
+e_cal_component_range_copy (const ECalComponentRange *range)
+{
+       g_return_val_if_fail (range != NULL, NULL);
+
+       return e_cal_component_range_new (
+               e_cal_component_range_get_kind (range),
+               e_cal_component_range_get_datetime (range));
+}
+
+/**
+ * e_cal_component_range_free: (skip)
+ * @range: (type ECalComponentRange) (nullable): an #ECalComponentRange to free
+ *
+ * Free the @range, previously allocated by e_cal_component_range_new(),
+ * e_cal_component_range_new_take() or e_cal_component_range_copy().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_range_free (gpointer range)
+{
+       ECalComponentRange *rng = range;
+
+       if (rng) {
+               e_cal_component_datetime_free (rng->datetime);
+               g_free (rng);
+       }
+}
+
+/**
+ * e_cal_component_range_get_kind:
+ * @range: an #ECalComponentRange
+ *
+ * Returns: the #ECalComponentRangeKind of the @range
+ *
+ * Since: 3.36
+ **/
+ECalComponentRangeKind
+e_cal_component_range_get_kind (const ECalComponentRange *range)
+{
+       g_return_val_if_fail (range != NULL, E_CAL_COMPONENT_RANGE_SINGLE);
+
+       return range->kind;
+}
+
+/**
+ * e_cal_component_range_set_kind:
+ * @range: an #ECalComponentRange
+ * @kind: an #ECalComponentRangeKind
+ *
+ * Set the @kind of the @range.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_range_set_kind (ECalComponentRange *range,
+                               ECalComponentRangeKind kind)
+{
+       g_return_if_fail (range != NULL);
+
+       range->kind = kind;
+}
+
+/**
+ * e_cal_component_range_get_datetime:
+ * @range: an #ECalComponentRange
+ *
+ * Returns the date/time of the @range. The returned #ECalComponentDateTime
+ * is owned by @range and should not be freed. It's valid until the @range
+ * is freed or its date/time changed.
+ *
+ * Returns: (transfer none): the date/time of the @range, as an #ECalComponentDateTime
+ *
+ * Since: 3.36
+ **/
+ECalComponentDateTime *
+e_cal_component_range_get_datetime (const ECalComponentRange *range)
+{
+       g_return_val_if_fail (range != NULL, NULL);
+
+       return range->datetime;
+}
+
+/**
+ * e_cal_component_range_set_datetime:
+ * @range: an #ECalComponentRange
+ * @datetime: (not nullable): an #ECalComponentDateTime
+ *
+ * Set the date/time part of the @range.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_range_set_datetime (ECalComponentRange *range,
+                                   const ECalComponentDateTime *datetime)
+{
+       g_return_if_fail (range != NULL);
+       g_return_if_fail (datetime != NULL);
+
+       if (range->datetime != datetime) {
+               ECalComponentDateTime *dt;
+
+               dt = e_cal_component_datetime_copy (datetime);
+               g_return_if_fail (dt != NULL);
+
+               e_cal_component_range_take_datetime (range, dt);
+       }
+}
+
+/**
+ * e_cal_component_range_take_datetime: (skip)
+ * @range: an #ECalComponentRange
+ * @datetime: (not nullable) (transfer full): an #ECalComponentDateTime
+ *
+ * Set the date/time part of the @range, similar to e_cal_component_range_set_datetime(),
+ * except it assumes ownership of the @datetime.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_range_take_datetime (ECalComponentRange *range,
+                                    ECalComponentDateTime *datetime)
+{
+       g_return_if_fail (range != NULL);
+       g_return_if_fail (datetime != NULL);
+
+       if (range->datetime != datetime) {
+               e_cal_component_datetime_free (range->datetime);
+               range->datetime = datetime;
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-range.h b/src/calendar/libecal/e-cal-component-range.h
new file mode 100644
index 000000000..40a1b9863
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-range.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_RANGE_H
+#define E_CAL_COMPONENT_RANGE_H
+
+#include <glib-object.h>
+#include <libecal/e-cal-enums.h>
+#include <libecal/e-cal-component-datetime.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentRange:
+ *
+ * Describes a range. Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentRange ECalComponentRange;
+
+GType          e_cal_component_range_get_type  (void);
+ECalComponentRange *
+               e_cal_component_range_new       (ECalComponentRangeKind kind,
+                                                const ECalComponentDateTime *datetime);
+ECalComponentRange *
+               e_cal_component_range_new_take  (ECalComponentRangeKind kind,
+                                                ECalComponentDateTime *datetime);
+ECalComponentRange *
+               e_cal_component_range_copy      (const ECalComponentRange *range);
+void           e_cal_component_range_free      (gpointer range); /* ECalComponentRange * */
+ECalComponentRangeKind
+               e_cal_component_range_get_kind  (const ECalComponentRange *range);
+void           e_cal_component_range_set_kind  (ECalComponentRange *range,
+                                                ECalComponentRangeKind kind);
+ECalComponentDateTime *
+               e_cal_component_range_get_datetime
+                                               (const ECalComponentRange *range);
+void           e_cal_component_range_set_datetime
+                                               (ECalComponentRange *range,
+                                                const ECalComponentDateTime *datetime);
+void           e_cal_component_range_take_datetime
+                                               (ECalComponentRange *range,
+                                                ECalComponentDateTime *datetime);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_RANGE_H */
diff --git a/src/calendar/libecal/e-cal-component-text.c b/src/calendar/libecal/e-cal-component-text.c
new file mode 100644
index 000000000..616e6553c
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-text.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+/**
+ * SECTION:e-cal-component-text
+ * @short_description: An ECalComponentText structure
+ * @include: libecal/libecal.h
+ *
+ * Contains functions to work with the #ECalComponentText structure.
+ **/
+
+#include "e-cal-component-text.h"
+
+G_DEFINE_BOXED_TYPE (ECalComponentText, e_cal_component_text, e_cal_component_text_copy, 
e_cal_component_text_free)
+
+struct _ECalComponentText {
+       gchar *value;
+       gchar *altrep;
+};
+
+/**
+ * e_cal_component_text_new:
+ * @value: (nullable): description text
+ * @altrep: (nullable): alternate representation URI
+ *
+ * Creates a new #ECalComponentText describing text properties.
+ * The returned structure should be freed with e_cal_component_text_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentText
+ *
+ * Since: 3.36
+ **/
+ECalComponentText *
+e_cal_component_text_new (const gchar *value,
+                         const gchar *altrep)
+{
+       ECalComponentText *text;
+
+       text = g_new0 (ECalComponentText, 1);
+       text->value = g_strdup (value);
+       text->altrep = g_strdup (altrep);
+
+       return text;
+}
+
+/**
+ * e_cal_component_text_copy:
+ * @text: (not nullable): an #ECalComponentText to copy
+ *
+ * Returns: (transfer full): a newly allocated #ECalComponentText, copy of @text.
+ *    The returned structure should be freed with e_cal_component_text_free(),
+ *    when no longer needed.
+ *
+ * Since: 3.36
+ **/
+ECalComponentText *
+e_cal_component_text_copy (const ECalComponentText *text)
+{
+       g_return_val_if_fail (text != NULL, NULL);
+
+       return e_cal_component_text_new (text->value, text->altrep);
+}
+
+/**
+ * e_cal_component_text_free: (skip)
+ * @text: (type ECalComponentText) (nullable): an #ECalComponentText to free
+ *
+ * Free the @text, previously allocated by e_cal_component_text_new() or
+ * e_cal_component_text_copy().
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_text_free (gpointer text)
+{
+       ECalComponentText *te = text;
+
+       if (te) {
+               g_free (te->value);
+               g_free (te->altrep);
+               g_free (te);
+       }
+}
+
+/**
+ * e_cal_component_text_get_value:
+ * @text: an #ECalComponentText
+ *
+ * Returns: the description string of the @text
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_text_get_value (const ECalComponentText *text)
+{
+       g_return_val_if_fail (text != NULL, NULL);
+
+       return text->value;
+}
+
+/**
+ * e_cal_component_text_set_value:
+ * @text: an #ECalComponentText
+ * @value: (nullable): description string to set
+ *
+ * Set the @value as the description string of the @text.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_text_set_value (ECalComponentText *text,
+                               const gchar *value)
+{
+       g_return_if_fail (text != NULL);
+
+       if (g_strcmp0 (text->value, value) != 0) {
+               g_free (text->value);
+               text->value = g_strdup (value);
+       }
+}
+
+/**
+ * e_cal_component_text_get_altrep:
+ * @text: an #ECalComponentText
+ *
+ * Returns: the alternate representation URI of the @text
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_text_get_altrep (const ECalComponentText *text)
+{
+       g_return_val_if_fail (text != NULL, NULL);
+
+       return text->altrep;
+}
+
+/**
+ * e_cal_component_text_set_altrep:
+ * @text: an #ECalComponentText
+ * @altrep: (nullable): alternate representation URI to set
+ *
+ * Set the @altrep as the alternate representation URI of the @text.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_text_set_altrep (ECalComponentText *text,
+                                const gchar *altrep)
+{
+       g_return_if_fail (text != NULL);
+
+       if (g_strcmp0 (text->altrep, altrep) != 0) {
+               g_free (text->altrep);
+               text->altrep = g_strdup (altrep);
+       }
+}
diff --git a/src/calendar/libecal/e-cal-component-text.h b/src/calendar/libecal/e-cal-component-text.h
new file mode 100644
index 000000000..44044f37e
--- /dev/null
+++ b/src/calendar/libecal/e-cal-component-text.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_COMPONENT_TEXT_H
+#define E_CAL_COMPONENT_TEXT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ECalComponentText:
+ *
+ * Contains description string and an alternate representation URI
+ * for text properties. Use the functions below to work with it.
+ **/
+typedef struct _ECalComponentText ECalComponentText;
+
+GType          e_cal_component_text_get_type   (void);
+ECalComponentText *
+               e_cal_component_text_new        (const gchar *value,
+                                                const gchar *altrep);
+ECalComponentText *
+               e_cal_component_text_copy       (const ECalComponentText *text);
+void           e_cal_component_text_free       (gpointer text); /* ECalComponentText * */
+const gchar *  e_cal_component_text_get_value  (const ECalComponentText *text);
+void           e_cal_component_text_set_value  (ECalComponentText *text,
+                                                const gchar *value);
+const gchar *  e_cal_component_text_get_altrep (const ECalComponentText *text);
+void           e_cal_component_text_set_altrep (ECalComponentText *text,
+                                                const gchar *altrep);
+
+G_END_DECLS
+
+#endif /* E_CAL_COMPONENT_TEXT_H */
diff --git a/src/calendar/libecal/e-cal-component.c b/src/calendar/libecal/e-cal-component.c
index a2e2c1fdc..cb315c163 100644
--- a/src/calendar/libecal/e-cal-component.c
+++ b/src/calendar/libecal/e-cal-component.c
@@ -20,7 +20,7 @@
 /**
  * SECTION:e-cal-component
  * @short_description: A convenience interface for interacting with events
- * @include: libebook-contacts/libebook-contacts.h
+ * @include: libecal/libecal.h
  *
  * This is the main user facing interface used for representing an event
  * or other component in a given calendar.
@@ -38,152 +38,18 @@
 
 #include "e-cal-component.h"
 #include "e-cal-time-util.h"
+#include "e-cal-util.h"
 
 #ifdef G_OS_WIN32
 #define getgid() 0
 #define getppid() 0
 #endif
 
-#define E_CAL_COMPONENT_GET_PRIVATE(obj) \
-       (G_TYPE_INSTANCE_GET_PRIVATE \
-       ((obj), E_TYPE_CAL_COMPONENT, ECalComponentPrivate))
-
 G_DEFINE_TYPE (ECalComponent, e_cal_component, G_TYPE_OBJECT)
-G_DEFINE_BOXED_TYPE (ECalComponentId,
-               e_cal_component_id,
-               e_cal_component_id_copy,
-               e_cal_component_free_id)
-G_DEFINE_BOXED_TYPE (ECalComponentAlarm,
-               e_cal_component_alarm,
-               e_cal_component_alarm_clone,
-               e_cal_component_alarm_free)
-
-/* Extension property for alarm components so that we can reference them by UID */
-#define EVOLUTION_ALARM_UID_PROPERTY "X-EVOLUTION-ALARM-UID"
-
-struct attendee {
-       icalproperty *prop;
-       icalparameter *cutype_param;
-       icalparameter *member_param;
-       icalparameter *role_param;
-       icalparameter *partstat_param;
-       icalparameter *rsvp_param;
-       icalparameter *delto_param;
-       icalparameter *delfrom_param;
-       icalparameter *sentby_param;
-       icalparameter *cn_param;
-       icalparameter *language_param;
-};
-
-struct attachment {
-       icalproperty *prop;
-       icalattach *attach;
-
-       /* for inline attachments, where the file is stored;
-        * it unlinks it on attachment free. */
-       gchar *temporary_filename;
-};
-
-struct text {
-       icalproperty *prop;
-       icalparameter *altrep_param;
-};
-
-struct datetime {
-       icalproperty *prop;
-       icalparameter *tzid_param;
-};
-
-struct organizer {
-       icalproperty *prop;
-       icalparameter *sentby_param;
-       icalparameter *cn_param;
-       icalparameter *language_param;
-};
-
-struct period {
-       icalproperty *prop;
-       icalparameter *value_param;
-};
-
-struct recur_id {
-       struct datetime recur_time;
-
-       icalparameter *range_param;
-};
 
-/* Private part of the CalComponent structure */
 struct _ECalComponentPrivate {
        /* The icalcomponent we wrap */
-       icalcomponent *icalcomp;
-
-       /* Properties */
-
-       icalproperty *uid;
-
-       icalproperty *status;
-       GSList *attendee_list;
-
-       GString *categories_str;
-
-       icalproperty *classification;
-
-       GSList *comment_list; /* list of struct text */
-
-       icalproperty *completed;
-
-       GSList *contact_list; /* list of struct text */
-
-       icalproperty *created;
-
-       GSList *description_list; /* list of struct text */
-
-       struct datetime dtstart;
-       struct datetime dtend;
-
-       icalproperty *dtstamp;
-
-       /* The DURATION property can be used instead of the VEVENT DTEND or
-        * the VTODO DUE dates. We do not use it directly ourselves, but we
-        * must be able to handle it from incoming data. If a DTEND or DUE
-        * is requested, we convert the DURATION if necessary. If DTEND or
-        * DUE is set, we remove any DURATION. */
-       icalproperty *duration;
-
-       struct datetime due;
-
-       GSList *exdate_list; /* list of struct datetime */
-       GSList *exrule_list; /* list of icalproperty objects */
-
-       struct organizer organizer;
-
-       icalproperty *geo;
-       icalproperty *last_modified;
-       icalproperty *percent;
-       icalproperty *priority;
-
-       struct recur_id recur_id;
-
-       GSList *rdate_list; /* list of struct period */
-
-       GSList *rrule_list; /* list of icalproperty objects */
-
-       icalproperty *sequence;
-
-       struct {
-               icalproperty *prop;
-               icalparameter *altrep_param;
-       } summary;
-
-       icalproperty *transparency;
-       icalproperty *url;
-       icalproperty *location;
-
-       GSList *attachment_list;
-
-       /* Subcomponents */
-
-       GHashTable *alarm_uid_hash;
+       ICalComponent *icalcomp;
 
        /* Whether we should increment the sequence number when piping the
         * object over the wire.
@@ -191,188 +57,191 @@ struct _ECalComponentPrivate {
        guint need_sequence_inc : 1;
 };
 
-/* Private structure for alarms */
-struct _ECalComponentAlarm {
-       /* Alarm icalcomponent we wrap */
-       icalcomponent *icalcomp;
-
-       /* Our extension UID property */
-       icalproperty *uid;
-
-       /* Properties */
-
-       icalproperty *action;
-       icalproperty *attach; /* FIXME: see scan_alarm_property () below */
-
-       struct {
-               icalproperty *prop;
-               icalparameter *altrep_param;
-       } description;
-
-       icalproperty *duration;
-       icalproperty *repeat;
-       icalproperty *trigger;
-
-       GSList *attendee_list;
-};
-
-/* Does a simple g_free() of the elements of a GSList and then frees the list
- * itself.  Returns NULL.
+/* Frees the internal icalcomponent only if it does not have a parent.  If it
+ * does, it means we don't own it and we shouldn't free it.
  */
-static GSList *
-free_slist (GSList *slist)
+static void
+free_icalcomponent (ECalComponent *comp,
+                    gboolean free)
 {
-       g_slist_free_full (slist, (GDestroyNotify) g_free);
+       if (!comp->priv->icalcomp)
+               return;
 
-       return NULL;
-}
+       if (free) {
+               g_clear_object (&comp->priv->icalcomp);
+       }
 
-/* Used from g_hash_table_foreach_remove() to free the alarm UIDs hash table.
- * We do not need to do anything to individual elements since we were storing
- * the UID pointers inside the icalproperties themselves.
- */
-static gboolean
-free_alarm_cb (gpointer key,
-               gpointer value,
-               gpointer data)
-{
-       return TRUE;
+       /* Clean up */
+       comp->priv->need_sequence_inc = FALSE;
 }
 
+/* The 'func' returns TRUE to continue */
 static void
-free_attachment (struct attachment *attachment)
+foreach_subcomponent (ICalComponent *icalcomp,
+                     ICalComponentKind comp_kind,
+                     gboolean (* func) (ICalComponent *icalcomp,
+                                        ICalComponent *subcomp,
+                                        gpointer user_data),
+                     gpointer user_data)
 {
-       if (!attachment)
-               return;
+       ICalCompIter *iter;
+       ICalComponent *subcomp;
 
-       icalattach_unref (attachment->attach);
+       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (func != NULL);
 
-       if (attachment->temporary_filename) {
-               gchar *sep;
+       iter = i_cal_component_begin_component (icalcomp, comp_kind);
+       subcomp = i_cal_comp_iter_deref (iter);
+       while (subcomp) {
+               ICalComponent *next_subcomp;
 
-               g_unlink (attachment->temporary_filename);
+               next_subcomp = i_cal_comp_iter_next (iter);
 
-               sep = strrchr (attachment->temporary_filename, G_DIR_SEPARATOR);
-               if (sep) {
-                       *sep = '\0';
-                       g_rmdir (attachment->temporary_filename);
+               if (!func (icalcomp, subcomp, user_data)) {
+                       g_clear_object (&next_subcomp);
+                       g_object_unref (subcomp);
+                       break;
                }
+
+               g_object_unref (subcomp);
+               subcomp = next_subcomp;
        }
 
-       g_free (attachment->temporary_filename);
-       g_free (attachment);
+       g_clear_object (&iter);
 }
 
-/* Frees the internal icalcomponent only if it does not have a parent.  If it
- * does, it means we don't own it and we shouldn't free it.
- */
+/* The 'func' returns TRUE to continue */
 static void
-free_icalcomponent (ECalComponent *comp,
-                    gboolean free)
+foreach_property (ICalComponent *icalcomp,
+                 ICalPropertyKind prop_kind,
+                 gboolean (* func) (ICalComponent *icalcomp,
+                                    ICalProperty *prop,
+                                    gpointer user_data),
+                 gpointer user_data)
 {
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-
-       if (!priv->icalcomp)
-               return;
+       ICalProperty *prop;
 
-       /* Free the mappings */
+       g_return_if_fail (func != NULL);
 
-       priv->uid = NULL;
-       priv->recur_id.recur_time.prop = NULL;
+       for (prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, prop_kind)) {
+               if (!func (icalcomp, prop, user_data))
+                       break;
+       }
+}
 
-       priv->status = NULL;
+static gboolean
+gather_all_properties_cb (ICalComponent *icalcomp,
+                         ICalProperty *prop,
+                         gpointer user_data)
+{
+       GSList **pprops = user_data;
 
-       g_slist_foreach (priv->attachment_list, (GFunc) free_attachment, NULL);
-       g_slist_free (priv->attachment_list);
-       priv->attachment_list = NULL;
+       g_return_val_if_fail (pprops != NULL, FALSE);
 
-       g_slist_foreach (priv->attendee_list, (GFunc) g_free, NULL);
-       g_slist_free (priv->attendee_list);
-       priv->attendee_list = NULL;
+       *pprops = g_slist_prepend (*pprops, g_object_ref (prop));
 
-       if (priv->categories_str)
-               g_string_free (priv->categories_str, TRUE);
-       priv->categories_str = NULL;
+       return TRUE;
+}
 
-       priv->classification = NULL;
-       priv->comment_list = free_slist (priv->comment_list);
-       priv->completed = NULL;
-       priv->contact_list = free_slist (priv->contact_list);
-       priv->created = NULL;
+static GSList * /* ICalProperty * */
+gather_all_properties (ICalComponent *icalcomp,
+                      ICalPropertyKind prop_kind,
+                      gboolean in_original_order)
+{
+       GSList *props = NULL;
 
-       priv->description_list = free_slist (priv->description_list);
+       foreach_property (icalcomp, prop_kind, gather_all_properties_cb, &props);
 
-       priv->dtend.prop = NULL;
-       priv->dtend.tzid_param = NULL;
+       return in_original_order ? g_slist_reverse (props) : props;
+}
 
-       priv->dtstamp = NULL;
+static void
+remove_all_properties_of_kind (ICalComponent *icalcomp,
+                              ICalPropertyKind prop_kind)
+{
+       ICalProperty *prop;
+       GSList *to_remove, *link;
 
-       priv->dtstart.prop = NULL;
-       priv->dtstart.tzid_param = NULL;
+       to_remove = gather_all_properties (icalcomp, prop_kind, FALSE);
 
-       priv->due.prop = NULL;
-       priv->due.tzid_param = NULL;
+       for (link = to_remove; link; link = g_slist_next (link)) {
+               prop = link->data;
 
-       priv->duration = NULL;
+               i_cal_component_remove_property (icalcomp, prop);
+       }
 
-       priv->exdate_list = free_slist (priv->exdate_list);
+       g_slist_free_full (to_remove, g_object_unref);
+}
 
-       g_slist_free (priv->exrule_list);
-       priv->exrule_list = NULL;
+/* returns NULL when value is NULL or empty string */
+static ECalComponentText *
+get_text_from_prop (ICalProperty *prop,
+                   const gchar *(* get_prop_func) (ICalProperty *prop))
+{
+       ICalParameter *altrep_param;
+       const gchar *value, *altrep;
 
-       priv->geo = NULL;
-       priv->last_modified = NULL;
-       priv->percent = NULL;
-       priv->priority = NULL;
+       g_return_val_if_fail (prop != NULL, NULL);
+       g_return_val_if_fail (get_prop_func != NULL, NULL);
 
-       priv->rdate_list = free_slist (priv->rdate_list);
+       value = get_prop_func (prop);
 
-       g_slist_free (priv->rrule_list);
-       priv->rrule_list = NULL;
+       /* Skip empty values */
+       if (!value || !*value)
+               return NULL;
 
-       priv->sequence = NULL;
+       altrep_param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
+       altrep = altrep_param ? i_cal_parameter_get_altrep (altrep_param) : NULL;
+       g_clear_object (&altrep_param);
 
-       priv->summary.prop = NULL;
-       priv->summary.altrep_param = NULL;
+       if (altrep && !*altrep)
+               altrep = NULL;
 
-       priv->transparency = NULL;
-       priv->url = NULL;
-       priv->location = NULL;
+       return e_cal_component_text_new (value, altrep);
+}
 
-       /* Free the subcomponents */
+static void
+set_text_altrep_on_prop (ICalProperty *prop,
+                        const ECalComponentText *text)
+{
+       ICalParameter *param;
+       const gchar *altrep;
 
-       g_hash_table_foreach_remove (priv->alarm_uid_hash, free_alarm_cb, NULL);
+       g_return_if_fail (prop != NULL);
+       g_return_if_fail (text != NULL);
 
-       /* Free the icalcomponent */
+       altrep = e_cal_component_text_get_altrep (text);
+       param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
 
-       if (free && icalcomponent_get_parent (priv->icalcomp) == NULL) {
-               icalcomponent_free (priv->icalcomp);
-               priv->icalcomp = NULL;
+       if (altrep && *altrep) {
+               if (param) {
+                       i_cal_parameter_set_altrep (param, (gchar *) altrep);
+               } else {
+                       param = i_cal_parameter_new_altrep ((gchar *) altrep);
+                       i_cal_property_take_parameter (prop, param);
+                       param = NULL;
+               }
+       } else if (param) {
+               i_cal_property_remove_parameter_by_kind (prop, I_CAL_ALTREP_PARAMETER);
        }
 
-       /* Clean up */
-
-       priv->need_sequence_inc = FALSE;
+       g_clear_object (&param);
 }
 
+
 static void
 cal_component_finalize (GObject *object)
 {
-       ECalComponentPrivate *priv;
-
-       priv = E_CAL_COMPONENT_GET_PRIVATE (object);
+       ECalComponent *comp = E_CAL_COMPONENT (object);
 
-       free_icalcomponent (E_CAL_COMPONENT (object), TRUE);
-       g_hash_table_destroy (priv->alarm_uid_hash);
+       free_icalcomponent (comp, TRUE);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_cal_component_parent_class)->finalize (object);
 }
 
-
-
 /* Class initialization function for the calendar component object */
 static void
 e_cal_component_class_init (ECalComponentClass *class)
@@ -389,39 +258,46 @@ e_cal_component_class_init (ECalComponentClass *class)
 static void
 e_cal_component_init (ECalComponent *comp)
 {
-       comp->priv = E_CAL_COMPONENT_GET_PRIVATE (comp);
-       comp->priv->alarm_uid_hash = g_hash_table_new (g_str_hash, g_str_equal);
+       comp->priv = G_TYPE_INSTANCE_GET_PRIVATE (comp, E_TYPE_CAL_COMPONENT, ECalComponentPrivate);
+       comp->priv->icalcomp = NULL;
 }
 
 /**
- * e_cal_component_gen_uid:
+ * e_cal_component_new:
  *
- * Generates a unique identifier suitable for calendar components.
+ * Creates a new empty calendar component object.  Once created, you should set it from an
+ * existing #icalcomponent structure by using e_cal_component_set_icalcomponent() or with a
+ * new empty component type by using e_cal_component_set_new_vtype().
  *
- * Returns: A unique identifier string.  Every time this function is called
- * a different string is returned.
+ * Returns: (transfer full): A newly-created calendar component object.
  *
- * Deprecated: Since 3.26, use e_util_generate_uid() instead
+ * Since: 3.36
  **/
-gchar *
-e_cal_component_gen_uid (void)
+ECalComponent *
+e_cal_component_new (void)
 {
-       return e_util_generate_uid ();
+       return E_CAL_COMPONENT (g_object_new (E_TYPE_CAL_COMPONENT, NULL));
 }
 
 /**
- * e_cal_component_new:
+ * e_cal_component_new_vtype:
+ * @vtype: an #ECalComponentVType
  *
- * Creates a new empty calendar component object.  Once created, you should set it from an
- * existing #icalcomponent structure by using e_cal_component_set_icalcomponent() or with a
- * new empty component type by using e_cal_component_set_new_vtype().
+ * Creates a new #ECalComponent of type @vtype.
  *
- * Returns: A newly-created calendar component object.
+ * Returns: (transfer full): A newly-created calendar component object with set @vtype.
+ *
+ * Since: 3.36
  **/
 ECalComponent *
-e_cal_component_new (void)
+e_cal_component_new_vtype (ECalComponentVType vtype)
 {
-       return E_CAL_COMPONENT (g_object_new (E_TYPE_CAL_COMPONENT, NULL));
+       ECalComponent *comp;
+
+       comp = e_cal_component_new ();
+       e_cal_component_set_new_vtype (comp, vtype);
+
+       return comp;
 }
 
 /**
@@ -430,17 +306,19 @@ e_cal_component_new (void)
  *
  * Creates a new calendar component object from the given iCalendar string.
  *
- * Returns: A calendar component representing the given iCalendar string on
+ * Returns: (transfer full): A calendar component representing the given iCalendar string on
  * success, NULL if there was an error.
+ *
+ * Since: 3.36
  **/
 ECalComponent *
 e_cal_component_new_from_string (const gchar *calobj)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icalcomp;
 
        g_return_val_if_fail (calobj != NULL, NULL);
 
-       icalcomp = icalparser_parse_string (calobj);
+       icalcomp = i_cal_parser_parse_string (calobj);
        if (!icalcomp)
                return NULL;
 
@@ -449,21 +327,21 @@ e_cal_component_new_from_string (const gchar *calobj)
 
 /**
  * e_cal_component_new_from_icalcomponent:
- * @icalcomp: An #icalcomponent to use
+ * @icalcomp: (transfer full): An #ICalComponent to use
  *
  * Creates a new #ECalComponent which will has set @icalcomp as
- * an inner #icalcomponent. The newly created #ECalComponent takes
+ * an inner #ICalComponent. The newly created #ECalComponent takes
  * ownership of the @icalcomp, and if the call
  * to e_cal_component_set_icalcomponent() fails, then @icalcomp
  * is freed.
  *
- * Returns: An #ECalComponent with @icalcomp assigned on success,
+ * Returns: (transfer full): An #ECalComponent with @icalcomp assigned on success,
  * NULL if the @icalcomp cannot be assigned to #ECalComponent.
  *
- * Since: 3.4
+ * Since: 3.36
  **/
 ECalComponent *
-e_cal_component_new_from_icalcomponent (icalcomponent *icalcomp)
+e_cal_component_new_from_icalcomponent (ICalComponent *icalcomp)
 {
        ECalComponent *comp;
 
@@ -471,7 +349,7 @@ e_cal_component_new_from_icalcomponent (icalcomponent *icalcomp)
 
        comp = e_cal_component_new ();
        if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
-               icalcomponent_free (icalcomp);
+               g_object_unref (icalcomp);
                g_object_unref (comp);
 
                return NULL;
@@ -489,648 +367,238 @@ e_cal_component_new_from_icalcomponent (icalcomponent *icalcomp)
  *
  * Returns: (transfer full): A newly-created calendar component with the same
  * values as the original one.
+ *
+ * Since: 3.36
  **/
 ECalComponent *
 e_cal_component_clone (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
        ECalComponent *new_comp;
-       icalcomponent *new_icalcomp;
+       ICalComponent *new_icalcomp;
 
-       g_return_val_if_fail (comp != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->need_sequence_inc == FALSE, NULL);
+       g_return_val_if_fail (comp->priv->need_sequence_inc == FALSE, NULL);
 
        new_comp = e_cal_component_new ();
 
-       if (priv->icalcomp) {
-               new_icalcomp = icalcomponent_new_clone (priv->icalcomp);
-               e_cal_component_set_icalcomponent (new_comp, new_icalcomp);
+       if (comp->priv->icalcomp) {
+               new_icalcomp = i_cal_component_new_clone (comp->priv->icalcomp);
+               if (!new_icalcomp || !e_cal_component_set_icalcomponent (new_comp, new_icalcomp)) {
+                       g_clear_object (&new_icalcomp);
+                       g_clear_object (&new_comp);
+               }
        }
 
        return new_comp;
 }
 
-/* Scans an attachment property */
-static void
-scan_attachment (GSList **attachment_list,
-                 icalproperty *prop)
-{
-       struct attachment *attachment;
-
-       attachment = g_new0 (struct attachment, 1);
-       attachment->prop = prop;
-
-       attachment->attach = icalproperty_get_attach (prop);
-       icalattach_ref (attachment->attach);
-
-       *attachment_list = g_slist_append (*attachment_list, attachment);
-}
-
-/* Scans an attendee property */
-static void
-scan_attendee (GSList **attendee_list,
-               icalproperty *prop)
-{
-       struct attendee *attendee;
-
-       attendee = g_new (struct attendee, 1);
-       attendee->prop = prop;
-
-       attendee->cutype_param = icalproperty_get_first_parameter (prop, ICAL_CUTYPE_PARAMETER);
-       attendee->member_param = icalproperty_get_first_parameter (prop, ICAL_MEMBER_PARAMETER);
-       attendee->role_param = icalproperty_get_first_parameter (prop, ICAL_ROLE_PARAMETER);
-       attendee->partstat_param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
-       attendee->rsvp_param = icalproperty_get_first_parameter (prop, ICAL_RSVP_PARAMETER);
-       attendee->delto_param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDTO_PARAMETER);
-       attendee->delfrom_param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER);
-       attendee->sentby_param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
-       attendee->cn_param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
-       attendee->language_param = icalproperty_get_first_parameter (prop, ICAL_LANGUAGE_PARAMETER);
-
-       *attendee_list = g_slist_append (*attendee_list, attendee);
-}
-
-/* Scans a date/time and timezone pair property */
-static void
-scan_datetime (ECalComponent *comp,
-               struct datetime *datetime,
-               icalproperty *prop)
-{
-       datetime->prop = prop;
-       datetime->tzid_param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
-}
-
-/* Scans an exception date property */
-static void
-scan_exdate (ECalComponent *comp,
-             icalproperty *prop)
-{
-       ECalComponentPrivate *priv;
-       struct datetime *dt;
-
-       priv = comp->priv;
-
-       dt = g_new (struct datetime, 1);
-       dt->prop = prop;
-       dt->tzid_param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
-
-       priv->exdate_list = g_slist_append (priv->exdate_list, dt);
-}
-
-/* Scans and attendee property */
-static void
-scan_organizer (ECalComponent *comp,
-                struct organizer *organizer,
-                icalproperty *prop)
-{
-       organizer->prop = prop;
-
-       organizer->sentby_param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
-       organizer->cn_param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
-       organizer->language_param = icalproperty_get_first_parameter (prop, ICAL_LANGUAGE_PARAMETER);
-}
-
-/* Scans an icalperiodtype property */
+/* Ensures that the mandatory calendar component properties (uid, dtstamp) do
+ * exist.  If they don't exist, it creates them automatically.
+ */
 static void
-scan_period (ECalComponent *comp,
-             GSList **list,
-             icalproperty *prop)
+ensure_mandatory_properties (ECalComponent *comp)
 {
-       struct period *period;
+       ICalProperty *prop;
 
-       period = g_new (struct period, 1);
-       period->prop = prop;
-       period->value_param = icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER);
-
-       *list = g_slist_append (*list, period);
-}
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-/* Scans an icalrecurtype property */
-static void
-scan_recur_id (ECalComponent *comp,
-               struct recur_id *recur_id,
-               icalproperty *prop)
-{
-       scan_datetime (comp, &recur_id->recur_time, prop);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_UID_PROPERTY);
+       if (prop) {
+               g_object_unref (prop);
+       } else {
+               gchar *uid;
 
-       recur_id->range_param = icalproperty_get_first_parameter (prop, ICAL_RANGE_PARAMETER);
-}
+               uid = e_util_generate_uid ();
+               i_cal_component_set_uid (comp->priv->icalcomp, uid);
+               g_free (uid);
+       }
 
-/* Scans an icalrecurtype property */
-static void
-scan_recur (ECalComponent *comp,
-            GSList **list,
-            icalproperty *prop)
-{
-       *list = g_slist_append (*list, prop);
-}
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DTSTAMP_PROPERTY);
+       if (prop) {
+               g_object_unref (prop);
+       } else {
+               ICalTime *tt;
 
-/* Scans the summary property */
-static void
-scan_summary (ECalComponent *comp,
-              icalproperty *prop)
-{
-       ECalComponentPrivate *priv;
+               tt = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
 
-       priv = comp->priv;
+               prop = i_cal_property_new_dtstamp (tt);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
 
-       priv->summary.prop = prop;
-       priv->summary.altrep_param = icalproperty_get_first_parameter (prop, ICAL_ALTREP_PARAMETER);
+               g_object_unref (tt);
+       }
 }
 
-/* Scans a text (i.e. text + altrep) property */
-static void
-scan_text (ECalComponent *comp,
-           GSList **text_list,
-           icalproperty *prop)
+static gboolean
+ensure_alarm_uid_cb (ICalComponent *icalcomp,
+                    ICalComponent *subcomp,
+                    gpointer user_data)
 {
-       struct text *text;
+       if (!e_cal_util_component_has_x_property (subcomp, E_CAL_EVOLUTION_ALARM_UID_PROPERTY)) {
+               gchar *uid;
 
-       text = g_new (struct text, 1);
-       text->prop = prop;
-       text->altrep_param = icalproperty_get_first_parameter (prop, ICAL_ALTREP_PARAMETER);
+               uid = e_util_generate_uid ();
+               e_cal_util_component_set_x_property (subcomp, E_CAL_EVOLUTION_ALARM_UID_PROPERTY, uid);
+               g_free (uid);
+       }
 
-       *text_list = g_slist_append (*text_list, text);
+       return TRUE;
 }
 
-/* Scans an icalproperty and adds its mapping to the component */
-static void
-scan_property (ECalComponent *comp,
-               icalproperty *prop)
+/**
+ * e_cal_component_set_new_vtype:
+ * @comp: A calendar component object.
+ * @type: Type of calendar component to create.
+ *
+ * Clears any existing component data from a calendar component object and
+ * creates a new #ICalComponent of the specified type for it.  The only property
+ * that will be set in the new component will be its unique identifier.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_set_new_vtype (ECalComponent *comp,
+                               ECalComponentVType type)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_kind kind;
+       ICalComponent *icalcomp;
+       ICalComponentKind kind;
 
-       priv = comp->priv;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
 
-       kind = icalproperty_isa (prop);
+       free_icalcomponent (comp, TRUE);
 
-       switch (kind) {
-       case ICAL_STATUS_PROPERTY:
-               priv->status = prop;
-               break;
+       if (type == E_CAL_COMPONENT_NO_TYPE)
+               return;
 
-       case ICAL_ATTACH_PROPERTY:
-               scan_attachment (&priv->attachment_list, prop);
-               break;
+       /* Figure out the kind and create the icalcomponent */
 
-       case ICAL_ATTENDEE_PROPERTY:
-               scan_attendee (&priv->attendee_list, prop);
+       switch (type) {
+       case E_CAL_COMPONENT_EVENT:
+               kind = I_CAL_VEVENT_COMPONENT;
                break;
 
-       case ICAL_CATEGORIES_PROPERTY:
-               if (icalproperty_get_categories (prop)) {
-                       const gchar *categories = icalproperty_get_categories (prop);
-                       if (*categories) {
-                               if (!priv->categories_str) {
-                                       priv->categories_str = g_string_new (categories);
-                               } else {
-                                       g_string_append_c (priv->categories_str, ',');
-                                       g_string_append (priv->categories_str, categories);
-                               }
-                       }
-               }
+       case E_CAL_COMPONENT_TODO:
+               kind = I_CAL_VTODO_COMPONENT;
                break;
 
-       case ICAL_CLASS_PROPERTY:
-               priv->classification = prop;
+       case E_CAL_COMPONENT_JOURNAL:
+               kind = I_CAL_VJOURNAL_COMPONENT;
                break;
 
-       case ICAL_COMMENT_PROPERTY:
-               scan_text (comp, &priv->comment_list, prop);
+       case E_CAL_COMPONENT_FREEBUSY:
+               kind = I_CAL_VFREEBUSY_COMPONENT;
                break;
 
-       case ICAL_COMPLETED_PROPERTY:
-               priv->completed = prop;
+       case E_CAL_COMPONENT_TIMEZONE:
+               kind = I_CAL_VTIMEZONE_COMPONENT;
                break;
 
-       case ICAL_CONTACT_PROPERTY:
-               scan_text (comp, &priv->contact_list, prop);
-               break;
+       default:
+               g_warn_if_reached ();
+               kind = I_CAL_NO_COMPONENT;
+       }
 
-       case ICAL_CREATED_PROPERTY:
-               priv->created = prop;
-               break;
+       icalcomp = i_cal_component_new (kind);
+       if (!icalcomp) {
+               g_message ("e_cal_component_set_new_vtype(): Could not create the ICalComponent of kind %d!", 
kind);
+               return;
+       }
 
-       case ICAL_DESCRIPTION_PROPERTY:
-               scan_text (comp, &priv->description_list, prop);
-               break;
+       /* Scan the component to build our mapping table */
 
-       case ICAL_DTEND_PROPERTY:
-               scan_datetime (comp, &priv->dtend, prop);
-               break;
+       comp->priv->icalcomp = icalcomp;
 
-       case ICAL_DTSTAMP_PROPERTY:
-               priv->dtstamp = prop;
-               break;
+       /* Add missing stuff */
 
-       case ICAL_DTSTART_PROPERTY:
-               scan_datetime (comp, &priv->dtstart, prop);
-               break;
+       ensure_mandatory_properties (comp);
+}
 
-       case ICAL_DUE_PROPERTY:
-               scan_datetime (comp, &priv->due, prop);
-               break;
+/**
+ * e_cal_component_get_vtype:
+ * @comp: A calendar component object.
+ *
+ * Queries the type of a calendar component object.
+ *
+ * Returns: The type of the component, as defined by RFC 2445.
+ *
+ * Since: 3.36
+ **/
+ECalComponentVType
+e_cal_component_get_vtype (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_NO_TYPE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, E_CAL_COMPONENT_NO_TYPE);
 
-       case ICAL_DURATION_PROPERTY:
-               priv->duration = prop;
-               break;
+       switch (i_cal_component_isa (comp->priv->icalcomp)) {
+       case I_CAL_VEVENT_COMPONENT:
+               return E_CAL_COMPONENT_EVENT;
 
-       case ICAL_EXDATE_PROPERTY:
-               scan_exdate (comp, prop);
-               break;
+       case I_CAL_VTODO_COMPONENT:
+               return E_CAL_COMPONENT_TODO;
 
-       case ICAL_EXRULE_PROPERTY:
-               scan_recur (comp, &priv->exrule_list, prop);
-               break;
+       case I_CAL_VJOURNAL_COMPONENT:
+               return E_CAL_COMPONENT_JOURNAL;
 
-       case ICAL_GEO_PROPERTY:
-               priv->geo = prop;
-               break;
+       case I_CAL_VFREEBUSY_COMPONENT:
+               return E_CAL_COMPONENT_FREEBUSY;
 
-       case ICAL_LASTMODIFIED_PROPERTY:
-               priv->last_modified = prop;
-               break;
-
-       case ICAL_ORGANIZER_PROPERTY:
-               scan_organizer (comp, &priv->organizer, prop);
-               break;
-
-       case ICAL_PERCENTCOMPLETE_PROPERTY:
-               priv->percent = prop;
-               break;
-
-       case ICAL_PRIORITY_PROPERTY:
-               priv->priority = prop;
-               break;
-
-       case ICAL_RECURRENCEID_PROPERTY:
-               scan_recur_id (comp, &priv->recur_id, prop);
-               break;
-
-       case ICAL_RDATE_PROPERTY:
-               scan_period (comp, &priv->rdate_list, prop);
-               break;
-
-       case ICAL_RRULE_PROPERTY:
-               scan_recur (comp, &priv->rrule_list, prop);
-               break;
-
-       case ICAL_SEQUENCE_PROPERTY:
-               priv->sequence = prop;
-               break;
-
-       case ICAL_SUMMARY_PROPERTY:
-               scan_summary (comp, prop);
-               break;
-
-       case ICAL_TRANSP_PROPERTY:
-               priv->transparency = prop;
-               break;
-
-       case ICAL_UID_PROPERTY:
-               priv->uid = prop;
-               break;
-
-       case ICAL_URL_PROPERTY:
-               priv->url = prop;
-               break;
-
-       case ICAL_LOCATION_PROPERTY :
-               priv->location = prop;
-               break;
-
-       default:
-               break;
-       }
-}
-
-/* Gets our alarm UID string from a property that is known to contain it */
-static const gchar *
-alarm_uid_from_prop (icalproperty *prop)
-{
-       const gchar *xstr;
-
-       g_return_val_if_fail (icalproperty_isa (prop) == ICAL_X_PROPERTY, NULL);
-
-       xstr = icalproperty_get_x (prop);
-       g_return_val_if_fail (xstr != NULL, NULL);
-
-       return xstr;
-}
-
-/* Sets our alarm UID extension property on an alarm component.  Returns a
- * pointer to the UID string inside the property itself.
- */
-static const gchar *
-set_alarm_uid (icalcomponent *alarm,
-               const gchar *auid)
-{
-       icalproperty *prop;
-       const gchar *inprop_auid;
-
-       /* Create the new property */
-
-       prop = icalproperty_new_x ((gchar *) auid);
-       icalproperty_set_x_name (prop, EVOLUTION_ALARM_UID_PROPERTY);
-
-       icalcomponent_add_property (alarm, prop);
-
-       inprop_auid = alarm_uid_from_prop (prop);
-       return inprop_auid;
-}
-
-/* Removes any alarm UID extension properties from an alarm subcomponent */
-static void
-remove_alarm_uid (icalcomponent *alarm)
-{
-       icalproperty *prop;
-       GSList *list, *l;
-
-       list = NULL;
-
-       for (prop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY)) {
-               const gchar *xname;
-
-               xname = icalproperty_get_x_name (prop);
-               g_return_if_fail (xname != NULL);
-
-               if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0)
-                       list = g_slist_prepend (list, prop);
-       }
-
-       for (l = list; l; l = l->next) {
-               prop = l->data;
-               icalcomponent_remove_property (alarm, prop);
-               icalproperty_free (prop);
-       }
-
-       g_slist_free (list);
-}
-
-/* Adds an alarm subcomponent to the calendar component's mapping table.  The
- * actual UID with which it gets added may not be the same as the specified one;
- * this function will change it if the table already had an alarm subcomponent
- * with the specified UID.  Returns the actual UID used.
- */
-static const gchar *
-add_alarm (ECalComponent *comp,
-           icalcomponent *alarm,
-           const gchar *auid)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent *old_alarm;
-
-       priv = comp->priv;
-
-       /* First we see if we already have an alarm with the requested UID.  In
-        * that case, we need to change the new UID to something else.  This
-        * should never happen, but who knows.
-        */
-
-       old_alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid);
-       if (old_alarm != NULL) {
-               gchar *new_auid;
-
-               g_message ("add_alarm(): Got alarm with duplicated UID `%s', changing it...", auid);
-
-               remove_alarm_uid (alarm);
-
-               new_auid = e_util_generate_uid ();
-               auid = set_alarm_uid (alarm, new_auid);
-               g_free (new_auid);
-       }
-
-       g_hash_table_insert (priv->alarm_uid_hash, (gchar *) auid, alarm);
-       return auid;
-}
-
-/* Scans an alarm subcomponent, adds an UID extension property to it (so that we
- * can reference alarms by unique IDs), and adds its mapping to the component.  */
-static void
-scan_alarm (ECalComponent *comp,
-            icalcomponent *alarm)
-{
-       icalproperty *prop;
-       const gchar *auid;
-       gchar *new_auid;
-
-       for (prop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY)) {
-               const gchar *xname;
-
-               xname = icalproperty_get_x_name (prop);
-               g_return_if_fail (xname != NULL);
-
-               if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0) {
-                       auid = alarm_uid_from_prop (prop);
-                       add_alarm (comp, alarm, auid);
-                       return;
-               }
-       }
-
-       /* The component has no alarm UID property, so we create one. */
-
-       new_auid = e_util_generate_uid ();
-       auid = set_alarm_uid (alarm, new_auid);
-       g_free (new_auid);
-
-       add_alarm (comp, alarm, auid);
-}
-
-/* Scans an icalcomponent for its properties so that we can provide
- * random-access to them.  It also builds a hash table of the component's alarm
- * subcomponents.
- */
-static void
-scan_icalcomponent (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       icalproperty *prop;
-       icalcompiter iter;
-
-       priv = comp->priv;
-
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* Scan properties */
-
-       for (prop = icalcomponent_get_first_property (priv->icalcomp, ICAL_ANY_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (priv->icalcomp, ICAL_ANY_PROPERTY))
-               scan_property (comp, prop);
-
-       /* Scan subcomponents */
-
-       for (iter = icalcomponent_begin_component (priv->icalcomp, ICAL_VALARM_COMPONENT);
-            icalcompiter_deref (&iter) != NULL;
-            icalcompiter_next (&iter)) {
-               icalcomponent *subcomp;
-
-               subcomp = icalcompiter_deref (&iter);
-               scan_alarm (comp, subcomp);
-       }
-}
-
-/* Ensures that the mandatory calendar component properties (uid, dtstamp) do
- * exist.  If they don't exist, it creates them automatically.
- */
-static void
-ensure_mandatory_properties (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->uid) {
-               gchar *uid;
-
-               uid = e_util_generate_uid ();
-               priv->uid = icalproperty_new_uid (uid);
-               g_free (uid);
-
-               icalcomponent_add_property (priv->icalcomp, priv->uid);
-       }
-
-       if (!priv->dtstamp) {
-               struct icaltimetype t;
-
-               t = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-
-               priv->dtstamp = icalproperty_new_dtstamp (t);
-               icalcomponent_add_property (priv->icalcomp, priv->dtstamp);
-       }
-}
-
-/**
- * e_cal_component_set_new_vtype:
- * @comp: A calendar component object.
- * @type: Type of calendar component to create.
- *
- * Clears any existing component data from a calendar component object and
- * creates a new #icalcomponent of the specified type for it.  The only property
- * that will be set in the new component will be its unique identifier.
- **/
-void
-e_cal_component_set_new_vtype (ECalComponent *comp,
-                               ECalComponentVType type)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent *icalcomp;
-       icalcomponent_kind kind;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-
-       free_icalcomponent (comp, TRUE);
-
-       if (type == E_CAL_COMPONENT_NO_TYPE)
-               return;
-
-       /* Figure out the kind and create the icalcomponent */
-
-       switch (type) {
-       case E_CAL_COMPONENT_EVENT:
-               kind = ICAL_VEVENT_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_TODO:
-               kind = ICAL_VTODO_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_JOURNAL:
-               kind = ICAL_VJOURNAL_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_FREEBUSY:
-               kind = ICAL_VFREEBUSY_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_TIMEZONE:
-               kind = ICAL_VTIMEZONE_COMPONENT;
-               break;
+       case I_CAL_VTIMEZONE_COMPONENT:
+               return E_CAL_COMPONENT_TIMEZONE;
 
        default:
+               /* We should have been loaded with a supported type! */
                g_warn_if_reached ();
-               kind = ICAL_NO_COMPONENT;
-       }
-
-       icalcomp = icalcomponent_new (kind);
-       if (!icalcomp) {
-               g_message ("e_cal_component_set_new_vtype(): Could not create the icalcomponent!");
-               return;
+               return E_CAL_COMPONENT_NO_TYPE;
        }
-
-       /* Scan the component to build our mapping table */
-
-       priv->icalcomp = icalcomp;
-       scan_icalcomponent (comp);
-
-       /* Add missing stuff */
-
-       ensure_mandatory_properties (comp);
 }
 
 /**
  * e_cal_component_set_icalcomponent:
  * @comp: A calendar component object.
- * @icalcomp: (type long): An #icalcomponent.
+ * @icalcomp: (transfer full) (nullable): An #ICalComponent.
  *
- * Sets the contents of a calendar component object from an #icalcomponent
- * structure.  If the @comp already had an #icalcomponent set into it, it will
- * will be freed automatically if the #icalcomponent does not have a parent
- * component itself.
+ * Sets the contents of a calendar component object from an #ICalComponent.
+ * If the @comp already had an #ICalComponent set into it, it will
+ * be freed automatically.
  *
  * Supported component types are VEVENT, VTODO, VJOURNAL, VFREEBUSY, and VTIMEZONE.
  *
- * Returns: TRUE on success, FALSE if @icalcomp is an unsupported component
- * type.
+ * Returns: %TRUE on success, %FALSE if @icalcomp is an unsupported component type.
+ *
+ * Since: 3.36
  **/
 gboolean
 e_cal_component_set_icalcomponent (ECalComponent *comp,
-                                   icalcomponent *icalcomp)
+                                  ICalComponent *icalcomp)
 {
-       ECalComponentPrivate *priv;
-       icalcomponent_kind kind;
+       ICalComponentKind kind;
 
-       g_return_val_if_fail (comp != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       priv = comp->priv;
-
-       if (priv->icalcomp == icalcomp)
+       if (comp->priv->icalcomp == icalcomp)
                return TRUE;
 
        free_icalcomponent (comp, TRUE);
 
        if (!icalcomp) {
-               priv->icalcomp = NULL;
+               comp->priv->icalcomp = NULL;
                return TRUE;
        }
 
-       kind = icalcomponent_isa (icalcomp);
+       kind = i_cal_component_isa (icalcomp);
 
-       if (!(kind == ICAL_VEVENT_COMPONENT
-             || kind == ICAL_VTODO_COMPONENT
-             || kind == ICAL_VJOURNAL_COMPONENT
-             || kind == ICAL_VFREEBUSY_COMPONENT
-             || kind == ICAL_VTIMEZONE_COMPONENT))
+       if (!(kind == I_CAL_VEVENT_COMPONENT
+             || kind == I_CAL_VTODO_COMPONENT
+             || kind == I_CAL_VJOURNAL_COMPONENT
+             || kind == I_CAL_VFREEBUSY_COMPONENT
+             || kind == I_CAL_VTIMEZONE_COMPONENT))
                return FALSE;
 
-       priv->icalcomp = icalcomp;
+       comp->priv->icalcomp = icalcomp;
 
-       scan_icalcomponent (comp);
        ensure_mandatory_properties (comp);
 
+       foreach_subcomponent (icalcomp, I_CAL_VALARM_COMPONENT, ensure_alarm_uid_cb, NULL);
+
        return TRUE;
 }
 
@@ -1141,41 +609,17 @@ e_cal_component_set_icalcomponent (ECalComponent *comp,
  * Queries the #icalcomponent structure that a calendar component object is
  * wrapping.
  *
- * Returns: An #icalcomponent structure, or NULL if the @comp has no
- * #icalcomponent set to it.
+ * Returns: (transfer none) (nullable): An #ICalComponent structure, or %NULL
+ *    if the @comp has no #ICalComponent set to it.
+ *
+ * Since: 3.36
  **/
-icalcomponent *
+ICalComponent *
 e_cal_component_get_icalcomponent (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       priv = comp->priv;
-
-       return priv->icalcomp;
-}
-
-/**
- * e_cal_component_rescan:
- * @comp: A calendar component object.
- *
- * Rescans the #icalcomponent being wrapped by the given calendar component. This
- * would replace any value that was changed in the wrapped #icalcomponent.
- */
-void
-e_cal_component_rescan (ECalComponent *comp)
-{
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       /* Clear everything out */
-       free_icalcomponent (comp, FALSE);
-
-       /* Rescan */
-       scan_icalcomponent (comp);
-       ensure_mandatory_properties (comp);
+       return comp->priv->icalcomp;
 }
 
 /**
@@ -1185,62 +629,16 @@ e_cal_component_rescan (ECalComponent *comp)
  * Strips all error messages from the calendar component. Those error messages are
  * added to the iCalendar string representation whenever an invalid is used for
  * one of its fields.
- */
+ *
+ * Since: 3.36
+ **/
 void
 e_cal_component_strip_errors (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
 
-       priv = comp->priv;
-
-       icalcomponent_strip_errors (priv->icalcomp);
-}
-
-/**
- * e_cal_component_get_vtype:
- * @comp: A calendar component object.
- *
- * Queries the type of a calendar component object.
- *
- * Returns: The type of the component, as defined by RFC 2445.
- **/
-ECalComponentVType
-e_cal_component_get_vtype (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent_kind kind;
-
-       g_return_val_if_fail (comp != NULL, E_CAL_COMPONENT_NO_TYPE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_NO_TYPE);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, E_CAL_COMPONENT_NO_TYPE);
-
-       kind = icalcomponent_isa (priv->icalcomp);
-       switch (kind) {
-       case ICAL_VEVENT_COMPONENT:
-               return E_CAL_COMPONENT_EVENT;
-
-       case ICAL_VTODO_COMPONENT:
-               return E_CAL_COMPONENT_TODO;
-
-       case ICAL_VJOURNAL_COMPONENT:
-               return E_CAL_COMPONENT_JOURNAL;
-
-       case ICAL_VFREEBUSY_COMPONENT:
-               return E_CAL_COMPONENT_FREEBUSY;
-
-       case ICAL_VTIMEZONE_COMPONENT:
-               return E_CAL_COMPONENT_TIMEZONE;
-
-       default:
-               /* We should have been loaded with a supported type! */
-               g_warn_if_reached ();
-               return E_CAL_COMPONENT_NO_TYPE;
-       }
+       if (comp->priv->icalcomp)
+               i_cal_component_strip_errors (comp->priv->icalcomp);
 }
 
 /**
@@ -1253,112 +651,89 @@ e_cal_component_get_vtype (ECalComponent *comp)
  *
  * Returns: String representation of the calendar component according to
  * RFC 2445.
+ *
+ * Since: 3.36
  **/
 gchar *
 e_cal_component_get_as_string (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       gchar *str;
-
-       g_return_val_if_fail (comp != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
        /* Ensure that the user has committed the new SEQUENCE */
-       g_return_val_if_fail (priv->need_sequence_inc == FALSE, NULL);
-
-       str = icalcomponent_as_ical_string_r (priv->icalcomp);
+       g_return_val_if_fail (comp->priv->need_sequence_inc == FALSE, NULL);
 
-       return str;
+       return i_cal_component_as_ical_string_r (comp->priv->icalcomp);
 }
 
-/* Used from g_hash_table_foreach(); ensures that an alarm subcomponent
- * has the mandatory properties it needs.
- */
-static void
-ensure_alarm_properties_cb (gpointer key,
-                            gpointer value,
-                            gpointer data)
+/* Ensures that an alarm subcomponent has the mandatory properties it needs. */
+static gboolean
+ensure_alarm_properties_cb (ICalComponent *icalcomp,
+                           ICalComponent *subcomp,
+                           gpointer user_data)
 {
-       ECalComponent *comp;
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm;
-       icalproperty *prop;
-       enum icalproperty_action action;
-       const gchar *str;
-
-       alarm = value;
+       ICalProperty *prop;
+       ICalPropertyAction action;
+       const gchar *summary;
 
-       comp = E_CAL_COMPONENT (data);
-       priv = comp->priv;
-
-       prop = icalcomponent_get_first_property (alarm, ICAL_ACTION_PROPERTY);
+       prop = i_cal_component_get_first_property (subcomp, I_CAL_ACTION_PROPERTY);
        if (!prop)
-               return;
+               return TRUE;
+
+       action = i_cal_property_get_action (prop);
 
-       action = icalproperty_get_action (prop);
+       g_object_unref (prop);
 
        switch (action) {
-       case ICAL_ACTION_DISPLAY:
+       case I_CAL_ACTION_DISPLAY:
+               summary = i_cal_component_get_summary (icalcomp);
+
                /* Ensure we have a DESCRIPTION property */
-               prop = icalcomponent_get_first_property (alarm, ICAL_DESCRIPTION_PROPERTY);
+               prop = i_cal_component_get_first_property (subcomp, I_CAL_DESCRIPTION_PROPERTY);
                if (prop) {
-                       if (priv->summary.prop) {
-                               icalproperty *xprop;
+                       if (summary && *summary) {
+                               ICalProperty *xprop;
+
+                               for (xprop = i_cal_component_get_first_property (subcomp, I_CAL_X_PROPERTY);
+                                    xprop;
+                                    g_object_unref (xprop), xprop = i_cal_component_get_next_property 
(subcomp, I_CAL_X_PROPERTY)) {
+                                       const gchar *str;
 
-                               xprop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-                               while (xprop) {
-                                       str = icalproperty_get_x_name (xprop);
-                                       if (!strcmp (str, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
-                                               icalproperty_set_description (prop, icalproperty_get_summary 
(priv->summary.prop));
+                                       str = i_cal_property_get_x_name (xprop);
+                                       if (!g_strcmp0 (str, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
+                                               i_cal_property_set_description (prop, summary);
 
-                                               icalcomponent_remove_property (alarm, xprop);
-                                               icalproperty_free (xprop);
+                                               i_cal_component_remove_property (subcomp, xprop);
+                                               g_object_unref (xprop);
                                                break;
                                        }
-
-                                       xprop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY);
                                }
-
-                               break;
                        }
+
+                       g_object_unref (prop);
+                       break;
                }
 
-               if (!priv->summary.prop) {
-                       str = _("Untitled appointment");
+               if (!summary || !*summary) {
+                       summary = _("Untitled appointment");
 
                        /* add the X-EVOLUTION-NEEDS-DESCRIPTION property */
-                       prop = icalproperty_new_x ("1");
-                       icalproperty_set_x_name (prop, "X-EVOLUTION-NEEDS-DESCRIPTION");
-                       icalcomponent_add_property (alarm, prop);
-               } else
-                       str = icalproperty_get_summary (priv->summary.prop);
+                       prop = i_cal_property_new_x ("1");
+                       i_cal_property_set_x_name (prop, "X-EVOLUTION-NEEDS-DESCRIPTION");
+                       i_cal_component_take_property (subcomp, prop);
+               }
 
-               prop = icalproperty_new_description (str);
-               icalcomponent_add_property (alarm, prop);
+               prop = i_cal_property_new_description (summary);
+               i_cal_component_take_property (subcomp, prop);
 
                break;
 
        default:
                break;
-               /* FIXME: add other action types here */
        }
-}
 
-/* Ensures that alarm subcomponents have the mandatory properties they need,
- * even when clients may not have set them properly.
- */
-static void
-ensure_alarm_properties (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-
-       g_hash_table_foreach (priv->alarm_uid_hash, ensure_alarm_properties_cb, comp);
-}
+       return TRUE;
+}
 
 /**
  * e_cal_component_commit_sequence:
@@ -1370,38 +745,40 @@ ensure_alarm_properties (ECalComponent *comp)
  *
  * This function must be called before calling e_cal_component_get_as_string() to
  * ensure that the component is fully consistent.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_commit_sequence (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, ensure_alarm_properties_cb, comp);
 
-       ensure_alarm_properties (comp);
-
-       if (!priv->need_sequence_inc)
+       if (!comp->priv->need_sequence_inc)
                return;
 
-       if (priv->sequence) {
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SEQUENCE_PROPERTY);
+
+       if (prop) {
                gint seq;
 
-               seq = icalproperty_get_sequence (priv->sequence);
-               icalproperty_set_sequence (priv->sequence, seq + 1);
+               seq = i_cal_property_get_sequence (prop);
+               i_cal_property_set_sequence (prop, seq + 1);
+               g_object_unref (prop);
        } else {
                /* The component had no SEQUENCE property, so assume that the
                 * default would have been zero.  Since it needed incrementing
                 * anyways, we use a value of 1 here.
                 */
-               priv->sequence = icalproperty_new_sequence (1);
-               icalcomponent_add_property (priv->icalcomp, priv->sequence);
+               prop = i_cal_property_new_sequence (1);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 
-       priv->need_sequence_inc = FALSE;
+       comp->priv->need_sequence_inc = FALSE;
 }
 
 /**
@@ -1412,72 +789,56 @@ e_cal_component_commit_sequence (ECalComponent *comp)
  * which means it will not require a sequence commit (via
  * e_cal_component_commit_sequence()) even if the changes done require a
  * sequence increment.
- */
+ *
+ * Since: 3.36
+ **/
 void
 e_cal_component_abort_sequence (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
 
-       priv = comp->priv;
-
-       priv->need_sequence_inc = FALSE;
+       comp->priv->need_sequence_inc = FALSE;
 }
 
 /**
  * e_cal_component_get_id:
  * @comp: A calendar component object.
  *
- * Get the ID of the component as a #ECalComponentId.  The return value should
- * be freed with e_cal_component_free_id() when you have finished with it.
+ * Get the ID of the component as an #ECalComponentId. The return value should
+ * be freed with e_cal_component_id_free(), when no longer needed.
  *
- * Returns: the id of the component
- */
+ * Returns: (transfer full): the id of the component
+ *
+ * Since: 3.36
+ **/
 ECalComponentId *
 e_cal_component_get_id (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       ECalComponentId *id = NULL;
-
-       g_return_val_if_fail (comp != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
-       id = g_new0 (ECalComponentId, 1);
-       id->uid = g_strdup (icalproperty_get_uid (priv->uid));
-       id->rid = e_cal_component_get_recurid_as_string (comp);
-
-       return id;
+       return e_cal_component_id_new_take (
+               g_strdup (i_cal_component_get_uid (comp->priv->icalcomp)),
+               e_cal_component_get_recurid_as_string (comp));
 }
 
 /**
  * e_cal_component_get_uid:
  * @comp: A calendar component object.
- * @uid: (out) (transfer none): Return value for the UID string.
  *
  * Queries the unique identifier of a calendar component object.
+ *
+ * Returns: (transfer none): the UID string
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_uid (ECalComponent *comp,
-                         const gchar **uid)
+const gchar *
+e_cal_component_get_uid (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (uid != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->uid != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       *uid = icalproperty_get_uid (priv->uid);
+       return i_cal_component_get_uid (comp->priv->icalcomp);
 }
 
 /**
@@ -1486,248 +847,98 @@ e_cal_component_get_uid (ECalComponent *comp,
  * @uid: Unique identifier.
  *
  * Sets the unique identifier string of a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_uid (ECalComponent *comp,
                          const gchar *uid)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
        g_return_if_fail (uid != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->uid != NULL);
-
-       icalproperty_set_uid (priv->uid, (gchar *) uid);
+       i_cal_component_set_uid (comp->priv->icalcomp, (gchar *) uid);
 }
 
 static gboolean
-case_contains (const gchar *where,
-               const gchar *what)
-{
-       gchar *lwhere, *lwhat;
-       gboolean res = FALSE;
-
-       if (!where || !what) {
-               return FALSE;
-       }
-
-       lwhere = g_ascii_strdown (where, -1);
-       lwhat = g_ascii_strdown (what, -1);
-
-       res = lwhere && lwhat && strstr (lwhere, lwhat) != NULL;
-
-       g_free (lwhat);
-       g_free (lwhere);
-
-       return res;
-}
-
-/* Gets a text list value */
-static void
-get_attachment_list (ECalComponent *comp,
-                     GSList *attachment_list,
-                     GSList **al)
-{
-       GSList *l;
-       gint index;
-
-       *al = NULL;
-
-       if (!attachment_list)
-               return;
-
-       for (index = 0, l = attachment_list; l; l = l->next, index++) {
-               struct attachment *attachment;
-               gchar *buf = NULL;
-
-               attachment = l->data;
-               g_return_if_fail (attachment->attach != NULL);
-
-               if (icalattach_get_is_url (attachment->attach)) {
-                       const gchar *data;
-                       gsize buf_size;
-
-                       /* FIXME : this ref count is screwed up
-                        * These structures are being leaked.
-                        */
-                       icalattach_ref (attachment->attach);
-                       data = icalattach_get_url (attachment->attach);
-                       buf_size = strlen (data);
-                       buf = g_malloc0 (buf_size + 1);
-                       icalvalue_decode_ical_string (data, buf, buf_size);
-               } else if (attachment->prop) {
-                       if (!attachment->temporary_filename) {
-                               icalparameter *encoding_par = icalproperty_get_first_parameter 
(attachment->prop, ICAL_ENCODING_PARAMETER);
-                               if (encoding_par) {
-                                       gchar *str_value = icalproperty_get_value_as_string_r 
(attachment->prop);
-
-                                       if (str_value) {
-                                               icalparameter_encoding encoding = icalparameter_get_encoding 
(encoding_par);
-                                               guint8 *data = NULL;
-                                               gsize data_len = 0;
-
-                                               switch (encoding) {
-                                               case ICAL_ENCODING_8BIT:
-                                                       data = (guint8 *) str_value;
-                                                       data_len = strlen (str_value);
-                                                       str_value = NULL;
-                                                       break;
-                                               case ICAL_ENCODING_BASE64:
-                                                       data = g_base64_decode (str_value, &data_len);
-                                                       break;
-                                               default:
-                                                       break;
-                                               }
-
-                                               if (data) {
-                                                       gchar *dir, *id_str;
-                                                       ECalComponentId *id = e_cal_component_get_id (comp);
-
-                                                       id_str = g_strconcat (id ? id->uid : NULL, "-", id ? 
id->rid : NULL, NULL);
-                                                       dir = g_build_filename (e_get_user_cache_dir (), 
"tmp", "calendar", id_str, NULL);
-                                                       e_cal_component_free_id (id);
-                                                       g_free (id_str);
-
-                                                       if (g_mkdir_with_parents (dir, 0700) >= 0) {
-                                                               icalparameter *param;
-                                                               gchar *file = NULL;
-
-                                                               for (param = icalproperty_get_first_parameter 
(attachment->prop, ICAL_X_PARAMETER);
-                                                                    param && !file;
-                                                                    param = icalproperty_get_next_parameter 
(attachment->prop, ICAL_X_PARAMETER)) {
-                                                                       if (case_contains 
(icalparameter_get_xname (param), "NAME") && icalparameter_get_xvalue (param) && *icalparameter_get_xvalue 
(param))
-                                                                               file = g_strdup 
(icalparameter_get_xvalue (param));
-                                                               }
-
-                                                               if (!file)
-                                                                       file = g_strdup_printf ("%d.dat", 
index);
-
-                                                               attachment->temporary_filename = 
g_build_filename (dir, file, NULL);
-                                                               if (!g_file_set_contents 
(attachment->temporary_filename, (const gchar *) data, data_len, NULL)) {
-                                                                       g_free 
(attachment->temporary_filename);
-                                                                       attachment->temporary_filename = NULL;
-                                                               }
-                                                       }
-
-                                                       g_free (dir);
-                                               }
-
-                                               g_free (str_value);
-                                               g_free (data);
-                                       }
-                               }
-                       }
-
-                       if (attachment->temporary_filename)
-                               buf = g_filename_to_uri (attachment->temporary_filename, NULL, NULL);
-               }
-
-               if (buf)
-                       *al = g_slist_prepend (*al, buf);
-       }
-
-       *al = g_slist_reverse (*al);
-}
-
-static void
-set_attachment_list (icalcomponent *icalcomp,
-                     GSList **attachment_list,
-                     GSList *al)
+get_attachments_cb (ICalComponent *icalcomp,
+                   ICalProperty *prop,
+                   gpointer user_data)
 {
-       GSList *l;
-
-       /* Remove old attachments */
+       GSList **pattaches = user_data;
+       ICalAttach *attach;
 
-       if (*attachment_list) {
-               for (l = *attachment_list; l; l = l->next) {
-                       struct attachment *attachment;
+       g_return_val_if_fail (pattaches != NULL, FALSE);
 
-                       attachment = l->data;
-                       g_return_if_fail (attachment->prop != NULL);
-                       g_return_if_fail (attachment->attach != NULL);
-
-                       icalcomponent_remove_property (icalcomp, attachment->prop);
-                       free_attachment (attachment);
-               }
+       attach = i_cal_property_get_attach (prop);
 
-               g_slist_free (*attachment_list);
-               *attachment_list = NULL;
-       }
-       /* Add in new attachments */
-
-       for (l = al; l; l = l->next) {
-               struct attachment *attachment;
-               gsize buf_size;
-               gchar *buf;
-
-               attachment = g_new0 (struct attachment, 1);
-               buf_size = 2 * strlen ((gchar *) l->data);
-               buf = g_malloc0 (buf_size);
-               icalvalue_encode_ical_string (l->data, buf, buf_size);
-               attachment->attach = icalattach_new_from_url ((gchar *) buf);
-               attachment->prop = icalproperty_new_attach (attachment->attach);
-               icalcomponent_add_property (icalcomp, attachment->prop);
-               g_free (buf);
-               *attachment_list = g_slist_prepend (*attachment_list, attachment);
-       }
+       if (attach)
+               *pattaches = g_slist_prepend (*pattaches, attach);
 
-       *attachment_list = g_slist_reverse (*attachment_list);
+       return TRUE;
 }
 
 /**
- * e_cal_component_get_attachment_list:
+ * e_cal_component_get_attachments:
  * @comp: A calendar component object
- * @attachment_list: (out) (transfer full) (element-type utf8): Return list of
- * URIs to attachments
  *
- * Queries the attachment properties of the calendar component object. When done,
- * the @attachment_list should be freed by calling g_slist_free().
+ * Queries the attachment properties as #ICalAttach objects of the calendar
+ * component object. Changes on these objects are directly affecting the component.
+ * Free the returned #GSList with g_slist_free_full (slist, g_object_unref);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalAttach): a #GSList of
+ *    attachments, as #ICalAttach objects
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_attachment_list (ECalComponent *comp,
-                                     GSList **attachment_list)
+GSList *
+e_cal_component_get_attachments (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       GSList *attaches = NULL;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (attachment_list != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       foreach_property (comp->priv->icalcomp, I_CAL_ATTACH_PROPERTY, get_attachments_cb, &attaches);
 
-       get_attachment_list (comp, priv->attachment_list, attachment_list);
+       return g_slist_reverse (attaches);
 }
 
 /**
- * e_cal_component_set_attachment_list:
+ * e_cal_component_set_attachments:
  * @comp: A calendar component object
- * @attachment_list: (element-type utf8): list of URIs to attachment pointers
+ * @attachments: (nullable) (element-type ICalAttach): a #GSList of an #ICalAttach,
+ *    or %NULL to remove any existing
  *
- * This currently handles only attachments that are URIs
- * in the file system - not inline binaries.
+ * Sets the attachments of the calendar component object.
  *
- * Sets the attachments of a calendar component object
+ * Since: 3.36
  **/
 void
-e_cal_component_set_attachment_list (ECalComponent *comp,
-                                     GSList *attachment_list)
+e_cal_component_set_attachments (ECalComponent *comp,
+                                const GSList *attachments)
 {
-       ECalComponentPrivate *priv;
+       GSList *link;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_ATTACH_PROPERTY);
 
-       set_attachment_list (priv->icalcomp, &priv->attachment_list, attachment_list);
+       for (link = (GSList *) attachments; link; link = g_slist_next (link)) {
+               ICalAttach *attach = link->data;
+               ICalProperty *prop;
+
+               if (!attach)
+                       continue;
+
+               prop = i_cal_property_new_attach (attach);
+
+               if (prop)
+                       i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
 }
 
 /**
@@ -1737,88 +948,72 @@ e_cal_component_set_attachment_list (ECalComponent *comp,
  * Queries the component to see if it has attachments.
  *
  * Returns: TRUE if there are attachments, FALSE otherwise.
- */
+ *
+ * Since: 3.36
+ **/
 gboolean
 e_cal_component_has_attachments (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       priv = comp->priv;
-
-       if (g_slist_length (priv->attachment_list) > 0)
-               return TRUE;
-
-       return FALSE;
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_ATTACH_PROPERTY);
 }
 
-/**
- * e_cal_component_get_num_attachments:
- * @comp: A calendar component object.
- *
- * Get the number of attachments to this calendar component object.
- *
- * Returns: the number of attachments.
- */
-gint
-e_cal_component_get_num_attachments (ECalComponent *comp)
+/* Creates a comma-delimited string of categories */
+static gchar *
+stringify_categories (const GSList *categ_list)
 {
-       ECalComponentPrivate *priv;
+       GString *str;
+       GSList *link;
 
-       g_return_val_if_fail (comp != NULL, 0);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), 0);
+       str = g_string_new (NULL);
 
-       priv = comp->priv;
+       for (link = (GSList *) categ_list; link; link = g_slist_next (link)) {
+               const gchar *category = link->data;
 
-       return g_slist_length (priv->attachment_list) > 0;
+               if (category && *category) {
+                       if (str->len)
+                               g_string_append_c (str, ',');
+                       g_string_append (str, category);
+               }
+       }
 
+       return g_string_free (str, !str->len);
 }
 
 /**
  * e_cal_component_get_categories:
  * @comp: A calendar component object.
- * @categories: (out) (transfer none): Return holder for the categories.
  *
  * Queries the categories of the given calendar component. The categories
  * are returned in the @categories argument, which, on success, will contain
  * a comma-separated list of all categories set in the component.
+ * Free the returned string with g_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the categories as string, or %NULL
+ *    if none are set
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_categories (ECalComponent *comp,
-                                const gchar **categories)
+gchar *
+e_cal_component_get_categories (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (categories != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       GSList *categories;
+       gchar *str;
 
-       if (priv->categories_str)
-               *categories = priv->categories_str->str;
-       else
-               *categories = NULL;
-}
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-static void
-remove_all_categories (icalcomponent *icalcomp)
-{
-       icalproperty *prop, *to_remove;
+       categories = e_cal_component_get_categories_list (comp);
+       if (!categories)
+               return NULL;
 
-       g_return_if_fail (icalcomp != NULL);
+       str = stringify_categories (categories);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_CATEGORIES_PROPERTY);
-       while (prop) {
-               to_remove = prop;
-               prop = icalcomponent_get_next_property (icalcomp, ICAL_CATEGORIES_PROPERTY);
+       g_slist_free_full (categories, g_free);
 
-               icalcomponent_remove_property (icalcomp, to_remove);
-               icalproperty_free (to_remove);
-       }
+       return str;
 }
 
 /**
@@ -1827,119 +1022,78 @@ remove_all_categories (icalcomponent *icalcomp)
  * @categories: Comma-separated list of categories.
  *
  * Sets the list of categories for a calendar component.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_categories (ECalComponent *comp,
                                 const gchar *categories)
 {
-       ECalComponentPrivate *priv;
-       icalproperty *prop;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!categories || !(*categories)) {
-               remove_all_categories (priv->icalcomp);
-               if (priv->categories_str) {
-                       g_string_free (priv->categories_str, TRUE);
-                       priv->categories_str = NULL;
-               }
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_CATEGORIES_PROPERTY);
 
+       if (!categories || !*categories)
                return;
-       }
 
-       remove_all_categories (priv->icalcomp);
-       prop = icalproperty_new_categories (categories);
-       icalcomponent_add_property (priv->icalcomp, prop);
-
-       if (priv->categories_str)
-               g_string_free (priv->categories_str, TRUE);
-       priv->categories_str = g_string_new (categories);
+       prop = i_cal_property_new_categories (categories);
+       i_cal_component_take_property (comp->priv->icalcomp, prop);
 }
 
 /**
  * e_cal_component_get_categories_list:
  * @comp: A calendar component object.
- * @categ_list: (out) (transfer full) (element-type utf8): Return value for the
- * list of strings, where each string is a category. This should be freed using
- * e_cal_component_free_categories_list().
  *
- * Queries the list of categories of a calendar component object.  Each element
+ * Queries the list of categories of a calendar component object. Each element
  * in the returned categ_list is a string with the corresponding category.
+ * Free the returned #GSList with g_slist_free_full (categories, g_free); , when
+ * no longer needed.
+ *
+ * Returns: (transfer full) (element-type utf8) (nullable): the #GSList of strings, where each
+ *    string is a category, or %NULL, when no category is set.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_categories_list (ECalComponent *comp,
-                                     GSList **categ_list)
+GSList *
+e_cal_component_get_categories_list (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalproperty *prop;
+       ICalProperty *prop;
        const gchar *categories;
        const gchar *p;
        const gchar *cat_start;
+       GSList *categ_list = NULL;
        gchar *str;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (categ_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->categories_str) {
-               *categ_list = NULL;
-               return;
-       }
-
-       *categ_list = NULL;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       for (prop = icalcomponent_get_first_property (priv->icalcomp, ICAL_CATEGORIES_PROPERTY);
+       for (prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_CATEGORIES_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (priv->icalcomp, ICAL_CATEGORIES_PROPERTY)) {
-               categories = icalproperty_get_categories (prop);
-               g_return_if_fail (categories != NULL);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (comp->priv->icalcomp, 
I_CAL_CATEGORIES_PROPERTY)) {
+               categories = i_cal_property_get_categories (prop);
+
+               if (!categories)
+                       continue;
 
                cat_start = categories;
 
                for (p = categories; *p; p++) {
                        if (*p == ',') {
                                str = g_strndup (cat_start, p - cat_start);
-                               *categ_list = g_slist_prepend (*categ_list, str);
+                               categ_list = g_slist_prepend (categ_list, str);
 
                                cat_start = p + 1;
                        }
                }
 
                str = g_strndup (cat_start, p - cat_start);
-               *categ_list = g_slist_prepend (*categ_list, str);
-       }
-
-       *categ_list = g_slist_reverse (*categ_list);
-}
-
-/* Creates a comma-delimited string of categories */
-static gchar *
-stringify_categories (GSList *categ_list)
-{
-       GString *s;
-       GSList *l;
-       gchar *str;
-
-       s = g_string_new (NULL);
-
-       for (l = categ_list; l; l = l->next) {
-               g_string_append (s, l->data);
-
-               if (l->next != NULL)
-                       g_string_append (s, ",");
+               categ_list = g_slist_prepend (categ_list, str);
        }
 
-       str = s->str;
-       g_string_free (s, FALSE);
-
-       return str;
+       return g_slist_reverse (categ_list);
 }
 
 /**
@@ -1948,18 +1102,15 @@ stringify_categories (GSList *categ_list)
  * @categ_list: (element-type utf8): List of strings, one for each category.
  *
  * Sets the list of categories of a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_categories_list (ECalComponent *comp,
-                                     GSList *categ_list)
+                                     const GSList *categ_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
        if (!categ_list) {
                e_cal_component_set_categories (comp, NULL);
@@ -1978,48 +1129,47 @@ e_cal_component_set_categories_list (ECalComponent *comp,
 /**
  * e_cal_component_get_classification:
  * @comp: A calendar component object.
- * @classif: (out): Return value for the classification.
  *
  * Queries the classification of a calendar component object.  If the
  * classification property is not set on this component, this function returns
  * #E_CAL_COMPONENT_CLASS_NONE.
+ *
+ * Retuurns: a classification of the @comp, as an #ECalComponentClassification
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_classification (ECalComponent *comp,
-                                    ECalComponentClassification *classif)
+ECalComponentClassification
+e_cal_component_get_classification (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_class class;
+       ICalProperty *prop;
+       ECalComponentClassification classif;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (classif != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_CLASS_UNKNOWN);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, E_CAL_COMPONENT_CLASS_UNKNOWN);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_CLASS_PROPERTY);
 
-       if (!priv->classification) {
-               *classif = E_CAL_COMPONENT_CLASS_NONE;
-               return;
-       }
+       if (!prop)
+               return E_CAL_COMPONENT_CLASS_NONE;
 
-       class = icalproperty_get_class (priv->classification);
-
-       switch (class)
-       {
-       case ICAL_CLASS_PUBLIC:
-         *classif = E_CAL_COMPONENT_CLASS_PUBLIC;
-         break;
-       case ICAL_CLASS_PRIVATE:
-         *classif = E_CAL_COMPONENT_CLASS_PRIVATE;
-         break;
-       case ICAL_CLASS_CONFIDENTIAL:
-         *classif = E_CAL_COMPONENT_CLASS_CONFIDENTIAL;
-         break;
+       switch (i_cal_property_get_class (prop)) {
+       case I_CAL_CLASS_PUBLIC:
+               classif = E_CAL_COMPONENT_CLASS_PUBLIC;
+               break;
+       case I_CAL_CLASS_PRIVATE:
+               classif = E_CAL_COMPONENT_CLASS_PRIVATE;
+               break;
+       case I_CAL_CLASS_CONFIDENTIAL:
+               classif = E_CAL_COMPONENT_CLASS_CONFIDENTIAL;
+               break;
        default:
-         *classif = E_CAL_COMPONENT_CLASS_UNKNOWN;
-         break;
+               classif = E_CAL_COMPONENT_CLASS_UNKNOWN;
+               break;
        }
+
+       g_object_unref (prop);
+
+       return classif;
 }
 
 /**
@@ -2029,26 +1179,26 @@ e_cal_component_get_classification (ECalComponent *comp,
  *
  * Sets the classification property of a calendar component object.  To unset
  * the property, specify E_CAL_COMPONENT_CLASS_NONE for @classif.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_classification (ECalComponent *comp,
                                     ECalComponentClassification classif)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_class class;
+       ICalProperty_Class prop_class;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
        g_return_if_fail (classif != E_CAL_COMPONENT_CLASS_UNKNOWN);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_CLASS_PROPERTY);
 
        if (classif == E_CAL_COMPONENT_CLASS_NONE) {
-               if (priv->classification) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->classification);
-                       icalproperty_free (priv->classification);
-                       priv->classification = NULL;
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
                }
 
                return;
@@ -2056,1073 +1206,1049 @@ e_cal_component_set_classification (ECalComponent *comp,
 
        switch (classif) {
        case E_CAL_COMPONENT_CLASS_PUBLIC:
-         class = ICAL_CLASS_PUBLIC;
+               prop_class = I_CAL_CLASS_PUBLIC;
                break;
 
        case E_CAL_COMPONENT_CLASS_PRIVATE:
-         class = ICAL_CLASS_PRIVATE;
+               prop_class = I_CAL_CLASS_PRIVATE;
                break;
 
        case E_CAL_COMPONENT_CLASS_CONFIDENTIAL:
-         class = ICAL_CLASS_CONFIDENTIAL;
+               prop_class = I_CAL_CLASS_CONFIDENTIAL;
                break;
 
        default:
                g_warn_if_reached ();
-               class = ICAL_CLASS_NONE;
+               prop_class = I_CAL_CLASS_NONE;
+               break;
        }
 
-       if (priv->classification)
-               icalproperty_set_class (priv->classification, class);
-       else {
-               priv->classification = icalproperty_new_class (class);
-               icalcomponent_add_property (priv->icalcomp, priv->classification);
+       if (prop) {
+               i_cal_property_set_class (prop, prop_class);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_class (prop_class);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
 /* Gets a text list value */
-static void
-get_text_list (GSList *text_list,
-               const gchar *(* get_prop_func) (const icalproperty *prop),
-               GSList **tl)
+static GSList *
+get_text_list (ICalComponent *icalcomp,
+              ICalPropertyKind prop_kind,
+               const gchar *(* get_prop_func) (ICalProperty *prop))
 {
-       GSList *l;
+       GSList *link, *props, *tl = NULL;
 
-       *tl = NULL;
-
-       if (!text_list)
-               return;
-
-       for (l = text_list; l; l = l->next) {
-               struct text *text;
-               ECalComponentText *t;
-               const gchar *value;
+       if (!icalcomp)
+               return NULL;
 
-               text = l->data;
-               g_return_if_fail (text->prop != NULL);
+       props = gather_all_properties (icalcomp, prop_kind, FALSE);
+       for (link = props; link; link = g_slist_next (link)) {
+               ICalProperty *prop = link->data;
+               ECalComponentText *text;
 
-               value = (* get_prop_func) (text->prop);
-               /* Skip empty values */
-               if (!value || !*value)
+               if (!prop)
                        continue;
 
-               t = g_new (ECalComponentText, 1);
-               t->value = value;
-
-               if (text->altrep_param)
-                       t->altrep = icalparameter_get_altrep (text->altrep_param);
-               else
-                       t->altrep = NULL;
+               text = get_text_from_prop (prop, get_prop_func);
+               if (!text)
+                       continue;
 
-               *tl = g_slist_prepend (*tl, t);
+               tl = g_slist_prepend (tl, text);
        }
 
-       *tl = g_slist_reverse (*tl);
+       g_slist_free_full (props, g_object_unref);
+
+       /* No need to reverse it, the props are in reverse order
+          and processed in the reverse order, thus the result
+          is in the expected order. */
+       return tl;
 }
 
 /* Sets a text list value */
 static void
-set_text_list (ECalComponent *comp,
-               icalproperty *(* new_prop_func) (const gchar *value),
-               GSList **text_list,
-               GSList *tl)
+set_text_list (ICalComponent *icalcomp,
+              ICalPropertyKind prop_kind,
+               ICalProperty * (* new_prop_func) (const gchar *value),
+               const GSList *tl)
 {
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       priv = comp->priv;
+       GSList *link;
 
        /* Remove old texts */
-
-       for (l = *text_list; l; l = l->next) {
-               struct text *text;
-
-               text = l->data;
-               g_return_if_fail (text->prop != NULL);
-
-               icalcomponent_remove_property (priv->icalcomp, text->prop);
-               icalproperty_free (text->prop);
-               g_free (text);
-       }
-
-       g_slist_free (*text_list);
-       *text_list = NULL;
+       remove_all_properties_of_kind (icalcomp, prop_kind);
 
        /* Add in new texts */
 
-       for (l = tl; l; l = l->next) {
-               ECalComponentText *t;
-               struct text *text;
-
-               t = l->data;
-               g_return_if_fail (t->value != NULL);
+       for (link = (GSList *) tl; link; link = g_slist_next (link)) {
+               ECalComponentText *text;
+               ICalProperty *prop;
 
-               text = g_new (struct text, 1);
+               text = link->data;
+               if (!text || !e_cal_component_text_get_value (text))
+                       continue;
 
-               text->prop = (* new_prop_func) ((gchar *) t->value);
-               icalcomponent_add_property (priv->icalcomp, text->prop);
+               prop = new_prop_func ((gchar *) e_cal_component_text_get_value (text));
 
-               if (t->altrep) {
-                       text->altrep_param = icalparameter_new_altrep ((gchar *) t->altrep);
-                       icalproperty_add_parameter (text->prop, text->altrep_param);
-               } else
-                       text->altrep_param = NULL;
+               set_text_altrep_on_prop (prop, text);
 
-               *text_list = g_slist_prepend (*text_list, text);
+               i_cal_component_take_property (icalcomp, prop);
        }
-
-       *text_list = g_slist_reverse (*text_list);
 }
 
 /**
- * e_cal_component_get_comment_list:
+ * e_cal_component_get_comments:
  * @comp: A calendar component object.
- * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
- * value for the comment properties and their parameters, as a list of
- * #ECalComponentText structures.  This should be freed using the
- * e_cal_component_free_text_list() function.
  *
  * Queries the comments of a calendar component object.  The comment property can
  * appear several times inside a calendar component, and so a list of
- * #ECalComponentText is returned.
+ * #ECalComponentText is returned. Free the returned #GSList with
+ * g_slist_free_full (slist, e_cal_component_text_free);, when no longer needed.
+ *
+ * Returns: (transfer full) (element-type ECalComponentText) (nullable): the comment properties
+ *    and their parameters, as a list of #ECalComponentText structures; or %NULL, when
+ *    the component doesn't contain any.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_comment_list (ECalComponent *comp,
-                                  GSList **text_list)
+GSList *
+e_cal_component_get_comments (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (text_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_text_list (priv->comment_list, icalproperty_get_comment, text_list);
+       return get_text_list (comp->priv->icalcomp, I_CAL_COMMENT_PROPERTY, i_cal_property_get_comment);
 }
 
 /**
- * e_cal_component_set_comment_list:
+ * e_cal_component_set_comments:
  * @comp: A calendar component object.
- * @text_list: (element-type ECalComponentText): List of #ECalComponentText
- * structures.
+ * @text_list: (element-type ECalComponentText): List of #ECalComponentText structures.
  *
  * Sets the comments of a calendar component object.  The comment property can
  * appear several times inside a calendar component, and so a list of
  * #ECalComponentText structures is used.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_comment_list (ECalComponent *comp,
-                                  GSList *text_list)
+e_cal_component_set_comments (ECalComponent *comp,
+                             const GSList *text_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_text_list (comp, icalproperty_new_comment, &priv->comment_list, text_list);
+       set_text_list (comp->priv->icalcomp, I_CAL_COMMENT_PROPERTY, i_cal_property_new_comment, text_list);
 }
 
 /**
- * e_cal_component_get_contact_list:
+ * e_cal_component_get_contacts:
  * @comp: A calendar component object.
- * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
- * value for the contact properties and their parameters, as a list of
- * #ECalComponentText structures.  This should be freed using the
- * e_cal_component_free_text_list() function.
  *
  * Queries the contact of a calendar component object.  The contact property can
  * appear several times inside a calendar component, and so a list of
- * #ECalComponentText is returned.
+ * #ECalComponentText is returned. Free the returned #GSList with
+ * g_slist_free_full (slist, e_cal_component_text_free);, when no longer needed.
+ *
+ * Returns: (transfer full) (element-type ECalComponentText): the contact properties and
+ *    their parameters, as a #GSList of #ECalComponentText structures.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_contact_list (ECalComponent *comp,
-                                  GSList **text_list)
+GSList *
+e_cal_component_get_contacts (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (text_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_text_list (priv->contact_list, icalproperty_get_contact, text_list);
+       return get_text_list (comp->priv->icalcomp, I_CAL_CONTACT_PROPERTY, i_cal_property_get_contact);
 }
 
 /**
- * e_cal_component_set_contact_list:
+ * e_cal_component_set_contacts:
  * @comp: A calendar component object.
- * @text_list: (element-type ECalComponentText): List of #ECalComponentText
- * structures.
+ * @text_list: (element-type ECalComponentText): List of #ECalComponentText structures.
  *
  * Sets the contact of a calendar component object.  The contact property can
  * appear several times inside a calendar component, and so a list of
  * #ECalComponentText structures is used.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_contact_list (ECalComponent *comp,
-                                  GSList *text_list)
+e_cal_component_set_contacts (ECalComponent *comp,
+                             const GSList *text_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_text_list (comp, icalproperty_new_contact, &priv->contact_list, text_list);
+       set_text_list (comp->priv->icalcomp, I_CAL_CONTACT_PROPERTY, i_cal_property_new_contact, text_list);
 }
 
 /* Gets a struct icaltimetype value */
-static void
-get_icaltimetype (icalproperty *prop,
-                  struct icaltimetype (*get_prop_func) (const icalproperty *prop),
-                                                        struct icaltimetype **t)
+static ICalTime *
+get_icaltimetype (ICalComponent *icalcomp,
+                 ICalPropertyKind prop_kind,
+                  ICalTime * (* get_prop_func) (ICalProperty *prop))
 {
-       if (!prop) {
-               *t = NULL;
-               return;
-       }
+       ICalProperty *prop;
+       ICalTime *tt;
+
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+       if (!prop)
+               return NULL;
+
+       tt = get_prop_func (prop);
 
-       *t = g_new (struct icaltimetype, 1);
-       **t = (* get_prop_func) (prop);
+       g_object_unref (prop);
+
+       return tt;
 }
 
 /* Sets a struct icaltimetype value */
 static void
-set_icaltimetype (ECalComponent *comp,
-                  icalproperty **prop,
-                  icalproperty *(*prop_new_func) (struct icaltimetype v),
-                  void (* prop_set_func) (icalproperty *prop,
-                                          struct icaltimetype v),
-                  struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-
-       if (!t) {
-               if (*prop) {
-                       icalcomponent_remove_property (priv->icalcomp, *prop);
-                       icalproperty_free (*prop);
-                       *prop = NULL;
+set_icaltimetype (ICalComponent *icalcomp,
+                  ICalPropertyKind prop_kind,
+                  ICalProperty *(* prop_new_func) (ICalTime *tt),
+                  void (* prop_set_func) (ICalProperty *prop,
+                                          ICalTime *tt),
+                  const ICalTime *tt)
+{
+       ICalProperty *prop;
+
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+
+       if (!tt) {
+               if (prop) {
+                       i_cal_component_remove_property (icalcomp, prop);
+                       g_clear_object (&prop);
                }
 
                return;
        }
 
-       if (*prop)
-               (* prop_set_func) (*prop, *t);
-       else {
-               *prop = (* prop_new_func) (*t);
-               icalcomponent_add_property (priv->icalcomp, *prop);
+       if (prop) {
+               prop_set_func (prop, (ICalTime *) tt);
+               g_object_unref (prop);
+       } else {
+               prop = prop_new_func ((ICalTime *) tt);
+               i_cal_component_take_property (icalcomp, prop);
        }
 }
 
 /**
  * e_cal_component_get_completed:
  * @comp: A calendar component object.
- * @t: (out): Return value for the completion date.  This should be freed using the
- * e_cal_component_free_icaltimetype() function.
  *
  * Queries the date at which a calendar compoment object was completed.
+ * Free the returned non-NULL pointer with g_object_unref(), when
+ * no longer needed.
+ *
+ * Returns: (transfer full): the completion date, as an #ICalTime, or %NULL, when none is set
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_completed (ECalComponent *comp,
-                               struct icaltimetype **t)
+ICalTime *
+e_cal_component_get_completed (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_icaltimetype (priv->completed, icalproperty_get_completed, t);
+       return get_icaltimetype (comp->priv->icalcomp, I_CAL_COMPLETED_PROPERTY, 
i_cal_property_get_completed);
 }
 
 /**
  * e_cal_component_set_completed:
  * @comp: A calendar component object.
- * @t: Value for the completion date.
+ * @tt: (nullable): Value for the completion date.
  *
  * Sets the date at which a calendar component object was completed.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_completed (ECalComponent *comp,
-                               struct icaltimetype *t)
+                              const ICalTime *tt)
 {
-       ECalComponentPrivate *priv;
-       struct icaltimetype tmp_tt;
+       ICalTime *tmp_tt = NULL;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       if (tt && i_cal_time_is_date ((ICalTime *) tt)) {
+               tmp_tt = i_cal_time_new_clone (tt);
+               tt = tmp_tt;
 
-       if (t && t->is_date) {
-               tmp_tt = *t;
-               t = &tmp_tt;
-
-               tmp_tt.is_date = 0;
-               tmp_tt.hour = 0;
-               tmp_tt.minute = 0;
-               tmp_tt.second = 0;
-               tmp_tt.zone = icaltimezone_get_utc_timezone ();
+               i_cal_time_set_is_date (tmp_tt, FALSE);
+               i_cal_time_set_hour (tmp_tt, 0);
+               i_cal_time_set_minute (tmp_tt, 0);
+               i_cal_time_set_second (tmp_tt, 0);
+               i_cal_time_set_timezone (tmp_tt, i_cal_timezone_get_utc_timezone ());
        }
 
-       set_icaltimetype (
-               comp, &priv->completed,
-               icalproperty_new_completed,
-               icalproperty_set_completed,
-               t);
+       set_icaltimetype (comp->priv->icalcomp, I_CAL_COMPLETED_PROPERTY,
+               i_cal_property_new_completed,
+               i_cal_property_set_completed,
+               tt);
+
+       g_clear_object (&tmp_tt);
 }
 
 /**
  * e_cal_component_get_created:
  * @comp: A calendar component object.
- * @t: (out): Return value for the creation date.  This should be freed using the
- * e_cal_component_free_icaltimetype() function.
  *
  * Queries the date in which a calendar component object was created in the
- * calendar store.
+ * calendar store. Free the returned non-NULL pointer with g_object_unref(), when
+ * no longer needed.
+ *
+ * Returns: (transfer full): the creation date, as an #ICalTime, or %NULL, when none is set
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_created (ECalComponent *comp,
-                             struct icaltimetype **t)
+ICalTime *
+e_cal_component_get_created (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_icaltimetype (priv->created, icalproperty_get_created, t);
+       return get_icaltimetype (comp->priv->icalcomp, I_CAL_CREATED_PROPERTY, i_cal_property_get_created);
 }
 
 /**
  * e_cal_component_set_created:
  * @comp: A calendar component object.
- * @t: Value for the creation date.
+ * @tt: (nullable): Value for the creation date.
  *
  * Sets the date in which a calendar component object is created in the calendar
  * store.  This should only be used inside a calendar store application, i.e.
  * not by calendar user agents.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_created (ECalComponent *comp,
-                             struct icaltimetype *t)
+                            const ICalTime *tt)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_icaltimetype (
-               comp, &priv->created,
-               icalproperty_new_created,
-               icalproperty_set_created,
-               t);
+       set_icaltimetype (comp->priv->icalcomp, I_CAL_CREATED_PROPERTY,
+               i_cal_property_new_created,
+               i_cal_property_set_created,
+               tt);
 }
 
 /**
- * e_cal_component_get_description_list:
+ * e_cal_component_get_descriptions:
  * @comp: A calendar component object.
- * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
- * value for the description properties and their parameters, as a list of
- * #ECalComponentText structures.  This should be freed using the
- * e_cal_component_free_text_list() function.
  *
  * Queries the description of a calendar component object.  Journal components
  * may have more than one description, and as such this function returns a list
  * of #ECalComponentText structures.  All other types of components can have at
- * most one description.
+ * most one description. Free the returned #GSList with
+ * g_slist_free_full (slist, e_cal_component_text_free);, when no longer needed.
+ *
+ * Returns: (transfer full) (element-type ECalComponentText) (nullable): the description
+ *    properties and their parameters, as a #GSList of #ECalComponentText structures.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_description_list (ECalComponent *comp,
-                                      GSList **text_list)
+GSList *
+e_cal_component_get_descriptions (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (text_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_text_list (priv->description_list, icalproperty_get_description, text_list);
+       return get_text_list (comp->priv->icalcomp, I_CAL_DESCRIPTION_PROPERTY, 
i_cal_property_get_description);
 }
 
 /**
- * e_cal_component_set_description_list:
+ * e_cal_component_set_descriptions:
  * @comp: A calendar component object.
- * @text_list: (element-type ECalComponentText): List of
- * #ECalComponentText structures.
+ * @text_list: (element-type ECalComponentText): List of #ECalComponentText structures.
  *
  * Sets the description of a calendar component object.  Journal components may
  * have more than one description, and as such this function takes in a list of
  * #ECalComponentText structures.  All other types of components can have
  * at most one description.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_description_list (ECalComponent *comp,
-                                      GSList *text_list)
+e_cal_component_set_descriptions (ECalComponent *comp,
+                                 const GSList *text_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_text_list (comp, icalproperty_new_description, &priv->description_list, text_list);
+       set_text_list (comp->priv->icalcomp, I_CAL_DESCRIPTION_PROPERTY, i_cal_property_new_description, 
text_list);
 }
 
 /* Gets a date/time and timezone pair */
-static void
-get_datetime (struct datetime *datetime,
-              struct icaltimetype (* get_prop_func) (const icalproperty *prop),
-              ECalComponentDateTime *dt)
-{
-       if (datetime->prop) {
-               dt->value = g_new (struct icaltimetype, 1);
-               *dt->value = (* get_prop_func) (datetime->prop);
-       } else
-               dt->value = NULL;
+static ECalComponentDateTime *
+get_datetime (ICalComponent *icalcomp,
+             ICalPropertyKind prop_kind,
+              ICalTime * (* get_prop_func) (ICalProperty *prop))
+{
+       ICalProperty *prop;
+       ICalParameter *param;
+       ICalTime *value = NULL;
+       gchar *tzid;
+
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+       if (prop)
+               value = get_prop_func (prop);
+
+       if (!value) {
+               g_clear_object (&prop);
+               return NULL;
+       }
 
-       /* If the icaltimetype has is_utc set, we set "UTC" as the TZID.
+       param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+       /* If the ICalTime has is_utc set, we set "UTC" as the TZID.
         * This makes the timezone code simpler. */
-       if (datetime->tzid_param)
-               dt->tzid = g_strdup (icalparameter_get_tzid (datetime->tzid_param));
-       else if (dt->value && icaltime_is_utc (*dt->value))
-               dt->tzid = g_strdup ("UTC");
+       if (param)
+               tzid = g_strdup (i_cal_parameter_get_tzid (param));
+       else if (i_cal_time_is_utc (value))
+               tzid = g_strdup ("UTC");
        else
-               dt->tzid = NULL;
+               tzid = NULL;
+
+       g_clear_object (&param);
+       g_clear_object (&prop);
+
+       return e_cal_component_datetime_new_take (value, tzid);
 }
 
 /* Sets a date/time and timezone pair */
 static void
-set_datetime (ECalComponent *comp,
-              struct datetime *datetime,
-              icalproperty *(* prop_new_func) (struct icaltimetype v),
-              void (* prop_set_func) (icalproperty *prop,
-                                      struct icaltimetype v),
-              ECalComponentDateTime *dt)
+set_datetime (ICalComponent *icalcomp,
+             ICalPropertyKind prop_kind,
+             ICalProperty *(* prop_new_func) (ICalTime *tt),
+              void (* prop_set_func) (ICalProperty *prop,
+                                     ICalTime *tt),
+             const ECalComponentDateTime *dt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       ICalParameter *param;
+       ICalTime *tt;
+       const gchar *tzid;
 
-       priv = comp->priv;
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
 
        /* If we are setting the property to NULL (i.e. removing it), then
         * we remove it if it exists. */
        if (!dt) {
-               if (datetime->prop) {
-                       icalcomponent_remove_property (priv->icalcomp, datetime->prop);
-                       icalproperty_free (datetime->prop);
-
-                       datetime->prop = NULL;
-                       datetime->tzid_param = NULL;
+               if (prop) {
+                       i_cal_component_remove_property (icalcomp, prop);
+                       g_clear_object (&prop);
                }
 
                return;
        }
 
-       g_return_if_fail (dt->value != NULL);
+       tt = e_cal_component_datetime_get_value (dt);
 
-       /* If the TZID is set to "UTC", we set the is_utc flag. */
-       if (dt->tzid && !strcmp (dt->tzid, "UTC"))
-               dt->value->zone = icaltimezone_get_utc_timezone ();
-       else if (dt->value->zone == icaltimezone_get_utc_timezone ())
-               dt->value->zone = NULL;
+       g_return_if_fail (tt != NULL);
 
-       if (datetime->prop) {
+       tzid = e_cal_component_datetime_get_tzid (dt);
+
+       /* If the TZID is set to "UTC", we set the is_utc flag. */
+       if (!g_strcmp0 (tzid, "UTC"))
+               i_cal_time_set_timezone (tt, i_cal_timezone_get_utc_timezone ());
+       else if (i_cal_time_is_utc (tt))
+               i_cal_time_set_timezone (tt, NULL);
+
+       if (prop) {
                /* make sure no VALUE property is left if not needed */
-               icalproperty_remove_parameter_by_kind (datetime->prop, ICAL_VALUE_PARAMETER);
+               i_cal_property_remove_parameter_by_kind (prop, I_CAL_VALUE_PARAMETER);
 
-               (* prop_set_func) (datetime->prop, *dt->value);
+               prop_set_func (prop, tt);
        } else {
-               datetime->prop = (* prop_new_func) (*dt->value);
-               icalcomponent_add_property (priv->icalcomp, datetime->prop);
+               prop = prop_new_func (tt);
+               i_cal_component_add_property (icalcomp, prop);
        }
 
-       /* If the TZID is set to "UTC", we don't want to save the TZID. */
-       if (dt->tzid && strcmp (dt->tzid, "UTC")) {
-               g_return_if_fail (datetime->prop != NULL);
+       param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
 
-               if (datetime->tzid_param) {
-                       icalparameter_set_tzid (datetime->tzid_param, (gchar *) dt->tzid);
+       /* If the TZID is set to "UTC", we don't want to save the TZID. */
+       if (tzid && g_strcmp0 (tzid, "UTC") != 0) {
+               if (param) {
+                       i_cal_parameter_set_tzid (param, (gchar *) tzid);
                } else {
-                       datetime->tzid_param = icalparameter_new_tzid ((gchar *) dt->tzid);
-                       icalproperty_add_parameter (datetime->prop, datetime->tzid_param);
+                       param = i_cal_parameter_new_tzid ((gchar *) tzid);
+                       i_cal_property_add_parameter (prop, param);
                }
-       } else if (datetime->tzid_param) {
-               icalproperty_remove_parameter_by_kind (datetime->prop, ICAL_TZID_PARAMETER);
-               datetime->tzid_param = NULL;
+       } else if (param) {
+               i_cal_property_remove_parameter_by_kind (prop, I_CAL_TZID_PARAMETER);
        }
+
+       g_clear_object (&param);
+       g_clear_object (&prop);
 }
 
 /* This tries to get the DTSTART + DURATION for a VEVENT or VTODO. In a
  * VEVENT this is used for the DTEND if no DTEND exists, In a VTOTO it is
  * used for the DUE date if DUE doesn't exist. */
-static void
-e_cal_component_get_start_plus_duration (ECalComponent *comp,
-                                         ECalComponentDateTime *dt)
+static ECalComponentDateTime *
+e_cal_component_get_start_plus_duration (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       struct icaldurationtype duration;
+       ICalDuration *duration;
+       ICalTime *tt;
+       ECalComponentDateTime *dt;
+       guint dur_days, dur_hours, dur_minutes, dur_seconds;
 
-       priv = comp->priv;
-
-       if (!priv->duration)
-               return;
+       duration = i_cal_component_get_duration (comp->priv->icalcomp);
+       if (!duration)
+               return NULL;
 
        /* Get the DTSTART time. */
-       get_datetime (&priv->dtstart, icalproperty_get_dtstart, dt);
-       if (!dt->value)
-               return;
-
-       duration = icalproperty_get_duration (priv->duration);
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart);
+       if (!dt) {
+               g_object_unref (duration);
+               return NULL;
+       }
 
        /* The DURATION shouldn't be negative, but just return DTSTART if it
         * is, i.e. assume it is 0. */
-       if (duration.is_neg)
-               return;
+       if (i_cal_duration_is_neg (duration)) {
+               g_object_unref (duration);
+               return dt;
+       }
 
        /* If DTSTART is a DATE value, then we need to check if the DURATION
         * includes any hours, minutes or seconds. If it does, we need to
         * make the DTEND/DUE a DATE-TIME value. */
-       duration.days += duration.weeks * 7;
-       if (dt->value->is_date) {
-               if (duration.hours != 0 || duration.minutes != 0
-                   || duration.seconds != 0) {
-                       dt->value->is_date = 0;
-               }
+       dur_days = i_cal_duration_get_days (duration) + (7 * i_cal_duration_get_weeks (duration));
+       dur_hours = i_cal_duration_get_hours (duration);
+       dur_minutes = i_cal_duration_get_minutes (duration);
+       dur_seconds = i_cal_duration_get_seconds (duration);
+
+       tt = e_cal_component_datetime_get_value (dt);
+       if (i_cal_time_is_date (tt) && (
+           dur_hours != 0 || dur_minutes != 0 || dur_seconds != 0)) {
+               i_cal_time_set_is_date (tt, FALSE);
        }
 
        /* Add on the DURATION. */
-       icaltime_adjust (
-               dt->value, duration.days, duration.hours,
-               duration.minutes, duration.seconds);
+       i_cal_time_adjust (tt, dur_days, dur_hours, dur_minutes, dur_seconds);
+
+       g_object_unref (duration);
+
+       return dt;
 }
 
 /**
  * e_cal_component_get_dtend:
  * @comp: A calendar component object.
- * @dt: (out): Return value for the date/time end.  This should be freed with the
- * e_cal_component_free_datetime() function.
  *
- * Queries the date/time end of a calendar component object.
+ * Queries the date/time end of a calendar component object. In case there's no DTEND,
+ * but only DTSTART and DURATION, then the end is computed from the later two.
+ * Free the returned #ECalComponentDateTime with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the date/time end, as an #ECalComponentDateTime
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_dtend (ECalComponent *comp,
-                           ECalComponentDateTime *dt)
+ECalComponentDateTime *
+e_cal_component_get_dtend (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ECalComponentDateTime *dt;
 
-       g_return_if_fail (dt != NULL);
-
-       dt->tzid = NULL;
-       dt->value = NULL;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_datetime (&priv->dtend, icalproperty_get_dtend, dt);
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_DTEND_PROPERTY, i_cal_property_get_dtend);
 
        /* If we don't have a DTEND property, then we try to get DTSTART
         * + DURATION. */
-       if (!dt->value)
-               e_cal_component_get_start_plus_duration (comp, dt);
+       if (!dt)
+               dt = e_cal_component_get_start_plus_duration (comp);
+
+       return dt;
 }
 
 /**
  * e_cal_component_set_dtend:
  * @comp: A calendar component object.
- * @dt: End date/time.
+ * @dt: (nullable): End date/time, or %NULL, to remove the property.
  *
  * Sets the date/time end property of a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_dtend (ECalComponent *comp,
-                           ECalComponentDateTime *dt)
+                           const ECalComponentDateTime *dt)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->dtend,
-               icalproperty_new_dtend,
-               icalproperty_set_dtend,
+       set_datetime (comp->priv->icalcomp, I_CAL_DTEND_PROPERTY,
+               i_cal_property_new_dtend,
+               i_cal_property_set_dtend,
                dt);
 
        /* Make sure we remove any existing DURATION property, as it can't be
         * used with a DTEND. If DTEND is set to NULL, i.e. removed, we also
         * want to remove any DURATION. */
-       if (priv->duration) {
-               icalcomponent_remove_property (priv->icalcomp, priv->duration);
-               icalproperty_free (priv->duration);
-               priv->duration = NULL;
-       }
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_DURATION_PROPERTY);
 
-       priv->need_sequence_inc = TRUE;
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
  * e_cal_component_get_dtstamp:
  * @comp: A calendar component object.
- * @t: (out): A value for the date/timestamp.
  *
  * Queries the date/timestamp property of a calendar component object, which is
  * the last time at which the object was modified by a calendar user agent.
+ *
+ * Free a non-NULL returned object with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): A value for the date/timestamp, or %NULL, when none found.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_dtstamp (ECalComponent *comp,
-                             struct icaltimetype *t)
+ICalTime *
+e_cal_component_get_dtstamp (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       ICalTime *tt;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DTSTAMP_PROPERTY);
 
        /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->dtstamp != NULL);
+       g_return_val_if_fail (prop != NULL, NULL);
 
-       *t = icalproperty_get_dtstamp (priv->dtstamp);
+       tt = i_cal_property_get_dtstamp (prop);
+
+       g_clear_object (&prop);
+
+       return tt;
 }
 
 /**
  * e_cal_component_set_dtstamp:
  * @comp: A calendar component object.
- * @t: Date/timestamp value.
+ * @tt: Date/timestamp value.
  *
  * Sets the date/timestamp of a calendar component object.  This should be
  * called whenever a calendar user agent makes a change to a component's
  * properties.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_dtstamp (ECalComponent *comp,
-                             struct icaltimetype *t)
+                            const ICalTime *tt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
+       g_return_if_fail (I_CAL_IS_TIME (tt));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DTSTAMP_PROPERTY);
 
        /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->dtstamp != NULL);
+       g_return_if_fail (prop != NULL);
+
+       i_cal_property_set_dtstamp (prop, (ICalTime *) tt);
 
-       icalproperty_set_dtstamp (priv->dtstamp, *t);
+       g_clear_object (&prop);
 }
 
 /**
  * e_cal_component_get_dtstart:
  * @comp: A calendar component object.
- * @dt: (out): Return value for the date/time start.  This should be freed with the
- * e_cal_component_free_datetime() function.
  *
  * Queries the date/time start of a calendar component object.
+ * Free the returned #ECalComponentDateTime with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the date/time start, as an #ECalComponentDateTime
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_dtstart (ECalComponent *comp,
-                             ECalComponentDateTime *dt)
+ECalComponentDateTime *
+e_cal_component_get_dtstart (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (dt != NULL);
-
-       dt->tzid = NULL;
-       dt->value = NULL;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_datetime (&priv->dtstart, icalproperty_get_dtstart, dt);
+       return get_datetime (comp->priv->icalcomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart);
 }
 
 /**
  * e_cal_component_set_dtstart:
  * @comp: A calendar component object.
- * @dt: Start date/time.
+ * @dt: (nullable): Start date/time, or %NULL, to remove the property.
  *
  * Sets the date/time start property of a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_dtstart (ECalComponent *comp,
-                             ECalComponentDateTime *dt)
+                            const ECalComponentDateTime *dt)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->dtstart,
-               icalproperty_new_dtstart,
-               icalproperty_set_dtstart,
+       set_datetime (comp->priv->icalcomp, I_CAL_DTSTART_PROPERTY,
+               i_cal_property_new_dtstart,
+               i_cal_property_set_dtstart,
                dt);
 
-       priv->need_sequence_inc = TRUE;
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
  * e_cal_component_get_due:
  * @comp: A calendar component object.
- * @dt: (out): Return value for the due date/time.  This should be freed with the
- * e_cal_component_free_datetime() function.
  *
- * Queries the due date/time of a calendar component object.
+ * Queries the due date/time of a calendar component object. In case there's no DUE,
+ * but only DTSTART and DURATION, then the due is computed from the later two.
+ * Free the returned #ECalComponentDateTime with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the due date/time, as an #ECalComponentDateTime
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_due (ECalComponent *comp,
-                         ECalComponentDateTime *dt)
+ECalComponentDateTime *
+e_cal_component_get_due (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (dt != NULL);
+       ECalComponentDateTime *dt;
 
-       dt->tzid = NULL;
-       dt->value = NULL;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_datetime (&priv->due, icalproperty_get_due, dt);
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_DUE_PROPERTY, i_cal_property_get_due);
 
        /* If we don't have a DTEND property, then we try to get DTSTART
         * + DURATION. */
-       if (!dt->value)
-               e_cal_component_get_start_plus_duration (comp, dt);
+       if (!dt)
+               dt = e_cal_component_get_start_plus_duration (comp);
+
+       return dt;
 }
 
 /**
  * e_cal_component_set_due:
  * @comp: A calendar component object.
- * @dt: End date/time.
+ * @dt: (nullable): End date/time, or %NULL, to remove the property.
  *
  * Sets the due date/time property of a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
 e_cal_component_set_due (ECalComponent *comp,
-                         ECalComponentDateTime *dt)
+                        const ECalComponentDateTime *dt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->due,
-               icalproperty_new_due,
-               icalproperty_set_due,
+       set_datetime (comp->priv->icalcomp, I_CAL_DUE_PROPERTY,
+               i_cal_property_new_due,
+               i_cal_property_set_due,
                dt);
 
        /* Make sure we remove any existing DURATION property, as it can't be
         * used with a DTEND. If DTEND is set to NULL, i.e. removed, we also
         * want to remove any DURATION. */
-       if (priv->duration) {
-               icalcomponent_remove_property (priv->icalcomp, priv->duration);
-               icalproperty_free (priv->duration);
-               priv->duration = NULL;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DURATION_PROPERTY);
+       if (prop) {
+               i_cal_component_remove_property (comp->priv->icalcomp, prop);
+               g_clear_object (&prop);
        }
 
-       priv->need_sequence_inc = TRUE;
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /* Builds a list of ECalComponentPeriod structures based on a list of icalproperties */
-static void
-get_period_list (GSList *period_list,
-                 struct icaldatetimeperiodtype (* get_prop_func) (const icalproperty *prop),
-                 GSList **list)
-{
-       GSList *l;
+static GSList * /* ECalComponentPeriod * */
+get_period_list (ICalComponent *icalcomp,
+                ICalPropertyKind prop_kind,
+                ICalDatetimeperiod * (* get_prop_func) (ICalProperty *prop))
+{
+       GSList *props, *link, *periods = NULL;
+
+       props = gather_all_properties (icalcomp, prop_kind, FALSE);
+
+       for (link = props; link; link = g_slist_next (link)) {
+               ICalProperty *prop = link->data;
+               ICalParameter *param;
+               ICalPeriod *icalperiod;
+               ICalDatetimeperiod *pt;
+               ICalDuration *duration = NULL;
+               ICalTime *start = NULL, *end = NULL;
+               ECalComponentPeriod *period;
+               ECalComponentPeriodKind period_kind;
+
+               if (!prop)
+                       continue;
 
-       *list = NULL;
+               /* Get start and end/duration */
+               pt = get_prop_func (prop);
+               if (!pt)
+                       continue;
 
-       if (!period_list)
-               return;
+               icalperiod = i_cal_datetimeperiod_get_period (pt);
 
-       for (l = period_list; l; l = l->next) {
-               struct period *period;
-               ECalComponentPeriod *p;
-               struct icaldatetimeperiodtype ip;
+               /* Get value parameter */
+               param = i_cal_property_get_first_parameter (prop, I_CAL_VALUE_PARAMETER);
 
-               period = l->data;
-               g_return_if_fail (period->prop != NULL);
+               if (param) {
+                       ICalParameterValue value_type;
 
-               p = g_new (ECalComponentPeriod, 1);
+                       value_type = i_cal_parameter_get_value (param);
 
-               /* Get start and end/duration */
-               ip = (* get_prop_func) (period->prop);
+                       if (value_type == I_CAL_VALUE_DATE || value_type == I_CAL_VALUE_DATETIME) {
+                               period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+                       } else if (value_type == I_CAL_VALUE_PERIOD) {
+                               period_kind = E_CAL_COMPONENT_PERIOD_DURATION;
+                               duration = i_cal_period_get_duration (icalperiod);
 
-               /* Get value parameter */
-               if (period->value_param) {
-                       icalparameter_value value_type;
-
-                       value_type = icalparameter_get_value (period->value_param);
-
-                       if (value_type == ICAL_VALUE_DATE || value_type == ICAL_VALUE_DATETIME)
-                               p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
-                       else if (value_type == ICAL_VALUE_DURATION)
-                               p->type = E_CAL_COMPONENT_PERIOD_DURATION;
-                       else if (value_type == ICAL_VALUE_PERIOD) {
-                               if (icaldurationtype_is_null_duration (ip.period.duration) || 
icaldurationtype_is_bad_duration (ip.period.duration))
-                                       p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
+                               if (!duration ||
+                                   i_cal_duration_is_null_duration (duration) ||
+                                   i_cal_duration_is_bad_duration (duration))
+                                       period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
                                else
-                                       p->type = E_CAL_COMPONENT_PERIOD_DURATION;
+                                       period_kind = E_CAL_COMPONENT_PERIOD_DURATION;
+
+                               g_clear_object (&duration);
                        } else {
-                               g_message (
-                                       "get_period_list(): Unknown value for period %d; "
-                                       "using DATETIME", value_type);
-                               p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
+                               g_message ("get_period_list(): Unknown value for period %d; using DATETIME", 
value_type);
+                               period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
                        }
-               } else
-                       p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
+               } else {
+                       period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+               }
 
-               p->start = ip.period.start;
+               start = i_cal_period_get_start (icalperiod);
 
-               if (p->type == E_CAL_COMPONENT_PERIOD_DATETIME)
-                       p->u.end = ip.period.end;
-               else if (p->type == E_CAL_COMPONENT_PERIOD_DURATION)
-                       p->u.duration = ip.period.duration;
-               else
-                       g_return_if_reached ();
+               if (period_kind == E_CAL_COMPONENT_PERIOD_DATETIME) {
+                       if (!start || i_cal_time_is_null_time (start)) {
+                               g_clear_object (&start);
+                               start = i_cal_datetimeperiod_get_time (pt);
+                       } else {
+                               end = i_cal_period_get_end (icalperiod);
+                       }
+               } else /* if (period_kind == E_CAL_COMPONENT_PERIOD_DURATION) */ {
+                       duration = i_cal_period_get_duration (icalperiod);
+               }
 
-               /* Put in list */
+               period = period_kind == E_CAL_COMPONENT_PERIOD_DATETIME ?
+                       e_cal_component_period_new_datetime (start, end) :
+                       e_cal_component_period_new_duration (start, duration);
 
-               *list = g_slist_prepend (*list, p);
+               if (period)
+                       periods = g_slist_prepend (periods, period);
+
+               g_clear_object (&param);
+               g_clear_object (&icalperiod);
+               g_clear_object (&pt);
+               g_clear_object (&duration);
+               g_clear_object (&start);
+               g_clear_object (&end);
        }
 
-       *list = g_slist_reverse (*list);
+       g_slist_free_full (props, g_object_unref);
+
+       /* No need to reverse it, the props are in reverse order
+          and processed in the reverse order, thus the result
+          is in the expected order. */
+       return periods;
 }
 
 /* Sets a period list value */
 static void
-set_period_list (ECalComponent *comp,
-                 icalproperty *(* new_prop_func) (struct icaldatetimeperiodtype period),
-                 GSList **period_list,
-                 GSList *pl)
+set_period_list (ICalComponent *icalcomp,
+                ICalPropertyKind prop_kind,
+                ICalProperty *(* new_prop_func) (ICalDatetimeperiod *period),
+                const GSList *periods_list)
 {
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       priv = comp->priv;
+       GSList *link;
 
        /* Remove old periods */
 
-       for (l = *period_list; l; l = l->next) {
-               struct period *period;
-
-               period = l->data;
-               g_return_if_fail (period->prop != NULL);
-
-               icalcomponent_remove_property (priv->icalcomp, period->prop);
-               icalproperty_free (period->prop);
-               g_free (period);
-       }
-
-       g_slist_free (*period_list);
-       *period_list = NULL;
+       remove_all_properties_of_kind (icalcomp, prop_kind);
 
        /* Add in new periods */
 
-       for (l = pl; l; l = l->next) {
-               ECalComponentPeriod *p;
-               struct period *period;
-               struct icaldatetimeperiodtype ip = {};
-               icalparameter_value value_type;
+       for (link = (GSList *) periods_list; link; link = g_slist_next (link)) {
+               const ECalComponentPeriod *period = link->data;
+               ICalDatetimeperiod *ic_datetimeperiod;
+               ICalPeriod *ic_period;
+               ICalProperty *prop;
+               ICalParameter *param;
+               ICalParameterValue value_type = I_CAL_VALUE_PERIOD;
+               ICalTime *end;
 
-               g_return_if_fail (l->data != NULL);
-               p = l->data;
+               if (!period)
+                       continue;
 
-               /* Create libical value */
+               ic_period = i_cal_period_null_period ();
+               ic_datetimeperiod = i_cal_datetimeperiod_new ();
 
-               ip.period.start = p->start;
+               i_cal_period_set_start (ic_period, e_cal_component_period_get_start (period));
 
-               if (p->type == E_CAL_COMPONENT_PERIOD_DATETIME) {
-                       value_type = ICAL_VALUE_DATETIME;
-                       ip.period.end = p->u.end;
-               } else if (p->type == E_CAL_COMPONENT_PERIOD_DURATION) {
-                       value_type = ICAL_VALUE_DURATION;
-                       ip.period.duration = p->u.duration;
-               } else {
-                       g_return_if_reached ();
+               switch (e_cal_component_period_get_kind (period)) {
+               case E_CAL_COMPONENT_PERIOD_DATETIME:
+                       end = e_cal_component_period_get_end (period);
+                       if (!end || i_cal_time_is_null_time (end)) {
+                               i_cal_datetimeperiod_set_time (ic_datetimeperiod, 
e_cal_component_period_get_start (period));
+                               if (i_cal_time_is_date (e_cal_component_period_get_start (period))) {
+                                       value_type = I_CAL_VALUE_DATE;
+                               } else {
+                                       value_type = I_CAL_VALUE_DATETIME;
+                               }
+                       } else {
+                               i_cal_period_set_end (ic_period, e_cal_component_period_get_end (period));
+                       }
+                       break;
+               case E_CAL_COMPONENT_PERIOD_DURATION:
+                       i_cal_period_set_duration (ic_period, e_cal_component_period_get_duration (period));
+                       break;
                }
 
-               /* Create property */
+               i_cal_datetimeperiod_set_period (ic_datetimeperiod, ic_period);
 
-               period = g_new (struct period, 1);
+               prop = new_prop_func (ic_datetimeperiod);
 
-               period->prop = (* new_prop_func) (ip);
-               period->value_param = icalparameter_new_value (value_type);
-               icalproperty_add_parameter (period->prop, period->value_param);
+               param = i_cal_parameter_new_value (value_type);
+               i_cal_property_take_parameter (prop, param);
 
-               /* Add to list */
+               i_cal_component_take_property (icalcomp, prop);
 
-               *period_list = g_slist_prepend (*period_list, period);
+               g_object_unref (ic_datetimeperiod);
+               g_object_unref (ic_period);
        }
-
-       *period_list = g_slist_reverse (*period_list);
 }
 
-/**
- * e_cal_component_get_exdate_list:
- * @comp: A calendar component object.
- * @exdate_list: (out) (transfer full) (element-type ECalComponentDateTime):
- * Return value for the list of exception dates, as a list of
- * #ECalComponentDateTime structures.  This should be freed using the
- * e_cal_component_free_exdate_list() function.
- *
- * Queries the list of exception date properties in a calendar component object.
- **/
-void
-e_cal_component_get_exdate_list (ECalComponent *comp,
-                                 GSList **exdate_list)
+static gboolean
+extract_exdate_properties_cb (ICalComponent *icalcomp,
+                             ICalProperty *prop,
+                             gpointer user_data)
 {
-       ECalComponentPrivate *priv;
-       GSList *l;
+       GSList **pexdates = user_data;
+       ICalTime *tt;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (exdate_list != NULL);
+       g_return_val_if_fail (pexdates != NULL, FALSE);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       tt = i_cal_property_get_exdate (prop);
+       if (tt) {
+               ICalParameter *param;
+               gchar *tzid;
 
-       *exdate_list = NULL;
+               param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+               if (param)
+                       tzid = g_strdup (i_cal_parameter_get_tzid (param));
+               else
+                       tzid = NULL;
+
+               if (tzid && !*tzid) {
+                       g_free (tzid);
+                       tzid = NULL;
+               }
 
-       for (l = priv->exdate_list; l; l = l->next) {
-               struct datetime *dt;
-               ECalComponentDateTime *cdt;
+               *pexdates = g_slist_prepend (*pexdates, e_cal_component_datetime_new_take (tt, tzid));
 
-               dt = l->data;
+               g_clear_object (&param);
+       }
 
-               cdt = g_new (ECalComponentDateTime, 1);
-               cdt->value = g_new (struct icaltimetype, 1);
+       return TRUE;
+}
 
-               *cdt->value = icalproperty_get_exdate (dt->prop);
+/**
+ * e_cal_component_get_exdates:
+ * @comp: A calendar component object.
+ *
+ * Queries the list of exception date properties in a calendar component object.
+ * Free the returned #GSList with g_slist_free_full (exdates, e_cal_component_datetime_free);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ECalComponentDateTime):
+ *    the list of exception dates, as a #GSList of #ECalComponentDateTime
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_get_exdates (ECalComponent *comp)
+{
+       GSList *exdates = NULL;
 
-               if (dt->tzid_param)
-                       cdt->tzid = g_strdup (icalparameter_get_tzid (dt->tzid_param));
-               else
-                       cdt->tzid = NULL;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               *exdate_list = g_slist_prepend (*exdate_list, cdt);
-       }
+       foreach_property (comp->priv->icalcomp, I_CAL_EXDATE_PROPERTY,
+               extract_exdate_properties_cb, &exdates);
 
-       *exdate_list = g_slist_reverse (*exdate_list);
+       return g_slist_reverse (exdates);
 }
 
 /**
- * e_cal_component_set_exdate_list:
+ * e_cal_component_set_exdates:
  * @comp: A calendar component object.
- * @exdate_list: (element-type ECalComponentDateTime): List of
- * #ECalComponentDateTime structures.
+ * @exdate_list: (nullable) (element-type ECalComponentDateTime): List of #ECalComponentDateTime structures.
  *
  * Sets the list of exception dates in a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_exdate_list (ECalComponent *comp,
-                                 GSList *exdate_list)
+e_cal_component_set_exdates (ECalComponent *comp,
+                            const GSList *exdate_list)
 {
-       ECalComponentPrivate *priv;
-       GSList *l;
+       GSList *link;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
        /* Remove old exception dates */
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_EXDATE_PROPERTY);
 
-       for (l = priv->exdate_list; l; l = l->next) {
-               struct datetime *dt;
-
-               dt = l->data;
-
-               /* Removing the DATE or DATE-TIME property will also remove
-                * any TZID parameter. */
-               icalcomponent_remove_property (priv->icalcomp, dt->prop);
-               icalproperty_free (dt->prop);
-               g_free (dt);
-       }
+       /* Add in new exception dates */
 
-       g_slist_free (priv->exdate_list);
-       priv->exdate_list = NULL;
+       for (link = (GSList *) exdate_list; link; link = g_slist_next (link)) {
+               const ECalComponentDateTime *dt = link->data;
+               ICalProperty *prop;
+               ICalTime *tt;
+               const gchar *tzid;
 
-       /* Add in new exception dates */
+               if (!dt)
+                       continue;
 
-       for (l = exdate_list; l; l = l->next) {
-               ECalComponentDateTime *cdt;
-               struct datetime *dt;
+               tt = e_cal_component_datetime_get_value (dt);
+               if (!tt)
+                       continue;
 
-               g_return_if_fail (l->data != NULL);
-               cdt = l->data;
+               tzid = e_cal_component_datetime_get_tzid (dt);
 
-               g_return_if_fail (cdt->value != NULL);
+               prop = i_cal_property_new_exdate (tt);
 
-               dt = g_new (struct datetime, 1);
-               dt->prop = icalproperty_new_exdate (*cdt->value);
+               if (tzid && *tzid) {
+                       ICalParameter *param;
 
-               if (cdt->tzid) {
-                       dt->tzid_param = icalparameter_new_tzid ((gchar *) cdt->tzid);
-                       icalproperty_add_parameter (dt->prop, dt->tzid_param);
-               } else
-                       dt->tzid_param = NULL;
+                       param = i_cal_parameter_new_tzid ((gchar *) tzid);
+                       i_cal_property_take_parameter (prop, param);
+               }
 
-               icalcomponent_add_property (priv->icalcomp, dt->prop);
-               priv->exdate_list = g_slist_prepend (priv->exdate_list, dt);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 
-       priv->exdate_list = g_slist_reverse (priv->exdate_list);
-
-       priv->need_sequence_inc = TRUE;
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
@@ -3133,3265 +2259,1919 @@ e_cal_component_set_exdate_list (ECalComponent *comp,
  * for it.
  *
  * Returns: TRUE if the component has exception dates, FALSE otherwise.
+ *
+ * Since: 3.36
  **/
 gboolean
 e_cal_component_has_exdates (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
-
-       return (priv->exdate_list != NULL);
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_EXDATE_PROPERTY);
 }
 
 /* Gets a list of recurrence rules */
-static void
-get_recur_list (GSList *recur_list,
-                struct icalrecurrencetype (* get_prop_func) (const icalproperty *prop),
-                GSList **list)
+static GSList *
+get_recur_list (ICalComponent *icalcomp,
+               ICalPropertyKind prop_kind,
+                ICalRecurrence * (* get_prop_func) (ICalProperty *prop))
 {
-       GSList *l;
-
-       *list = NULL;
-
-       for (l = recur_list; l; l = l->next) {
-               icalproperty *prop;
-               struct icalrecurrencetype *r;
+       GSList *props, *link, *recurs = NULL;
 
-               prop = l->data;
+       props = gather_all_properties (icalcomp, prop_kind, FALSE);
 
-               r = g_new (struct icalrecurrencetype, 1);
-               *r = (* get_prop_func) (prop);
+       for (link = props; link; link = g_slist_next (link)) {
+               ICalProperty *prop = link->data;
+               ICalRecurrence *rt;
 
-               *list = g_slist_prepend (*list, r);
+               rt = get_prop_func (prop);
+               if (rt)
+                       recurs = g_slist_prepend (recurs, rt);
        }
 
-       *list = g_slist_reverse (*list);
+       g_slist_free_full (props, g_object_unref);
+
+       /* No need to reverse it, the props are in reverse order
+          and processed in the reverse order, thus the result
+          is in the expected order. */
+       return recurs;
 }
 
 /* Sets a list of recurrence rules */
 static void
-set_recur_list (ECalComponent *comp,
-                icalproperty *(* new_prop_func) (struct icalrecurrencetype recur),
-                GSList **recur_list,
-                GSList *rl)
+set_recur_list (ICalComponent *icalcomp,
+               ICalPropertyKind prop_kind,
+               ICalProperty * (* new_prop_func) (ICalRecurrence *recur),
+               const GSList *rl) /* ICalRecurrence * */
 {
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       priv = comp->priv;
+       GSList *link;
 
        /* Remove old recurrences */
-
-       for (l = *recur_list; l; l = l->next) {
-               icalproperty *prop;
-
-               prop = l->data;
-               icalcomponent_remove_property (priv->icalcomp, prop);
-               icalproperty_free (prop);
-       }
-
-       g_slist_free (*recur_list);
-       *recur_list = NULL;
+       remove_all_properties_of_kind (icalcomp, prop_kind);
 
        /* Add in new recurrences */
 
-       for (l = rl; l; l = l->next) {
-               icalproperty *prop;
-               struct icalrecurrencetype *recur;
-
-               g_return_if_fail (l->data != NULL);
-               recur = l->data;
-
-               prop = (* new_prop_func) (*recur);
-               icalcomponent_add_property (priv->icalcomp, prop);
+       for (link = (GSList *) rl; link; link = g_slist_next (link)) {
+               ICalProperty *prop;
+               ICalRecurrence *recur = link->data;
 
-               *recur_list = g_slist_prepend (*recur_list, prop);
+               if (recur) {
+                       prop = (* new_prop_func) (recur);
+                       i_cal_component_take_property (icalcomp, prop);
+               }
        }
-
-       *recur_list = g_slist_reverse (*recur_list);
 }
 
 /**
- * e_cal_component_get_exrule_list:
+ * e_cal_component_get_exrules:
  * @comp: A calendar component object.
- * @recur_list: (out) (element-type icalrecurrencetype) (transfer full): List of
- * exception rules as struct #icalrecurrencetype structures.  This should be
- * freed using the e_cal_component_free_recur_list() function.
  *
  * Queries the list of exception rule properties of a calendar component
- * object.
- **/
-void
-e_cal_component_get_exrule_list (ECalComponent *comp,
-                                 GSList **recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_recur_list (priv->exrule_list, icalproperty_get_exrule, recur_list);
-}
-
-/**
- * e_cal_component_get_exrule_property_list:
- * @comp: A calendar component object.
- * @recur_list: (out) (transfer none) (element-type icalrecurrencetype):
- *
- * Queries the list of exception rule properties of a calendar component object.
+ * object. Free the returned list with g_slist_free_full (slist, g_object_unref);,
+ * when no longer needed.
  *
- * Returns: a list of exception rule properties
- **/
-void
-e_cal_component_get_exrule_property_list (ECalComponent *comp,
-                                          GSList **recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       *recur_list = priv->exrule_list;
-}
-
-/**
- * e_cal_component_set_exrule_list:
- * @comp: A calendar component object.
- * @recur_list: (element-type icalrecurrencetype): List of struct
- * #icalrecurrencetype structures.
+ * Returns: (transfer full) (nullable) (element-type ICalRecurrence): a #GSList
+ *    of exception rules as #ICalRecurrence structures, or %NULL, when none exist.
  *
- * Sets the list of exception rules in a calendar component object.
+ * Since: 3.36
  **/
-void
-e_cal_component_set_exrule_list (ECalComponent *comp,
-                                 GSList *recur_list)
+GSList *
+e_cal_component_get_exrules (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_recur_list (comp, icalproperty_new_exrule, &priv->exrule_list, recur_list);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv->need_sequence_inc = TRUE;
+       return get_recur_list (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY, i_cal_property_get_exrule);
 }
 
 /**
- * e_cal_component_has_exrules:
+ * e_cal_component_get_exrule_properties:
  * @comp: A calendar component object.
  *
- * Queries whether a calendar component object has any exception rules defined
- * for it.
- *
- * Returns: TRUE if the component has exception rules, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_exrules (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
-
-       return (priv->exrule_list != NULL);
-}
-
-/**
- * e_cal_component_has_exceptions:
- * @comp: A calendar component object
- *
- * Queries whether a calendar component object has any exception dates
- * or exception rules.
+ * Queries the list of exception rule properties of a calendar component object.
+ * Free the list with g_slist_free_full (slist, g_object_unref);, when
+ * no longer needed.
  *
- * Returns: TRUE if the component has exceptions, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_exceptions (ECalComponent *comp)
-{
-       return e_cal_component_has_exdates (comp) || e_cal_component_has_exrules (comp);
-}
-
-/**
- * e_cal_component_get_geo:
- * @comp: A calendar component object.
- * @geo: (out): Return value for the geographic position property.  This should be
- * freed using the e_cal_component_free_geo() function.
+ * Returns: (transfer full) (nullable) (element-type ICalProperty): a list of exception
+ *    rule properties
  *
- * Gets the geographic position property of a calendar component object.
+ * Since: 3.36
  **/
-void
-e_cal_component_get_geo (ECalComponent *comp,
-                         struct icalgeotype **geo)
+GSList *
+e_cal_component_get_exrule_properties (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (geo != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (priv->geo) {
-               *geo = g_new (struct icalgeotype, 1);
-               **geo = icalproperty_get_geo (priv->geo);
-       } else
-               *geo = NULL;
+       return gather_all_properties (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY, TRUE);
 }
 
 /**
- * e_cal_component_set_geo:
+ * e_cal_component_set_exrules:
  * @comp: A calendar component object.
- * @geo: Value for the geographic position property.
+ * @recur_list: (nullable) (element-type ICalRecurrence): a #GSList
+ *    of #ICalRecurrence structures, or %NULL.
  *
- * Sets the geographic position property on a calendar component object.
- **/
-void
-e_cal_component_set_geo (ECalComponent *comp,
-                         struct icalgeotype *geo)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!geo) {
-               if (priv->geo) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->geo);
-                       icalproperty_free (priv->geo);
-                       priv->geo = NULL;
-               }
-
-               return;
-       }
-
-       if (priv->geo)
-               icalproperty_set_geo (priv->geo, *geo);
-       else {
-               priv->geo = icalproperty_new_geo (*geo);
-               icalcomponent_add_property (priv->icalcomp, priv->geo);
-       }
-}
-
-/**
- * e_cal_component_get_last_modified:
- * @comp: A calendar component object.
- * @t: Return value for the last modified time value.
+ * Sets the list of exception rules in a calendar component object.
  *
- * Queries the time at which a calendar component object was last modified in
- * the calendar store.
+ * Since: 3.36
  **/
 void
-e_cal_component_get_last_modified (ECalComponent *comp,
-                                   struct icaltimetype **t)
+e_cal_component_set_exrules (ECalComponent *comp,
+                            const GSList *recur_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       set_recur_list (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY, i_cal_property_new_exrule, recur_list);
 
-       get_icaltimetype (priv->last_modified, icalproperty_get_lastmodified, t);
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_set_last_modified:
+ * e_cal_component_has_exrules:
  * @comp: A calendar component object.
- * @t: Value for the last time modified.
- *
- * Sets the time at which a calendar component object was last stored in the
- * calendar store.  This should not be called by plain calendar user agents.
- **/
-void
-e_cal_component_set_last_modified (ECalComponent *comp,
-                                   struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_icaltimetype (
-               comp, &priv->last_modified,
-               icalproperty_new_lastmodified,
-               icalproperty_set_lastmodified,
-               t);
-}
-
-/**
- * e_cal_component_get_organizer:
- * @comp:  A calendar component object
- * @organizer: (out): A value for the organizer
- *
- * Queries the organizer property of a calendar component object
- **/
-void
-e_cal_component_get_organizer (ECalComponent *comp,
-                               ECalComponentOrganizer *organizer)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (organizer != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (priv->organizer.prop)
-               organizer->value = icalproperty_get_organizer (priv->organizer.prop);
-       else
-               organizer->value = NULL;
-
-       if (priv->organizer.sentby_param)
-               organizer->sentby = icalparameter_get_sentby (priv->organizer.sentby_param);
-       else
-               organizer->sentby = NULL;
-
-       if (priv->organizer.cn_param)
-               organizer->cn = icalparameter_get_sentby (priv->organizer.cn_param);
-       else
-               organizer->cn = NULL;
-
-       if (priv->organizer.language_param)
-               organizer->language = icalparameter_get_sentby (priv->organizer.language_param);
-       else
-               organizer->language = NULL;
-
-}
-
-/**
- * e_cal_component_set_organizer:
- * @comp:  A calendar component object.
- * @organizer: Value for the organizer property
- *
- * Sets the organizer of a calendar component object
- **/
-void
-e_cal_component_set_organizer (ECalComponent *comp,
-                               ECalComponentOrganizer *organizer)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!organizer) {
-               if (priv->organizer.prop) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->organizer.prop);
-                       icalproperty_free (priv->organizer.prop);
-
-                       priv->organizer.prop = NULL;
-                       priv->organizer.sentby_param = NULL;
-                       priv->organizer.cn_param = NULL;
-                       priv->organizer.language_param = NULL;
-               }
-
-               return;
-       }
-
-       g_return_if_fail (organizer->value != NULL);
-
-       if (priv->organizer.prop)
-               icalproperty_set_organizer (priv->organizer.prop, (gchar *) organizer->value);
-       else {
-               priv->organizer.prop = icalproperty_new_organizer ((gchar *) organizer->value);
-               icalcomponent_add_property (priv->icalcomp, priv->organizer.prop);
-       }
-
-       if (organizer->sentby) {
-               g_return_if_fail (priv->organizer.prop != NULL);
-
-               if (priv->organizer.sentby_param)
-                       icalparameter_set_sentby (
-                               priv->organizer.sentby_param,
-                               (gchar *) organizer->sentby);
-               else {
-                       priv->organizer.sentby_param = icalparameter_new_sentby (
-                               (gchar *) organizer->sentby);
-                       icalproperty_add_parameter (
-                               priv->organizer.prop,
-                               priv->organizer.sentby_param);
-               }
-       } else if (priv->organizer.sentby_param) {
-               icalproperty_remove_parameter_by_kind (priv->organizer.prop, ICAL_SENTBY_PARAMETER);
-               priv->organizer.sentby_param = NULL;
-       }
-
-       if (organizer->cn) {
-               g_return_if_fail (priv->organizer.prop != NULL);
-
-               if (priv->organizer.cn_param)
-                       icalparameter_set_cn (
-                               priv->organizer.cn_param,
-                               (gchar *) organizer->cn);
-               else {
-                       priv->organizer.cn_param = icalparameter_new_cn (
-                               (gchar *) organizer->cn);
-                       icalproperty_add_parameter (
-                               priv->organizer.prop,
-                               priv->organizer.cn_param);
-               }
-       } else if (priv->organizer.cn_param) {
-               icalproperty_remove_parameter_by_kind (priv->organizer.prop, ICAL_CN_PARAMETER);
-               priv->organizer.cn_param = NULL;
-       }
-
-       if (organizer->language) {
-               g_return_if_fail (priv->organizer.prop != NULL);
-
-               if (priv->organizer.language_param)
-                       icalparameter_set_language (
-                               priv->organizer.language_param,
-                               (gchar *) organizer->language);
-               else {
-                       priv->organizer.language_param = icalparameter_new_language (
-                               (gchar *) organizer->language);
-                       icalproperty_add_parameter (
-                               priv->organizer.prop,
-                               priv->organizer.language_param);
-               }
-       } else if (priv->organizer.language_param) {
-               icalproperty_remove_parameter_by_kind (priv->organizer.prop, ICAL_LANGUAGE_PARAMETER);
-               priv->organizer.language_param = NULL;
-       }
-
-}
-
-/**
- * e_cal_component_has_organizer:
- * @comp: A calendar component object.
- *
- * Check whether a calendar component object has an organizer or not.
- *
- * Returns: TRUE if there is an organizer, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_organizer (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-
-       return priv->organizer.prop != NULL;
-}
-
-/**
- * e_cal_component_get_percent:
- * @comp: A calendar component object.
- * @percent: (out): Return value for the percent-complete property.  This should be
- * freed using the e_cal_component_free_percent() function.
- *
- * Queries the percent-complete property of a calendar component object.
- **/
-void
-e_cal_component_get_percent (ECalComponent *comp,
-                             gint **percent)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (percent != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (priv->percent) {
-               *percent = g_new (int, 1);
-               **percent = icalproperty_get_percentcomplete (priv->percent);
-       } else
-               *percent = NULL;
-}
-
-/**
- * e_cal_component_set_percent_as_int:
- * @comp: an #ECalComponent
- * @percent: a percent to set, or -1 to remove the property
- *
- * Sets percent complete as integer. The @percent can be between 0 and 100, inclusive.
- * A special value -1 can be used to remove the percent complete property.
- *
- * Since: 2.28
- **/
-void
-e_cal_component_set_percent_as_int (ECalComponent *comp,
-                                    gint percent)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (percent == -1) {
-               if (priv->percent) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->percent);
-                       icalproperty_free (priv->percent);
-                       priv->percent = NULL;
-               }
-
-               return;
-       }
-
-       g_return_if_fail (percent >= 0 && percent <= 100);
-
-       if (priv->percent)
-               icalproperty_set_percentcomplete (priv->percent, percent);
-       else {
-               priv->percent = icalproperty_new_percentcomplete (percent);
-               icalcomponent_add_property (priv->icalcomp, priv->percent);
-       }
-
-}
-
-/**
- * e_cal_component_get_percent_as_int:
- * @comp: an #ECalComponent
- *
- * Get percent complete as an integer value
- *
- * Returns: percent complete as an integer value, -1 when the @comp doesn't have the property
- *
- * Since: 2.28
- **/
-gint
-e_cal_component_get_percent_as_int (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       gint percent;
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, -1);
-
-       if (priv->percent) {
-               percent = icalproperty_get_percentcomplete (priv->percent);
-       } else
-               percent = -1;
-
-       return percent;
-}
-
-/**
- * e_cal_component_set_percent:
- * @comp: A calendar component object.
- * @percent: Value for the percent-complete property.
- *
- * Sets the percent-complete property of a calendar component object.
- **/
-void
-e_cal_component_set_percent (ECalComponent *comp,
-                             gint *percent)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!percent) {
-               if (priv->percent) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->percent);
-                       icalproperty_free (priv->percent);
-                       priv->percent = NULL;
-               }
-
-               return;
-       }
-
-       g_return_if_fail (*percent >= 0 && *percent <= 100);
-
-       if (priv->percent)
-               icalproperty_set_percentcomplete (priv->percent, *percent);
-       else {
-               priv->percent = icalproperty_new_percentcomplete (*percent);
-               icalcomponent_add_property (priv->icalcomp, priv->percent);
-       }
-}
-
-/**
- * e_cal_component_get_priority:
- * @comp: A calendar component object.
- * @priority: (out): Return value for the priority property.  This should be freed using
- * the e_cal_component_free_priority() function.
- *
- * Queries the priority property of a calendar component object.
- **/
-void
-e_cal_component_get_priority (ECalComponent *comp,
-                              gint **priority)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (priority != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (priv->priority) {
-               *priority = g_new (int, 1);
-               **priority = icalproperty_get_priority (priv->priority);
-       } else
-               *priority = NULL;
-}
-
-/**
- * e_cal_component_set_priority:
- * @comp: A calendar component object.
- * @priority: Value for the priority property.
- *
- * Sets the priority property of a calendar component object.
- **/
-void
-e_cal_component_set_priority (ECalComponent *comp,
-                              gint *priority)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priority) {
-               if (priv->priority) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->priority);
-                       icalproperty_free (priv->priority);
-                       priv->priority = NULL;
-               }
-
-               return;
-       }
-
-       g_return_if_fail (*priority >= 0 && *priority <= 9);
-
-       if (priv->priority)
-               icalproperty_set_priority (priv->priority, *priority);
-       else {
-               priv->priority = icalproperty_new_priority (*priority);
-               icalcomponent_add_property (priv->icalcomp, priv->priority);
-       }
-}
-
-/**
- * e_cal_component_get_recurid:
- * @comp: A calendar component object.
- * @recur_id: (out): Return value for the recurrence id property
- *
- * Queries the recurrence id property of a calendar component object.
- **/
-void
-e_cal_component_get_recurid (ECalComponent *comp,
-                             ECalComponentRange *recur_id)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_id != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
-
-       get_datetime (
-               &priv->recur_id.recur_time,
-               icalproperty_get_recurrenceid,
-               &recur_id->datetime);
-}
-
-/**
- * e_cal_component_get_recurid_as_string:
- * @comp: A calendar component object.
- *
- * Gets the recurrence ID property as a string.
- *
- * Returns: the recurrence ID as a string.
- */
-gchar *
-e_cal_component_get_recurid_as_string (ECalComponent *comp)
-{
-       ECalComponentRange range;
-       struct icaltimetype tt;
-
-       if (!e_cal_component_is_instance (comp))
-               return NULL;
-
-       e_cal_component_get_recurid (comp, &range);
-       if (!range.datetime.value) {
-               e_cal_component_free_range (&range);
-               return g_strdup ("0");
-       }
-
-       tt = *range.datetime.value;
-       e_cal_component_free_range (&range);
-
-       return icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt) ?
-               icaltime_as_ical_string_r (tt) : g_strdup ("0");
-}
-
-/**
- * e_cal_component_set_recurid:
- * @comp: A calendar component object.
- * @recur_id: Value for the recurrence id property.
- *
- * Sets the recurrence id property of a calendar component object.
- **/
-void
-e_cal_component_set_recurid (ECalComponent *comp,
-                             ECalComponentRange *recur_id)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->recur_id.recur_time,
-               icalproperty_new_recurrenceid,
-               icalproperty_set_recurrenceid,
-               recur_id ? &recur_id->datetime : NULL);
-}
-
-/**
- * e_cal_component_get_rdate_list:
- * @comp: A calendar component object.
- * @period_list: (out) (transfer full) (element-type ECalComponentPeriod):
- * Return value for the list of recurrence dates, as a list of
- * #ECalComponentPeriod structures.  This should be freed using
- * e_cal_component_free_period_list()
- *
- * Queries the list of recurrence date properties in a calendar component
- * object.
- **/
-void
-e_cal_component_get_rdate_list (ECalComponent *comp,
-                                GSList **period_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (period_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_period_list (priv->rdate_list, icalproperty_get_rdate, period_list);
-}
-
-/**
- * e_cal_component_set_rdate_list:
- * @comp: A calendar component object.
- * @period_list: (element-type ECalComponentPeriod): List of
- * #ECalComponentPeriod structures
- *
- * Sets the list of recurrence dates in a calendar component object.
- **/
-void
-e_cal_component_set_rdate_list (ECalComponent *comp,
-                                GSList *period_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_period_list (comp, icalproperty_new_rdate, &priv->rdate_list, period_list);
-
-       priv->need_sequence_inc = TRUE;
-}
-
-/**
- * e_cal_component_has_rdates:
- * @comp: A calendar component object.
- *
- * Queries whether a calendar component object has any recurrence dates defined
- * for it.
- *
- * Returns: TRUE if the component has recurrence dates, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_rdates (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
-
-       return (priv->rdate_list != NULL);
-}
-
-/**
- * e_cal_component_get_rrule_list:
- * @comp: A calendar component object.
- * @recur_list: (out) (transfer full) (element-type icalrecurrencetype): List of
- * recurrence rules as struct #icalrecurrencetype structures.  This should be
- * freed using e_cal_component_free_recur_list().
- *
- * Queries the list of recurrence rule properties of a calendar component
- * object.
- **/
-void
-e_cal_component_get_rrule_list (ECalComponent *comp,
-                                GSList **recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_recur_list (priv->rrule_list, icalproperty_get_rrule, recur_list);
-}
-
-/**
- * e_cal_component_get_rrule_property_list:
- * @comp: A calendar component object.
- * @recur_list: (out) (transfer none) (element-type icalrecurrencetype): Returns
- * a list of recurrence rule properties.
- *
- * Queries a list of recurrence rule properties of a calendar component object.
- **/
-void
-e_cal_component_get_rrule_property_list (ECalComponent *comp,
-                                         GSList **recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       *recur_list = priv->rrule_list;
-}
-
-/**
- * e_cal_component_set_rrule_list:
- * @comp: A calendar component object.
- * @recur_list: (element-type icalrecurrencetype): List of struct
- * #icalrecurrencetype structures.
- *
- * Sets the list of recurrence rules in a calendar component object.
- **/
-void
-e_cal_component_set_rrule_list (ECalComponent *comp,
-                                GSList *recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_recur_list (comp, icalproperty_new_rrule, &priv->rrule_list, recur_list);
-
-       priv->need_sequence_inc = TRUE;
-}
-
-/**
- * e_cal_component_has_rrules:
- * @comp: A calendar component object.
- *
- * Queries whether a calendar component object has any recurrence rules defined
- * for it.
- *
- * Returns: TRUE if the component has recurrence rules, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_rrules (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
-
-       return (priv->rrule_list != NULL);
-}
-
-/**
- * e_cal_component_has_recurrences:
- * @comp: A calendar component object
- *
- * Queries whether a calendar component object has any recurrence dates or
- * recurrence rules.
- *
- * Returns: TRUE if the component has recurrences, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_recurrences (ECalComponent *comp)
-{
-       return e_cal_component_has_rdates (comp) || e_cal_component_has_rrules (comp);
-}
-
-/* Counts the elements in the by_xxx fields of an icalrecurrencetype */
-static gint
-count_by_xxx (gshort *field,
-              gint max_elements)
-{
-       gint i;
-
-       for (i = 0; i < max_elements; i++)
-               if (field[i] == ICAL_RECURRENCE_ARRAY_MAX)
-                       break;
-
-       return i;
-}
-
-/**
- * e_cal_component_has_simple_recurrence:
- * @comp: A calendar component object.
- *
- * Checks whether the given calendar component object has simple recurrence
- * rules or more complicated ones.
- *
- * Returns: TRUE if it has a simple recurrence rule, FALSE otherwise.
- */
-gboolean
-e_cal_component_has_simple_recurrence (ECalComponent *comp)
-{
-       GSList *rrule_list;
-       struct icalrecurrencetype *r;
-       gint n_by_second, n_by_minute, n_by_hour;
-       gint n_by_day, n_by_month_day, n_by_year_day;
-       gint n_by_week_no, n_by_month, n_by_set_pos;
-       gint len, i;
-       gboolean simple = FALSE;
-
-       if (!e_cal_component_has_recurrences (comp))
-               return TRUE;
-
-       e_cal_component_get_rrule_list (comp, &rrule_list);
-       len = g_slist_length (rrule_list);
-       if (len > 1
-           || e_cal_component_has_rdates (comp)
-           || e_cal_component_has_exrules (comp))
-               goto cleanup;
-
-       /* Down to one rule, so test that one */
-       r = rrule_list->data;
-
-       /* Any funky frequency? */
-       if (r->freq == ICAL_SECONDLY_RECURRENCE
-           || r->freq == ICAL_MINUTELY_RECURRENCE
-           || r->freq == ICAL_HOURLY_RECURRENCE)
-               goto cleanup;
-
-       /* Any funky BY_* */
-#define N_HAS_BY(field) (count_by_xxx (field, G_N_ELEMENTS (field)))
-
-       n_by_second = N_HAS_BY (r->by_second);
-       n_by_minute = N_HAS_BY (r->by_minute);
-       n_by_hour = N_HAS_BY (r->by_hour);
-       n_by_day = N_HAS_BY (r->by_day);
-       n_by_month_day = N_HAS_BY (r->by_month_day);
-       n_by_year_day = N_HAS_BY (r->by_year_day);
-       n_by_week_no = N_HAS_BY (r->by_week_no);
-       n_by_month = N_HAS_BY (r->by_month);
-       n_by_set_pos = N_HAS_BY (r->by_set_pos);
-
-       if (n_by_second != 0
-           || n_by_minute != 0
-           || n_by_hour != 0)
-               goto cleanup;
-
-       switch (r->freq) {
-       case ICAL_DAILY_RECURRENCE:
-               if (n_by_day != 0
-                   || n_by_month_day != 0
-                   || n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos != 0)
-                       goto cleanup;
-
-               simple = TRUE;
-               break;
-
-       case ICAL_WEEKLY_RECURRENCE:
-               if (n_by_month_day != 0
-                   || n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos != 0)
-                       goto cleanup;
-
-               for (i = 0; i < 8 && r->by_day[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) {
-                       gint pos;
-                       pos = icalrecurrencetype_day_position (r->by_day[i]);
-
-                       if (pos != 0)
-                               goto cleanup;
-               }
-
-               simple = TRUE;
-               break;
-
-       case ICAL_MONTHLY_RECURRENCE:
-               if (n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos > 1)
-                       goto cleanup;
-
-               if (n_by_month_day == 1) {
-                       gint nth;
-
-                       if (n_by_set_pos != 0)
-                               goto cleanup;
-
-                       nth = r->by_month_day[0];
-                       if (nth < 1 && nth != -1)
-                               goto cleanup;
-
-               } else if (n_by_day == 1) {
-                       enum icalrecurrencetype_weekday weekday;
-                       gint pos;
-
-                       /* Outlook 2000 uses BYDAY=TU;BYSETPOS=2, and will not
-                        * accept BYDAY=2TU. So we now use the same as Outlook
-                        * by default. */
-
-                       weekday = icalrecurrencetype_day_day_of_week (r->by_day[0]);
-                       pos = icalrecurrencetype_day_position (r->by_day[0]);
-
-                       if (pos == 0) {
-                               if (n_by_set_pos != 1)
-                                       goto cleanup;
-                               pos = r->by_set_pos[0];
-                       } else if (pos < 0) {
-                               goto cleanup;
-                       }
-
-                       switch (weekday) {
-                       case ICAL_MONDAY_WEEKDAY:
-                       case ICAL_TUESDAY_WEEKDAY:
-                       case ICAL_WEDNESDAY_WEEKDAY:
-                       case ICAL_THURSDAY_WEEKDAY:
-                       case ICAL_FRIDAY_WEEKDAY:
-                       case ICAL_SATURDAY_WEEKDAY:
-                       case ICAL_SUNDAY_WEEKDAY:
-                               break;
-
-                       default:
-                               goto cleanup;
-                       }
-               } else {
-                       goto cleanup;
-               }
-
-               simple = TRUE;
-               break;
-
-       case ICAL_YEARLY_RECURRENCE:
-               if (n_by_day != 0
-                   || n_by_month_day != 0
-                   || n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos != 0)
-                       goto cleanup;
-
-               simple = TRUE;
-               break;
-
-       default:
-               goto cleanup;
-       }
-
- cleanup:
-       e_cal_component_free_recur_list (rrule_list);
-
-       return simple;
-}
-
-/**
- * e_cal_component_is_instance:
- * @comp: A calendar component object.
- *
- * Checks whether a calendar component object is an instance of a recurring
- * event.
- *
- * Returns: TRUE if it is an instance, FALSE if not.
- */
-gboolean
-e_cal_component_is_instance (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-
-       return !(priv->recur_id.recur_time.prop == NULL);
-}
-
-/**
- * e_cal_component_get_sequence:
- * @comp: A calendar component object.
- * @sequence: (out): Return value for the sequence number.  This should be freed using
- * e_cal_component_free_sequence().
- *
- * Queries the sequence number of a calendar component object.
- **/
-void
-e_cal_component_get_sequence (ECalComponent *comp,
-                              gint **sequence)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (sequence != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->sequence) {
-               *sequence = NULL;
-               return;
-       }
-
-       *sequence = g_new (int, 1);
-       **sequence = icalproperty_get_sequence (priv->sequence);
-}
-
-/**
- * e_cal_component_set_sequence:
- * @comp: A calendar component object.
- * @sequence: Sequence number value.
- *
- * Sets the sequence number of a calendar component object.  Normally this
- * function should not be called, since the sequence number is incremented
- * automatically at the proper times.
- **/
-void
-e_cal_component_set_sequence (ECalComponent *comp,
-                              gint *sequence)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       priv->need_sequence_inc = FALSE;
-
-       if (!sequence) {
-               if (priv->sequence) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->sequence);
-                       icalproperty_free (priv->sequence);
-                       priv->sequence = NULL;
-               }
-
-               return;
-       }
-
-       if (priv->sequence)
-               icalproperty_set_sequence (priv->sequence, *sequence);
-       else {
-               priv->sequence = icalproperty_new_sequence (*sequence);
-               icalcomponent_add_property (priv->icalcomp, priv->sequence);
-       }
-}
-
-/**
- * e_cal_component_get_status:
- * @comp: A calendar component object.
- * @status: (out): Return value for the status value.  It is set to #ICAL_STATUS_NONE
- * if the component has no status property.
- *
- * Queries the status property of a calendar component object.
- **/
-void
-e_cal_component_get_status (ECalComponent *comp,
-                            icalproperty_status *status)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (status != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->status) {
-               *status = ICAL_STATUS_NONE;
-               return;
-       }
-
-       *status = icalproperty_get_status (priv->status);
-}
-
-/**
- * e_cal_component_set_status:
- * @comp: A calendar component object.
- * @status: Status value.  You should use #ICAL_STATUS_NONE if you want to unset
- * this property.
- *
- * Sets the status property of a calendar component object.
- **/
-void
-e_cal_component_set_status (ECalComponent *comp,
-                            icalproperty_status status)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       priv->need_sequence_inc = TRUE;
-
-       if (status == ICAL_STATUS_NONE) {
-               if (priv->status) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->status);
-                       icalproperty_free (priv->status);
-                       priv->status = NULL;
-               }
-
-               return;
-       }
-
-       if (priv->status) {
-               icalproperty_set_status (priv->status, status);
-       } else {
-               priv->status = icalproperty_new_status (status);
-               icalcomponent_add_property (priv->icalcomp, priv->status);
-       }
-}
-
-/**
- * e_cal_component_get_summary:
- * @comp: A calendar component object.
- * @summary: (out): Return value for the summary property and its parameters.
- *
- * Queries the summary of a calendar component object.
- **/
-void
-e_cal_component_get_summary (ECalComponent *comp,
-                             ECalComponentText *summary)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (summary != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (priv->summary.prop)
-               summary->value = icalproperty_get_summary (priv->summary.prop);
-       else
-               summary->value = NULL;
-
-       if (priv->summary.altrep_param)
-               summary->altrep = icalparameter_get_altrep (priv->summary.altrep_param);
-       else
-               summary->altrep = NULL;
-}
-
-typedef struct {
-       gchar *old_summary;
-       const gchar *new_summary;
-} SetAlarmDescriptionData;
-
-static void
-set_alarm_description_cb (gpointer key,
-                          gpointer value,
-                          gpointer user_data)
-{
-       icalcomponent *alarm;
-       icalproperty *icalprop, *desc_prop;
-       SetAlarmDescriptionData *sadd;
-       gboolean changed = FALSE;
-       const gchar *old_summary = NULL;
-       gboolean free_description = FALSE;
-
-       alarm = value;
-       sadd = user_data;
-
-       /* set the new description on the alarm */
-       desc_prop = icalcomponent_get_first_property (alarm, ICAL_DESCRIPTION_PROPERTY);
-       if (desc_prop) {
-               old_summary = icalproperty_get_description (desc_prop);
-       } else {
-               desc_prop = icalproperty_new_description (sadd->new_summary);
-               free_description = TRUE;
-       }
-
-       /* remove the X-EVOLUTION-NEEDS_DESCRIPTION property */
-       icalprop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-       while (icalprop) {
-               const gchar *x_name;
-
-               x_name = icalproperty_get_x_name (icalprop);
-               if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
-                       icalcomponent_remove_property (alarm, icalprop);
-                       icalproperty_free (icalprop);
-
-                       icalproperty_set_description (desc_prop, sadd->new_summary);
-                       changed = TRUE;
-                       break;
-               }
-
-               icalprop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY);
-       }
-
-       if (!changed) {
-               if (!strcmp (old_summary ? old_summary : "", sadd->old_summary ? sadd->old_summary : "")) {
-                       icalproperty_set_description (desc_prop, sadd->new_summary);
-               }
-       }
-
-       if (free_description)
-               icalproperty_free (desc_prop);
-}
-
-/**
- * e_cal_component_set_summary:
- * @comp: A calendar component object.
- * @summary: Summary property and its parameters.
- *
- * Sets the summary of a calendar component object.
- **/
-void
-e_cal_component_set_summary (ECalComponent *comp,
-                             ECalComponentText *summary)
-{
-       ECalComponentPrivate *priv;
-       SetAlarmDescriptionData sadd;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!summary) {
-               if (priv->summary.prop) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->summary.prop);
-                       icalproperty_free (priv->summary.prop);
-
-                       priv->summary.prop = NULL;
-                       priv->summary.altrep_param = NULL;
-               }
-
-               return;
-       }
-
-       g_return_if_fail (summary->value != NULL);
-
-       if (priv->summary.prop) {
-               /* Make a copy, to avoid use-after-free */
-               sadd.old_summary = g_strdup (icalproperty_get_summary (priv->summary.prop));
-               icalproperty_set_summary (priv->summary.prop, (gchar *) summary->value);
-       } else {
-               sadd.old_summary = NULL;
-               priv->summary.prop = icalproperty_new_summary ((gchar *) summary->value);
-               icalcomponent_add_property (priv->icalcomp, priv->summary.prop);
-       }
-
-       if (summary->altrep) {
-               g_return_if_fail (priv->summary.prop != NULL);
-
-               if (priv->summary.altrep_param)
-                       icalparameter_set_altrep (
-                               priv->summary.altrep_param,
-                               (gchar *) summary->altrep);
-               else {
-                       priv->summary.altrep_param = icalparameter_new_altrep (
-                               (gchar *) summary->altrep);
-                       icalproperty_add_parameter (
-                               priv->summary.prop,
-                               priv->summary.altrep_param);
-               }
-       } else if (priv->summary.altrep_param) {
-               icalproperty_remove_parameter_by_kind (priv->summary.prop, ICAL_ALTREP_PARAMETER);
-               priv->summary.altrep_param = NULL;
-       }
+ *
+ * Queries whether a calendar component object has any exception rules defined
+ * for it.
+ *
+ * Returns: TRUE if the component has exception rules, FALSE otherwise.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_has_exrules (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       /* look for alarms that need a description */
-       sadd.new_summary = summary->value;
-       g_hash_table_foreach (priv->alarm_uid_hash, set_alarm_description_cb, &sadd);
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY);
+}
 
-       g_free (sadd.old_summary);
+/**
+ * e_cal_component_has_exceptions:
+ * @comp: A calendar component object
+ *
+ * Queries whether a calendar component object has any exception dates
+ * or exception rules.
+ *
+ * Returns: TRUE if the component has exceptions, FALSE otherwise.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_has_exceptions (ECalComponent *comp)
+{
+       return e_cal_component_has_exdates (comp) || e_cal_component_has_exrules (comp);
 }
 
 /**
- * e_cal_component_get_transparency:
+ * e_cal_component_get_geo:
  * @comp: A calendar component object.
- * @transp: (out): Return value for the time transparency.
  *
- * Queries the time transparency of a calendar component object.
+ * Gets the geographic position property of a calendar component object.
+ * Free the returned non-NULL object with g_object_unref(), when
+ * no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the geographic position as #ICalGeo,
+ *    or %NULL, when none set.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_transparency (ECalComponent *comp,
-                                  ECalComponentTransparency *transp)
+ICalGeo *
+e_cal_component_get_geo (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_transp ical_transp;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (transp != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       ICalProperty *prop;
+       ICalGeo *geo;
 
-       if (!priv->transparency) {
-               *transp = E_CAL_COMPONENT_TRANSP_NONE;
-               return;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       ical_transp = icalproperty_get_transp (priv->transparency);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_GEO_PROPERTY);
+       if (!prop)
+               return NULL;
 
-       switch (ical_transp)
-       {
-       case ICAL_TRANSP_TRANSPARENT:
-       case ICAL_TRANSP_TRANSPARENTNOCONFLICT:
-         *transp = E_CAL_COMPONENT_TRANSP_TRANSPARENT;
-         break;
+       geo = i_cal_property_get_geo (prop);
 
-       case ICAL_TRANSP_OPAQUE:
-       case ICAL_TRANSP_OPAQUENOCONFLICT:
-         *transp = E_CAL_COMPONENT_TRANSP_OPAQUE;
-         break;
+       g_object_unref (prop);
 
-       default:
-         *transp = E_CAL_COMPONENT_TRANSP_UNKNOWN;
-         break;
-       }
+       return geo;
 }
 
 /**
- * e_cal_component_set_transparency:
+ * e_cal_component_set_geo:
  * @comp: A calendar component object.
- * @transp: Time transparency value.
+ * @geo: (nullable): Value for the geographic position property, or %NULL to unset.
  *
- * Sets the time transparency of a calendar component object.
+ * Sets the geographic position property on a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_transparency (ECalComponent *comp,
-                                  ECalComponentTransparency transp)
+e_cal_component_set_geo (ECalComponent *comp,
+                        const ICalGeo *geo)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_transp ical_transp;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (transp != E_CAL_COMPONENT_TRANSP_UNKNOWN);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_GEO_PROPERTY);
 
-       if (transp == E_CAL_COMPONENT_TRANSP_NONE) {
-               if (priv->transparency) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->transparency);
-                       icalproperty_free (priv->transparency);
-                       priv->transparency = NULL;
+       if (!geo) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
                }
 
                return;
        }
 
-       switch (transp) {
-       case E_CAL_COMPONENT_TRANSP_TRANSPARENT:
-         ical_transp = ICAL_TRANSP_TRANSPARENT;
-               break;
-
-       case E_CAL_COMPONENT_TRANSP_OPAQUE:
-         ical_transp = ICAL_TRANSP_OPAQUE;
-               break;
-
-       default:
-               g_warn_if_reached ();
-               ical_transp = ICAL_TRANSP_NONE;
+       if (prop) {
+               i_cal_property_set_geo (prop, (ICalGeo *) geo);
+       } else {
+               prop = i_cal_property_new_geo ((ICalGeo *) geo);
+               i_cal_component_add_property (comp->priv->icalcomp, prop);
        }
 
-       if (priv->transparency)
-               icalproperty_set_transp (priv->transparency, ical_transp);
-       else {
-               priv->transparency = icalproperty_new_transp (ical_transp);
-               icalcomponent_add_property (priv->icalcomp, priv->transparency);
-       }
+       g_clear_object (&prop);
 }
 
 /**
- * e_cal_component_get_url:
+ * e_cal_component_get_last_modified:
  * @comp: A calendar component object.
- * @url: (out) (transfer none): Return value for the URL.
  *
- * Queries the uniform resource locator property of a calendar component object.
+ * Queries the time at which a calendar component object was last modified in
+ * the calendar store. Free the returned non-NULL pointer with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): the last modified time, as an #ICalTime, or %NULL, when none is set
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_url (ECalComponent *comp,
-                         const gchar **url)
+ICalTime *
+e_cal_component_get_last_modified (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (url != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (priv->url)
-               *url = icalproperty_get_url (priv->url);
-       else
-               *url = NULL;
+       return get_icaltimetype (comp->priv->icalcomp, I_CAL_LASTMODIFIED_PROPERTY, 
i_cal_property_get_lastmodified);
 }
 
 /**
- * e_cal_component_set_url:
+ * e_cal_component_set_last_modified:
  * @comp: A calendar component object.
- * @url: URL value.
+ * @tt: (nullable): Value for the last time modified.
  *
- * Sets the uniform resource locator property of a calendar component object.
+ * Sets the time at which a calendar component object was last stored in the
+ * calendar store.  This should not be called by plain calendar user agents.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_url (ECalComponent *comp,
-                         const gchar *url)
+e_cal_component_set_last_modified (ECalComponent *comp,
+                                  const ICalTime *tt)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!url || !(*url)) {
-               if (priv->url) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->url);
-                       icalproperty_free (priv->url);
-                       priv->url = NULL;
-               }
-
-               return;
-       }
-
-       if (priv->url)
-               icalproperty_set_url (priv->url, (gchar *) url);
-       else {
-               priv->url = icalproperty_new_url ((gchar *) url);
-               icalcomponent_add_property (priv->icalcomp, priv->url);
-       }
-}
-
-/* Gets a text list value */
-static void
-get_attendee_list (GSList *attendee_list,
-                   GSList **al)
-{
-       GSList *l;
-
-       *al = NULL;
-
-       if (!attendee_list)
-               return;
-
-       for (l = attendee_list; l; l = l->next) {
-               struct attendee *attendee;
-               ECalComponentAttendee *a;
-
-               attendee = l->data;
-               g_return_if_fail (attendee->prop != NULL);
-
-               a = g_new0 (ECalComponentAttendee, 1);
-               a->value = icalproperty_get_attendee (attendee->prop);
-
-               if (attendee->member_param)
-                       a->member = icalparameter_get_member (attendee->member_param);
-               if (attendee->cutype_param)
-                       a->cutype = icalparameter_get_cutype (attendee->cutype_param);
-               else
-                       a->cutype = ICAL_CUTYPE_UNKNOWN;
-               if (attendee->role_param)
-                       a->role = icalparameter_get_role (attendee->role_param);
-               else
-                       a->role = ICAL_ROLE_REQPARTICIPANT;
-               if (attendee->partstat_param)
-                       a->status = icalparameter_get_partstat (attendee->partstat_param);
-               else
-                       a->status = ICAL_PARTSTAT_NEEDSACTION;
-               if (attendee->rsvp_param && icalparameter_get_rsvp (attendee->rsvp_param) == ICAL_RSVP_TRUE)
-                       a->rsvp = TRUE;
-               else
-                       a->rsvp = FALSE;
-               if (attendee->delfrom_param)
-                       a->delfrom = icalparameter_get_delegatedfrom (attendee->delfrom_param);
-               if (attendee->delto_param)
-                       a->delto = icalparameter_get_delegatedto (attendee->delto_param);
-               if (attendee->sentby_param)
-                       a->sentby = icalparameter_get_sentby (attendee->sentby_param);
-               if (attendee->cn_param)
-                       a->cn = icalparameter_get_cn (attendee->cn_param);
-               if (attendee->language_param)
-                       a->language = icalparameter_get_language (attendee->language_param);
-
-               *al = g_slist_prepend (*al, a);
-       }
-
-       *al = g_slist_reverse (*al);
+       set_icaltimetype (comp->priv->icalcomp, I_CAL_LASTMODIFIED_PROPERTY,
+               i_cal_property_new_lastmodified,
+               i_cal_property_set_lastmodified,
+               tt);
 }
 
-/* Sets a text list value */
-static void
-set_attendee_list (icalcomponent *icalcomp,
-                   GSList **attendee_list,
-                   GSList *al)
+/**
+ * e_cal_component_get_organizer:
+ * @comp:  A calendar component object
+ *
+ * Queries the organizer property of a calendar component object.
+ * Free the returned structure with e_cal_component_organizer_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): an #ECalComponentOrganizer structure
+ *    destribing the organizer, or %NULL, when none exists.
+ *
+ * Since: 3.36
+ **/
+ECalComponentOrganizer *
+e_cal_component_get_organizer (ECalComponent *comp)
 {
-       GSList *l;
-
-       /* Remove old attendees */
-
-       for (l = *attendee_list; l; l = l->next) {
-               struct attendee *attendee;
+       ECalComponentOrganizer *organizer;
+       ICalProperty *prop;
 
-               attendee = l->data;
-               g_return_if_fail (attendee->prop != NULL);
-
-               icalcomponent_remove_property (icalcomp, attendee->prop);
-               icalproperty_free (attendee->prop);
-               g_free (attendee);
-       }
-
-       g_slist_free (*attendee_list);
-       *attendee_list = NULL;
-
-       /* Add in new attendees */
-
-       for (l = al; l; l = l->next) {
-               ECalComponentAttendee *a;
-               struct attendee *attendee;
-
-               a = l->data;
-               g_return_if_fail (a->value != NULL);
-
-               attendee = g_new0 (struct attendee, 1);
-
-               attendee->prop = icalproperty_new_attendee (a->value);
-               icalcomponent_add_property (icalcomp, attendee->prop);
-
-               if (a->member) {
-                       attendee->member_param = icalparameter_new_member (a->member);
-                       icalproperty_add_parameter (attendee->prop, attendee->member_param);
-               }
-
-               attendee->cutype_param = icalparameter_new_cutype (a->cutype);
-               icalproperty_add_parameter (attendee->prop, attendee->cutype_param);
-
-               attendee->role_param = icalparameter_new_role (a->role);
-               icalproperty_add_parameter (attendee->prop, attendee->role_param);
-
-               attendee->partstat_param = icalparameter_new_partstat (a->status);
-               icalproperty_add_parameter (attendee->prop, attendee->partstat_param);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               if (a->rsvp)
-                       attendee->rsvp_param = icalparameter_new_rsvp (ICAL_RSVP_TRUE);
-               else
-                       attendee->rsvp_param = icalparameter_new_rsvp (ICAL_RSVP_FALSE);
-               icalproperty_add_parameter (attendee->prop, attendee->rsvp_param);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_ORGANIZER_PROPERTY);
+       if (!prop)
+               return NULL;
 
-               if (a->delfrom) {
-                       attendee->delfrom_param = icalparameter_new_delegatedfrom (a->delfrom);
-                       icalproperty_add_parameter (attendee->prop, attendee->delfrom_param);
-               }
-               if (a->delto) {
-                       attendee->delto_param = icalparameter_new_delegatedto (a->delto);
-                       icalproperty_add_parameter (attendee->prop, attendee->delto_param);
-               }
-               if (a->sentby) {
-                       attendee->sentby_param = icalparameter_new_sentby (a->sentby);
-                       icalproperty_add_parameter (attendee->prop, attendee->sentby_param);
-               }
-               if (a->cn) {
-                       attendee->cn_param = icalparameter_new_cn (a->cn);
-                       icalproperty_add_parameter (attendee->prop, attendee->cn_param);
-               }
-               if (a->language) {
-                       attendee->language_param = icalparameter_new_language (a->language);
-                       icalproperty_add_parameter (attendee->prop, attendee->language_param);
-               }
+       organizer = e_cal_component_organizer_new_from_property (prop);
 
-               *attendee_list = g_slist_prepend (*attendee_list, attendee);
-       }
+       g_object_unref (prop);
 
-       *attendee_list = g_slist_reverse (*attendee_list);
+       return organizer;
 }
 
 /**
- * e_cal_component_get_attendee_list:
- * @comp: A calendar component object.
- * @attendee_list: (out) (transfer full) (element-type ECalComponentAttendee):
- * Return value for the attendee property. This should be freed using
- * e_cal_component_free_attendee_list().
+ * e_cal_component_set_organizer:
+ * @comp:  A calendar component object.
+ * @organizer: (nullable): Value for the organizer property, as an #ECalComponentOrganizer
+ *
+ * Sets the organizer of a calendar component object
  *
- * Queries the attendee properties of the calendar component object
+ * Since: 3.36
  **/
 void
-e_cal_component_get_attendee_list (ECalComponent *comp,
-                                   GSList **attendee_list)
+e_cal_component_set_organizer (ECalComponent *comp,
+                              const ECalComponentOrganizer *organizer)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (attendee_list != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_ORGANIZER_PROPERTY);
 
-       get_attendee_list (priv->attendee_list, attendee_list);
-}
+       if (!organizer) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
+               }
 
-/**
- * e_cal_component_set_attendee_list:
- * @comp: A calendar component object.
- * @attendee_list: (element-type ECalComponentAttendee): Values for attendee
- * properties
- *
- * Sets the attendees of a calendar component object
- **/
-void
-e_cal_component_set_attendee_list (ECalComponent *comp,
-                                   GSList *attendee_list)
-{
-       ECalComponentPrivate *priv;
+               return;
+       }
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       if (!prop) {
+               prop = i_cal_property_new (I_CAL_ORGANIZER_PROPERTY);
+               i_cal_component_add_property (comp->priv->icalcomp, prop);
+       }
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       e_cal_component_organizer_fill_property (organizer, prop);
 
-       set_attendee_list (priv->icalcomp, &priv->attendee_list, attendee_list);
+       g_clear_object (&prop);
 }
 
 /**
- * e_cal_component_has_attendees:
+ * e_cal_component_has_organizer:
  * @comp: A calendar component object.
  *
- * Queries a calendar component object for the existence of attendees.
+ * Check whether a calendar component object has an organizer or not.
  *
- * Returns: TRUE if there are attendees, FALSE if not.
- */
+ * Returns: TRUE if there is an organizer, FALSE otherwise.
+ *
+ * Since: 3.36
+ **/
 gboolean
-e_cal_component_has_attendees (ECalComponent *comp)
+e_cal_component_has_organizer (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       priv = comp->priv;
-
-       if (g_slist_length (priv->attendee_list) > 0)
-               return TRUE;
-
-       return FALSE;
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_ORGANIZER_PROPERTY);
 }
 
 /**
- * e_cal_component_get_location:
- * @comp: A calendar component object
- * @location: (out) (transfer none): Return value for the location.
+ * e_cal_component_get_percent_complete:
+ * @comp: A calendar component object.
  *
- * Queries the location property of a calendar component object.
+ * Queries the percent-complete property of a calendar component object.
+ *
+ * Returns: the percent-complete property value, or -1 if not found
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_get_location (ECalComponent *comp,
-                              const gchar **location)
+gint
+e_cal_component_get_percent_complete (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       gint percent;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (location != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), -1);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, -1);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PERCENTCOMPLETE_PROPERTY);
+       if (!prop)
+               return -1;
 
-       if (priv->location)
-               *location = icalproperty_get_location (priv->location);
-       else
-               *location = NULL;
+       percent = i_cal_property_get_percentcomplete (prop);
+
+       g_object_unref (prop);
+
+       return percent;
 }
 
 /**
- * e_cal_component_set_location:
- * @comp: A calendar component object.
- * @location: Location value.
+ * e_cal_component_set_percent_complete:
+ * @comp: an #ECalComponent
+ * @percent: a percent to set, or -1 to remove the property
  *
- * Sets the location property of a calendar component object.
+ * Sets percent complete. The @percent can be between 0 and 100, inclusive.
+ * A special value -1 can be used to remove the percent complete property.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_set_location (ECalComponent *comp,
-                              const gchar *location)
+e_cal_component_set_percent_complete (ECalComponent *comp,
+                                     gint percent)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+       g_return_if_fail (percent >= -1 && percent <= 100);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PERCENTCOMPLETE_PROPERTY);
 
-       if (!location || !(*location)) {
-               if (priv->location) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->location);
-                       icalproperty_free (priv->location);
-                       priv->location = NULL;
+       if (percent == -1) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
                }
 
                return;
        }
 
-       if (priv->location)
-               icalproperty_set_location (priv->location, (gchar *) location);
-       else {
-               priv->location = icalproperty_new_location ((gchar *) location);
-               icalcomponent_add_property (priv->icalcomp, priv->location);
+       if (prop) {
+               i_cal_property_set_percentcomplete (prop, percent);
+               g_clear_object (&prop);
+       } else {
+               prop = i_cal_property_new_percentcomplete (percent);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
-
-
 /**
- * e_cal_component_free_categories_list:
- * @categ_list: (element-type utf8): List of category strings
+ * e_cal_component_get_priority:
+ * @comp: A calendar component object.
  *
- * Frees a list of category strings.
+ * Queries the priority property of a calendar component object.
+ *
+ * Returns: the priority property value, or -1, if not found
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_free_categories_list (GSList *categ_list)
+gint
+e_cal_component_get_priority (ECalComponent *comp)
 {
-       GSList *l;
+       ICalProperty *prop;
+       gint priority;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), -1);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, -1);
+
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PRIORITY_PROPERTY);
+       if (!prop)
+               return -1;
 
-       for (l = categ_list; l; l = l->next)
-               g_free (l->data);
+       priority = i_cal_property_get_priority (prop);
 
-       g_slist_free (categ_list);
+       g_object_unref (prop);
+
+       return priority;
 }
 
 /**
- * e_cal_component_free_datetime:
- * @dt: A date/time structure.
+ * e_cal_component_set_priority:
+ * @comp: A calendar component object.
+ * @priority: Value for the priority property.
  *
- * Frees a date/time structure.
+ * Sets the priority property of a calendar component object.
+ * The @priority can be between 0 and 9, inclusive.
+ * A special value -1 can be used to remove the priority property.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_free_datetime (ECalComponentDateTime *dt)
+e_cal_component_set_priority (ECalComponent *comp,
+                             gint priority)
 {
-       g_return_if_fail (dt != NULL);
+       ICalProperty *prop;
 
-       g_free (dt->value);
-       g_free ((gchar *) dt->tzid);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+       g_return_if_fail (priority >= -1 && priority <= 9);
 
-       dt->value = NULL;
-       dt->tzid = NULL;
-}
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PRIORITY_PROPERTY);
 
-/**
- * e_cal_component_free_range:
- * @range: A #ECalComponentRange.
- *
- * Frees an #ECalComponentRange structure.
- */
-void
-e_cal_component_free_range (ECalComponentRange *range)
-{
-       g_return_if_fail (range != NULL);
+       if (priority == -1) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
+               }
 
-       e_cal_component_free_datetime (&range->datetime);
+               return;
+       }
+
+       if (prop) {
+               i_cal_property_set_priority (prop, priority);
+               g_clear_object (&prop);
+       } else {
+               prop = i_cal_property_new_priority (priority);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
 }
 
 /**
- * e_cal_component_free_exdate_list:
- * @exdate_list: (element-type ECalComponentDateTime): List of
- * #ECalComponentDateTime structures
+ * e_cal_component_get_recurid:
+ * @comp: A calendar component object.
+ *
+ * Queries the recurrence id property of a calendar component object.
+ * Free the returned #ECalComponentRange with e_cal_component_range_free(),
+ * whe no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the recurrence id property, as an #ECalComponentRange
  *
- * Frees a list of #ECalComponentDateTime structures as returned by the
- * e_cal_component_get_exdate_list() function.
+ * Since: 3.36
  **/
-void
-e_cal_component_free_exdate_list (GSList *exdate_list)
+ECalComponentRange *
+e_cal_component_get_recurid (ECalComponent *comp)
 {
-       GSList *l;
-
-       for (l = exdate_list; l; l = l->next) {
-               ECalComponentDateTime *cdt;
+       ECalComponentDateTime *dt;
 
-               g_return_if_fail (l->data != NULL);
-               cdt = l->data;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               g_return_if_fail (cdt->value != NULL);
-               g_free (cdt->value);
-               g_free ((gchar *) cdt->tzid);
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_RECURRENCEID_PROPERTY, 
i_cal_property_get_recurrenceid);
 
-               g_free (cdt);
-       }
+       if (!dt)
+               return NULL;
 
-       g_slist_free (exdate_list);
+       return e_cal_component_range_new_take (E_CAL_COMPONENT_RANGE_SINGLE, dt);
 }
 
 /**
- * e_cal_component_free_geo:
- * @geo: An #icalgeotype structure.
+ * e_cal_component_get_recurid_as_string:
+ * @comp: A calendar component object.
+ *
+ * Gets the recurrence ID property as a string.
+ *
+ * Returns: the recurrence ID as a string.
  *
- * Frees a struct #icalgeotype structure as returned by the calendar component
- * functions.
+ * Since: 3.36
  **/
-void
-e_cal_component_free_geo (struct icalgeotype *geo)
+gchar *
+e_cal_component_get_recurid_as_string (ECalComponent *comp)
 {
-       g_return_if_fail (geo != NULL);
-
-       g_free (geo);
+       return e_cal_util_component_get_recurid_as_string (comp->priv->icalcomp);
 }
 
 /**
- * e_cal_component_free_icaltimetype:
- * @t: An #icaltimetype structure.
+ * e_cal_component_set_recurid:
+ * @comp: A calendar component object.
+ * @recur_id: (nullable): Value for the recurrence id property, or %NULL, to remove the property.
+ *
+ * Sets the recurrence id property of a calendar component object.
  *
- * Frees a struct #icaltimetype value as returned by the calendar component
- * functions.
+ * Since: 3.36
  **/
 void
-e_cal_component_free_icaltimetype (struct icaltimetype *t)
+e_cal_component_set_recurid (ECalComponent *comp,
+                            const ECalComponentRange *recur_id)
 {
-       g_return_if_fail (t != NULL);
+       ECalComponentDateTime *dt;
+
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       g_free (t);
+       dt = recur_id ? e_cal_component_range_get_datetime (recur_id) : NULL;
+
+       set_datetime (comp->priv->icalcomp, I_CAL_RECURRENCEID_PROPERTY,
+               i_cal_property_new_recurrenceid,
+               i_cal_property_set_recurrenceid,
+               dt);
 }
 
 /**
- * e_cal_component_free_percent:
- * @percent: Percent value.
+ * e_cal_component_get_rdates:
+ * @comp: A calendar component object.
  *
- * Frees a percent value as returned by the e_cal_component_get_percent()
- * function.
+ * Queries the list of recurrence date properties in a calendar component
+ * object. Free the returned #GSList with g_slist_free_full (slist, e_cal_component_period_free);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ECalComponentPeriod): the list
+ *    of recurrence dates, as a #GSList of #ECalComponentPeriod structures.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_free_percent (gint *percent)
+GSList *
+e_cal_component_get_rdates (ECalComponent *comp)
 {
-       g_return_if_fail (percent != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       g_free (percent);
+       return get_period_list (comp->priv->icalcomp, I_CAL_RDATE_PROPERTY, i_cal_property_get_rdate);
 }
 
 /**
- * e_cal_component_free_priority:
- * @priority: Priority value.
+ * e_cal_component_set_rdates:
+ * @comp: A calendar component object.
+ * @rdate_list: (nullable) (element-type ECalComponentPeriod): List of
+ *    #ECalComponentPeriod structures, or %NULL to set none
  *
- * Frees a priority value as returned by the e_cal_component_get_priority()
- * function.
+ * Sets the list of recurrence dates in a calendar component object.
+ *
+ * Since: 3.36
  **/
 void
-e_cal_component_free_priority (gint *priority)
+e_cal_component_set_rdates (ECalComponent *comp,
+                           const GSList *rdate_list)
 {
-       g_return_if_fail (priority != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       g_free (priority);
+       set_period_list (comp->priv->icalcomp, I_CAL_RDATE_PROPERTY, i_cal_property_new_rdate, rdate_list);
+
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_free_period_list:
- * @period_list: (element-type ECalComponentPeriod): List of
- * #ECalComponentPeriod structures
+ * e_cal_component_has_rdates:
+ * @comp: A calendar component object.
+ *
+ * Queries whether a calendar component object has any recurrence dates defined
+ * for it.
  *
- * Frees a list of #ECalComponentPeriod structures.
+ * Returns: TRUE if the component has recurrence dates, FALSE otherwise.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_free_period_list (GSList *period_list)
+gboolean
+e_cal_component_has_rdates (ECalComponent *comp)
 {
-       g_slist_foreach (period_list, (GFunc) g_free, NULL);
-       g_slist_free (period_list);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
+
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_RDATE_PROPERTY);
 }
 
 /**
- * e_cal_component_free_recur_list:
- * @recur_list: (element-type icalrecurrencetype): List of struct
- * #icalrecurrencetype structures.
+ * e_cal_component_get_rrules:
+ * @comp: A calendar component object.
  *
- * Frees a list of struct #icalrecurrencetype structures.
+ * Queries the list of recurrence rule properties of a calendar component
+ * object. Free the returned list with g_slist_free_full (slist, g_object_unref);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalRecurrence): a #GSList
+ *    of recurrence rules as #ICalRecurrence structures, or %NULL, when none exist.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_free_recur_list (GSList *recur_list)
+GSList *
+e_cal_component_get_rrules (ECalComponent *comp)
 {
-       g_slist_foreach (recur_list, (GFunc) g_free, NULL);
-       g_slist_free (recur_list);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       return get_recur_list (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY, i_cal_property_get_rrule);
 }
 
 /**
- * e_cal_component_free_sequence:
- * @sequence: Sequence number value.
+ * e_cal_component_get_rrule_properties:
+ * @comp: A calendar component object.
+ *
+ * Queries a list of recurrence rule properties of a calendar component object.
+ * Free the list with g_slist_free_full (slist, g_object_unref);, when
+ * no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalProperty): a list of recurrence
+ *    rule properties
  *
- * Frees a sequence number value.
+ * Since: 3.36
  **/
-void
-e_cal_component_free_sequence (gint *sequence)
+GSList *
+e_cal_component_get_rrule_properties (ECalComponent *comp)
 {
-       g_return_if_fail (sequence != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       g_free (sequence);
+       return gather_all_properties (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY, TRUE);
 }
 
 /**
- * e_cal_component_free_id:
- * @id: an #ECalComponentId
+ * e_cal_component_set_rrules:
+ * @comp: A calendar component object.
+ * @recur_list: (nullable) (element-type ICalRecurrence): List of #ICalRecurrence structures, or %NULL.
+ *
+ * Sets the list of recurrence rules in a calendar component object.
  *
- * Frees the @id.
+ * Since: 3.36
  **/
 void
-e_cal_component_free_id (ECalComponentId *id)
+e_cal_component_set_rrules (ECalComponent *comp,
+                           const GSList *recur_list)
 {
-       g_return_if_fail (id != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       g_free (id->uid);
-       g_free (id->rid);
+       set_recur_list (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY, i_cal_property_new_rrule, recur_list);
 
-       g_free (id);
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_id_new:
- * @uid: a unique ID string
- * @rid: (allow-none): an optional recurrence ID string
+ * e_cal_component_has_rrules:
+ * @comp: A calendar component object.
  *
- * Creates a new #ECalComponentId from @uid and @rid, which should be
- * freed with e_cal_component_free_id().
+ * Queries whether a calendar component object has any recurrence rules defined
+ * for it.
  *
- * Returns: an #ECalComponentId
+ * Returns: TRUE if the component has recurrence rules, FALSE otherwise.
  *
- * Since: 3.10
+ * Since: 3.36
  **/
-ECalComponentId *
-e_cal_component_id_new (const gchar *uid,
-                        const gchar *rid)
+gboolean
+e_cal_component_has_rrules (ECalComponent *comp)
 {
-       ECalComponentId *id;
-
-       g_return_val_if_fail (uid != NULL, NULL);
-
-       /* Normalize an empty recurrence ID to NULL. */
-       if (rid != NULL && *rid == '\0')
-               rid = NULL;
-
-       id = g_new0 (ECalComponentId, 1);
-       id->uid = g_strdup (uid);
-       id->rid = g_strdup (rid);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       return id;
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY);
 }
 
 /**
- * e_cal_component_id_copy:
- * @id: an #ECalComponentId
+ * e_cal_component_has_recurrences:
+ * @comp: A calendar component object
  *
- * Returns a newly-allocated copy of @id, which should be freed with
- * e_cal_component_free_id().
+ * Queries whether a calendar component object has any recurrence dates or
+ * recurrence rules.
  *
- * Returns: a newly-allocated copy of @id
+ * Returns: TRUE if the component has recurrences, FALSE otherwise.
  *
- * Since: 3.10
+ * Since: 3.36
  **/
-ECalComponentId *
-e_cal_component_id_copy (const ECalComponentId *id)
+gboolean
+e_cal_component_has_recurrences (ECalComponent *comp)
 {
-       g_return_val_if_fail (id != NULL, NULL);
-
-       return e_cal_component_id_new (id->uid, id->rid);
+       return e_cal_component_has_rdates (comp) || e_cal_component_has_rrules (comp);
 }
 
-/**
- * e_cal_component_id_hash:
- * @id: an #ECalComponentId
- *
- * Generates a hash value for @id.
- *
- * Returns: a hash value for @id
- *
- * Since: 3.10
- **/
-guint
-e_cal_component_id_hash (const ECalComponentId *id)
+/* Counts the elements in the by_xxx fields of an ICalRecurrence;
+   it also frees the 'field' array*/
+static gint
+count_by_xxx_and_free (GArray *field) /* gshort */
 {
-       guint uid_hash;
-       guint rid_hash;
+       gint ii;
 
-       g_return_val_if_fail (id != NULL, 0);
+       if (!field)
+               return 0;
 
-       uid_hash = g_str_hash (id->uid);
-       rid_hash = (id->rid != NULL) ? g_str_hash (id->rid) : 0;
+       for (ii = 0; ii < field->len; ii++) {
+               if (g_array_index (field, gshort, ii) == I_CAL_RECURRENCE_ARRAY_MAX)
+                       break;
+       }
 
-       return uid_hash ^ rid_hash;
+       g_array_unref (field);
+
+       return ii;
 }
 
 /**
- * e_cal_component_id_equal:
- * @id1: the first #ECalComponentId
- * @id2: the second #ECalComponentId
+ * e_cal_component_has_simple_recurrence:
+ * @comp: A calendar component object.
  *
- * Compares two #ECalComponentId structs for equality.
+ * Checks whether the given calendar component object has simple recurrence
+ * rules or more complicated ones.
  *
- * Returns: %TRUE if @id1 and @id2 are equal
+ * Returns: TRUE if it has a simple recurrence rule, FALSE otherwise.
  *
- * Since: 3.10
+ * Since: 3.36
  **/
 gboolean
-e_cal_component_id_equal (const ECalComponentId *id1,
-                          const ECalComponentId *id2)
+e_cal_component_has_simple_recurrence (ECalComponent *comp)
 {
-       gboolean uids_equal;
-       gboolean rids_equal;
+       GSList *rrule_list;
+       ICalRecurrence *rt;
+       gint n_by_second, n_by_minute, n_by_hour;
+       gint n_by_day, n_by_month_day, n_by_year_day;
+       gint n_by_week_no, n_by_month, n_by_set_pos;
+       gint len, i;
+       gboolean simple = FALSE;
 
-       if (id1 == id2)
+       if (!e_cal_component_has_recurrences (comp))
                return TRUE;
 
-       /* Safety check before we dereference. */
-       g_return_val_if_fail (id1 != NULL, FALSE);
-       g_return_val_if_fail (id2 != NULL, FALSE);
+       rrule_list = e_cal_component_get_rrules (comp);
+       len = g_slist_length (rrule_list);
+       if (len > 1
+           || e_cal_component_has_rdates (comp)
+           || e_cal_component_has_exrules (comp))
+               goto cleanup;
 
-       uids_equal = (g_strcmp0 (id1->uid, id2->uid) == 0);
-       rids_equal = (g_strcmp0 (id1->rid, id2->rid) == 0);
+       /* Down to one rule, so test that one */
+       rt = rrule_list->data;
 
-       return uids_equal && rids_equal;
-}
+       /* Any funky frequency? */
+       if (i_cal_recurrence_get_freq (rt) == I_CAL_SECONDLY_RECURRENCE ||
+           i_cal_recurrence_get_freq (rt) == I_CAL_MINUTELY_RECURRENCE ||
+           i_cal_recurrence_get_freq (rt) == I_CAL_HOURLY_RECURRENCE)
+               goto cleanup;
 
-/**
- * e_cal_component_free_text_list:
- * @text_list: (element-type ECalComponentText): List of #ECalComponentText
- * structures.
- *
- * Frees a list of #ECalComponentText structures.  This function should only be
- * used to free lists of text values as returned by the other getter functions
- * of #ECalComponent.
- **/
-void
-e_cal_component_free_text_list (GSList *text_list)
-{
-       g_slist_foreach (text_list, (GFunc) g_free, NULL);
-       g_slist_free (text_list);
-}
+       /* Any funky BY_* */
+#define N_HAS_BY(field) (count_by_xxx_and_free (field))
+
+       n_by_second = N_HAS_BY (i_cal_recurrence_get_by_second_array (rt));
+       n_by_minute = N_HAS_BY (i_cal_recurrence_get_by_minute_array (rt));
+       n_by_hour = N_HAS_BY (i_cal_recurrence_get_by_hour_array (rt));
+       n_by_day = N_HAS_BY (i_cal_recurrence_get_by_day_array (rt));
+       n_by_month_day = N_HAS_BY (i_cal_recurrence_get_by_month_day_array (rt));
+       n_by_year_day = N_HAS_BY (i_cal_recurrence_get_by_year_day_array (rt));
+       n_by_week_no = N_HAS_BY (i_cal_recurrence_get_by_week_no_array (rt));
+       n_by_month = N_HAS_BY (i_cal_recurrence_get_by_month_array (rt));
+       n_by_set_pos = N_HAS_BY (i_cal_recurrence_get_by_set_pos_array (rt));
 
-/**
- * e_cal_component_free_attendee_list:
- * @attendee_list: (element-type ECalComponentAttendee): List of attendees
- *
- * Frees a list of #ECalComponentAttendee structures.
- *
- **/
-void
-e_cal_component_free_attendee_list (GSList *attendee_list)
-{
-       g_slist_foreach (attendee_list, (GFunc) g_free, NULL);
-       g_slist_free (attendee_list);
-}
+       if (n_by_second != 0
+           || n_by_minute != 0
+           || n_by_hour != 0)
+               goto cleanup;
 
-
+       switch (i_cal_recurrence_get_freq (rt)) {
+       case I_CAL_DAILY_RECURRENCE:
+               if (n_by_day != 0
+                   || n_by_month_day != 0
+                   || n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos != 0)
+                       goto cleanup;
 
-/**
- * e_cal_component_has_alarms:
- * @comp: A calendar component object.
- *
- * Checks whether the component has any alarms.
- *
- * Returns: TRUE if the component has any alarms.
- **/
-gboolean
-e_cal_component_has_alarms (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
+               simple = TRUE;
+               break;
 
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       case I_CAL_WEEKLY_RECURRENCE:
+               if (n_by_month_day != 0
+                   || n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos != 0)
+                       goto cleanup;
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+               for (i = 0; i < 8; i++) {
+                       gint pos;
+                       gshort byday = i_cal_recurrence_get_by_day (rt, i);
 
-       return g_hash_table_size (priv->alarm_uid_hash) != 0;
-}
+                       if (byday == I_CAL_RECURRENCE_ARRAY_MAX)
+                               break;
 
-/**
- * e_cal_component_add_alarm:
- * @comp: A calendar component.
- * @alarm: An alarm.
- *
- * Adds an alarm subcomponent to a calendar component.  You should have created
- * the @alarm by using e_cal_component_alarm_new(); it is invalid to use a
- * #ECalComponentAlarm structure that came from e_cal_component_get_alarm().  After
- * adding the alarm, the @alarm structure is no longer valid because the
- * internal structures may change and you should get rid of it by using
- * e_cal_component_alarm_free().
- **/
-void
-e_cal_component_add_alarm (ECalComponent *comp,
-                           ECalComponentAlarm *alarm)
-{
-       ECalComponentPrivate *priv;
+                       pos = i_cal_recurrence_day_position (byday);
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (alarm != NULL);
+                       if (pos != 0)
+                               goto cleanup;
+               }
 
-       priv = comp->priv;
+               simple = TRUE;
+               break;
 
-       add_alarm (comp, alarm->icalcomp, icalproperty_get_x (alarm->uid));
-       icalcomponent_add_component (priv->icalcomp, alarm->icalcomp);
-}
+       case I_CAL_MONTHLY_RECURRENCE:
+               if (n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos > 1)
+                       goto cleanup;
 
-/**
- * e_cal_component_remove_alarm:
- * @comp: A calendar component.
- * @auid: UID of the alarm to remove.
- *
- * Removes an alarm subcomponent from a calendar component.  If the alarm that
- * corresponds to the specified @auid had been fetched with
- * e_cal_component_get_alarm(), then those alarm structures will be invalid; you
- * should get rid of them with e_cal_component_alarm_free() before using this
- * function.
- **/
-void
-e_cal_component_remove_alarm (ECalComponent *comp,
-                              const gchar *auid)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm;
+               if (n_by_month_day == 1) {
+                       gint nth;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (auid != NULL);
+                       if (n_by_set_pos != 0)
+                               goto cleanup;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+                       nth = i_cal_recurrence_get_by_month_day (rt, 0);
+                       if (nth < 1 && nth != -1)
+                               goto cleanup;
 
-       alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid);
-       if (!alarm)
-               return;
+               } else if (n_by_day == 1) {
+                       ICalRecurrenceWeekday weekday;
+                       gint pos;
 
-       g_hash_table_remove (priv->alarm_uid_hash, auid);
-       icalcomponent_remove_component (priv->icalcomp, alarm);
-       icalcomponent_free (alarm);
-}
+                       /* Outlook 2000 uses BYDAY=TU;BYSETPOS=2, and will not
+                        * accept BYDAY=2TU. So we now use the same as Outlook
+                        * by default. */
 
-static gboolean
-for_each_remove_all_alarms (gpointer key,
-                            gpointer value,
-                            gpointer data)
-{
-       ECalComponent *comp = E_CAL_COMPONENT (data);
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm = value;
+                       weekday = i_cal_recurrence_day_day_of_week (i_cal_recurrence_get_by_day (rt, 0));
+                       pos = i_cal_recurrence_day_position (i_cal_recurrence_get_by_day (rt, 0));
 
-       priv = comp->priv;
+                       if (pos == 0) {
+                               if (n_by_set_pos != 1)
+                                       goto cleanup;
+                               pos = i_cal_recurrence_get_by_set_pos (rt, 0);
+                       } else if (pos < 0) {
+                               goto cleanup;
+                       }
+
+                       switch (weekday) {
+                       case I_CAL_MONDAY_WEEKDAY:
+                       case I_CAL_TUESDAY_WEEKDAY:
+                       case I_CAL_WEDNESDAY_WEEKDAY:
+                       case I_CAL_THURSDAY_WEEKDAY:
+                       case I_CAL_FRIDAY_WEEKDAY:
+                       case I_CAL_SATURDAY_WEEKDAY:
+                       case I_CAL_SUNDAY_WEEKDAY:
+                               break;
+
+                       default:
+                               goto cleanup;
+                       }
+               } else {
+                       goto cleanup;
+               }
+
+               simple = TRUE;
+               break;
+
+       case I_CAL_YEARLY_RECURRENCE:
+               if (n_by_day != 0
+                   || n_by_month_day != 0
+                   || n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos != 0)
+                       goto cleanup;
+
+               simple = TRUE;
+               break;
+
+       default:
+               goto cleanup;
+       }
 
-       icalcomponent_remove_component (priv->icalcomp, alarm);
-       icalcomponent_free (alarm);
+ cleanup:
+       g_slist_free_full (rrule_list, g_object_unref);
 
-       return TRUE;
+       return simple;
 }
 
 /**
- * e_cal_component_remove_all_alarms:
- * @comp: A calendar component
+ * e_cal_component_is_instance:
+ * @comp: A calendar component object.
  *
- * Remove all alarms from the calendar component
+ * Checks whether a calendar component object is an instance of a recurring
+ * event.
+ *
+ * Returns: TRUE if it is an instance, FALSE if not.
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_remove_all_alarms (ECalComponent *comp)
+gboolean
+e_cal_component_is_instance (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       g_hash_table_foreach_remove (priv->alarm_uid_hash, for_each_remove_all_alarms, comp);
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_RECURRENCEID_PROPERTY);
 }
 
-/* Scans an icalproperty from a calendar component and adds its mapping to our
- * own alarm structure.
- */
-static void
-scan_alarm_property (ECalComponentAlarm *alarm,
-                     icalproperty *prop)
+/**
+ * e_cal_component_get_sequence:
+ * @comp: A calendar component object.
+ *
+ * Queries the sequence number of a calendar component object.
+ *
+ * Returns: the sequence number, or -1 if not found
+ *
+ * Since: 3.36
+ **/
+gint
+e_cal_component_get_sequence (ECalComponent *comp)
 {
-       icalproperty_kind kind;
-       const gchar *xname;
-
-       kind = icalproperty_isa (prop);
-
-       switch (kind) {
-       case ICAL_ACTION_PROPERTY:
-               alarm->action = prop;
-               break;
+       ICalProperty *prop;
+       gint sequence;
 
-       case ICAL_ATTACH_PROPERTY:
-               /* FIXME: mail alarms may have any number of these, not just one */
-               alarm->attach = prop;
-               break;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), -1);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, -1);
 
-       case ICAL_DESCRIPTION_PROPERTY:
-               alarm->description.prop = prop;
-               alarm->description.altrep_param = icalproperty_get_first_parameter (
-                       prop, ICAL_ALTREP_PARAMETER);
-               break;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SEQUENCE_PROPERTY);
+       if (!prop)
+               return -1;
 
-       case ICAL_DURATION_PROPERTY:
-               alarm->duration = prop;
-               break;
+       sequence = i_cal_property_get_sequence (prop);
 
-       case ICAL_REPEAT_PROPERTY:
-               alarm->repeat = prop;
-               break;
+       g_object_unref (prop);
 
-       case ICAL_TRIGGER_PROPERTY:
-               alarm->trigger = prop;
-               break;
+       return sequence;
+}
 
-       case ICAL_ATTENDEE_PROPERTY:
-               scan_attendee (&alarm->attendee_list, prop);
-               break;
+/**
+ * e_cal_component_set_sequence:
+ * @comp: A calendar component object.
+ * @sequence: a sequence number to set, or -1 to remove the property
+ *
+ * Sets the sequence number of a calendar component object.
+ * A special value -1 can be used to remove the sequence number property.
+ *
+ * Normally this function should not be called, since the sequence number
+ * is incremented automatically at the proper times.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_set_sequence (ECalComponent *comp,
+                             gint sequence)
+{
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       case ICAL_X_PROPERTY:
-               xname = icalproperty_get_x_name (prop);
-               g_return_if_fail (xname != NULL);
+       comp->priv->need_sequence_inc = FALSE;
 
-               if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0)
-                       alarm->uid = prop;
+       if (sequence <= -1) {
+               ICalProperty *prop;
 
-               break;
+               prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SEQUENCE_PROPERTY);
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       default:
-               break;
+               return;
        }
+
+       i_cal_component_set_sequence (comp->priv->icalcomp, sequence);
 }
 
-/* Creates a ECalComponentAlarm from a libical alarm subcomponent */
-static ECalComponentAlarm *
-make_alarm (icalcomponent *subcomp)
+/**
+ * e_cal_component_get_status:
+ * @comp: A calendar component object.
+ *
+ * Queries the status property of a calendar component object.
+ *
+ * Returns: the status value; or %I_CAL_STATUS_NONE, if the component
+ *   has no status property
+ *
+ * Since: 3.36
+ **/
+ICalPropertyStatus
+e_cal_component_get_status (ECalComponent *comp)
 {
-       ECalComponentAlarm *alarm;
-       icalproperty *prop;
+       ICalProperty *prop;
+       ICalPropertyStatus status;
 
-       alarm = g_new (ECalComponentAlarm, 1);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), I_CAL_STATUS_NONE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, I_CAL_STATUS_NONE);
 
-       alarm->icalcomp = subcomp;
-       alarm->uid = NULL;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_STATUS_PROPERTY);
 
-       alarm->action = NULL;
-       alarm->attach = NULL;
-       alarm->description.prop = NULL;
-       alarm->description.altrep_param = NULL;
-       alarm->duration = NULL;
-       alarm->repeat = NULL;
-       alarm->trigger = NULL;
-       alarm->attendee_list = NULL;
+       if (!prop)
+               return I_CAL_STATUS_NONE;
 
-       for (prop = icalcomponent_get_first_property (subcomp, ICAL_ANY_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (subcomp, ICAL_ANY_PROPERTY))
-               scan_alarm_property (alarm, prop);
+       status = i_cal_property_get_status (prop);
 
-       g_return_val_if_fail (alarm->uid != NULL, NULL);
+       g_object_unref (prop);
 
-       return alarm;
+       return status;
 }
 
 /**
- * e_cal_component_get_alarm_uids:
- * @comp: A calendar component.
+ * e_cal_component_set_status:
+ * @comp: A calendar component object.
+ * @status: Status value, as an #ICalPropertyStatus. Use %I_CAL_STATUS_NONE, to unset the property
  *
- * Builds a list of the unique identifiers of the alarm subcomponents inside a
- * calendar component.
+ * Sets the status property of a calendar component object.
  *
- * Returns: (element-type utf8) (transfer full): List of unique identifiers for
- * alarms.  This should be freed using cal_obj_uid_list_free().
+ * Since: 3.36
  **/
-GList *
-e_cal_component_get_alarm_uids (ECalComponent *comp)
+void
+e_cal_component_set_status (ECalComponent *comp,
+                           ICalPropertyStatus status)
 {
-       ECalComponentPrivate *priv;
-       icalcompiter iter;
-       GList *l;
-
-       g_return_val_if_fail (comp != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
-       l = NULL;
-       for (iter = icalcomponent_begin_component (priv->icalcomp, ICAL_VALARM_COMPONENT);
-            icalcompiter_deref (&iter) != NULL;
-            icalcompiter_next (&iter)) {
-               icalcomponent *subcomp;
-               icalproperty *prop;
+       ICalProperty *prop;
 
-               subcomp = icalcompiter_deref (&iter);
-               for (prop = icalcomponent_get_first_property (subcomp, ICAL_X_PROPERTY);
-                    prop;
-                    prop = icalcomponent_get_next_property (subcomp, ICAL_X_PROPERTY)) {
-                       const gchar *xname;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-                       xname = icalproperty_get_x_name (prop);
-                       g_return_val_if_fail (xname != NULL, NULL);
+       comp->priv->need_sequence_inc = TRUE;
 
-                       if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0) {
-                               const gchar *auid;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_STATUS_PROPERTY);
 
-                               auid = alarm_uid_from_prop (prop);
-                               l = g_list_append (l, g_strdup (auid));
-                       }
+       if (status == I_CAL_STATUS_NONE) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
                }
+
+               return;
        }
 
-       return l;
+       if (prop) {
+               i_cal_property_set_status (prop, status);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_status (status);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
 }
 
 /**
- * e_cal_component_get_alarm:
- * @comp: A calendar component.
- * @auid: Unique identifier for the sought alarm subcomponent.
+ * e_cal_component_get_summary:
+ * @comp: A calendar component object.
  *
- * Queries a particular alarm subcomponent of a calendar component.
+ * Queries the summary of a calendar component object.
+ * Free the returned pointer withe_cal_component_text_free(),
+ * when no longer needed.
  *
- * Returns: The alarm subcomponent that corresponds to the specified @auid,
- * or %NULL if no alarm exists with that UID.  This should be freed using
- * e_cal_component_alarm_free().
+ * Returns: (transfer full) (nullable): the summary, as an #ECalComponentText,
+ *    or %NULL, when none is set
+ *
+ * Since: 3.36
  **/
-ECalComponentAlarm *
-e_cal_component_get_alarm (ECalComponent *comp,
-                           const gchar *auid)
+ECalComponentText *
+e_cal_component_get_summary (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm;
+       ECalComponentText *text;
+       ICalProperty *prop;
 
-       g_return_val_if_fail (comp != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SUMMARY_PROPERTY);
+       if (!prop)
+               return NULL;
 
-       g_return_val_if_fail (auid != NULL, NULL);
+       text = get_text_from_prop (prop, i_cal_property_get_summary);
 
-       alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid);
+       g_object_unref (prop);
 
-       if (alarm)
-               return make_alarm (alarm);
-       else
-               return NULL;
+       return text;
 }
 
-/**
- * e_cal_component_alarms_free:
- * @alarms: Component alarms structure.
- *
- * Frees a #ECalComponentAlarms structure.
- **/
-void
-e_cal_component_alarms_free (ECalComponentAlarms *alarms)
+typedef struct {
+       gchar *old_summary;
+       const gchar *new_summary;
+} SetAlarmDescriptionData;
+
+static gboolean
+set_alarm_description_cb (ICalComponent *icalcomp,
+                         ICalComponent *subcomp,
+                         gpointer user_data)
 {
-       GSList *l;
+       ICalProperty *icalprop, *desc_prop;
+       SetAlarmDescriptionData *sadd = user_data;
+       gboolean changed = FALSE;
+       const gchar *old_summary = NULL;
+
+       g_return_val_if_fail (sadd != NULL, FALSE);
+
+       /* set the new description on the alarm */
+       desc_prop = i_cal_component_get_first_property (subcomp, I_CAL_DESCRIPTION_PROPERTY);
+       if (desc_prop) {
+               old_summary = i_cal_property_get_description (desc_prop);
+       } else {
+               desc_prop = i_cal_property_new_description (sadd->new_summary);
+       }
+
+       /* remove the X-EVOLUTION-NEEDS_DESCRIPTION property */
+       icalprop = i_cal_component_get_first_property (subcomp, I_CAL_X_PROPERTY);
+       while (icalprop) {
+               const gchar *x_name;
 
-       g_return_if_fail (alarms != NULL);
+               x_name = i_cal_property_get_x_name (icalprop);
+               if (!g_strcmp0 (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
+                       i_cal_component_remove_property (subcomp, icalprop);
+                       g_object_unref (icalprop);
 
-       if (alarms->comp != NULL)
-               g_object_unref (alarms->comp);
+                       i_cal_property_set_description (desc_prop, sadd->new_summary);
+                       changed = TRUE;
+                       break;
+               }
 
-       for (l = alarms->alarms; l; l = l->next) {
-               ECalComponentAlarmInstance *instance = l->data;
+               g_object_unref (icalprop);
+               icalprop = i_cal_component_get_next_property (subcomp, I_CAL_X_PROPERTY);
+       }
 
-               if (instance != NULL) {
-                       g_free (instance->auid);
-                       g_free (instance);
-               } else
-                       g_warn_if_reached ();
+       if (!changed) {
+               if (!g_strcmp0 (old_summary ? old_summary : "", sadd->old_summary ? sadd->old_summary : "")) {
+                       i_cal_property_set_description (desc_prop, sadd->new_summary);
+               }
        }
 
-       g_slist_free (alarms->alarms);
-       g_free (alarms);
+       g_object_unref (desc_prop);
+
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_new:
+ * e_cal_component_set_summary:
+ * @comp: A calendar component object.
+ * @summary: Summary property and its parameters.
  *
- * Create a new alarm object.
+ * Sets the summary of a calendar component object.
  *
- * Returns: a new alarm component
+ * Since: 3.36
  **/
-ECalComponentAlarm *
-e_cal_component_alarm_new (void)
+void
+e_cal_component_set_summary (ECalComponent *comp,
+                            const ECalComponentText *summary)
 {
-       ECalComponentAlarm *alarm;
-       gchar *new_auid;
+       ICalProperty *prop;
+       SetAlarmDescriptionData sadd;
 
-       alarm = g_new (ECalComponentAlarm, 1);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       alarm->icalcomp = icalcomponent_new (ICAL_VALARM_COMPONENT);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SUMMARY_PROPERTY);
 
-       new_auid = e_util_generate_uid ();
-       alarm->uid = icalproperty_new_x (new_auid);
-       icalproperty_set_x_name (alarm->uid, EVOLUTION_ALARM_UID_PROPERTY);
-       icalcomponent_add_property (alarm->icalcomp, alarm->uid);
-       g_free (new_auid);
+       if (!summary) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       alarm->action = NULL;
-       alarm->attach = NULL;
-       alarm->description.prop = NULL;
-       alarm->description.altrep_param = NULL;
-       alarm->duration = NULL;
-       alarm->repeat = NULL;
-       alarm->trigger = NULL;
-       alarm->attendee_list = NULL;
+               return;
+       }
 
-       return alarm;
+       if (!e_cal_component_text_get_value (summary)) {
+               g_clear_object (&prop);
+               return;
+       }
+
+       if (prop) {
+               /* Make a copy, to avoid use-after-free */
+               sadd.old_summary = g_strdup (i_cal_property_get_summary (prop));
+               i_cal_property_set_summary (prop, (gchar *) e_cal_component_text_get_value (summary));
+               set_text_altrep_on_prop (prop, summary);
+       } else {
+               sadd.old_summary = NULL;
+               prop = i_cal_property_new_summary ((gchar *) e_cal_component_text_get_value (summary));
+               set_text_altrep_on_prop (prop, summary);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+               prop = NULL;
+       }
+
+       g_clear_object (&prop);
+
+       /* look for alarms that need a description */
+       sadd.new_summary = e_cal_component_text_get_value (summary);
+
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, set_alarm_description_cb, &sadd);
+
+       g_free (sadd.old_summary);
 }
 
 /**
- * e_cal_component_alarm_clone:
- * @alarm: An alarm subcomponent.
+ * e_cal_component_get_transparency:
+ * @comp: A calendar component object.
+ *
+ * Queries the time transparency of a calendar component object.
  *
- * Creates a new alarm subcomponent by copying the information from another one.
+ * Returns: the time transparency, as an #ECalComponentTransparency;
+ *    value #E_CAL_COMPONENT_TRANSP_NONE is returned when none is set
  *
- * Returns: A newly-created alarm subcomponent with the same values as the
- * original one.  Should be freed with e_cal_component_alarm_free().
+ * Since: 3.36
  **/
-ECalComponentAlarm *
-e_cal_component_alarm_clone (ECalComponentAlarm *alarm)
+ECalComponentTransparency
+e_cal_component_get_transparency (ECalComponent *comp)
 {
-       icalcomponent *icalcomp;
+       ECalComponentTransparency transp;
+       ICalProperty *prop;
 
-       g_return_val_if_fail (alarm != NULL, NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_TRANSP_NONE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, E_CAL_COMPONENT_TRANSP_NONE);
 
-       icalcomp = icalcomponent_new_clone (alarm->icalcomp);
-       return make_alarm (icalcomp);
-}
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_TRANSP_PROPERTY);
 
-/**
- * e_cal_component_alarm_free:
- * @alarm: A calendar alarm.
- *
- * Frees an alarm structure.
- **/
-void
-e_cal_component_alarm_free (ECalComponentAlarm *alarm)
-{
-       GSList *l;
+       if (!prop)
+               return E_CAL_COMPONENT_TRANSP_NONE;
 
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       switch (i_cal_property_get_transp (prop)) {
+       case I_CAL_TRANSP_TRANSPARENT:
+       case I_CAL_TRANSP_TRANSPARENTNOCONFLICT:
+               transp = E_CAL_COMPONENT_TRANSP_TRANSPARENT;
+               break;
 
-       if (icalcomponent_get_parent (alarm->icalcomp) == NULL)
-               icalcomponent_free (alarm->icalcomp);
+       case I_CAL_TRANSP_OPAQUE:
+       case I_CAL_TRANSP_OPAQUENOCONFLICT:
+               transp = E_CAL_COMPONENT_TRANSP_OPAQUE;
+               break;
 
-       alarm->icalcomp = NULL;
-       alarm->uid = NULL;
-       alarm->action = NULL;
-       alarm->attach = NULL;
-       alarm->description.prop = NULL;
-       alarm->description.altrep_param = NULL;
-       alarm->duration = NULL;
-       alarm->repeat = NULL;
-       alarm->trigger = NULL;
+       default:
+               transp = E_CAL_COMPONENT_TRANSP_UNKNOWN;
+               break;
+       }
 
-       for (l = alarm->attendee_list; l != NULL; l = l->next)
-               g_free (l->data);
-       g_slist_free (alarm->attendee_list);
-       alarm->attendee_list = NULL;
+       g_object_unref (prop);
 
-       g_free (alarm);
+       return transp;
 }
 
 /**
- * e_cal_component_alarm_get_uid:
- * @alarm: An alarm subcomponent.
+ * e_cal_component_set_transparency:
+ * @comp: A calendar component object.
+ * @transp: Time transparency value.
  *
- * Queries the unique identifier of an alarm subcomponent.
+ * Sets the time transparency of a calendar component object.
+ * Use %E_CAL_COMPONENT_TRANSP_NONE to unset the property.
  *
- * Returns: UID of the alarm.
+ * Since: 3.36
  **/
-const gchar *
-e_cal_component_alarm_get_uid (ECalComponentAlarm *alarm)
+void
+e_cal_component_set_transparency (ECalComponent *comp,
+                                  ECalComponentTransparency transp)
 {
-       g_return_val_if_fail (alarm != NULL, NULL);
+       ICalProperty *prop;
+       ICalPropertyTransp ical_transp;
 
-       return alarm_uid_from_prop (alarm->uid);
-}
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (transp != E_CAL_COMPONENT_TRANSP_UNKNOWN);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-/**
- * e_cal_component_alarm_get_action:
- * @alarm: An alarm.
- * @action: (out): Return value for the alarm's action type.
- *
- * Queries the action type of an alarm.
- **/
-void
-e_cal_component_alarm_get_action (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmAction *action)
-{
-       enum icalproperty_action ipa;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_TRANSP_PROPERTY);
 
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (action != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       if (transp == E_CAL_COMPONENT_TRANSP_NONE) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       if (!alarm->action) {
-               *action = E_CAL_COMPONENT_ALARM_NONE;
                return;
        }
 
-       ipa = icalproperty_get_action (alarm->action);
-
-       switch (ipa) {
-       case ICAL_ACTION_AUDIO:
-               *action = E_CAL_COMPONENT_ALARM_AUDIO;
-               break;
-
-       case ICAL_ACTION_DISPLAY:
-               *action = E_CAL_COMPONENT_ALARM_DISPLAY;
-               break;
-
-       case ICAL_ACTION_EMAIL:
-               *action = E_CAL_COMPONENT_ALARM_EMAIL;
+       switch (transp) {
+       case E_CAL_COMPONENT_TRANSP_TRANSPARENT:
+               ical_transp = I_CAL_TRANSP_TRANSPARENT;
                break;
 
-       case ICAL_ACTION_PROCEDURE:
-               *action = E_CAL_COMPONENT_ALARM_PROCEDURE;
+       case E_CAL_COMPONENT_TRANSP_OPAQUE:
+               ical_transp = I_CAL_TRANSP_OPAQUE;
                break;
 
-       case ICAL_ACTION_NONE:
-               *action = E_CAL_COMPONENT_ALARM_NONE;
+       default:
+               g_warn_if_reached ();
+               ical_transp = I_CAL_TRANSP_NONE;
                break;
+       }
 
-       default:
-               *action = E_CAL_COMPONENT_ALARM_UNKNOWN;
+       if (prop) {
+               i_cal_property_set_transp (prop, ical_transp);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_transp (ical_transp);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
 /**
- * e_cal_component_alarm_set_action:
- * @alarm: An alarm.
- * @action: Action type.
+ * e_cal_component_get_url:
+ * @comp: A calendar component object.
+ *
+ * Queries the uniform resource locator property of a calendar component object.
+ * Free the returned URL with g_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the URL, or %NULL, when none is set
  *
- * Sets the action type for an alarm.
+ * Since: 3.36
  **/
-void
-e_cal_component_alarm_set_action (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmAction action)
+gchar *
+e_cal_component_get_url (ECalComponent *comp)
 {
-       enum icalproperty_action ipa;
+       ICalProperty *prop;
+       gchar *url;
 
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (action != E_CAL_COMPONENT_ALARM_NONE);
-       g_return_if_fail (action != E_CAL_COMPONENT_ALARM_UNKNOWN);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       switch (action) {
-       case E_CAL_COMPONENT_ALARM_AUDIO:
-               ipa = ICAL_ACTION_AUDIO;
-               break;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_URL_PROPERTY);
+       if (!prop)
+               return NULL;
 
-       case E_CAL_COMPONENT_ALARM_DISPLAY:
-               ipa = ICAL_ACTION_DISPLAY;
-               break;
+       url = g_strdup (i_cal_property_get_url (prop));
 
-       case E_CAL_COMPONENT_ALARM_EMAIL:
-               ipa = ICAL_ACTION_EMAIL;
-               break;
+       g_object_unref (prop);
 
-       case E_CAL_COMPONENT_ALARM_PROCEDURE:
-               ipa = ICAL_ACTION_PROCEDURE;
-               break;
+       return url;
+}
+
+/**
+ * e_cal_component_set_url:
+ * @comp: A calendar component object.
+ * @url: (nullable): URL value.
+ *
+ * Sets the uniform resource locator property of a calendar component object.
+ * A %NULL or an empty string removes the property.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_set_url (ECalComponent *comp,
+                         const gchar *url)
+{
+       ICalProperty *prop;
+
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_URL_PROPERTY);
+
+       if (!url || !(*url)) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       default:
-               g_warn_if_reached ();
-               ipa = ICAL_ACTION_NONE;
+               return;
        }
 
-       if (alarm->action)
-               icalproperty_set_action (alarm->action, ipa);
-       else {
-               alarm->action = icalproperty_new_action (ipa);
-               icalcomponent_add_property (alarm->icalcomp, alarm->action);
+       if (prop) {
+               i_cal_property_set_url (prop, (gchar *) url);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_url ((gchar *) url);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
-/**
- * e_cal_component_alarm_get_attach:
- * @alarm: An alarm.
- * @attach: (out): Return value for the attachment; should be freed using icalattach_unref().
- *
- * Queries the attachment property of an alarm.
- **/
-void
-e_cal_component_alarm_get_attach (ECalComponentAlarm *alarm,
-                                  icalattach **attach)
+static gboolean
+get_attendee_list_cb (ICalComponent *icalcomp,
+                     ICalProperty *prop,
+                     gpointer user_data)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (attach != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       GSList **pattendees = user_data;
+       ECalComponentAttendee *attendee;
 
-       if (alarm->attach) {
-               *attach = icalproperty_get_attach (alarm->attach);
-               icalattach_ref (*attach);
-       } else
-               *attach = NULL;
-}
+       g_return_val_if_fail (pattendees != NULL, FALSE);
 
-/**
- * e_cal_component_alarm_set_attach:
- * @alarm: An alarm.
- * @attach: Attachment property or NULL to remove an existing property.
- *
- * Sets the attachment property of an alarm.
- **/
-void
-e_cal_component_alarm_set_attach (ECalComponentAlarm *alarm,
-                                  icalattach *attach)
-{
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       attendee = e_cal_component_attendee_new_from_property (prop);
 
-       if (alarm->attach) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->attach);
-               icalproperty_free (alarm->attach);
-               alarm->attach = NULL;
-       }
+       if (attendee)
+               *pattendees = g_slist_prepend (*pattendees, attendee);
 
-       if (attach) {
-               alarm->attach = icalproperty_new_attach (attach);
-               icalcomponent_add_property (alarm->icalcomp, alarm->attach);
-       }
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_get_description:
- * @alarm: An alarm.
- * @description: (out): Return value for the description property and its parameters.
+ * e_cal_component_get_attendees:
+ * @comp: A calendar component object.
  *
- * Queries the description property of an alarm.
+ * Queries the attendee properties of the calendar component object.
+ * Free the returned #GSList with g_slist_free_full (slist, e_cal_component_attendee_free);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ECalComponentAttendee):
+ *    the attendees, as a #GSList of an #ECalComponentAttendee, or %NULL,
+ *    when none are set
+ *
+ * Since: 3.36
  **/
-void
-e_cal_component_alarm_get_description (ECalComponentAlarm *alarm,
-                                       ECalComponentText *description)
+GSList *
+e_cal_component_get_attendees (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (description != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       GSList *attendees = NULL;
 
-       if (alarm->description.prop)
-               description->value = icalproperty_get_description (alarm->description.prop);
-       else
-               description->value = NULL;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (alarm->description.altrep_param)
-               description->altrep = icalparameter_get_altrep (alarm->description.altrep_param);
-       else
-               description->altrep = NULL;
+       foreach_property (comp->priv->icalcomp, I_CAL_ATTENDEE_PROPERTY, get_attendee_list_cb, &attendees);
+
+       return g_slist_reverse (attendees);
 }
 
 /**
- * e_cal_component_alarm_set_description:
- * @alarm: An alarm.
- * @description: Description property and its parameters, or NULL for no description.
+ * e_cal_component_set_attendees:
+ * @comp: A calendar component object.
+ * @attendee_list: (nullable) (element-type ECalComponentAttendee): Values for attendee
+ *    properties, or %NULL to unset
+ *
+ * Sets the attendees of a calendar component object
  *
- * Sets the description property of an alarm.
+ * Since: 3.36
  **/
 void
-e_cal_component_alarm_set_description (ECalComponentAlarm *alarm,
-                                       ECalComponentText *description)
+e_cal_component_set_attendees (ECalComponent *comp,
+                              const GSList *attendee_list)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       GSList *link;
 
-       if (alarm->description.prop) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->description.prop);
-               icalproperty_free (alarm->description.prop);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-               alarm->description.prop = NULL;
-               alarm->description.altrep_param = NULL;
-       }
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_ATTENDEE_PROPERTY);
 
-       if (!description)
-               return;
+       for (link = (GSList *) attendee_list; link; link = g_slist_next (link)) {
+               const ECalComponentAttendee *attendee = link->data;
+               ICalProperty *prop;
 
-       g_return_if_fail (description->value != NULL);
+               if (!attendee)
+                       continue;
 
-       alarm->description.prop = icalproperty_new_description (description->value);
-       icalcomponent_add_property (alarm->icalcomp, alarm->description.prop);
+               prop = e_cal_component_attendee_get_as_property (attendee);
+               if (!prop)
+                       continue;
 
-       if (description->altrep) {
-               alarm->description.altrep_param = icalparameter_new_altrep (
-                       (gchar *) description->altrep);
-               icalproperty_add_parameter (
-                       alarm->description.prop,
-                       alarm->description.altrep_param);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
 /**
- * e_cal_component_alarm_get_repeat:
- * @alarm: An alarm.
- * @repeat: (out): Return value for the repeat/duration properties.
+ * e_cal_component_has_attendees:
+ * @comp: A calendar component object.
  *
- * Queries the repeat/duration properties of an alarm.
- **/
-void
-e_cal_component_alarm_get_repeat (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmRepeat *repeat)
+ * Queries a calendar component object for the existence of attendees.
+ *
+ * Returns: TRUE if there are attendees, FALSE if not.
+ *
+ * Since: 3.36
+ */
+gboolean
+e_cal_component_has_attendees (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (repeat != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       if (!(alarm->repeat && alarm->duration)) {
-               repeat->repetitions = 0;
-               memset (&repeat->duration, 0, sizeof (repeat->duration));
-               return;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       repeat->repetitions = icalproperty_get_repeat (alarm->repeat);
-       repeat->duration = icalproperty_get_duration (alarm->duration);
+       return e_cal_util_component_has_property (comp->priv->icalcomp, I_CAL_ATTENDEE_PROPERTY);
 }
 
 /**
- * e_cal_component_alarm_set_repeat:
- * @alarm: An alarm.
- * @repeat: Repeat/duration values.  To remove any repetitions from the alarm,
- * set the @repeat.repetitions to 0.
+ * e_cal_component_get_location:
+ * @comp: A calendar component object
+ *
+ * Queries the location property of a calendar component object.
+ *
+ * Returns: (transfer full) (nullable): the locatio, or %NULL, if none is set
  *
- * Sets the repeat/duration values for an alarm.
+ * Since: 3.36
  **/
-void
-e_cal_component_alarm_set_repeat (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmRepeat repeat)
+gchar *
+e_cal_component_get_location (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (repeat.repetitions >= 0);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       /* Delete old properties */
+       ICalProperty *prop;
+       gchar *location;
 
-       if (alarm->repeat) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->repeat);
-               icalproperty_free (alarm->repeat);
-               alarm->repeat = NULL;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (alarm->duration) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->duration);
-               icalproperty_free (alarm->duration);
-               alarm->duration = NULL;
-       }
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_LOCATION_PROPERTY);
 
-       /* Set the new properties */
+       if (!prop)
+               return NULL;
 
-       if (repeat.repetitions == 0)
-               return; /* For zero extra repetitions the properties should not exist */
+       location = g_strdup (i_cal_property_get_location (prop));
 
-       alarm->repeat = icalproperty_new_repeat (repeat.repetitions);
-       icalcomponent_add_property (alarm->icalcomp, alarm->repeat);
+       g_object_unref (prop);
 
-       alarm->duration = icalproperty_new_duration (repeat.duration);
-       icalcomponent_add_property (alarm->icalcomp, alarm->duration);
+       return location;
 }
 
 /**
- * e_cal_component_alarm_get_trigger:
- * @alarm: An alarm.
- * @trigger: (out): Return value for the trigger time.
+ * e_cal_component_set_location:
+ * @comp: A calendar component object.
+ * @location: (nullable): Location value. Use %NULL or empty string, to unset the property.
+ *
+ * Sets the location property of a calendar component object.
  *
- * Queries the trigger time for an alarm.
+ * Since: 3.36
  **/
 void
-e_cal_component_alarm_get_trigger (ECalComponentAlarm *alarm,
-                                   ECalComponentAlarmTrigger *trigger)
+e_cal_component_set_location (ECalComponent *comp,
+                              const gchar *location)
 {
-       icalparameter *param;
-       struct icaltriggertype t;
-       gboolean relative;
-
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (trigger != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       ICalProperty *prop;
 
-       if (!alarm->trigger) {
-               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_NONE;
-               return;
-       }
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       /* Get trigger type */
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_LOCATION_PROPERTY);
 
-       param = icalproperty_get_first_parameter (alarm->trigger, ICAL_VALUE_PARAMETER);
-       if (param) {
-               icalparameter_value value;
+       if (!location || !*location) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-               value = icalparameter_get_value (param);
+               return;
+       }
 
-               switch (value) {
-               case ICAL_VALUE_DURATION:
-                       relative = TRUE;
-                       break;
+       if (prop) {
+               i_cal_property_set_location (prop, (gchar *) location);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_location ((gchar *) location);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
+}
 
-               case ICAL_VALUE_DATETIME:
-                       relative = FALSE;
-                       break;
+/**
+ * e_cal_component_has_alarms:
+ * @comp: A calendar component object.
+ *
+ * Checks whether the component has any alarms.
+ *
+ * Returns: TRUE if the component has any alarms.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_has_alarms (ECalComponent *comp)
+{
+       ICalComponent *subcomp;
 
-               default:
-                       g_message (
-                               "e_cal_component_alarm_get_trigger(): "
-                               "Unknown value for trigger "
-                               "value %d; using RELATIVE", value);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-                       relative = TRUE;
-                       break;
-               }
-       } else
-               relative = TRUE;
+       subcomp = i_cal_component_get_first_component (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT);
+       if (subcomp) {
+               g_object_unref (subcomp);
+               return TRUE;
+       }
 
-       /* Get trigger value and the RELATED parameter */
+       return FALSE;
+}
 
-       t = icalproperty_get_trigger (alarm->trigger);
+static gchar *
+dup_alarm_uid_from_component (ICalComponent *valarm)
+{
+       ICalProperty *prop;
+       gchar *auid = NULL;
 
-       if (relative) {
-               trigger->u.rel_duration = t.duration;
+       g_return_val_if_fail (valarm != NULL, NULL);
 
-               param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER);
-               if (param) {
-                       icalparameter_related rel;
+       for (prop = i_cal_component_get_first_property (valarm, I_CAL_X_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (valarm, I_CAL_X_PROPERTY)) {
+               const gchar *xname;
 
-                       rel = icalparameter_get_related (param);
+               xname = i_cal_property_get_x_name (prop);
 
-                       switch (rel) {
-                       case ICAL_RELATED_START:
-                               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
-                               break;
+               if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
+                       const gchar *xvalue;
 
-                       case ICAL_RELATED_END:
-                               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END;
+                       xvalue = i_cal_property_get_x (prop);
+                       if (xvalue) {
+                               auid = g_strdup (xvalue);
+                               g_object_unref (prop);
                                break;
-
-                       default:
-                               g_return_if_reached ();
                        }
-               } else
-                       trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
-       } else {
-               trigger->u.abs_time = t.time;
-               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE;
+               }
        }
+
+       return auid;
 }
 
 /**
- * e_cal_component_alarm_set_trigger:
- * @alarm: An alarm.
- * @trigger: Trigger time structure.
+ * e_cal_component_add_alarm:
+ * @comp: A calendar component.
+ * @alarm: (transfer none): an alarm, as an #ECalComponentAlarm
+ *
+ * Adds an alarm subcomponent to a calendar component.  You should have created
+ * the @alarm by using e_cal_component_alarm_new(); it is invalid to use a
+ * #ECalComponentAlarm structure that came from e_cal_component_get_alarm().  After
+ * adding the alarm, the @alarm structure is no longer valid because the
+ * internal structures may change and you should get rid of it by using
+ * e_cal_component_alarm_free().
  *
- * Sets the trigger time of an alarm.
+ * Since: 3.36
  **/
 void
-e_cal_component_alarm_set_trigger (ECalComponentAlarm *alarm,
-                                   ECalComponentAlarmTrigger trigger)
+e_cal_component_add_alarm (ECalComponent *comp,
+                          ECalComponentAlarm *alarm)
 {
-       struct icaltriggertype t;
-       icalparameter *param;
-       icalparameter_value value_type;
-       icalparameter_related related;
+       GSList *existing_uids, *link;
+       ICalComponent *valarm;
+       const gchar *auid;
 
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
        g_return_if_fail (alarm != NULL);
-       g_return_if_fail (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_NONE);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       /* Delete old trigger */
-
-       if (alarm->trigger) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->trigger);
-               icalproperty_free (alarm->trigger);
-               alarm->trigger = NULL;
-       }
+       g_return_if_fail (comp->priv->icalcomp);
 
-       /* Set the value */
+       auid = e_cal_component_alarm_get_uid (alarm);
 
-       related = ICAL_RELATED_START; /* Keep GCC happy */
+       existing_uids = e_cal_component_get_alarm_uids (comp);
 
-       t.time = icaltime_null_time ();
-       t.duration = icaldurationtype_null_duration ();
-       switch (trigger.type) {
-       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
-               t.duration = trigger.u.rel_duration;
-               value_type = ICAL_VALUE_DURATION;
-               related = ICAL_RELATED_START;
-               break;
+       for (link = existing_uids; link; link = g_slist_next (link)) {
+               const gchar *existing_auid = link->data;
 
-       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
-               t.duration = trigger.u.rel_duration;
-               value_type = ICAL_VALUE_DURATION;
-               related = ICAL_RELATED_END;
-               break;
+               if (g_strcmp0 (auid, existing_auid) == 0)
+                       break;
+       }
 
-       case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
-               t.time = trigger.u.abs_time;
-               value_type = ICAL_VALUE_DATETIME;
-               break;
+       g_slist_free_full (existing_uids, g_free);
 
-       default:
-               g_return_if_reached ();
+       /* Not NULL, when found an alarm with the same UID */
+       if (link) {
+               /* This generates new UID for the alarm */
+               e_cal_component_alarm_set_uid (alarm, NULL);
        }
 
-       alarm->trigger = icalproperty_new_trigger (t);
-       icalcomponent_add_property (alarm->icalcomp, alarm->trigger);
+       valarm = e_cal_component_alarm_get_as_component (alarm);
+       if (valarm)
+               i_cal_component_take_component (comp->priv->icalcomp, valarm);
+}
+
+static gboolean
+remove_alarm_cb (ICalComponent *icalcomp,
+                ICalComponent *subcomp,
+                gpointer user_data)
+{
+       const gchar *auid = user_data;
+       gchar *existing;
 
-       /* Value parameters */
+       g_return_val_if_fail (auid != NULL, FALSE);
 
-       param = icalproperty_get_first_parameter (alarm->trigger, ICAL_VALUE_PARAMETER);
-       if (param)
-               icalparameter_set_value (param, value_type);
-       else {
-               param = icalparameter_new_value (value_type);
-               icalproperty_add_parameter (alarm->trigger, param);
+       existing = dup_alarm_uid_from_component (subcomp);
+       if (g_strcmp0 (existing, auid) == 0) {
+               g_free (existing);
+               i_cal_component_remove_component (icalcomp, subcomp);
+               return FALSE;
        }
 
-       /* Related parameter */
-
-       if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
-               param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER);
+       g_free (existing);
 
-               if (param)
-                       icalparameter_set_related (param, related);
-               else {
-                       param = icalparameter_new_related (related);
-                       icalproperty_add_parameter (alarm->trigger, param);
-               }
-       }
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_get_attendee_list:
- * @alarm: An alarm.
- * @attendee_list: (out) (transfer full) (element-type ECalComponentAttendee): Return value for the list of 
attendees.
+ * e_cal_component_remove_alarm:
+ * @comp: A calendar component.
+ * @auid: UID of the alarm to remove.
  *
- * Gets the list of attendees associated with an alarm.
- */
+ * Removes an alarm subcomponent from a calendar component.  If the alarm that
+ * corresponds to the specified @auid had been fetched with
+ * e_cal_component_get_alarm(), then those alarm structures will be invalid; you
+ * should get rid of them with e_cal_component_alarm_free() before using this
+ * function.
+ *
+ * Since: 3.36
+ **/
 void
-e_cal_component_alarm_get_attendee_list (ECalComponentAlarm *alarm,
-                                         GSList **attendee_list)
+e_cal_component_remove_alarm (ECalComponent *comp,
+                              const gchar *auid)
 {
-       g_return_if_fail (alarm != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (auid != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       get_attendee_list (alarm->attendee_list, attendee_list);
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, remove_alarm_cb, (gpointer) auid);
 }
 
-/**
- * e_cal_component_alarm_set_attendee_list:
- * @alarm: An alarm.
- * @attendee_list: (element-type ECalComponentAttendee): List of attendees.
- *
- * Sets the list of attendees for an alarm.
- */
-void
-e_cal_component_alarm_set_attendee_list (ECalComponentAlarm *alarm,
-                                         GSList *attendee_list)
+static gboolean
+remove_all_alarms_cb (ICalComponent *icalcomp,
+                     ICalComponent *subcomp,
+                     gpointer user_data)
 {
-       g_return_if_fail (alarm != NULL);
+       i_cal_component_remove_component (icalcomp, subcomp);
 
-       set_attendee_list (alarm->icalcomp, &alarm->attendee_list, attendee_list);
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_has_attendees:
- * @alarm: An alarm.
+ * e_cal_component_remove_all_alarms:
+ * @comp: A calendar component
  *
- * Queries an alarm to see if it has attendees associated with it.
+ * Remove all alarms from the calendar component
  *
- * Returns: TRUE if there are attendees in the alarm, FALSE if not.
- */
-gboolean
-e_cal_component_alarm_has_attendees (ECalComponentAlarm *alarm)
+ * Since: 3.36
+ **/
+void
+e_cal_component_remove_all_alarms (ECalComponent *comp)
 {
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       g_return_val_if_fail (alarm != NULL, FALSE);
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, remove_all_alarms_cb, NULL);
+}
 
-       if (g_slist_length (alarm->attendee_list) > 0)
-               return TRUE;
+static gboolean
+get_alarm_uids_cb (ICalComponent *icalcomp,
+                  ICalComponent *subcomp,
+                  gpointer user_data)
+{
+       GSList **puids = user_data;
+       gchar *auid;
 
-       return FALSE;
+       g_return_val_if_fail (puids != NULL, FALSE);
+
+       auid = dup_alarm_uid_from_component (subcomp);
+       if (auid)
+               *puids = g_slist_prepend (*puids, auid);
+
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_get_icalcomponent:
- * @alarm: An alarm.
+ * e_cal_component_get_alarm_uids:
+ * @comp: A calendar component.
  *
- * Get the icalcomponent associated with the given #ECalComponentAlarm.
+ * Builds a list of the unique identifiers of the alarm subcomponents inside a
+ * calendar component. Free the returned #GSList with
+ * g_slist_free_full (slist, g_free);, when no longer needed.
  *
- * Returns: the icalcomponent.
- */
-icalcomponent *
-e_cal_component_alarm_get_icalcomponent (ECalComponentAlarm *alarm)
+ * Returns: (transfer full) (nullable) (element-type utf8): a #GSList of unique
+ *    identifiers for alarms.
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_get_alarm_uids (ECalComponent *comp)
 {
-       g_return_val_if_fail (alarm != NULL, NULL);
-       return alarm->icalcomp;
+       GSList *uids = NULL;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, get_alarm_uids_cb, &uids);
+
+       return g_slist_reverse (uids);
 }
 
-/* Returns TRUE if both strings match, i.e. they are both NULL or the
- * strings are equal. */
+struct GetAlarmData {
+       const gchar *auid;
+       ICalComponent *valarm;
+};
+
 static gboolean
-e_cal_component_strings_match (const gchar *string1,
-                               const gchar *string2)
+get_alarm_cb (ICalComponent *icalcomp,
+             ICalComponent *subcomp,
+             gpointer user_data)
 {
-       if (string1 == NULL || string2 == NULL)
-               return (string1 == string2) ? TRUE : FALSE;
+       struct GetAlarmData *gad = user_data;
+       gchar *auid;
 
-       if (!strcmp (string1, string2))
-               return TRUE;
+       g_return_val_if_fail (gad != NULL, FALSE);
 
-       return FALSE;
+       auid = dup_alarm_uid_from_component (subcomp);
+       if (g_strcmp0 (auid, gad->auid) == 0) {
+               gad->valarm = g_object_ref (subcomp);
+       }
+
+       g_free (auid);
+
+       return !gad->valarm;
 }
 
 /**
- * e_cal_component_event_dates_match:
- * @comp1: A calendar component object.
- * @comp2: A calendar component object.
+ * e_cal_component_get_alarm:
+ * @comp: A calendar component.
+ * @auid: Unique identifier for the sought alarm subcomponent.
  *
- * Checks if the DTSTART and DTEND properties of the 2 components match.
- * Note that the events may have different recurrence properties which are not
- * taken into account here.
+ * Queries a particular alarm subcomponent of a calendar component.
+ * Free the returned pointer with e_cal_component_alarm_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the alarm subcomponent that corresponds
+ *    to the specified @auid, or %NULL if no alarm exists with that UID
  *
- * Returns: TRUE if the DTSTART and DTEND properties of the 2 components match.
+ * Since: 3.36
  **/
-gboolean
-e_cal_component_event_dates_match (ECalComponent *comp1,
-                                   ECalComponent *comp2)
-{
-       ECalComponentDateTime comp1_dtstart, comp1_dtend;
-       ECalComponentDateTime comp2_dtstart, comp2_dtend;
-       gboolean retval = TRUE;
-
-       e_cal_component_get_dtstart (comp1, &comp1_dtstart);
-       e_cal_component_get_dtend   (comp1, &comp1_dtend);
-       e_cal_component_get_dtstart (comp2, &comp2_dtstart);
-       e_cal_component_get_dtend   (comp2, &comp2_dtend);
-
-       /* If either value is NULL they must both be NULL to match. */
-       if (comp1_dtstart.value == NULL || comp2_dtstart.value == NULL) {
-               if (comp1_dtstart.value != comp2_dtstart.value) {
-                       retval = FALSE;
-                       goto out;
-               }
-       } else {
-               if (icaltime_compare (*comp1_dtstart.value,
-                                     *comp2_dtstart.value)) {
-                       retval = FALSE;
-                       goto out;
-               }
-       }
+ECalComponentAlarm *
+e_cal_component_get_alarm (ECalComponent *comp,
+                           const gchar *auid)
+{
+       ECalComponentAlarm *alarm = NULL;
+       struct GetAlarmData gad;
 
-       if (comp1_dtend.value == NULL || comp2_dtend.value == NULL) {
-               if (comp1_dtend.value != comp2_dtend.value) {
-                       retval = FALSE;
-                       goto out;
-               }
-       } else {
-               if (icaltime_compare (*comp1_dtend.value,
-                                     *comp2_dtend.value)) {
-                       retval = FALSE;
-                       goto out;
-               }
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+       g_return_val_if_fail (auid != NULL, NULL);
 
-       /* Now check the timezones. */
-       if (!e_cal_component_strings_match (comp1_dtstart.tzid,
-                                         comp2_dtstart.tzid)) {
-               retval = FALSE;
-               goto out;
-       }
+       gad.auid = auid;
+       gad.valarm = NULL;
 
-       if (!e_cal_component_strings_match (comp1_dtend.tzid,
-                                         comp2_dtend.tzid)) {
-               retval = FALSE;
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, get_alarm_cb, &gad);
+
+       if (gad.valarm) {
+               alarm = e_cal_component_alarm_new_from_component (gad.valarm);
+               g_object_unref (gad.valarm);
        }
 
- out:
+       return alarm;
+}
+
+static gboolean
+get_all_alarms_cb (ICalComponent *icalcomp,
+                  ICalComponent *subcomp,
+                  gpointer user_data)
+{
+       GSList **palarms = user_data;
+       ECalComponentAlarm *alarm;
+
+       g_return_val_if_fail (palarms != NULL, FALSE);
 
-       e_cal_component_free_datetime (&comp1_dtstart);
-       e_cal_component_free_datetime (&comp1_dtend);
-       e_cal_component_free_datetime (&comp2_dtstart);
-       e_cal_component_free_datetime (&comp2_dtend);
+       alarm = e_cal_component_alarm_new_from_component (subcomp);
+       if (alarm)
+               *palarms = g_slist_prepend (*palarms, alarm);
 
-       return retval;
+       return TRUE;
 }
 
+/**
+ * e_cal_component_get_all_alarms:
+ * @comp: A calendar component.
+ *
+ * Queries all alarm subcomponents of a calendar component.
+ * Free the returned #GSList with g_slist_free_full (slist, e_cal_component_alarm_free));,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ECalComponentAlarm): the alarm subcomponents
+ *    as a #GSList of #ECalComponentAlarm, or %NULL, if no alarm exists
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_get_all_alarms (ECalComponent *comp)
+{
+       GSList *alarms = NULL;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, get_all_alarms_cb, &alarms);
+
+       return g_slist_reverse (alarms);
+}
diff --git a/src/calendar/libecal/e-cal-component.h b/src/calendar/libecal/e-cal-component.h
index eb8441626..2ef22ecea 100644
--- a/src/calendar/libecal/e-cal-component.h
+++ b/src/calendar/libecal/e-cal-component.h
@@ -26,7 +26,21 @@
 
 #include <time.h>
 #include <glib-object.h>
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
+
+#include <libecal/e-cal-enums.h>
+#include <libecal/e-cal-component-alarm.h>
+#include <libecal/e-cal-component-alarm-instance.h>
+#include <libecal/e-cal-component-alarm-repeat.h>
+#include <libecal/e-cal-component-alarm-trigger.h>
+#include <libecal/e-cal-component-alarms.h>
+#include <libecal/e-cal-component-attendee.h>
+#include <libecal/e-cal-component-datetime.h>
+#include <libecal/e-cal-component-id.h>
+#include <libecal/e-cal-component-organizer.h>
+#include <libecal/e-cal-component-period.h>
+#include <libecal/e-cal-component-range.h>
+#include <libecal/e-cal-component-text.h>
 
 /* Standard GObject macros */
 #define E_TYPE_CAL_COMPONENT \
@@ -49,269 +63,6 @@
 
 G_BEGIN_DECLS
 
-/**
- * ECalComponentId:
- * @uid: UID of the component
- * @rid: recurrence ID of the component; can be %NULL
- **/
-typedef struct {
-       gchar *uid;
-       gchar *rid;
-} ECalComponentId;
-
-/**
- * ECalComponentVType:
- * @E_CAL_COMPONENT_NO_TYPE: Unknown or unsupported component type
- * @E_CAL_COMPONENT_EVENT: vEvent type
- * @E_CAL_COMPONENT_TODO: vTodo type
- * @E_CAL_COMPONENT_JOURNAL: vJournal type
- * @E_CAL_COMPONENT_FREEBUSY: vFreeBusy type
- * @E_CAL_COMPONENT_TIMEZONE: vTimezone type
- *
- * Types of calendar components to be stored by a ECalComponent, as per RFC 2445.
- * We don't put the alarm component type here since we store alarms as separate
- * structures inside the other "real" components.
- **/
-typedef enum {
-       E_CAL_COMPONENT_NO_TYPE,
-       E_CAL_COMPONENT_EVENT,
-       E_CAL_COMPONENT_TODO,
-       E_CAL_COMPONENT_JOURNAL,
-       E_CAL_COMPONENT_FREEBUSY,
-       E_CAL_COMPONENT_TIMEZONE
-} ECalComponentVType;
-
-/**
- * ECalComponentField:
- * @E_CAL_COMPONENT_FIELD_CATEGORIES: Concatenation of categories
- * @E_CAL_COMPONENT_FIELD_CLASSIFICATION: Classification
- * @E_CAL_COMPONENT_FIELD_COMPLETED: Completed
- * @E_CAL_COMPONENT_FIELD_DTEND: Dtend
- * @E_CAL_COMPONENT_FIELD_DTSTART: Dtstart
- * @E_CAL_COMPONENT_FIELD_DUE: Due
- * @E_CAL_COMPONENT_FIELD_GEO: Geo
- * @E_CAL_COMPONENT_FIELD_PERCENT: Percent
- * @E_CAL_COMPONENT_FIELD_PRIORITY: Priority
- * @E_CAL_COMPONENT_FIELD_SUMMARY: Summary
- * @E_CAL_COMPONENT_FIELD_TRANSPARENCY: Transparency
- * @E_CAL_COMPONENT_FIELD_URL: URL
- * @E_CAL_COMPONENT_FIELD_HAS_ALARMS: not a real field
- * @E_CAL_COMPONENT_FIELD_ICON: not a real field
- * @E_CAL_COMPONENT_FIELD_COMPLETE: not a real field
- * @E_CAL_COMPONENT_FIELD_RECURRING: not a real field
- * @E_CAL_COMPONENT_FIELD_OVERDUE: not a real field
- * @E_CAL_COMPONENT_FIELD_COLOR: not a real field
- * @E_CAL_COMPONENT_FIELD_STATUS: Status
- * @E_CAL_COMPONENT_FIELD_COMPONENT: not a real field
- * @E_CAL_COMPONENT_FIELD_LOCATION: Location
- * @E_CAL_COMPONENT_FIELD_NUM_FIELDS: the last member
- *
- * Field identifiers for a calendar component.
- **/
-
-/*
- * NOTE: These are also used in the ETable specification, and the column
- *       numbers are saved in the user settings file. So don't reorder them!
- */
-typedef enum {
-       E_CAL_COMPONENT_FIELD_CATEGORIES,       /* concatenation of categories */
-       E_CAL_COMPONENT_FIELD_CLASSIFICATION,
-       E_CAL_COMPONENT_FIELD_COMPLETED,
-       E_CAL_COMPONENT_FIELD_DTEND,
-       E_CAL_COMPONENT_FIELD_DTSTART,
-       E_CAL_COMPONENT_FIELD_DUE,
-       E_CAL_COMPONENT_FIELD_GEO,
-       E_CAL_COMPONENT_FIELD_PERCENT,
-       E_CAL_COMPONENT_FIELD_PRIORITY,
-       E_CAL_COMPONENT_FIELD_SUMMARY,
-       E_CAL_COMPONENT_FIELD_TRANSPARENCY,
-       E_CAL_COMPONENT_FIELD_URL,
-       E_CAL_COMPONENT_FIELD_HAS_ALARMS,       /* not a real field */
-       E_CAL_COMPONENT_FIELD_ICON,             /* not a real field */
-       E_CAL_COMPONENT_FIELD_COMPLETE,         /* not a real field */
-       E_CAL_COMPONENT_FIELD_RECURRING,        /* not a real field */
-       E_CAL_COMPONENT_FIELD_OVERDUE,          /* not a real field */
-       E_CAL_COMPONENT_FIELD_COLOR,            /* not a real field */
-       E_CAL_COMPONENT_FIELD_STATUS,
-       E_CAL_COMPONENT_FIELD_COMPONENT,        /* not a real field */
-       E_CAL_COMPONENT_FIELD_LOCATION,
-       E_CAL_COMPONENT_FIELD_NUM_FIELDS
-} ECalComponentField;
-
-/* Structures and enumerations to return properties and their parameters */
-
-/**
- * ECalComponentClassification:
- * @E_CAL_COMPONENT_CLASS_NONE: None
- * @E_CAL_COMPONENT_CLASS_PUBLIC: Public
- * @E_CAL_COMPONENT_CLASS_PRIVATE: Private
- * @E_CAL_COMPONENT_CLASS_CONFIDENTIAL: Confidential
- * @E_CAL_COMPONENT_CLASS_UNKNOWN: Unknown
- *
- * CLASSIFICATION property
- **/
-typedef enum {
-       E_CAL_COMPONENT_CLASS_NONE,
-       E_CAL_COMPONENT_CLASS_PUBLIC,
-       E_CAL_COMPONENT_CLASS_PRIVATE,
-       E_CAL_COMPONENT_CLASS_CONFIDENTIAL,
-       E_CAL_COMPONENT_CLASS_UNKNOWN
-} ECalComponentClassification;
-
-/* Properties that have time and timezone information */
-/**
- * ECalComponentDateTime:
- * @value: an icaltimetype value
- * @tzid: a timezone ID for the @value
- *
- * Time with timezone property
- **/
-typedef struct {
-       /* Actual date/time value */
-       struct icaltimetype *value;
-
-       /* Timezone ID */
-       const gchar *tzid;
-} ECalComponentDateTime;
-
-/**
- * ECalComponentPeriodType:
- * @E_CAL_COMPONENT_PERIOD_DATETIME: Date and time
- * @E_CAL_COMPONENT_PERIOD_DURATION: Duration
- *
- * Way in which a period of time is specified
- **/
-typedef enum {
-       E_CAL_COMPONENT_PERIOD_DATETIME,
-       E_CAL_COMPONENT_PERIOD_DURATION
-} ECalComponentPeriodType;
-
-/**
- * ECalComponentPeriod:
- * @type: An #ECalComponentPeriodType
- * @start: When the period starts
- *
- * Period of time, can have explicit start/end times or start/duration instead
- **/
-typedef struct {
-       ECalComponentPeriodType type;
-
-       struct icaltimetype start;
-
-       union {
-               struct icaltimetype end;
-               struct icaldurationtype duration;
-       } u;
-} ECalComponentPeriod;
-
-/**
- * ECalComponentRangeType:
- * @E_CAL_COMPONENT_RANGE_SINGLE: Single
- * @E_CAL_COMPONENT_RANGE_THISPRIOR: This and prior
- * @E_CAL_COMPONENT_RANGE_THISFUTURE: This and future
- *
- * The type of range
- **/
-typedef enum {
-       E_CAL_COMPONENT_RANGE_SINGLE,
-       E_CAL_COMPONENT_RANGE_THISPRIOR,
-       E_CAL_COMPONENT_RANGE_THISFUTURE
-} ECalComponentRangeType;
-
-/**
- * ECalComponentRange:
- * @type: an #ECalComponentRangeType
- * @datetime: an #ECalComponentDateTime of the range
- *
- * Describes a range
- **/
-typedef struct {
-       ECalComponentRangeType type;
-
-       ECalComponentDateTime datetime;
-} ECalComponentRange;
-
-/**
- * ECalComponentText:
- * @value: Description string
- * @altrep: Alternate representation URI
- *
- * For the text properties
- **/
-typedef struct {
-       /* Description string */
-       const gchar *value;
-
-       /* Alternate representation URI */
-       const gchar *altrep;
-} ECalComponentText;
-
-/**
- * ECalComponentTransparency:
- * @E_CAL_COMPONENT_TRANSP_NONE: None
- * @E_CAL_COMPONENT_TRANSP_TRANSPARENT: Transparent
- * @E_CAL_COMPONENT_TRANSP_OPAQUE: Opaque
- * @E_CAL_COMPONENT_TRANSP_UNKNOWN: Unknown
- *
- * Time transparency
- **/
-typedef enum {
-       E_CAL_COMPONENT_TRANSP_NONE,
-       E_CAL_COMPONENT_TRANSP_TRANSPARENT,
-       E_CAL_COMPONENT_TRANSP_OPAQUE,
-       E_CAL_COMPONENT_TRANSP_UNKNOWN
-} ECalComponentTransparency;
-
-/**
- * ECalComponentAttendee:
- * @value: usually a "mailto:email"; of the attendee
- * @member: Member
- * @cutype: Type of the attendee
- * @role: Role of the attendee
- * @status: Current status of the attendee
- * @rsvp: Whether requires RSVP
- * @delto: Delegated to
- * @delfrom: Delegated from
- * @sentby: Sent by
- * @cn: Common name
- * @language: Language
- *
- * Describes an attendee
- **/
-typedef struct {
-       const gchar *value;
-
-       const gchar *member;
-       icalparameter_cutype cutype;
-       icalparameter_role role;
-       icalparameter_partstat status;
-       gboolean rsvp;
-
-       const gchar *delto;
-       const gchar *delfrom;
-       const gchar *sentby;
-       const gchar *cn;
-       const gchar *language;
-} ECalComponentAttendee;
-
-/**
- * ECalComponentOrganizer:
- * @value: usually a "mailto:email"; of the organizer
- * @sentby: Sent by
- * @cn: Common name
- * @language: Language
- *
- * Describes an organizer
- **/
-typedef struct {
-       const gchar *value;
-       const gchar *sentby;
-       const gchar *cn;
-       const gchar *language;
-} ECalComponentOrganizer;
-
-/* Main calendar component object */
-
 typedef struct _ECalComponent ECalComponent;
 typedef struct _ECalComponentClass ECalComponentClass;
 typedef struct _ECalComponentPrivate ECalComponentPrivate;
@@ -327,198 +78,152 @@ struct _ECalComponentClass {
        GObjectClass parent_class;
 };
 
-/* Calendar component */
-
 GType          e_cal_component_get_type        (void);
 
-/* #ifndef EDS_DISABLE_DEPRECATED*/
-gchar *                e_cal_component_gen_uid         (void);
-/*#endif / * EDS_DISABLE_DEPRECATED */
-
 ECalComponent *        e_cal_component_new             (void);
+ECalComponent *        e_cal_component_new_vtype       (ECalComponentVType vtype);
 ECalComponent *        e_cal_component_new_from_string (const gchar *calobj);
 ECalComponent *        e_cal_component_new_from_icalcomponent
-                                               (icalcomponent *icalcomp);
+                                               (ICalComponent *icalcomp);
 
 ECalComponent *        e_cal_component_clone           (ECalComponent *comp);
 
 void           e_cal_component_set_new_vtype   (ECalComponent *comp,
                                                 ECalComponentVType type);
+ECalComponentVType
+               e_cal_component_get_vtype       (ECalComponent *comp);
 
-icalcomponent *        e_cal_component_get_icalcomponent
+ICalComponent *        e_cal_component_get_icalcomponent
                                                (ECalComponent *comp);
 gboolean       e_cal_component_set_icalcomponent
                                                (ECalComponent *comp,
-                                                icalcomponent *icalcomp);
-void           e_cal_component_rescan          (ECalComponent *comp);
+                                                ICalComponent *icalcomp);
 void           e_cal_component_strip_errors    (ECalComponent *comp);
 
-ECalComponentVType
-               e_cal_component_get_vtype       (ECalComponent *comp);
-
 gchar *                e_cal_component_get_as_string   (ECalComponent *comp);
 
 void           e_cal_component_commit_sequence (ECalComponent *comp);
 void           e_cal_component_abort_sequence  (ECalComponent *comp);
 
-void           e_cal_component_get_uid         (ECalComponent *comp,
-                                                const gchar **uid);
+const gchar *  e_cal_component_get_uid         (ECalComponent *comp);
 void           e_cal_component_set_uid         (ECalComponent *comp,
                                                 const gchar *uid);
 
 ECalComponentId *
                e_cal_component_get_id          (ECalComponent *comp);
-void           e_cal_component_free_id         (ECalComponentId *id);
-GType          e_cal_component_id_get_type     (void);
-ECalComponentId *
-               e_cal_component_id_new          (const gchar *uid,
-                                                const gchar *rid);
-ECalComponentId *
-               e_cal_component_id_copy         (const ECalComponentId *id);
-guint          e_cal_component_id_hash         (const ECalComponentId *id);
-gboolean       e_cal_component_id_equal        (const ECalComponentId *id1,
-                                                const ECalComponentId *id2);
 
-void           e_cal_component_get_categories  (ECalComponent *comp,
-                                                const gchar **categories);
+gchar *                e_cal_component_get_categories  (ECalComponent *comp);
 void           e_cal_component_set_categories  (ECalComponent *comp,
                                                 const gchar *categories);
-void           e_cal_component_get_categories_list
-                                               (ECalComponent *comp,
-                                                GSList **categ_list);
+GSList *       e_cal_component_get_categories_list /* gchar * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_categories_list
                                                (ECalComponent *comp,
-                                                GSList *categ_list);
+                                                const GSList *categ_list); /* gchar * */
 
-void           e_cal_component_get_classification
-                                               (ECalComponent *comp,
-                                                ECalComponentClassification *classif);
+ECalComponentClassification
+               e_cal_component_get_classification
+                                               (ECalComponent *comp);
 void           e_cal_component_set_classification
                                                (ECalComponent *comp,
                                                 ECalComponentClassification classif);
 
-void           e_cal_component_get_comment_list
-                                               (ECalComponent *comp,
-                                                GSList **text_list);
-void           e_cal_component_set_comment_list
-                                               (ECalComponent *comp,
-                                                GSList *text_list);
+GSList *       e_cal_component_get_comments    (ECalComponent *comp); /* ECalComponentText * */
+void           e_cal_component_set_comments    (ECalComponent *comp,
+                                                const GSList *text_list); /* ECalComponentText * */
 
-void           e_cal_component_get_completed   (ECalComponent *comp,
-                                                struct icaltimetype **t);
+ICalTime *     e_cal_component_get_completed   (ECalComponent *comp);
 void           e_cal_component_set_completed   (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTime *tt);
 
-void           e_cal_component_get_contact_list
-                                               (ECalComponent *comp,
-                                                GSList **text_list);
-void           e_cal_component_set_contact_list
-                                               (ECalComponent *comp,
-                                                GSList *text_list);
+GSList *       e_cal_component_get_contacts    (ECalComponent *comp); /* ECalComponentText * */
+void           e_cal_component_set_contacts    (ECalComponent *comp,
+                                                const GSList *text_list); /* ECalComponentText * */
 
-void           e_cal_component_get_created     (ECalComponent *comp,
-                                                struct icaltimetype **t);
+ICalTime *     e_cal_component_get_created     (ECalComponent *comp);
 void           e_cal_component_set_created     (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTime *tt);
 
-void           e_cal_component_get_description_list
-                                               (ECalComponent *comp,
-                                                GSList **text_list);
-void           e_cal_component_set_description_list
-                                               (ECalComponent *comp,
-                                                GSList *text_list);
+GSList *       e_cal_component_get_descriptions(ECalComponent *comp);  /* ECalComponentText * */
+void           e_cal_component_set_descriptions(ECalComponent *comp,
+                                                const GSList *text_list); /* ECalComponentText * */
 
-void           e_cal_component_get_dtend       (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+ECalComponentDateTime *
+               e_cal_component_get_dtend       (ECalComponent *comp);
 void           e_cal_component_set_dtend       (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+                                                const ECalComponentDateTime *dt);
 
-void           e_cal_component_get_dtstamp     (ECalComponent *comp,
-                                                struct icaltimetype *t);
+ICalTime *     e_cal_component_get_dtstamp     (ECalComponent *comp);
 void           e_cal_component_set_dtstamp     (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTime *tt);
 
-void           e_cal_component_get_dtstart     (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+ECalComponentDateTime *
+               e_cal_component_get_dtstart     (ECalComponent *comp);
 void           e_cal_component_set_dtstart     (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+                                                const ECalComponentDateTime *dt);
 
-void           e_cal_component_get_due         (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+ECalComponentDateTime *
+               e_cal_component_get_due         (ECalComponent *comp);
 void           e_cal_component_set_due         (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+                                                const ECalComponentDateTime *dt);
 
-void           e_cal_component_get_exdate_list (ECalComponent *comp,
-                                                GSList **exdate_list);
-void           e_cal_component_set_exdate_list (ECalComponent *comp,
-                                                GSList *exdate_list);
+GSList *       e_cal_component_get_exdates     (ECalComponent *comp); /* ECalComponentDateTime * */
+void           e_cal_component_set_exdates     (ECalComponent *comp,
+                                                const GSList *exdate_list); /* ECalComponentDateTime * */
 gboolean       e_cal_component_has_exdates     (ECalComponent *comp);
 
-void           e_cal_component_get_exrule_list (ECalComponent *comp,
-                                                GSList **recur_list);
-void           e_cal_component_get_exrule_property_list
-                                               (ECalComponent *comp,
-                                                GSList **recur_list);
-void           e_cal_component_set_exrule_list (ECalComponent *comp,
-                                                GSList *recur_list);
+GSList *       e_cal_component_get_exrules     (ECalComponent *comp); /* ICalRecurrence * */
+GSList *       e_cal_component_get_exrule_properties /* ICalProperty * */
+                                               (ECalComponent *comp);
+void           e_cal_component_set_exrules     (ECalComponent *comp,
+                                                const GSList *recur_list); /* ICalRecurrence * */
 gboolean       e_cal_component_has_exrules     (ECalComponent *comp);
 
 gboolean       e_cal_component_has_exceptions  (ECalComponent *comp);
 
-void           e_cal_component_get_geo         (ECalComponent *comp,
-                                                struct icalgeotype **geo);
+ICalGeo *      e_cal_component_get_geo         (ECalComponent *comp);
 void           e_cal_component_set_geo         (ECalComponent *comp,
-                                                struct icalgeotype *geo);
+                                                const ICalGeo *geo);
 
-void           e_cal_component_get_last_modified
-                                               (ECalComponent *comp,
-                                                struct icaltimetype **t);
+ICalTime *     e_cal_component_get_last_modified
+                                               (ECalComponent *comp);
 void           e_cal_component_set_last_modified
                                                (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTime *tt);
 
-void           e_cal_component_get_organizer   (ECalComponent *comp,
-                                                ECalComponentOrganizer *organizer);
+ECalComponentOrganizer *
+               e_cal_component_get_organizer   (ECalComponent *comp);
 void           e_cal_component_set_organizer   (ECalComponent *comp,
-                                                ECalComponentOrganizer *organizer);
+                                                const ECalComponentOrganizer *organizer);
 gboolean       e_cal_component_has_organizer   (ECalComponent *comp);
 
-gint           e_cal_component_get_percent_as_int
+gint           e_cal_component_get_percent_complete
                                                (ECalComponent *comp);
-void           e_cal_component_set_percent_as_int
+void           e_cal_component_set_percent_complete
                                                (ECalComponent *comp,
                                                 gint percent);
 
-void           e_cal_component_get_percent     (ECalComponent *comp,
-                                                gint **percent);
-void           e_cal_component_set_percent     (ECalComponent *comp,
-                                                gint *percent);
-
-void           e_cal_component_get_priority    (ECalComponent *comp,
-                                                gint **priority);
+gint           e_cal_component_get_priority    (ECalComponent *comp);
 void           e_cal_component_set_priority    (ECalComponent *comp,
-                                                gint *priority);
+                                                gint priority);
 
-void           e_cal_component_get_recurid     (ECalComponent *comp,
-                                                ECalComponentRange *recur_id);
+ECalComponentRange *
+               e_cal_component_get_recurid     (ECalComponent *comp);
 gchar *                e_cal_component_get_recurid_as_string
                                                (ECalComponent *comp);
 void           e_cal_component_set_recurid     (ECalComponent *comp,
-                                                ECalComponentRange *recur_id);
+                                                const ECalComponentRange *recur_id);
 
-void           e_cal_component_get_rdate_list  (ECalComponent *comp,
-                                                GSList **period_list);
-void           e_cal_component_set_rdate_list  (ECalComponent *comp,
-                                                GSList *period_list);
+GSList *       e_cal_component_get_rdates      (ECalComponent *comp); /* ECalComponentPeriod * */
+void           e_cal_component_set_rdates      (ECalComponent *comp,
+                                                const GSList *rdate_list); /* ECalComponentPeriod * */
 gboolean       e_cal_component_has_rdates      (ECalComponent *comp);
 
-void           e_cal_component_get_rrule_list  (ECalComponent *comp,
-                                                GSList **recur_list);
-void           e_cal_component_get_rrule_property_list
-                                               (ECalComponent *comp,
-                                                GSList **recur_list);
-void           e_cal_component_set_rrule_list  (ECalComponent *comp,
-                                                GSList *recur_list);
+GSList *       e_cal_component_get_rrules      (ECalComponent *comp); /* ICalRecurrence * */
+GSList *       e_cal_component_get_rrule_properties /* ICalProperty * */
+                                               (ECalComponent *comp);
+void           e_cal_component_set_rrules      (ECalComponent *comp,
+                                                const GSList *recur_list); /* ICalRecurrence * */
 gboolean       e_cal_component_has_rrules      (ECalComponent *comp);
 
 gboolean       e_cal_component_has_recurrences (ECalComponent *comp);
@@ -526,190 +231,45 @@ gboolean e_cal_component_has_simple_recurrence
                                                (ECalComponent *comp);
 gboolean       e_cal_component_is_instance     (ECalComponent *comp);
 
-void           e_cal_component_get_sequence    (ECalComponent *comp,
-                                                gint **sequence);
+gint           e_cal_component_get_sequence    (ECalComponent *comp);
 void           e_cal_component_set_sequence    (ECalComponent *comp,
-                                                gint *sequence);
+                                                gint sequence);
 
-void           e_cal_component_get_status      (ECalComponent *comp,
-                                                icalproperty_status *status);
+ICalPropertyStatus
+               e_cal_component_get_status      (ECalComponent *comp);
 void           e_cal_component_set_status      (ECalComponent *comp,
-                                                icalproperty_status status);
+                                                ICalPropertyStatus status);
 
-void           e_cal_component_get_summary     (ECalComponent *comp,
-                                                ECalComponentText *summary);
+ECalComponentText *
+               e_cal_component_get_summary     (ECalComponent *comp);
 void           e_cal_component_set_summary     (ECalComponent *comp,
-                                                ECalComponentText *summary);
+                                                const ECalComponentText *summary);
 
-void           e_cal_component_get_transparency
-                                               (ECalComponent *comp,
-                                                ECalComponentTransparency *transp);
-void           e_cal_component_set_transparency
-                                               (ECalComponent *comp,
+ECalComponentTransparency
+               e_cal_component_get_transparency(ECalComponent *comp);
+void           e_cal_component_set_transparency(ECalComponent *comp,
                                                 ECalComponentTransparency transp);
 
-void           e_cal_component_get_url         (ECalComponent *comp,
-                                                const gchar **url);
+gchar *                e_cal_component_get_url         (ECalComponent *comp);
 void           e_cal_component_set_url         (ECalComponent *comp,
                                                 const gchar *url);
 
-void           e_cal_component_get_attendee_list
-                                               (ECalComponent *comp,
-                                                GSList **attendee_list);
-void           e_cal_component_set_attendee_list
-                                               (ECalComponent *comp,
-                                                GSList *attendee_list);
+GSList *       e_cal_component_get_attendees   (ECalComponent *comp);  /* ECalComponentAttendee * */
+void           e_cal_component_set_attendees   (ECalComponent *comp,
+                                                const GSList *attendee_list); /* ECalComponentAttendee * */
 gboolean       e_cal_component_has_attendees   (ECalComponent *comp);
 
-void           e_cal_component_get_location    (ECalComponent *comp,
-                                                const gchar **location);
+gchar *                e_cal_component_get_location    (ECalComponent *comp);
 void           e_cal_component_set_location    (ECalComponent *comp,
                                                 const gchar *location);
 
 /* Attachment handling */
-void           e_cal_component_get_attachment_list
-                                               (ECalComponent *comp,
-                                                GSList **attachment_list);
-void           e_cal_component_set_attachment_list
-                                               (ECalComponent *comp,
-                                                GSList *attachment_list);
+GSList *       e_cal_component_get_attachments (ECalComponent *comp); /* ICalAttach * */
+void           e_cal_component_set_attachments (ECalComponent *comp,
+                                                const GSList *attachments); /* ICalAttach * */
 gboolean       e_cal_component_has_attachments (ECalComponent *comp);
-gint           e_cal_component_get_num_attachments
-                                               (ECalComponent *comp);
-
-gboolean       e_cal_component_event_dates_match
-                                               (ECalComponent *comp1,
-                                                ECalComponent *comp2);
-
-/* Functions to free returned values */
-
-void           e_cal_component_free_categories_list
-                                               (GSList *categ_list);
-void           e_cal_component_free_datetime   (ECalComponentDateTime *dt);
-void           e_cal_component_free_range      (ECalComponentRange *range);
-void           e_cal_component_free_exdate_list
-                                               (GSList *exdate_list);
-void           e_cal_component_free_geo        (struct icalgeotype *geo);
-void           e_cal_component_free_icaltimetype
-                                               (struct icaltimetype *t);
-void           e_cal_component_free_percent    (gint *percent);
-void           e_cal_component_free_priority   (gint *priority);
-void           e_cal_component_free_period_list
-                                               (GSList *period_list);
-void           e_cal_component_free_recur_list (GSList *recur_list);
-void           e_cal_component_free_sequence   (gint *sequence);
-void           e_cal_component_free_text_list  (GSList *text_list);
-void           e_cal_component_free_attendee_list
-                                               (GSList *attendee_list);
 
 /* Alarms */
-
-/* Opaque structure used to represent alarm subcomponents */
-typedef struct _ECalComponentAlarm ECalComponentAlarm;
-
-/**
- * ECalComponentAlarmInstance:
- * @auid: UID of the alarm
- * @trigger: Trigger time, i.e. "5 minutes before the appointment"
- * @occur_start: Actual event occurrence start to which this trigger corresponds
- * @occur_end: Actual event occurrence end to which this trigger corresponds
- *
- * An alarm occurrence, i.e. a trigger instance
- **/
-typedef struct {
-       /* UID of the alarm that triggered */
-       gchar *auid;
-
-       /* Trigger time, i.e. "5 minutes before the appointment" */
-       time_t trigger;
-
-       /* Actual event occurrence to which this trigger corresponds */
-       time_t occur_start;
-       time_t occur_end;
-} ECalComponentAlarmInstance;
-
-/**
- * ECalComponentAlarms:
- * @comp: The actual alarm component
- * @alarms: (element-type ECalComponentAlarmInstance): List of #ECalComponentAlarmInstance structures
- *
- * Alarm trigger instances for a particular component
- **/
-typedef struct {
-       /* The actual component */
-       ECalComponent *comp;
-
-       /* List of ECalComponentAlarmInstance structures */
-       GSList *alarms;
-} ECalComponentAlarms;
-
-/**
- * ECalComponentAlarmAction:
- * @E_CAL_COMPONENT_ALARM_NONE: None
- * @E_CAL_COMPONENT_ALARM_AUDIO: Audio
- * @E_CAL_COMPONENT_ALARM_DISPLAY: Display message
- * @E_CAL_COMPONENT_ALARM_EMAIL: Email
- * @E_CAL_COMPONENT_ALARM_PROCEDURE: Procedure
- * @E_CAL_COMPONENT_ALARM_UNKNOWN: Unknown
- *
- * Alarm types
- **/
-typedef enum {
-       E_CAL_COMPONENT_ALARM_NONE,
-       E_CAL_COMPONENT_ALARM_AUDIO,
-       E_CAL_COMPONENT_ALARM_DISPLAY,
-       E_CAL_COMPONENT_ALARM_EMAIL,
-       E_CAL_COMPONENT_ALARM_PROCEDURE,
-       E_CAL_COMPONENT_ALARM_UNKNOWN
-} ECalComponentAlarmAction;
-
-/**
- * ECalComponentAlarmTriggerType:
- * @E_CAL_COMPONENT_ALARM_TRIGGER_NONE: None
- * @E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START: Relative to the start
- * @E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END: Relative to the end
- * @E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE: Absolute
- *
- * Whether a trigger is relative to the start or end of an event occurrence, or
- * whether it is specified to occur at an absolute time.
- */
-typedef enum {
-       E_CAL_COMPONENT_ALARM_TRIGGER_NONE,
-       E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START,
-       E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END,
-       E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE
-} ECalComponentAlarmTriggerType;
-
-/**
- * ECalComponentAlarmTrigger:
- * @type: An #ECalComponentAlarmTriggerType
- *
- * When the alarm is supposed to be triggered
- **/
-typedef struct {
-       ECalComponentAlarmTriggerType type;
-
-       union {
-               struct icaldurationtype rel_duration;
-               struct icaltimetype abs_time;
-       } u;
-} ECalComponentAlarmTrigger;
-
-/**
- * ECalComponentAlarmRepeat:
- * @repetitions: Number of extra repetitions, zero for none
- * @duration: Interval between repetitions
- *
- * Whether and how the alarm repeats.
- **/
-typedef struct {
-       /* Number of extra repetitions, zero for none */
-       gint repetitions;
-
-       /* Interval between repetitions */
-       struct icaldurationtype duration;
-} ECalComponentAlarmRepeat;
-
 gboolean       e_cal_component_has_alarms      (ECalComponent *comp);
 void           e_cal_component_add_alarm       (ECalComponent *comp,
                                                 ECalComponentAlarm *alarm);
@@ -718,69 +278,11 @@ void              e_cal_component_remove_alarm    (ECalComponent *comp,
 void           e_cal_component_remove_all_alarms
                                                (ECalComponent *comp);
 
-GList *                e_cal_component_get_alarm_uids  (ECalComponent *comp);
+GSList *       e_cal_component_get_alarm_uids  (ECalComponent *comp); /* gchar * */
 ECalComponentAlarm *
                e_cal_component_get_alarm       (ECalComponent *comp,
                                                 const gchar *auid);
-
-void           e_cal_component_alarms_free     (ECalComponentAlarms *alarms);
-
-/* ECalComponentAlarms */
-GType          e_cal_component_alarm_get_type  (void);
-ECalComponentAlarm *
-               e_cal_component_alarm_new       (void);
-ECalComponentAlarm *
-               e_cal_component_alarm_clone     (ECalComponentAlarm *alarm);
-void           e_cal_component_alarm_free      (ECalComponentAlarm *alarm);
-
-const gchar *  e_cal_component_alarm_get_uid   (ECalComponentAlarm *alarm);
-
-void           e_cal_component_alarm_get_action
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentAlarmAction *action);
-void           e_cal_component_alarm_set_action
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentAlarmAction action);
-
-void           e_cal_component_alarm_get_attach
-                                               (ECalComponentAlarm *alarm,
-                                                icalattach **attach);
-void           e_cal_component_alarm_set_attach
-                                               (ECalComponentAlarm *alarm,
-                                                icalattach *attach);
-
-void           e_cal_component_alarm_get_description
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentText *description);
-void           e_cal_component_alarm_set_description
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentText *description);
-
-void           e_cal_component_alarm_get_repeat
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentAlarmRepeat *repeat);
-void           e_cal_component_alarm_set_repeat
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentAlarmRepeat repeat);
-
-void           e_cal_component_alarm_get_trigger
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentAlarmTrigger *trigger);
-void           e_cal_component_alarm_set_trigger
-                                               (ECalComponentAlarm *alarm,
-                                                ECalComponentAlarmTrigger trigger);
-
-void           e_cal_component_alarm_get_attendee_list
-                                               (ECalComponentAlarm *alarm,
-                                                GSList **attendee_list);
-void           e_cal_component_alarm_set_attendee_list
-                                               (ECalComponentAlarm *alarm,
-                                                GSList *attendee_list);
-gboolean       e_cal_component_alarm_has_attendees
-                                               (ECalComponentAlarm *alarm);
-
-icalcomponent *        e_cal_component_alarm_get_icalcomponent
-                                               (ECalComponentAlarm *alarm);
+GSList *       e_cal_component_get_all_alarms  (ECalComponent *comp); /* ECalComponentAlarm * */
 
 G_END_DECLS
 
diff --git a/src/calendar/libecal/e-cal-enums.h b/src/calendar/libecal/e-cal-enums.h
new file mode 100644
index 000000000..18af5dd26
--- /dev/null
+++ b/src/calendar/libecal/e-cal-enums.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Federico Mena-Quintero <federico ximian com>
+ *          JP Rosevear <jpr ximian com>
+ */
+
+#if !defined (__LIBECAL_H_INSIDE__) && !defined (LIBECAL_COMPILATION)
+#error "Only <libecal/libecal.h> should be included directly."
+#endif
+
+#ifndef E_CAL_ENUMS_H
+#define E_CAL_ENUMS_H
+
+G_BEGIN_DECLS
+
+/**
+ * ECalClientSourceType:
+ * @E_CAL_CLIENT_SOURCE_TYPE_EVENTS: Events calander
+ * @E_CAL_CLIENT_SOURCE_TYPE_TASKS: Task list calendar
+ * @E_CAL_CLIENT_SOURCE_TYPE_MEMOS: Memo list calendar
+ * @E_CAL_CLIENT_SOURCE_TYPE_LAST: Artificial 'last' value of the enum
+ *
+ * Indicates the type of calendar
+ *
+ * Since: 3.2
+ **/
+typedef enum {
+       E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
+       E_CAL_CLIENT_SOURCE_TYPE_TASKS,
+       E_CAL_CLIENT_SOURCE_TYPE_MEMOS,
+       E_CAL_CLIENT_SOURCE_TYPE_LAST  /*< skip >*/
+} ECalClientSourceType;
+
+/**
+ * ECalObjModType:
+ * @E_CAL_OBJ_MOD_THIS: Modify this component
+ * @E_CAL_OBJ_MOD_THIS_AND_PRIOR: Modify this component and all prior occurrances
+ * @E_CAL_OBJ_MOD_THIS_AND_FUTURE: Modify this component and all future occurrances
+ * @E_CAL_OBJ_MOD_ALL: Modify all occurrances of this component
+ * @E_CAL_OBJ_MOD_ONLY_THIS: Modify only this component
+ *
+ * Indicates the type of modification made to a calendar
+ *
+ * Since: 3.8
+ **/
+typedef enum {
+       E_CAL_OBJ_MOD_THIS = 1 << 0,
+       E_CAL_OBJ_MOD_THIS_AND_PRIOR = 1 << 1,
+       E_CAL_OBJ_MOD_THIS_AND_FUTURE = 1 << 2,
+       E_CAL_OBJ_MOD_ALL = 0x07,
+       E_CAL_OBJ_MOD_ONLY_THIS = 1 << 3
+} ECalObjModType;
+
+/**
+ * ECalComponentVType:
+ * @E_CAL_COMPONENT_NO_TYPE: Unknown or unsupported component type
+ * @E_CAL_COMPONENT_EVENT: vEvent type
+ * @E_CAL_COMPONENT_TODO: vTodo type
+ * @E_CAL_COMPONENT_JOURNAL: vJournal type
+ * @E_CAL_COMPONENT_FREEBUSY: vFreeBusy type
+ * @E_CAL_COMPONENT_TIMEZONE: vTimezone type
+ *
+ * Types of calendar components to be stored by a ECalComponent, as per RFC 2445.
+ * We don't put the alarm component type here since we store alarms as separate
+ * structures inside the other "real" components.
+ **/
+typedef enum {
+       E_CAL_COMPONENT_NO_TYPE,
+       E_CAL_COMPONENT_EVENT,
+       E_CAL_COMPONENT_TODO,
+       E_CAL_COMPONENT_JOURNAL,
+       E_CAL_COMPONENT_FREEBUSY,
+       E_CAL_COMPONENT_TIMEZONE
+} ECalComponentVType;
+
+/**
+ * ECalComponentClassification:
+ * @E_CAL_COMPONENT_CLASS_NONE: None
+ * @E_CAL_COMPONENT_CLASS_PUBLIC: Public
+ * @E_CAL_COMPONENT_CLASS_PRIVATE: Private
+ * @E_CAL_COMPONENT_CLASS_CONFIDENTIAL: Confidential
+ * @E_CAL_COMPONENT_CLASS_UNKNOWN: Unknown
+ *
+ * CLASSIFICATION property
+ **/
+typedef enum {
+       E_CAL_COMPONENT_CLASS_NONE,
+       E_CAL_COMPONENT_CLASS_PUBLIC,
+       E_CAL_COMPONENT_CLASS_PRIVATE,
+       E_CAL_COMPONENT_CLASS_CONFIDENTIAL,
+       E_CAL_COMPONENT_CLASS_UNKNOWN
+} ECalComponentClassification;
+
+/**
+ * ECalComponentPeriodKind:
+ * @E_CAL_COMPONENT_PERIOD_DATETIME: Date and time
+ * @E_CAL_COMPONENT_PERIOD_DURATION: Duration
+ *
+ * Way in which a period of time is specified
+ **/
+typedef enum {
+       E_CAL_COMPONENT_PERIOD_DATETIME,
+       E_CAL_COMPONENT_PERIOD_DURATION
+} ECalComponentPeriodKind;
+
+/**
+ * ECalComponentRangeKind:
+ * @E_CAL_COMPONENT_RANGE_SINGLE: Single
+ * @E_CAL_COMPONENT_RANGE_THISPRIOR: This and prior
+ * @E_CAL_COMPONENT_RANGE_THISFUTURE: This and future
+ *
+ * The kind of range
+ **/
+typedef enum {
+       E_CAL_COMPONENT_RANGE_SINGLE,
+       E_CAL_COMPONENT_RANGE_THISPRIOR,
+       E_CAL_COMPONENT_RANGE_THISFUTURE
+} ECalComponentRangeKind;
+
+/**
+ * ECalComponentTransparency:
+ * @E_CAL_COMPONENT_TRANSP_NONE: None
+ * @E_CAL_COMPONENT_TRANSP_TRANSPARENT: Transparent
+ * @E_CAL_COMPONENT_TRANSP_OPAQUE: Opaque
+ * @E_CAL_COMPONENT_TRANSP_UNKNOWN: Unknown
+ *
+ * Time transparency
+ **/
+typedef enum {
+       E_CAL_COMPONENT_TRANSP_NONE,
+       E_CAL_COMPONENT_TRANSP_TRANSPARENT,
+       E_CAL_COMPONENT_TRANSP_OPAQUE,
+       E_CAL_COMPONENT_TRANSP_UNKNOWN
+} ECalComponentTransparency;
+
+/**
+ * ECalComponentAlarmAction:
+ * @E_CAL_COMPONENT_ALARM_NONE: None
+ * @E_CAL_COMPONENT_ALARM_AUDIO: Audio
+ * @E_CAL_COMPONENT_ALARM_DISPLAY: Display message
+ * @E_CAL_COMPONENT_ALARM_EMAIL: Email
+ * @E_CAL_COMPONENT_ALARM_PROCEDURE: Procedure
+ * @E_CAL_COMPONENT_ALARM_UNKNOWN: Unknown
+ *
+ * Alarm types
+ **/
+typedef enum {
+       E_CAL_COMPONENT_ALARM_NONE,
+       E_CAL_COMPONENT_ALARM_AUDIO,
+       E_CAL_COMPONENT_ALARM_DISPLAY,
+       E_CAL_COMPONENT_ALARM_EMAIL,
+       E_CAL_COMPONENT_ALARM_PROCEDURE,
+       E_CAL_COMPONENT_ALARM_UNKNOWN
+} ECalComponentAlarmAction;
+
+/**
+ * ECalComponentAlarmTriggerkind:
+ * @E_CAL_COMPONENT_ALARM_TRIGGER_NONE: None
+ * @E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START: Relative to the start
+ * @E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END: Relative to the end
+ * @E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE: Absolute
+ *
+ * Whether a trigger is relative to the start or end of an event occurrence, or
+ * whether it is specified to occur at an absolute time.
+ */
+typedef enum {
+       E_CAL_COMPONENT_ALARM_TRIGGER_NONE,
+       E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START,
+       E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END,
+       E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE
+} ECalComponentAlarmTriggerKind;
+
+/**
+ * ECalRecurDescribeRecurrenceFlags:
+ * @E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_NONE: no extra flags, either returns %NULL or the recurrence 
description,
+ *    something like "Every 2 weeks..."
+ * @E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_PREFIXED: either returns %NULL or the recurrence description 
prefixed
+ *    with text like "The meeting recurs", forming something like "The meeting recurs every 2 weeks..."
+ * @E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_FALLBACK: returns %NULL only if the component doesn't recur,
+ *    otherwise returns either the recurrence description or at least text like "The meeting recurs"
+ *
+ * Influences behaviour of e_cal_recur_describe_recurrence().
+ *
+ * Since: 3.30
+ **/
+typedef enum { /*< flags >*/
+       E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_NONE       = 0,
+       E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_PREFIXED   = (1 << 0),
+       E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_FALLBACK   = (1 << 1)
+} ECalRecurDescribeRecurrenceFlags;
+
+/**
+ * ECalOperationFlags:
+ * @E_CAL_OPERATION_FLAG_NONE: no operation flags defined
+ * @E_CAL_OPERATION_FLAG_CONFLICT_FAIL: conflict resolution mode, to fail and do not
+ *    do any changes, when a conflict is detected
+ * @E_CAL_OPERATION_FLAG_CONFLICT_USE_NEWER: conflict resolution mode, to use newer
+ *    of the local and the server side data, when a conflict is detected
+ * @E_CAL_OPERATION_FLAG_CONFLICT_KEEP_SERVER: conflict resolution mode, to use
+ *    the server data (and local changed), when a conflict is detected
+ * @E_CAL_OPERATION_FLAG_CONFLICT_KEEP_LOCAL: conflict resolution mode, to use
+ *    local data (and always overwrite server data), when a conflict is detected
+ * @E_CAL_OPERATION_FLAG_CONFLICT_WRITE_COPY: conflict resolution mode, to create
+ *    a copy of the data, when a conflict is detected
+ * @E_CAL_OPERATION_FLAG_DISABLE_ITIP_MESSAGE: request to disable send of an iTip
+ *    message by the server; this works only for servers which support iTip handling
+ *
+ * Calendar operation flags, to specify behavior in certain situations. The conflict
+ * resolution mode flags cannot be combined together, where the @E_CAL_OPERATION_FLAG_CONFLICT_KEEP_LOCAL
+ * is the default behavior (and it is used when no other conflict resolution flag is set).
+ * The flags can be ignored when the operation or the backend don't support it.
+ *
+ * Since: 3.36
+ **/
+typedef enum { /*< flags >*/
+       E_CAL_OPERATION_FLAG_NONE                       = 0,
+       E_CAL_OPERATION_FLAG_CONFLICT_FAIL              = (1 << 0),
+       E_CAL_OPERATION_FLAG_CONFLICT_USE_NEWER         = (1 << 1),
+       E_CAL_OPERATION_FLAG_CONFLICT_KEEP_SERVER       = (1 << 2),
+       E_CAL_OPERATION_FLAG_CONFLICT_KEEP_LOCAL        = 0,
+       E_CAL_OPERATION_FLAG_CONFLICT_WRITE_COPY        = (1 << 3),
+       E_CAL_OPERATION_FLAG_DISABLE_ITIP_MESSAGE       = (1 << 4)
+} ECalOperationFlags;
+
+G_END_DECLS
+
+#endif /* E_CAL_ENUMS_H */
diff --git a/src/calendar/libecal/e-cal-recur.c b/src/calendar/libecal/e-cal-recur.c
index 34ca5ca01..fb81e84da 100644
--- a/src/calendar/libecal/e-cal-recur.c
+++ b/src/calendar/libecal/e-cal-recur.c
@@ -30,11 +30,11 @@
 #include "e-cal-client.h"
 
 static gint
-e_timetype_compare (gconstpointer a,
-                   gconstpointer b)
+e_timetype_compare (gconstpointer aa,
+                   gconstpointer bb)
 {
-       const struct icaltimetype *tta = a;
-       const struct icaltimetype *ttb = b;
+       ICalTime *tta = (ICalTime *) aa;
+       ICalTime *ttb = (ICalTime *) bb;
 
        if (!tta || !ttb) {
                if (tta == ttb)
@@ -44,18 +44,18 @@ e_timetype_compare (gconstpointer a,
                return 1;
        }
 
-       if (tta->is_date || ttb->is_date)
-               return icaltime_compare_date_only (*tta, *ttb);
+       if (i_cal_time_is_date (tta) || i_cal_time_is_date (ttb))
+               return i_cal_time_compare_date_only (tta, ttb);
 
-       return icaltime_compare (*tta, *ttb);
+       return i_cal_time_compare (tta, ttb);
 }
 
 static gint
 e_timetype_compare_without_date (gconstpointer a,
                                 gconstpointer b)
 {
-       const struct icaltimetype *tta = a;
-       const struct icaltimetype *ttb = b;
+       ICalTime *tta = (ICalTime *) a;
+       ICalTime *ttb = (ICalTime *) b;
 
        if (!tta || !ttb) {
                if (tta == ttb)
@@ -65,56 +65,61 @@ e_timetype_compare_without_date (gconstpointer a,
                return 1;
        }
 
-       return icaltime_compare (*tta, *ttb);
+       return i_cal_time_compare (tta, ttb);
 }
 
 static guint
 e_timetype_hash (gconstpointer v)
 {
-       const struct icaltimetype *ttv = v;
-       struct icaltimetype tt;
+       const ICalTime *ttv = v;
+       ICalTime *tt;
+       guint value;
 
        if (!ttv)
                return 0;
 
-       tt = icaltime_convert_to_zone (*ttv, icaltimezone_get_utc_timezone ());
+       tt = i_cal_time_convert_to_zone (ttv, i_cal_timezone_get_utc_timezone ());
 
-       return g_int_hash (&(tt.year)) ^
-               g_int_hash (&(tt.month)) ^
-               g_int_hash (&(tt.day));
+       value = (i_cal_time_get_year (tt) * 10000) +
+               (i_cal_time_get_month (tt) * 100) +
+               i_cal_time_get_day (tt);
+
+       g_clear_object (&tt);
+
+       return value;
 }
 
-typedef struct _EInstanceTime
-{
-       struct icaltimetype tt;
+typedef struct _EInstanceTime {
+       ICalTime *tt;
        gboolean duration_set;
        gint duration_days;
        gint duration_seconds;
 } EInstanceTime;
 
 static EInstanceTime *
-e_instance_time_new (const struct icaltimetype *tt,
-                    const struct icaldurationtype *duration)
+e_instance_time_new (const ICalTime *tt,
+                    const ICalDuration *pduration)
 {
        EInstanceTime *it;
+       ICalDuration *duration = (ICalDuration *) pduration;
 
        if (!tt)
                return NULL;
 
        it = g_new0 (EInstanceTime, 1);
 
-       it->tt = *tt;
-       it->duration_set = duration && !icaldurationtype_is_null_duration (*duration);
+       it->tt = i_cal_time_new_clone (tt);
+       it->duration_set = duration && !i_cal_duration_is_null_duration (duration);
 
        if (it->duration_set) {
                gint64 dur;
 
-               g_warn_if_fail (!duration->is_neg);
+               g_warn_if_fail (!i_cal_duration_is_neg (duration));
 
-               dur = (gint64) (duration->weeks * 7 + duration->days) * (24 * 60 * 60) +
-                       (duration->hours * 60 * 60) +
-                       (duration->minutes * 60) +
-                       duration->seconds;
+               dur = (gint64) (i_cal_duration_get_weeks (duration) * 7 + i_cal_duration_get_days (duration)) 
* (24 * 60 * 60) +
+                       (i_cal_duration_get_hours (duration) * 60 * 60) +
+                       (i_cal_duration_get_minutes (duration) * 60) +
+                       i_cal_duration_get_seconds (duration);
 
                it->duration_days = dur / (24 * 60 * 60);
                it->duration_seconds = dur % (24 * 60 * 60);
@@ -123,6 +128,17 @@ e_instance_time_new (const struct icaltimetype *tt,
        return it;
 }
 
+static void
+e_instance_time_free (gpointer ptr)
+{
+       EInstanceTime *it = ptr;
+
+       if (it) {
+               g_clear_object (&it->tt);
+               g_free (it);
+       }
+}
+
 static gint
 e_instance_time_compare (gconstpointer a,
                         gconstpointer b)
@@ -140,7 +156,7 @@ e_instance_time_compare (gconstpointer a,
                return 1;
        }
 
-       return e_timetype_compare (&(ait->tt), &(bit->tt));
+       return e_timetype_compare (ait->tt, bit->tt);
 }
 
 static guint
@@ -151,7 +167,7 @@ e_instance_time_hash (gconstpointer v)
        if (!it)
                return 0;
 
-       return e_timetype_hash (&it->tt);
+       return e_timetype_hash (it->tt);
 }
 
 static gboolean
@@ -171,17 +187,19 @@ e_instance_time_compare_ptr_array (gconstpointer a,
 }
 
 static gboolean
-ensure_timezone (icalcomponent *comp,
-                struct icaltimetype *tt,
-                icalproperty_kind prop_kind,
-                icalproperty *prop,
+ensure_timezone (ICalComponent *comp,
+                ICalTime *tt,
+                ICalPropertyKind prop_kind,
+                ICalProperty *prop,
                 ECalRecurResolveTimezoneCb get_tz_callback,
                 gpointer get_tz_callback_user_data,
-                icaltimezone *default_timezone,
+                ICalTimezone *default_timezone,
+                GHashTable **pcached_zones,
                 GCancellable *cancellable,
                 GError **error)
 {
-       icalparameter *param;
+       ICalParameter *param;
+       ICalTimezone *zone;
        const gchar *tzid;
        GError *local_error = NULL;
 
@@ -193,37 +211,64 @@ ensure_timezone (icalcomponent *comp,
 
        /* Do not trust the 'zone' set on the structure, as it can come from
           a different icalcomponent and cause use-after-free. */
-       if (tt->zone != icaltimezone_get_utc_timezone ())
-               tt->zone = NULL;
+       zone = i_cal_time_get_timezone (tt);
+       if (zone != i_cal_timezone_get_utc_timezone ())
+               i_cal_time_set_timezone (tt, NULL);
 
-       if (icaltime_is_utc (*tt))
+       if (i_cal_time_is_utc (tt))
                return TRUE;
 
-       tt->zone = default_timezone;
+       i_cal_time_set_timezone (tt, default_timezone);
 
-       if (tt->is_date)
+       if (i_cal_time_is_date (tt))
                return TRUE;
 
        if (!prop)
-               prop = icalcomponent_get_first_property (comp, prop_kind);
+               prop = i_cal_component_get_first_property (comp, prop_kind);
+       else
+               g_object_ref (prop);
        if (!prop)
                return TRUE;
 
-       param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
-       if (!param)
+       param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+       if (!param) {
+               g_object_unref (prop);
                return TRUE;
+       }
 
-       tzid = icalparameter_get_tzid (param);
-       if (!tzid || !*tzid)
+       tzid = i_cal_parameter_get_tzid (param);
+       if (!tzid || !*tzid) {
+               g_object_unref (param);
+               g_object_unref (prop);
                return TRUE;
+       }
 
-       if (get_tz_callback)
-               tt->zone = get_tz_callback (tzid, get_tz_callback_user_data, cancellable, &local_error);
-       else
-               tt->zone = NULL;
+       if (get_tz_callback) {
+               ICalTimezone *zone = NULL;
 
-       if (!tt->zone)
-               tt->zone = default_timezone;
+               if (*pcached_zones)
+                       zone = g_hash_table_lookup (*pcached_zones, tzid);
+
+               if (!zone) {
+                       zone = get_tz_callback (tzid, get_tz_callback_user_data, cancellable, &local_error);
+                       if (zone) {
+                               if (!*pcached_zones)
+                                       *pcached_zones = g_hash_table_new_full (g_str_hash, g_str_equal, 
g_free, g_object_unref);
+
+                               g_hash_table_insert (*pcached_zones, g_strdup (tzid), g_object_ref (zone));
+                       }
+               }
+
+               i_cal_time_set_timezone (tt, zone);
+       } else
+               i_cal_time_set_timezone (tt, NULL);
+
+       zone = i_cal_time_get_timezone (tt);
+       if (!zone)
+               i_cal_time_set_timezone (tt, default_timezone);
+
+       g_object_unref (param);
+       g_object_unref (prop);
 
        /* Timezone not found is not a fatal error */
        if (g_error_matches (local_error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND))
@@ -238,72 +283,79 @@ ensure_timezone (icalcomponent *comp,
 }
 
 static void
-apply_duration (struct icaltimetype *tt,
-               const struct icaldurationtype *duration)
+apply_duration (ICalTime *tt,
+               ICalDuration *duration)
 {
        gint64 days, seconds;
 
        g_return_if_fail (tt != NULL);
        g_return_if_fail (duration != NULL);
 
-       if (icaldurationtype_is_null_duration (*duration))
+       if (i_cal_duration_is_null_duration (duration))
                return;
 
-       days = (gint64) duration->days + 7 * ((gint64) duration->weeks);
-       seconds = ((gint64) duration->hours * 60 * 60) + ((gint64) duration->minutes * 60) + 
duration->seconds;
+       days = (gint64) i_cal_duration_get_days (duration) + 7 * ((gint64) i_cal_duration_get_weeks 
(duration));
+       seconds = ((gint64) i_cal_duration_get_hours (duration) * 60 * 60) +
+                 ((gint64) i_cal_duration_get_minutes (duration) * 60) +
+                 i_cal_duration_get_seconds (duration);
        days += seconds / (24 * 60 * 60);
        seconds = seconds % (24 * 60 * 60);
 
-       if (seconds != 0) {
-               tt->is_date = 0;
-       }
+       if (seconds != 0)
+               i_cal_time_set_is_date (tt, FALSE);
 
-       icaltime_adjust (tt,
-               (duration->is_neg ? -1 : 1) * ((gint) days),
+       i_cal_time_adjust (tt,
+               (i_cal_duration_is_neg (duration) ? -1 : 1) * ((gint) days),
                0, 0,
-               (duration->is_neg ? -1 : 1) * ((gint) seconds));
+               (i_cal_duration_is_neg (duration) ? -1 : 1) * ((gint) seconds));
 }
 
 static gboolean
-intersects_interval (const struct icaltimetype *tt,
-                    const struct icaldurationtype *duration,
+intersects_interval (const ICalTime *tt,
+                    const ICalDuration *duration,
                     gint default_duration_days,
                     gint default_duration_seconds,
-                    const struct icaltimetype *interval_start,
-                    const struct icaltimetype *interval_end)
+                    const ICalTime *interval_start,
+                    const ICalTime *interval_end)
 {
-       struct icaltimetype ttstart, ttend;
+       ICalTime *ttstart, *ttend;
+       gboolean res;
 
        if (!tt || !interval_start || !interval_end)
                return FALSE;
 
-       ttstart = *tt;
-       ttend = ttstart;
+       ttstart = i_cal_time_new_clone (tt);
+       ttend = i_cal_time_new_clone (ttstart);
 
-       if (duration && !icaldurationtype_is_null_duration (*duration)) {
-               apply_duration (&ttend, duration);
+       if (duration && !i_cal_duration_is_null_duration ((ICalDuration *) duration)) {
+               apply_duration (ttend, (ICalDuration *) duration);
        } else if (default_duration_days || default_duration_seconds) {
                if (default_duration_seconds != 0) {
-                       ttend.is_date = 0;
+                       i_cal_time_set_is_date (ttend, FALSE);
                }
 
-               icaltime_adjust (&ttend, default_duration_days, 0, 0, default_duration_seconds);
+               i_cal_time_adjust (ttend, default_duration_days, 0, 0, default_duration_seconds);
        }
 
-       return e_timetype_compare_without_date (&ttstart, interval_end) < 0 &&
-              e_timetype_compare_without_date (interval_start, &ttend) < 0;
+       res = e_timetype_compare_without_date (ttstart, interval_end) < 0 &&
+             e_timetype_compare_without_date (interval_start, ttend) < 0;
+
+       g_clear_object (&ttstart);
+       g_clear_object (&ttend);
+
+       return res;
 }
 
 /**
  * e_cal_recur_generate_instances_sync:
- * @comp: an icalcomponent
+ * @icalcomp: an #ICalComponent
  * @interval_start: an interval start, for which generate instances
  * @interval_end: an interval end, for which generate instances
  * @callback: (scope call): a callback to be called for each instance
  * @callback_user_data: (closure callback): user data for @callback
  * @get_tz_callback: (scope call): a callback to call when resolving timezone
  * @get_tz_callback_user_data: (closure get_tz_callback): user data for @get_tz_callback
- * @default_timezone: a default icaltimezone
+ * @default_timezone: a default #ICalTimezone
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -317,7 +369,7 @@ intersects_interval (const struct icaltimetype *tt,
  * The start and end times are required valid times, start before end time.
  *
  * The @get_tz_callback is used to resolve references to timezones. It is passed
- * a TZID and should return the icaltimezone * corresponding to that TZID. We need to
+ * a TZID and should return the ICalTimezone * corresponding to that TZID. We need to
  * do this as we access timezones in different ways on the client & server.
  *
  * The default_timezone argument is used for DTSTART or DTEND properties that
@@ -328,79 +380,95 @@ intersects_interval (const struct icaltimetype *tt,
  * Since: 3.20
  **/
 gboolean
-e_cal_recur_generate_instances_sync (icalcomponent *comp,
-                                    struct icaltimetype interval_start,
-                                    struct icaltimetype interval_end,
+e_cal_recur_generate_instances_sync (ICalComponent *icalcomp,
+                                    ICalTime *interval_start,
+                                    ICalTime *interval_end,
                                     ECalRecurInstanceCb callback,
                                     gpointer callback_user_data,
                                     ECalRecurResolveTimezoneCb get_tz_callback,
                                     gpointer get_tz_callback_user_data,
-                                    icaltimezone *default_timezone,
+                                    ICalTimezone *default_timezone,
                                     GCancellable *cancellable,
                                     GError **error)
 {
-       struct icaltimetype dtstart, dtend, next;
+       ICalTime *dtstart, *dtend, *next;
+       ICalProperty *prop;
        gint64 duration_days, duration_seconds;
-       icalproperty *prop;
-       GHashTable *times;
+       GHashTable *times, *cached_zones = NULL;
        gboolean success = TRUE;
 
-       g_return_val_if_fail (comp != NULL, FALSE);
+       g_return_val_if_fail (icalcomp != NULL, FALSE);
        g_return_val_if_fail (callback != NULL, FALSE);
-       g_return_val_if_fail (icaltime_compare (interval_start, interval_end) < 0, FALSE);
+       g_return_val_if_fail (interval_start != NULL, FALSE);
+       g_return_val_if_fail (interval_end != NULL, FALSE);
+       g_return_val_if_fail (i_cal_time_compare (interval_start, interval_end) < 0, FALSE);
 
        if (g_cancellable_set_error_if_cancelled (cancellable, error))
                return FALSE;
 
-       times = g_hash_table_new_full (e_instance_time_hash, e_instance_time_equal, g_free, NULL);
+       times = g_hash_table_new_full (e_instance_time_hash, e_instance_time_equal, e_instance_time_free, 
NULL);
 
-       dtstart = icalcomponent_get_dtstart (comp);
-       success = ensure_timezone (comp, &dtstart, ICAL_DTSTART_PROPERTY, NULL,
-               get_tz_callback, get_tz_callback_user_data, default_timezone, cancellable, error);
+       dtstart = i_cal_component_get_dtstart (icalcomp);
+       success = ensure_timezone (icalcomp, dtstart, I_CAL_DTSTART_PROPERTY, NULL,
+               get_tz_callback, get_tz_callback_user_data, default_timezone, &cached_zones, cancellable, 
error);
 
        duration_seconds = 0;
-       dtend = icalcomponent_get_dtend (comp);
+       dtend = i_cal_component_get_dtend (icalcomp);
 
-       if (icaltime_is_null_time (dtend)) {
-               dtend = icalcomponent_get_due (comp);
-               if (icaltime_is_null_time (dtend)) {
-                       struct icaldurationtype comp_duration;
+       if (!dtend || i_cal_time_is_null_time (dtend)) {
+               g_clear_object (&dtend);
 
-                       comp_duration = icalcomponent_get_duration (comp);
+               dtend = i_cal_component_get_due (icalcomp);
+               if (!dtend || i_cal_time_is_null_time (dtend)) {
+                       ICalDuration *comp_duration;
 
-                       if (!icaldurationtype_is_null_duration (comp_duration)) {
-                               dtend = dtstart;
+                       g_clear_object (&dtend);
 
-                               apply_duration (&dtend, &comp_duration);
+                       comp_duration = i_cal_component_get_duration (icalcomp);
+
+                       if (comp_duration && !i_cal_duration_is_null_duration (comp_duration)) {
+                               dtend = i_cal_time_new_clone (dtstart);
+
+                               apply_duration (dtend, comp_duration);
                        }
+
+                       g_clear_object (&comp_duration);
                }
 
                /* If there is no DTEND, then if DTSTART is a DATE-TIME value
                 * we use the same time (so we have a single point in time).
                 * If DTSTART is a DATE value we add 1 day. */
-               if (icaltime_is_null_time (dtend)) {
-                       dtend = dtstart;
+               if (!dtend || i_cal_time_is_null_time (dtend)) {
+                       g_clear_object (&dtend);
+                       dtend = i_cal_time_new_clone (dtstart);
 
-                       if (dtend.is_date)
-                               icaltime_adjust (&dtend, 1, 0, 0, 0);
+                       if (i_cal_time_is_date (dtend))
+                               i_cal_time_adjust (dtend, 1, 0, 0, 0);
                }
        } else {
                /* If both DTSTART and DTEND are DATE values, and they are the
                 * same day, we add 1 day to DTEND. This means that most
                 * events created with the old Evolution behavior will still
                 * work OK. I'm not sure what Outlook does in this case. */
-               if (dtstart.is_date && dtend.is_date) {
-                       if (icaltime_compare_date_only (dtstart, dtend) == 0) {
-                               icaltime_adjust (&dtend, 1, 0, 0, 0);
+               if (i_cal_time_is_date (dtstart) && i_cal_time_is_date (dtend)) {
+                       if (i_cal_time_compare_date_only (dtstart, dtend) == 0) {
+                               i_cal_time_adjust (dtend, 1, 0, 0, 0);
                        }
                }
        }
 
-       if (success && !icaltime_is_null_time (dtend)) {
-               success = ensure_timezone (comp, &dtend, ICAL_DTEND_PROPERTY, NULL,
-                       get_tz_callback, get_tz_callback_user_data, default_timezone, cancellable, error);
-               duration_seconds = (gint64) icaltime_as_timet_with_zone (dtend, dtend.zone) -
-                       (gint64) icaltime_as_timet_with_zone (dtstart, dtstart.zone);
+       if (success && dtend && !i_cal_time_is_null_time (dtend)) {
+               ICalTimezone *dtstart_zone, *dtend_zone;
+
+               success = ensure_timezone (icalcomp, dtend, I_CAL_DTEND_PROPERTY, NULL,
+                       get_tz_callback, get_tz_callback_user_data, default_timezone, &cached_zones, 
cancellable, error);
+
+               dtstart_zone = i_cal_time_get_timezone (dtstart);
+               dtend_zone = i_cal_time_get_timezone (dtend);
+
+               duration_seconds = (gint64) i_cal_time_as_timet_with_zone (dtend, dtend_zone) -
+                       (gint64) i_cal_time_as_timet_with_zone (dtstart, dtstart_zone);
+
                if (duration_seconds < 0)
                        duration_seconds = 0;
        }
@@ -408,158 +476,209 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
        duration_days = duration_seconds / (24 * 60 * 60);
        duration_seconds = duration_seconds % (24 * 60 * 60);
 
-       if (success && intersects_interval (&dtstart, NULL, duration_days, duration_seconds, &interval_start, 
&interval_end)) {
-               g_hash_table_insert (times, e_instance_time_new (&dtstart, NULL), NULL);
+       if (success && intersects_interval (dtstart, NULL, duration_days, duration_seconds, interval_start, 
interval_end)) {
+               g_hash_table_insert (times, e_instance_time_new (dtstart, NULL), NULL);
        }
 
        /* If this is a detached instance, then use only the DTSTART value */
-       if (success && icaltime_is_null_time (icalcomponent_get_recurrenceid (comp))) {
-               for (prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
+       if (success && !e_cal_util_component_has_property (icalcomp, I_CAL_RECURRENCEID_PROPERTY)) {
+               ICalTimezone *dtstart_zone = i_cal_time_get_timezone (dtstart);
+
+               for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_RRULE_PROPERTY);
                     prop && success;
-                    prop = icalcomponent_get_next_property (comp, ICAL_RRULE_PROPERTY)) {
-                       struct icalrecurrencetype rrule = icalproperty_get_rrule (prop);
-                       icalrecur_iterator *riter;
-
-                       if (!icaltime_is_null_time (rrule.until)) {
-                               success = ensure_timezone (comp, &rrule.until, 0, prop,
-                                       get_tz_callback, get_tz_callback_user_data, (icaltimezone *) 
dtstart.zone,
-                                       cancellable, error);
-                               if (!success)
+                    g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_RRULE_PROPERTY)) {
+                       ICalRecurrence *rrule = i_cal_property_get_rrule (prop);
+                       ICalRecurIterator *riter;
+                       ICalTime *rrule_until;
+
+                       rrule_until = i_cal_recurrence_get_until (rrule);
+
+                       if (rrule_until && !i_cal_time_is_null_time (rrule_until)) {
+                               success = ensure_timezone (icalcomp, rrule_until, 0, prop,
+                                       get_tz_callback, get_tz_callback_user_data, dtstart_zone,
+                                       &cached_zones, cancellable, error);
+                               if (!success) {
+                                       g_clear_object (&rrule_until);
+                                       g_clear_object (&rrule);
                                        break;
+                               }
                        }
 
-                       if (!icaltime_is_null_time (rrule.until) &&
-                           rrule.until.is_date && !dtstart.is_date) {
-                               icaltime_adjust (&rrule.until, 1, 0, 0, 0);
-                               rrule.until.is_date = 0;
-                               rrule.until.hour = 0;
-                               rrule.until.minute = 0;
-                               rrule.until.second = 0;
+                       if (rrule_until && !i_cal_time_is_null_time (rrule_until) &&
+                           i_cal_time_is_date (rrule_until) && !i_cal_time_is_date (dtstart)) {
+                               i_cal_time_adjust (rrule_until, 1, 0, 0, 0);
+                               i_cal_time_set_is_date (rrule_until, FALSE);
+                               i_cal_time_set_time (rrule_until, 0, 0, 0);
 
-                               if (!rrule.until.zone && !icaltime_is_utc (rrule.until))
-                                       rrule.until.zone = dtstart.zone;
+                               if (!i_cal_time_get_timezone (rrule_until) && !i_cal_time_is_utc 
(rrule_until))
+                                       i_cal_time_set_timezone (rrule_until, dtstart_zone);
                        }
 
-                       riter = icalrecur_iterator_new (rrule, dtstart);
+                       if (rrule_until && !i_cal_time_is_null_time (rrule_until))
+                               i_cal_recurrence_set_until (rrule, rrule_until);
+                       g_clear_object (&rrule_until);
+
+                       riter = i_cal_recur_iterator_new (rrule, dtstart);
                        if (riter) {
-                               struct icaltimetype prev = icaltime_null_time ();
+                               ICalTime *prev = NULL;
 
-                               for (next = icalrecur_iterator_next (riter);
-                                    !icaltime_is_null_time (next) && icaltime_compare (next, interval_end) 
<= 0;
-                                    next = icalrecur_iterator_next (riter)) {
-                                       if (!icaltime_is_null_time (prev) &&
-                                           icaltime_compare (next, prev) == 0)
+                               for (next = i_cal_recur_iterator_next (riter);
+                                    next && !i_cal_time_is_null_time (next) && i_cal_time_compare (next, 
interval_end) <= 0;
+                                    g_object_unref (next), next = i_cal_recur_iterator_next (riter)) {
+                                       if (prev && !i_cal_time_is_null_time (prev) &&
+                                           i_cal_time_compare (next, prev) == 0)
                                                break;
-                                       prev = next;
 
-                                       if (intersects_interval (&next, NULL, duration_days, 
duration_seconds, &interval_start, &interval_end)) {
-                                               g_hash_table_insert (times, e_instance_time_new (&next, 
NULL), NULL);
+                                       g_clear_object (&prev);
+                                       prev = i_cal_time_new_clone (next);
+
+                                       if (intersects_interval (next, NULL, duration_days, duration_seconds, 
interval_start, interval_end)) {
+                                               g_hash_table_insert (times, e_instance_time_new (next, NULL), 
NULL);
                                        }
                                }
 
-                               icalrecur_iterator_free (riter);
+                               g_clear_object (&riter);
+                               g_clear_object (&prev);
+                               g_clear_object (&next);
                        }
+
+                       g_clear_object (&rrule);
                }
 
-               for (prop = icalcomponent_get_first_property (comp, ICAL_RDATE_PROPERTY);
+               g_clear_object (&prop);
+
+               for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_RDATE_PROPERTY);
                     prop && success;
-                    prop = icalcomponent_get_next_property (comp, ICAL_RDATE_PROPERTY)) {
-                       struct icaldatetimeperiodtype rdate = icalproperty_get_rdate (prop);
-                       struct icaltimetype tt = icaltime_null_time ();
-                       struct icaldurationtype duration = icaldurationtype_null_duration ();
-
-                       if (!icaltime_is_null_time (rdate.time)) {
-                               tt = rdate.time;
-                       } else if (!icalperiodtype_is_null_period (rdate.period)) {
-                               tt = rdate.period.start;
-
-                               if (!icaltime_is_null_time (rdate.period.end)) {
-                                       time_t diff;
-
-                                       diff = icaltime_as_timet (rdate.period.end) - icaltime_as_timet 
(rdate.period.start);
-                                       if (diff < 0) {
-                                               duration.is_neg = 1;
-                                               diff = diff * (-1);
+                    g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_RDATE_PROPERTY)) {
+                       ICalDatetimeperiod *rdate = i_cal_property_get_rdate (prop);
+                       ICalTime *tt = NULL;
+                       ICalDuration *duration = i_cal_duration_null_duration ();
+
+                       tt = i_cal_datetimeperiod_get_time (rdate);
+                       if (!tt || i_cal_time_is_null_time (tt)) {
+                               ICalPeriod *period;
+
+                               g_clear_object (&tt);
+                               period = i_cal_datetimeperiod_get_period (rdate);
+
+                               if (period && !i_cal_period_is_null_period (period)) {
+                                       ICalTime *pend;
+
+                                       tt = i_cal_period_get_start (period);
+                                       pend = i_cal_period_get_end (period);
+
+                                       if (pend && !i_cal_time_is_null_time (pend)) {
+                                               time_t diff;
+
+                                               diff = i_cal_time_as_timet (pend) - i_cal_time_as_timet (tt);
+                                               if (diff < 0) {
+                                                       i_cal_duration_set_is_neg (duration, TRUE);
+                                                       diff = diff * (-1);
+                                               }
+
+                                               #define set_and_dec(member, num) G_STMT_START { \
+                                                       i_cal_duration_set_ ## member (duration, diff / 
(num)); \
+                                                       diff = diff % (num); \
+                                                       } G_STMT_END
+                                               set_and_dec (weeks, 7 * 24 * 60 * 60);
+                                               set_and_dec (days, 24 * 60 * 60);
+                                               set_and_dec (hours, 60 * 60);
+                                               set_and_dec (minutes, 60);
+                                               set_and_dec (seconds, 1);
+                                               #undef set_and_dec
+
+                                               g_warn_if_fail (diff == 0);
+                                       } else {
+                                               g_clear_object (&duration);
+                                               duration = i_cal_period_get_duration (period);
                                        }
 
-                                       #define set_and_dec(member, num) G_STMT_START { \
-                                               member = diff / (num); \
-                                               diff = diff % (num); \
-                                               } G_STMT_END
-                                       set_and_dec (duration.weeks, 7 * 24 * 60 * 60);
-                                       set_and_dec (duration.days, 24 * 60 * 60);
-                                       set_and_dec (duration.hours, 60 * 60);
-                                       set_and_dec (duration.minutes, 60);
-                                       set_and_dec (duration.seconds, 1);
-                                       #undef set_and_dec
-
-                                       g_warn_if_fail (diff == 0);
-                               } else if (!icaldurationtype_is_null_duration (rdate.period.duration)) {
-                                       duration = rdate.period.duration;
-                               }
-
-                               if (!icaldurationtype_is_null_duration (duration) &&
-                                   !icaltime_is_null_time (tt)) {
-                                       if (duration.is_neg) {
-                                               apply_duration (&tt, &duration);
+                                       if (duration && !i_cal_duration_is_null_duration (duration) &&
+                                           tt && !i_cal_time_is_null_time (tt)) {
+                                               if (i_cal_duration_is_neg (duration)) {
+                                                       apply_duration (tt, duration);
 
-                                               duration.is_neg = 0;
+                                                       i_cal_duration_set_is_neg (duration, FALSE);
+                                               }
                                        }
+
+                                       g_clear_object (&pend);
                                }
+
+                               g_clear_object (&period);
                        }
 
-                       if (!icaltime_is_null_time (tt)) {
-                               success = ensure_timezone (comp, &tt, 0, prop,
-                                       get_tz_callback, get_tz_callback_user_data, (icaltimezone *) 
dtstart.zone,
-                                       cancellable, error);
-                               if (!success)
+                       if (tt && !i_cal_time_is_null_time (tt)) {
+                               success = ensure_timezone (icalcomp, tt, 0, prop,
+                                       get_tz_callback, get_tz_callback_user_data, dtstart_zone,
+                                       &cached_zones, cancellable, error);
+                               if (!success) {
+                                       g_clear_object (&duration);
+                                       g_clear_object (&rdate);
+                                       g_clear_object (&tt);
                                        break;
+                               }
 
-                               if (intersects_interval (&tt, &duration, duration_days, duration_seconds, 
&interval_start, &interval_end)) {
-                                       g_hash_table_insert (times, e_instance_time_new (&tt, &duration), 
NULL);
+                               if (intersects_interval (tt, duration, duration_days, duration_seconds, 
interval_start, interval_end)) {
+                                       g_hash_table_insert (times, e_instance_time_new (tt, duration), NULL);
                                }
                        }
+
+                       g_clear_object (&duration);
+                       g_clear_object (&rdate);
+                       g_clear_object (&tt);
                }
 
-               for (prop = icalcomponent_get_first_property (comp, ICAL_EXRULE_PROPERTY);
+               g_clear_object (&prop);
+
+               for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_EXRULE_PROPERTY);
                     prop && success;
-                    prop = icalcomponent_get_next_property (comp, ICAL_EXRULE_PROPERTY)) {
-                       struct icalrecurrencetype exrule = icalproperty_get_exrule (prop);
-                       icalrecur_iterator *riter;
-
-                       if (!icaltime_is_null_time (exrule.until)) {
-                               success = ensure_timezone (comp, &exrule.until, 0, prop,
-                                       get_tz_callback, get_tz_callback_user_data, (icaltimezone *) 
dtstart.zone,
-                                       cancellable, error);
-                               if (!success)
+                    g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_EXRULE_PROPERTY)) {
+                       ICalRecurrence *exrule = i_cal_property_get_exrule (prop);
+                       ICalRecurIterator *riter;
+                       ICalTime *exrule_until;
+
+                       exrule_until = i_cal_recurrence_get_until (exrule);
+
+                       if (exrule_until && !i_cal_time_is_null_time (exrule_until)) {
+                               success = ensure_timezone (icalcomp, exrule_until, 0, prop,
+                                       get_tz_callback, get_tz_callback_user_data, dtstart_zone,
+                                       &cached_zones, cancellable, error);
+                               if (!success) {
+                                       g_clear_object (&exrule_until);
+                                       g_clear_object (&exrule);
                                        break;
+                               }
                        }
 
-                       if (!icaltime_is_null_time (exrule.until) &&
-                           exrule.until.is_date && !dtstart.is_date) {
-                               icaltime_adjust (&exrule.until, 1, 0, 0, 0);
-                               exrule.until.is_date = 0;
-                               exrule.until.hour = 0;
-                               exrule.until.minute = 0;
-                               exrule.until.second = 0;
+                       if (exrule_until && !i_cal_time_is_null_time (exrule_until) &&
+                           i_cal_time_is_date (exrule_until) && !i_cal_time_is_date (dtstart)) {
+                               i_cal_time_adjust (exrule_until, 1, 0, 0, 0);
+                               i_cal_time_set_is_date (exrule_until, FALSE);
+                               i_cal_time_set_time (exrule_until, 0, 0, 0);
 
-                               if (!exrule.until.zone && !icaltime_is_utc (exrule.until))
-                                       exrule.until.zone = dtstart.zone;
+                               if (!i_cal_time_get_timezone (exrule_until) && !i_cal_time_is_utc 
(exrule_until))
+                                       i_cal_time_set_timezone (exrule_until, dtstart_zone);
                        }
 
-                       riter = icalrecur_iterator_new (exrule, dtstart);
+                       if (exrule_until && !i_cal_time_is_null_time (exrule_until))
+                               i_cal_recurrence_set_until (exrule, exrule_until);
+                       g_clear_object (&exrule_until);
+
+                       riter = i_cal_recur_iterator_new (exrule, dtstart);
                        if (riter) {
-                               struct icaltimetype prev = icaltime_null_time ();
+                               ICalTime *prev = NULL;
 
-                               for (next = icalrecur_iterator_next (riter);
-                                    !icaltime_is_null_time (next) && icaltime_compare (next, interval_end) 
<= 0;
-                                    next = icalrecur_iterator_next (riter)) {
-                                       if (!icaltime_is_null_time (prev) &&
-                                           icaltime_compare (next, prev) == 0)
+                               for (next = i_cal_recur_iterator_next (riter);
+                                    next && !i_cal_time_is_null_time (next) && i_cal_time_compare (next, 
interval_end) <= 0;
+                                    g_object_unref (next), next = i_cal_recur_iterator_next (riter)) {
+                                       if (prev && !i_cal_time_is_null_time (prev) &&
+                                           i_cal_time_compare (next, prev) == 0)
                                                break;
-                                       prev = next;
+                                       g_clear_object (&prev);
+                                       prev = i_cal_time_new_clone (next);
 
-                                       if (intersects_interval (&next, NULL, duration_days, 
duration_seconds, &interval_start, &interval_end)) {
+                                       if (intersects_interval (next, NULL, duration_days, duration_seconds, 
interval_start, interval_end)) {
                                                EInstanceTime it;
 
                                                it.tt = next;
@@ -569,28 +688,38 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
                                        }
                                }
 
-                               icalrecur_iterator_free (riter);
+                               g_clear_object (&riter);
+                               g_clear_object (&prev);
+                               g_clear_object (&next);
                        }
+
+                       g_clear_object (&exrule);
                }
 
-               for (prop = icalcomponent_get_first_property (comp, ICAL_EXDATE_PROPERTY);
+               g_clear_object (&prop);
+
+               for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_EXDATE_PROPERTY);
                     prop && success;
-                    prop = icalcomponent_get_next_property (comp, ICAL_EXDATE_PROPERTY)) {
-                       struct icaltimetype exdate = icalproperty_get_exdate (prop);
+                    prop = i_cal_component_get_next_property (icalcomp, I_CAL_EXDATE_PROPERTY)) {
+                       ICalTime *exdate = i_cal_property_get_exdate (prop);
 
-                       if (icaltime_is_null_time (exdate))
+                       if (exdate || i_cal_time_is_null_time (exdate)) {
+                               g_clear_object (&exdate);
                                continue;
+                       }
 
-                       success = ensure_timezone (comp, &exdate, 0, prop,
-                               get_tz_callback, get_tz_callback_user_data, (icaltimezone *) dtstart.zone,
-                               cancellable, error);
-                       if (!success)
+                       success = ensure_timezone (icalcomp, exdate, 0, prop,
+                               get_tz_callback, get_tz_callback_user_data, dtstart_zone,
+                               &cached_zones, cancellable, error);
+                       if (!success) {
+                               g_clear_object (&exdate);
                                break;
+                       }
 
-                       if (!exdate.zone && !icaltime_is_utc (exdate))
-                               exdate.zone = dtstart.zone;
+                       if (!i_cal_time_get_timezone (exdate) && !i_cal_time_is_utc (exdate))
+                               i_cal_time_set_timezone (exdate, dtstart_zone);
 
-                       if (intersects_interval (&exdate, NULL, duration_days, duration_seconds, 
&interval_start, &interval_end)) {
+                       if (intersects_interval (exdate, NULL, duration_days, duration_seconds, 
interval_start, interval_end)) {
                                EInstanceTime it;
 
                                it.tt = exdate;
@@ -598,7 +727,11 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
 
                                g_hash_table_remove (times, &it);
                        }
+
+                       g_clear_object (&exdate);
                }
+
+               g_clear_object (&prop);
        }
 
        if (success && g_hash_table_size (times) > 0) {
@@ -623,13 +756,13 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
 
                for (ii = 0; ii < times_array->len; ii++) {
                        EInstanceTime *it = g_ptr_array_index (times_array, ii);
-                       struct icaltimetype ttend;
+                       ICalTime *endtt;
                        gint dur_days = duration_days, dur_seconds = duration_seconds;
 
                        if (!it)
                                continue;
 
-                       ttend = it->tt;
+                       endtt = i_cal_time_new_clone (it->tt);
 
                        if (it->duration_set) {
                                dur_days = it->duration_days;
@@ -637,16 +770,20 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
                        }
 
                        if (dur_seconds != 0)
-                               ttend.is_date = 0;
+                               i_cal_time_set_is_date (endtt, FALSE);
 
-                       icaltime_adjust (&ttend, dur_days, 0, 0, dur_seconds);
+                       i_cal_time_adjust (endtt, dur_days, 0, 0, dur_seconds);
 
                        if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
                                success = FALSE;
+                               g_clear_object (&endtt);
                                break;
                        }
 
-                       success = callback (comp, it->tt, ttend, callback_user_data, cancellable, error);
+                       success = callback (icalcomp, it->tt, endtt, callback_user_data, cancellable, error);
+
+                       g_clear_object (&endtt);
+
                        if (!success)
                                break;
                }
@@ -656,6 +793,12 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
 
        g_hash_table_destroy (times);
 
+       if (cached_zones)
+               g_hash_table_destroy (cached_zones);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
        return success;
 }
 
@@ -745,9 +888,9 @@ e_cal_recur_generate_instances_sync (icalcomponent *comp,
 #define CAL_OBJ_DEBUG  1
 #endif
 
-/* We will use icalrecurrencetype instead of this eventually. */
+/* We will use ICalRecurrence instead of this eventually. */
 typedef struct {
-       icalrecurrencetype_frequency freq;
+       ICalRecurrenceFrequency freq;
 
        gint            interval;
 
@@ -849,9 +992,6 @@ struct _CalObjRecurrenceDate {
        ECalComponentPeriod *period;
 };
 
-/* The paramter we use to store the enddate in RRULE and EXRULE properties. */
-#define EVOLUTION_END_DATE_PARAMETER   "X-EVOLUTION-ENDDATE"
-
 typedef gboolean (*CalObjFindStartFn) (CalObjTime *event_start,
                                       CalObjTime *event_end,
                                       RecurData  *recur_data,
@@ -892,25 +1032,25 @@ typedef enum {
 } CalObjTimeComparison;
 
 static void e_cal_recur_generate_instances_of_rule (ECalComponent      *comp,
-                                                 icalproperty  *prop,
+                                                 ICalProperty  *prop,
                                                  time_t         start,
                                                  time_t         end,
-                                                 ECalRecurInstanceFn cb,
+                                                 ECalRecurInstanceCb cb,
                                                  gpointer       cb_data,
-                                                 ECalRecurResolveTimezoneFn  tz_cb,
+                                                 ECalRecurResolveTimezoneCb  tz_cb,
                                                  gpointer       tz_cb_data,
-                                                 icaltimezone  *default_timezone);
+                                                 ICalTimezone  *default_timezone);
 
-static ECalRecurrence * e_cal_recur_from_icalproperty (icalproperty *prop,
+static ECalRecurrence * e_cal_recur_from_icalproperty (ICalProperty *prop,
                                                    gboolean exception,
-                                                   icaltimezone *zone,
+                                                   ICalTimezone *zone,
                                                    gboolean convert_end_date);
-static gint e_cal_recur_ical_weekday_to_weekday        (enum icalrecurrencetype_weekday day);
+static gint e_cal_recur_ical_weekday_to_weekday        (ICalRecurrenceWeekday day);
 static void    e_cal_recur_free                        (ECalRecurrence *r);
 
 static gboolean cal_object_get_rdate_end       (CalObjTime     *occ,
                                                 GArray         *rdate_periods,
-                                                icaltimezone   *zone);
+                                                ICalTimezone   *zone);
 static void    cal_object_compute_duration     (CalObjTime     *start,
                                                 CalObjTime     *end,
                                                 gint           *days,
@@ -918,7 +1058,7 @@ static void        cal_object_compute_duration     (CalObjTime     *start,
 
 static gboolean generate_instances_for_chunk   (ECalComponent          *comp,
                                                 time_t                  comp_dtstart,
-                                                icaltimezone           *zone,
+                                                ICalTimezone           *zone,
                                                 GSList                 *rrules,
                                                 GSList                 *rdates,
                                                 GSList                 *exrules,
@@ -931,11 +1071,11 @@ static gboolean generate_instances_for_chunk     (ECalComponent          *comp,
                                                 gint                    duration_days,
                                                 gint                    duration_seconds,
                                                 gboolean                convert_end_date,
-                                                ECalRecurInstanceFn     cb,
+                                                ECalRecurInstanceCb     cb,
                                                 gpointer                cb_data);
 
 static GArray * cal_obj_expand_recurrence      (CalObjTime       *event_start,
-                                                icaltimezone     *zone,
+                                                ICalTimezone     *zone,
                                                 ECalRecurrence   *recur,
                                                 CalObjTime       *interval_start,
                                                 CalObjTime       *interval_end,
@@ -1103,22 +1243,26 @@ static void cal_obj_time_find_first_week        (CalObjTime *cotime,
                                                 RecurData  *recur_data);
 static void cal_object_time_from_time          (CalObjTime *cotime,
                                                 time_t      t,
-                                                icaltimezone *zone);
+                                                ICalTimezone *zone);
 static gint cal_obj_date_only_compare_func     (gconstpointer arg1,
                                                 gconstpointer arg2);
 static gboolean e_cal_recur_ensure_rule_end_date       (ECalComponent  *comp,
-                                                icalproperty   *prop,
+                                                ICalProperty   *prop,
                                                 gboolean        exception,
                                                 gboolean        refresh,
-                                                ECalRecurResolveTimezoneFn tz_cb,
-                                                gpointer        tz_cb_data);
-static gboolean e_cal_recur_ensure_rule_end_date_cb    (ECalComponent  *comp,
-                                                        time_t          instance_start,
-                                                        time_t          instance_end,
-                                                        gpointer        data);
-static time_t e_cal_recur_get_rule_end_date    (icalproperty   *prop,
-                                                icaltimezone   *default_timezone);
-static void e_cal_recur_set_rule_end_date              (icalproperty   *prop,
+                                                ECalRecurResolveTimezoneCb tz_cb,
+                                                gpointer        tz_cb_data,
+                                                GCancellable *cancellable,
+                                                GError **error);
+static gboolean e_cal_recur_ensure_rule_end_date_cb    (ICalComponent  *comp,
+                                                        ICalTime *instance_start,
+                                                        ICalTime *instance_end,
+                                                        gpointer user_data,
+                                                        GCancellable *cancellable,
+                                                        GError **error);
+static time_t e_cal_recur_get_rule_end_date    (ICalProperty   *prop,
+                                                ICalTimezone   *default_timezone);
+static void e_cal_recur_set_rule_end_date      (ICalProperty   *prop,
                                                 time_t          end_date);
 
 #ifdef CAL_OBJ_DEBUG
@@ -1223,125 +1367,29 @@ static ECalRecurVTable cal_obj_secondly_vtable = {
        cal_obj_bysecond_filter
 };
 
-#ifdef HAVE_LIBICAL_2_0
-struct BackwardCompatibilityData
-{
-       ECalComponent *comp;
-       ECalRecurInstanceFn cb;
-       gpointer cb_data;
-       ECalRecurResolveTimezoneFn tz_cb;
-       gpointer tz_cb_data;
-};
-
-static icaltimezone *
-backward_compatibility_resolve_timezone_cb (const gchar *tzid,
-                                           gpointer user_data,
-                                           GCancellable *cancellable,
-                                           GError **error)
-{
-       struct BackwardCompatibilityData *bcd = user_data;
-
-       if (bcd && bcd->tz_cb)
-               return bcd->tz_cb (tzid, bcd->tz_cb_data);
-
-       return NULL;
-}
-
 static gboolean
-backward_compatibility_instance_cb (icalcomponent *comp,
-                                   struct icaltimetype instance_start,
-                                   struct icaltimetype instance_end,
-                                   gpointer user_data,
-                                   GCancellable *cancellable,
-                                   GError **error)
+call_instance_callback (ECalRecurInstanceCb cb,
+                       ECalComponent *comp,
+                       time_t dtstart_time,
+                       time_t dtend_time,
+                       gpointer cb_data)
 {
-       struct BackwardCompatibilityData *bcd = user_data;
+       ICalTime *start, *end;
+       ICalTimezone *utc_zone;
+       gboolean res;
 
-       if (bcd && bcd->cb) {
-               time_t istart, iend;
+       g_return_val_if_fail (cb != NULL, FALSE);
 
-               if (instance_start.zone)
-                       istart = icaltime_as_timet_with_zone (instance_start, instance_start.zone);
-               else
-                       istart = icaltime_as_timet (instance_start);
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+       start = i_cal_time_from_timet_with_zone (dtstart_time, FALSE, utc_zone);
+       end = i_cal_time_from_timet_with_zone (dtend_time, FALSE, utc_zone);
 
-               if (instance_end.zone)
-                       iend = icaltime_as_timet_with_zone (instance_end, instance_end.zone);
-               else
-                       iend = icaltime_as_timet (instance_end);
+       res = cb (e_cal_component_get_icalcomponent (comp), start, end, cb_data, NULL, NULL);
 
-               return bcd->cb (bcd->comp, istart, iend, bcd->cb_data);
-       }
+       g_clear_object (&start);
+       g_clear_object (&end);
 
-       return FALSE;
-}
-
-#endif
-
-/**
- * e_cal_recur_generate_instances:
- * @comp: A calendar component object
- * @start: Range start time
- * @end: Range end time
- * @cb: (closure cb_data) (scope call): Callback function
- * @cb_data: (closure): Closure data for the callback function
- * @tz_cb: (closure tz_cb_data) (scope call): Callback for retrieving timezones
- * @tz_cb_data: (closure): Closure data for the timezone callback
- * @default_timezone: Default timezone to use when a timezone cannot be
- * found
- *
- * Calls the given callback function for each occurrence of the event that
- * intersects the range between the given @start and @end times (the end time is
- * not included). Note that the occurrences may start before the given start
- * time.
- *
- * If the callback routine returns FALSE the occurrence generation stops.
- *
- * Both start and end can be -1, in which case we start at the events first
- * instance and continue until it ends, or forever if it has no enddate.
- *
- * The tz_cb is used to resolve references to timezones. It is passed a TZID
- * and should return the icaltimezone* corresponding to that TZID. We need to
- * do this as we access timezones in different ways on the client & server.
- *
- * The default_timezone argument is used for DTSTART or DTEND properties that
- * are DATE values or do not have a TZID (i.e. floating times).
- *
- * Note: This will be replaced by e_cal_recur_generate_instances_sync().
- */
-void
-e_cal_recur_generate_instances (ECalComponent *comp,
-                                time_t start,
-                                time_t end,
-                                ECalRecurInstanceFn cb,
-                                gpointer cb_data,
-                                ECalRecurResolveTimezoneFn tz_cb,
-                                gpointer tz_cb_data,
-                                icaltimezone *default_timezone)
-{
-#ifdef HAVE_LIBICAL_2_0
-       struct icaltimetype istart, iend;
-       struct BackwardCompatibilityData bcd;
-
-       bcd.comp = comp;
-       bcd.cb = cb;
-       bcd.cb_data = cb_data;
-       bcd.tz_cb = tz_cb;
-       bcd.tz_cb_data = tz_cb_data;
-
-       istart = icaltime_from_timet_with_zone (start, FALSE, icaltimezone_get_utc_timezone ());
-       iend = icaltime_from_timet_with_zone (end, FALSE, icaltimezone_get_utc_timezone ());
-
-       e_cal_recur_generate_instances_sync (e_cal_component_get_icalcomponent (comp), istart, iend,
-               backward_compatibility_instance_cb, &bcd,
-               backward_compatibility_resolve_timezone_cb, &bcd,
-               default_timezone, NULL, NULL);
-#else
-       e_cal_recur_generate_instances_of_rule (
-               comp, NULL, start, end,
-               cb, cb_data, tz_cb, tz_cb_data,
-               default_timezone);
-#endif
+       return res;
 }
 
 /*
@@ -1360,24 +1408,25 @@ e_cal_recur_generate_instances (ECalComponent *comp,
  */
 static void
 e_cal_recur_generate_instances_of_rule (ECalComponent *comp,
-                                        icalproperty *prop,
+                                        ICalProperty *prop,
                                         time_t start,
                                         time_t end,
-                                        ECalRecurInstanceFn cb,
+                                        ECalRecurInstanceCb cb,
                                         gpointer cb_data,
-                                        ECalRecurResolveTimezoneFn tz_cb,
+                                        ECalRecurResolveTimezoneCb tz_cb,
                                         gpointer tz_cb_data,
-                                        icaltimezone *default_timezone)
+                                        ICalTimezone *default_timezone)
 {
-       ECalComponentDateTime dtstart, dtend;
+       ECalComponentDateTime *dtstart, *dtend;
        time_t dtstart_time, dtend_time;
-       GSList *rrules = NULL, *rdates = NULL, elem;
+       GSList *rrules = NULL, *rdates = NULL;
        GSList *exrules = NULL, *exdates = NULL;
        CalObjTime interval_start, interval_end, event_start, event_end;
        CalObjTime chunk_start, chunk_end;
        gint days, seconds, year;
        gboolean single_rule, convert_end_date = FALSE;
-       icaltimezone *start_zone = NULL, *end_zone = NULL;
+       ICalTimezone *start_zone = NULL, *end_zone = NULL;
+       ICalTime *dtstarttt, *dtendtt;
 
        g_return_if_fail (comp != NULL);
        g_return_if_fail (cb != NULL);
@@ -1389,10 +1438,15 @@ e_cal_recur_generate_instances_of_rule (ECalComponent *comp,
         * cal_component_get_dtend () will convert a DURATION property to a
         * DTEND so we don't need to worry about that. */
 
-       e_cal_component_get_dtstart (comp, &dtstart);
-       e_cal_component_get_dtend (comp, &dtend);
+       dtstart = e_cal_component_get_dtstart (comp);
+       dtend = e_cal_component_get_dtend (comp);
+
+       dtstarttt = (dtstart && e_cal_component_datetime_get_value (dtstart)) ?
+               e_cal_component_datetime_get_value (dtstart) : NULL;
+       dtendtt = (dtend && e_cal_component_datetime_get_value (dtend)) ?
+               e_cal_component_datetime_get_value (dtend) : NULL;
 
-       if (!dtstart.value) {
+       if (!dtstart || !dtstarttt) {
                g_message (
                        "e_cal_recur_generate_instances_of_rule(): bogus "
                        "component, does not have DTSTART.  Skipping...");
@@ -1402,8 +1456,8 @@ e_cal_recur_generate_instances_of_rule (ECalComponent *comp,
        /* For DATE-TIME values with a TZID, we use the supplied callback to
         * resolve the TZID. For DATE values and DATE-TIME values without a
         * TZID (i.e. floating times) we use the default timezone. */
-       if (dtstart.tzid && !dtstart.value->is_date) {
-               start_zone = (*tz_cb) (dtstart.tzid, tz_cb_data);
+       if (e_cal_component_datetime_get_tzid (dtstart) && !i_cal_time_is_date (dtstarttt)) {
+               start_zone = (*tz_cb) (e_cal_component_datetime_get_tzid (dtstart), tz_cb_data, NULL, NULL);
                if (!start_zone)
                        start_zone = default_timezone;
        } else {
@@ -1414,69 +1468,78 @@ e_cal_recur_generate_instances_of_rule (ECalComponent *comp,
                convert_end_date = TRUE;
        }
 
-       dtstart_time = icaltime_as_timet_with_zone (
-               *dtstart.value,
-               start_zone);
+       if (start_zone)
+               g_object_ref (start_zone);
+
+       dtstart_time = i_cal_time_as_timet_with_zone (dtstarttt, start_zone);
        if (start == -1)
                start = dtstart_time;
 
-       if (dtend.value) {
+       if (dtendtt) {
                /* If both DTSTART and DTEND are DATE values, and they are the
                 * same day, we add 1 day to DTEND. This means that most
                 * events created with the old Evolution behavior will still
                 * work OK. I'm not sure what Outlook does in this case. */
-               if (dtstart.value->is_date && dtend.value->is_date) {
-                       if (icaltime_compare_date_only (*dtstart.value,
-                                                       *dtend.value) == 0) {
-                               icaltime_adjust (dtend.value, 1, 0, 0, 0);
+               if (i_cal_time_is_date (dtstarttt) && i_cal_time_is_date (dtendtt)) {
+                       if (i_cal_time_compare_date_only (dtstarttt, dtendtt) == 0) {
+                               i_cal_time_adjust (dtendtt, 1, 0, 0, 0);
                        }
                }
        } else {
                /* If there is no DTEND, then if DTSTART is a DATE-TIME value
                 * we use the same time (so we have a single point in time).
                 * If DTSTART is a DATE value we add 1 day. */
-               dtend.value = g_new (struct icaltimetype, 1);
-               *dtend.value = *dtstart.value;
+               e_cal_component_datetime_free (dtend);
 
-               if (dtstart.value->is_date) {
-                       icaltime_adjust (dtend.value, 1, 0, 0, 0);
+               dtend = e_cal_component_datetime_copy (dtstart);
+               dtendtt = (dtend && e_cal_component_datetime_get_value (dtend)) ?
+                       e_cal_component_datetime_get_value (dtend) : NULL;
+
+               g_warn_if_fail (dtendtt != NULL);
+
+               if (i_cal_time_is_date (dtstarttt)) {
+                       i_cal_time_adjust (dtendtt, 1, 0, 0, 0);
                }
        }
 
-       if (dtend.tzid && !dtend.value->is_date) {
-               end_zone = (*tz_cb) (dtend.tzid, tz_cb_data);
+       if (e_cal_component_datetime_get_tzid (dtend) && dtendtt && !i_cal_time_is_date (dtendtt)) {
+               end_zone = (*tz_cb) (e_cal_component_datetime_get_tzid (dtend), tz_cb_data, NULL, NULL);
                if (!end_zone)
                        end_zone = default_timezone;
        } else {
                end_zone = default_timezone;
        }
 
+       if (end_zone)
+               g_object_ref (end_zone);
+
        /* We don't do this any more, since Outlook assumes that the DTEND
         * date is not included. */
 #if 0
        /* If DTEND is a DATE value, we add 1 day to it so that it includes
         * the entire day. */
-       if (dtend.value->is_date) {
-               dtend.value->hour = 0;
-               dtend.value->minute = 0;
-               dtend.value->second = 0;
-               icaltime_adjust (dtend.value, 1, 0, 0, 0);
+       if (i_cal_time_is_date (dtendtt)) {
+               i_cal_time_set_time (dtendtt, 0, 0, 0);
+               i_cal_time_adjust (dtendtt, 1, 0, 0, 0);
        }
 #endif
-       dtend_time = icaltime_as_timet_with_zone (*dtend.value, end_zone);
+       dtend_time = i_cal_time_as_timet_with_zone (dtendtt, end_zone);
 
        /* If there is no recurrence, just call the callback if the event
         * intersects the given interval. */
        if (!(e_cal_component_has_recurrences (comp)
              || e_cal_component_has_exceptions (comp))) {
                if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_JOURNAL) {
-                       icaltimetype start_t = icaltime_from_timet_with_zone (start, FALSE, default_timezone);
-                       icaltimetype end_t = icaltime_from_timet_with_zone (end, FALSE, default_timezone);
+                       ICalTime *start_t = i_cal_time_from_timet_with_zone (start, FALSE, default_timezone);
+                       ICalTime *end_t = i_cal_time_from_timet_with_zone (end, FALSE, default_timezone);
 
-                       if ((icaltime_compare_date_only (*dtstart.value, start_t) >= 0) && 
((icaltime_compare_date_only (*dtstart.value, end_t) < 0)))
-                               (* cb) (comp, dtstart_time, dtend_time, cb_data);
+                       if ((i_cal_time_compare_date_only (dtstarttt, start_t) >= 0) && 
((i_cal_time_compare_date_only (dtstarttt, end_t) < 0)))
+                               call_instance_callback (cb, comp, dtstart_time, dtend_time, cb_data);
+
+                       g_clear_object (&start_t);
+                       g_clear_object (&end_t);
                } else if  ((end == -1 || dtstart_time < end) && dtend_time > start) {
-                       (* cb) (comp, dtstart_time, dtend_time, cb_data);
+                       call_instance_callback (cb, comp, dtstart_time, dtend_time, cb_data);
                }
 
                goto out;
@@ -1487,21 +1550,19 @@ e_cal_recur_generate_instances_of_rule (ECalComponent *comp,
        if (prop) {
                single_rule = TRUE;
 
-               elem.data = prop;
-               elem.next = NULL;
-               rrules = &elem;
+               rrules = g_slist_prepend (NULL, g_object_ref (prop));
        } else if (e_cal_component_is_instance (comp)) {
                single_rule = FALSE;
        } else {
                single_rule = FALSE;
 
                /* Make sure all the enddates for the rules are set. */
-               e_cal_recur_ensure_end_dates (comp, FALSE, tz_cb, tz_cb_data);
+               e_cal_recur_ensure_end_dates (comp, FALSE, tz_cb, tz_cb_data, NULL, NULL);
 
-               e_cal_component_get_rrule_property_list (comp, &rrules);
-               e_cal_component_get_rdate_list (comp, &rdates);
-               e_cal_component_get_exrule_property_list (comp, &exrules);
-               e_cal_component_get_exdate_list (comp, &exdates);
+               rrules = e_cal_component_get_rrule_properties (comp);
+               rdates = e_cal_component_get_rdates (comp);
+               exrules = e_cal_component_get_exrule_properties (comp);
+               exdates = e_cal_component_get_exdates (comp);
        }
 
        /* Convert the interval start & end to CalObjTime. Note that if end
@@ -1580,42 +1641,55 @@ e_cal_recur_generate_instances_of_rule (ECalComponent *comp,
                        break;
        }
 
-       if (!prop) {
-               e_cal_component_free_period_list (rdates);
-               e_cal_component_free_exdate_list (exdates);
-       }
+       g_slist_free_full (rdates, e_cal_component_period_free);
+       g_slist_free_full (exdates, e_cal_component_datetime_free);
+       g_slist_free_full (rrules, g_object_unref);
+       g_slist_free_full (exrules, g_object_unref);
 
  out:
-       e_cal_component_free_datetime (&dtstart);
-       e_cal_component_free_datetime (&dtend);
+       e_cal_component_datetime_free (dtstart);
+       e_cal_component_datetime_free (dtend);
+       g_clear_object (&start_zone);
+       g_clear_object (&end_zone);
 }
 
-/* Builds a list of GINT_TO_POINTER() elements out of a short array from a
- * struct icalrecurrencetype.
+/* Builds a list of GINT_TO_POINTER() elements out of a short array from an
+ * ICalRecurrence array of gshort.
  */
 static GList *
-array_to_list (gshort *array,
-               gint max_elements)
+array_to_list_and_free (GArray *array)
 {
-       GList *l;
-       gint i;
+       GList *lst;
+       gint ii;
+
+       if (!array)
+               return NULL;
+
+       lst = NULL;
 
-       l = NULL;
+       for (ii = 0; ii < array->len; ii++) {
+               gshort value = g_array_index (array, gshort, ii);
 
-       for (i = 0; i < max_elements && array[i] != ICAL_RECURRENCE_ARRAY_MAX; i++)
-               l = g_list_prepend (l, GINT_TO_POINTER ((gint) (array[i])));
-       return g_list_reverse (l);
+               if (value == I_CAL_RECURRENCE_ARRAY_MAX)
+                       break;
+
+               lst = g_list_prepend (lst, GINT_TO_POINTER ((gint) value));
+       }
+
+       g_array_unref (array);
+
+       return g_list_reverse (lst);
 }
 
 /**
  * e_cal_recur_get_enddate:
  * @ir: RRULE or EXRULE recurrence 
- * @prop: An RRULE or EXRULE #icalproperty. 
+ * @prop: An RRULE or EXRULE #ICalProperty.
  * @zone: The DTSTART timezone, used for converting the UNTIL property if it
- * is given as a DATE value.
+ *    is given as a DATE value.
  * @convert_end_date: TRUE if the saved end date needs to be converted to the
- * given @zone timezone. This is needed if the DTSTART is a DATE or floating
- * time.
+ *    given @zone timezone. This is needed if the DTSTART is a DATE or floating
+ *    time.
  * 
  * Finds out end time of (reccurent) event.
  *
@@ -1624,54 +1698,52 @@ array_to_list (gshort *array,
  * Since: 2.32
  */
 time_t
-e_cal_recur_obtain_enddate (struct icalrecurrencetype *ir,
-                            icalproperty *prop,
-          icaltimezone *zone,
-                            gboolean convert_end_date)
+e_cal_recur_obtain_enddate (ICalRecurrence *ir,
+                           ICalProperty *prop,
+                           ICalTimezone *zone,
+                           gboolean convert_end_date)
 {
        time_t enddate = -1;
 
        g_return_val_if_fail (prop != NULL, 0);
        g_return_val_if_fail (ir != NULL, 0);
 
-       if (ir->count != 0) {
+       if (i_cal_recurrence_get_count (ir) != 0) {
                /* If COUNT is set, we use the pre-calculated enddate.
                Note that this can be 0 if the RULE doesn't actually
                generate COUNT instances. */
                enddate = e_cal_recur_get_rule_end_date (prop, convert_end_date ? zone : NULL);
        } else {
-               if (icaltime_is_null_time (ir->until)) {
+               ICalTime *until;
+
+               until = i_cal_recurrence_get_until (ir);
+
+               if (!until || i_cal_time_is_null_time (until)) {
                        /* If neither COUNT or UNTIL is set, the event
                        recurs forever. */
-               } else if (ir->until.is_date) {
+               } else if (i_cal_time_is_date (until)) {
                        /* If UNTIL is a DATE, we stop at the end of
                        the day, in local time (with the DTSTART timezone).
                        Note that UNTIL is inclusive so we stop before
                        midnight. */
-                       ir->until.hour = 23;
-                       ir->until.minute = 59;
-                       ir->until.second = 59;
-                       ir->until.is_date = FALSE;
-
-                       enddate = icaltime_as_timet_with_zone (ir->until, zone);
-#if 0
-       g_print ("  until: %li - %s", r->enddate, ctime (&r->enddate));
-#endif
+                       i_cal_time_set_time (until, 23, 59, 59);
+                       i_cal_time_set_is_date (until, FALSE);
 
+                       enddate = i_cal_time_as_timet_with_zone (until, zone);
                } else {
-               /* If UNTIL is a DATE-TIME, it must be in UTC. */
-               icaltimezone *utc_zone;
-               utc_zone = icaltimezone_get_utc_timezone ();
-               enddate = icaltime_as_timet_with_zone (ir->until, utc_zone);
+                       /* If UNTIL is a DATE-TIME, it must be in UTC. */
+                       enddate = i_cal_time_as_timet_with_zone (until, i_cal_timezone_get_utc_timezone ());
                }
+
+               g_clear_object (&until);
        }
 
        return enddate;
 }
 
-/**
+/*
  * e_cal_recur_from_icalproperty:
- * @prop: An RRULE or EXRULE #icalproperty.
+ * @prop: An RRULE or EXRULE #ICalProperty.
  * @exception: TRUE if this is an EXRULE rather than an RRULE.
  * @zone: The DTSTART timezone, used for converting the UNTIL property if it
  * is given as a DATE value.
@@ -1679,69 +1751,77 @@ e_cal_recur_obtain_enddate (struct icalrecurrencetype *ir,
  * given @zone timezone. This is needed if the DTSTART is a DATE or floating
  * time.
  *
- * Converts an #icalproperty to a #ECalRecurrence.  This should be
+ * Converts an #ICalProperty to a #ECalRecurrence.  This should be
  * freed using the e_cal_recur_free() function.
  *
  * Returns: #ECalRecurrence structure.
- **/
+ */
 static ECalRecurrence *
-e_cal_recur_from_icalproperty (icalproperty *prop,
-                               gboolean exception,
-                               icaltimezone *zone,
-                               gboolean convert_end_date)
+e_cal_recur_from_icalproperty (ICalProperty *prop,
+                              gboolean exception,
+                              ICalTimezone *zone,
+                              gboolean convert_end_date)
 {
-       struct icalrecurrencetype ir;
+       ICalRecurrence *ir;
        ECalRecurrence *r;
-       gint max_elements, i;
+       GArray *array;
+       gint ii;
        GList *elem;
 
        g_return_val_if_fail (prop != NULL, NULL);
 
        r = g_new (ECalRecurrence, 1);
 
-       if (exception)
-               ir = icalproperty_get_exrule (prop);
-       else
-               ir = icalproperty_get_rrule (prop);
+       if (exception) {
+               ir = i_cal_property_get_exrule (prop);
+       } else {
+               ir = i_cal_property_get_rrule (prop);
+       }
+
+       r->freq = i_cal_recurrence_get_freq (ir);
 
-       r->freq = ir.freq;
+       if (G_UNLIKELY (i_cal_recurrence_get_interval (ir) < 1)) {
+               gchar *str;
 
-       if (G_UNLIKELY (ir.interval < 1)) {
+               str = i_cal_recurrence_as_string_r (ir);
                g_warning (
                        "Invalid interval in rule %s - using 1\n",
-                       icalrecurrencetype_as_string (&ir));
+                       str);
+               g_free (str);
                r->interval = 1;
        } else {
-               r->interval = ir.interval;
+               r->interval = i_cal_recurrence_get_interval (ir);
        }
 
-  r->enddate = e_cal_recur_obtain_enddate (&ir, prop, zone, convert_end_date);
+       r->enddate = e_cal_recur_obtain_enddate (ir, prop, zone, convert_end_date);
+       r->week_start_day = e_cal_recur_ical_weekday_to_weekday (i_cal_recurrence_get_week_start (ir));
 
-       r->week_start_day = e_cal_recur_ical_weekday_to_weekday (ir.week_start);
-
-       r->bymonth = array_to_list (ir.by_month, G_N_ELEMENTS (ir.by_month));
+       r->bymonth = array_to_list_and_free (i_cal_recurrence_get_by_month_array (ir));
        for (elem = r->bymonth; elem; elem = elem->next) {
                /* We need to convert from 1-12 to 0-11, i.e. subtract 1. */
                gint month = GPOINTER_TO_INT (elem->data) - 1;
                elem->data = GINT_TO_POINTER (month);
        }
 
-       r->byweekno = array_to_list (ir.by_week_no, G_N_ELEMENTS (ir.by_week_no));
+       r->byweekno = array_to_list_and_free (i_cal_recurrence_get_by_week_no_array (ir));
 
-       r->byyearday = array_to_list (ir.by_year_day, G_N_ELEMENTS (ir.by_year_day));
+       r->byyearday = array_to_list_and_free (i_cal_recurrence_get_by_year_day_array (ir));
 
-       r->bymonthday = array_to_list (ir.by_month_day, G_N_ELEMENTS (ir.by_month_day));
+       r->bymonthday = array_to_list_and_free (i_cal_recurrence_get_by_month_day_array (ir));
 
        /* FIXME: libical only supports 8 values, out of possible 107 * 7. */
        r->byday = NULL;
-       max_elements = G_N_ELEMENTS (ir.by_day);
-       for (i = 0; i < max_elements && ir.by_day[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) {
-               enum icalrecurrencetype_weekday day;
+       array = i_cal_recurrence_get_by_day_array (ir);
+       for (ii = 0; array && ii < array->len; ii++) {
+               gshort value = g_array_index (array, gshort, ii);
+               ICalRecurrenceWeekday day;
                gint weeknum, weekday;
 
-               day = icalrecurrencetype_day_day_of_week (ir.by_day[i]);
-               weeknum = icalrecurrencetype_day_position (ir.by_day[i]);
+               if (value == I_CAL_RECURRENCE_ARRAY_MAX)
+                       break;
 
+               day = i_cal_recurrence_day_day_of_week (value);
+               weeknum = i_cal_recurrence_day_position (value);
                weekday = e_cal_recur_ical_weekday_to_weekday (day);
 
                r->byday = g_list_prepend (
@@ -1751,44 +1831,48 @@ e_cal_recur_from_icalproperty (icalproperty *prop,
                        r->byday,
                        GINT_TO_POINTER (weekday));
        }
+       if (array)
+               g_array_unref (array);
 
-       r->byhour = array_to_list (ir.by_hour, G_N_ELEMENTS (ir.by_hour));
+       r->byhour = array_to_list_and_free (i_cal_recurrence_get_by_hour_array (ir));
 
-       r->byminute = array_to_list (ir.by_minute, G_N_ELEMENTS (ir.by_minute));
+       r->byminute = array_to_list_and_free (i_cal_recurrence_get_by_minute_array (ir));
 
-       r->bysecond = array_to_list (ir.by_second, G_N_ELEMENTS (ir.by_second));
+       r->bysecond = array_to_list_and_free (i_cal_recurrence_get_by_second_array (ir));
 
-       r->bysetpos = array_to_list (ir.by_set_pos, G_N_ELEMENTS (ir.by_set_pos));
+       r->bysetpos = array_to_list_and_free (i_cal_recurrence_get_by_set_pos_array (ir));
+
+       g_clear_object (&ir);
 
        return r;
 }
 
 static gint
-e_cal_recur_ical_weekday_to_weekday (enum icalrecurrencetype_weekday day)
+e_cal_recur_ical_weekday_to_weekday (ICalRecurrenceWeekday day)
 {
        gint weekday;
 
        switch (day) {
-       case ICAL_NO_WEEKDAY:           /* Monday is the default in RFC2445. */
-       case ICAL_MONDAY_WEEKDAY:
+       case I_CAL_NO_WEEKDAY:          /* Monday is the default in RFC2445. */
+       case I_CAL_MONDAY_WEEKDAY:
                weekday = 0;
                break;
-       case ICAL_TUESDAY_WEEKDAY:
+       case I_CAL_TUESDAY_WEEKDAY:
                weekday = 1;
                break;
-       case ICAL_WEDNESDAY_WEEKDAY:
+       case I_CAL_WEDNESDAY_WEEKDAY:
                weekday = 2;
                break;
-       case ICAL_THURSDAY_WEEKDAY:
+       case I_CAL_THURSDAY_WEEKDAY:
                weekday = 3;
                break;
-       case ICAL_FRIDAY_WEEKDAY:
+       case I_CAL_FRIDAY_WEEKDAY:
                weekday = 4;
                break;
-       case ICAL_SATURDAY_WEEKDAY:
+       case I_CAL_SATURDAY_WEEKDAY:
                weekday = 5;
                break;
-       case ICAL_SUNDAY_WEEKDAY:
+       case I_CAL_SUNDAY_WEEKDAY:
                weekday = 6;
                break;
        default:
@@ -1841,8 +1925,8 @@ e_cal_recur_free (ECalRecurrence *r)
 static gboolean
 generate_instances_for_chunk (ECalComponent *comp,
                               time_t comp_dtstart,
-                              icaltimezone *zone,
-                              GSList *rrules,
+                              ICalTimezone *zone,
+                              GSList *rrules, /* ICalProperty * */
                               GSList *rdates,
                               GSList *exrules,
                               GSList *exdates,
@@ -1854,7 +1938,7 @@ generate_instances_for_chunk (ECalComponent *comp,
                               gint duration_days,
                               gint duration_seconds,
                               gboolean convert_end_date,
-                              ECalRecurInstanceFn cb,
+                              ECalRecurInstanceCb cb,
                               gpointer cb_data)
 {
        GArray *occs, *ex_occs, *tmp_occs, *rdate_periods;
@@ -1862,7 +1946,6 @@ generate_instances_for_chunk (ECalComponent *comp,
        GSList *elem;
        gint i;
        time_t start_time, end_time;
-       struct icaltimetype start_tt, end_tt;
        gboolean cb_status = TRUE, rule_finished, finished = TRUE;
 
 #if 0
@@ -1898,7 +1981,7 @@ generate_instances_for_chunk (ECalComponent *comp,
 
        /* Expand each of the recurrence rules. */
        for (elem = rrules; elem; elem = elem->next) {
-               icalproperty *prop;
+               ICalProperty *prop;
                ECalRecurrence *r;
 
                prop = elem->data;
@@ -1927,21 +2010,26 @@ generate_instances_for_chunk (ECalComponent *comp,
         * period in the rdate_periods array. Otherwise we can just treat them
         * as normal occurrences. */
        for (elem = rdates; elem; elem = elem->next) {
-               ECalComponentPeriod *p;
+               ECalComponentPeriod *period = elem->data;
                CalObjRecurrenceDate rdate;
-               struct icaltimetype tt;
+               ICalTime *tt;
 
-               p = elem->data;
+               tt = e_cal_component_period_get_start (period);
+               if (!tt)
+                       continue;
 
-               tt = icaltime_convert_to_zone (p->start, zone);
-               cotime.year = tt.year;
-               cotime.month = tt.month - 1;
-               cotime.day = tt.day;
-               cotime.hour = tt.hour;
-               cotime.minute = tt.minute;
-               cotime.second = tt.second;
+               tt = i_cal_time_new_clone (tt);
+               i_cal_time_convert_to_zone_inplace (tt, zone);
+               cotime.year = i_cal_time_get_year (tt);
+               cotime.month = i_cal_time_get_month (tt) - 1;
+               cotime.day = i_cal_time_get_day (tt);
+               cotime.hour = i_cal_time_get_hour (tt);
+               cotime.minute = i_cal_time_get_minute (tt);
+               cotime.second = i_cal_time_get_second (tt);
                cotime.flags = FALSE;
 
+               g_clear_object (&tt);
+
                /* If the rdate is after the current chunk we set finished
                 * to FALSE, and we skip it. */
                if (cal_obj_time_compare_func (&cotime, chunk_end) >= 0) {
@@ -1953,12 +2041,13 @@ generate_instances_for_chunk (ECalComponent *comp,
                 * to store it so we can get it later. (libical seems to set
                 * second to -1 to denote an unset time. See icalvalue.c)
                 * FIXME. */
-               if (p->type != E_CAL_COMPONENT_PERIOD_DATETIME
-                   || p->u.end.second != -1) {
+               if (e_cal_component_period_get_kind (period) != E_CAL_COMPONENT_PERIOD_DATETIME ||
+                   !e_cal_component_period_get_end (period) ||
+                   i_cal_time_get_second (e_cal_component_period_get_end (period)) != -1) {
                        cotime.flags = TRUE;
 
                        rdate.start = cotime;
-                       rdate.period = p;
+                       rdate.period = period;
                        g_array_append_val (rdate_periods, rdate);
                }
 
@@ -1967,7 +2056,7 @@ generate_instances_for_chunk (ECalComponent *comp,
 
        /* Expand each of the exception rules. */
        for (elem = exrules; elem; elem = elem->next) {
-               icalproperty *prop;
+               ICalProperty *prop;
                ECalRecurrence *r;
 
                prop = elem->data;
@@ -1989,31 +2078,42 @@ generate_instances_for_chunk (ECalComponent *comp,
        /* Add on specific exception dates. */
        for (elem = exdates; elem; elem = elem->next) {
                ECalComponentDateTime *cdt;
-               struct icaltimetype tt;
+               ICalTime *tt;
 
                cdt = elem->data;
-               tt = icaltime_convert_to_zone (*cdt->value, zone);
 
-               cotime.year = tt.year;
-               cotime.month = tt.month - 1;
-               cotime.day = tt.day;
+               if (!e_cal_component_datetime_get_value (cdt))
+                       continue;
+
+               tt = e_cal_component_datetime_get_value (cdt);
+               if (!tt)
+                       continue;
+
+               tt = i_cal_time_new_clone (tt);
+               i_cal_time_convert_to_zone_inplace (tt, zone);
+
+               cotime.year = i_cal_time_get_year (tt);
+               cotime.month = i_cal_time_get_month (tt) - 1;
+               cotime.day = i_cal_time_get_day (tt);
 
                /* If the EXDATE has a DATE value, set the time to the start
                 * of the day and set flags to TRUE so we know to skip all
                 * occurrences on that date. */
-               if (cdt->value->is_date) {
+               if (i_cal_time_is_date (tt)) {
                        cotime.hour = 0;
                        cotime.minute = 0;
                        cotime.second = 0;
                        cotime.flags = TRUE;
                } else {
-                       cotime.hour = tt.hour;
-                       cotime.minute = tt.minute;
-                       cotime.second = tt.second;
+                       cotime.hour = i_cal_time_get_hour (tt);
+                       cotime.minute = i_cal_time_get_minute (tt);
+                       cotime.second = i_cal_time_get_second (tt);
                        cotime.flags = FALSE;
                }
 
                g_array_append_val (ex_occs, cotime);
+
+               g_clear_object (&tt);
        }
 
        /* Sort all the arrays. */
@@ -2032,6 +2132,8 @@ generate_instances_for_chunk (ECalComponent *comp,
        /* Call the callback for each occurrence. If it returns 0 we break
         * out of the loop. */
        for (i = 0; i < occs->len; i++) {
+               ICalTime *start_tt, *end_tt;
+
                /* Convert each CalObjTime into a start & end time_t, and
                 * check it is within the bounds of the event & interval. */
                occ = &g_array_index (occs, CalObjTime, i);
@@ -2040,14 +2142,11 @@ generate_instances_for_chunk (ECalComponent *comp,
                        "Checking occurrence: %s\n",
                        cal_obj_time_to_string (occ));
 #endif
-               start_tt = icaltime_null_time ();
-               start_tt.year = occ->year;
-               start_tt.month = occ->month + 1;
-               start_tt.day = occ->day;
-               start_tt.hour = occ->hour;
-               start_tt.minute = occ->minute;
-               start_tt.second = occ->second;
-               start_time = icaltime_as_timet_with_zone (start_tt, zone);
+               start_tt = i_cal_time_null_time ();
+               i_cal_time_set_date (start_tt, occ->year, occ->month + 1, occ->day);
+               i_cal_time_set_time (start_tt, occ->hour, occ->minute, occ->second);
+               start_time = i_cal_time_as_timet_with_zone (start_tt, zone);
+               g_clear_object (&start_tt);
 
                if (start_time == -1) {
                        g_warning ("time_t out of range");
@@ -2084,14 +2183,11 @@ generate_instances_for_chunk (ECalComponent *comp,
                        cal_obj_time_add_seconds (occ, duration_seconds);
                }
 
-               end_tt = icaltime_null_time ();
-               end_tt.year = occ->year;
-               end_tt.month = occ->month + 1;
-               end_tt.day = occ->day;
-               end_tt.hour = occ->hour;
-               end_tt.minute = occ->minute;
-               end_tt.second = occ->second;
-               end_time = icaltime_as_timet_with_zone (end_tt, zone);
+               end_tt = i_cal_time_null_time ();
+               i_cal_time_set_date (end_tt, occ->year, occ->month + 1, occ->day);
+               i_cal_time_set_time (end_tt, occ->hour, occ->minute, occ->second);
+               end_time = i_cal_time_as_timet_with_zone (end_tt, zone);
+               g_clear_object (&end_tt);
 
                if (end_time == -1) {
                        g_warning ("time_t out of range");
@@ -2108,7 +2204,7 @@ generate_instances_for_chunk (ECalComponent *comp,
                        continue;
                }
 
-               cb_status = (*cb) (comp, start_time, end_time, cb_data);
+               cb_status = call_instance_callback (cb, comp, start_time, end_time, cb_data);
                if (!cb_status)
                        break;
        }
@@ -2128,11 +2224,11 @@ generate_instances_for_chunk (ECalComponent *comp,
  * is set it returns FALSE and the default duration will be used. */
 static gboolean
 cal_object_get_rdate_end (CalObjTime *occ,
-                          GArray *rdate_periods,
-                          icaltimezone *zone)
+                         GArray *rdate_periods,
+                         ICalTimezone *zone)
 {
        CalObjRecurrenceDate *rdate = NULL;
-       ECalComponentPeriod *p;
+       ECalComponentPeriod *period;
        gint lower, upper, middle, cmp = 0;
 
        lower = 0;
@@ -2162,25 +2258,39 @@ cal_object_get_rdate_end (CalObjTime *occ,
                return FALSE;
        }
 
-       p = rdate->period;
-       if (p->type == E_CAL_COMPONENT_PERIOD_DATETIME) {
-               struct icaltimetype tt =
-                       icaltime_convert_to_zone (p->u.end, zone);
-               occ->year = tt.year;
-               occ->month = tt.month - 1;
-               occ->day = tt.day;
-               occ->hour = tt.hour;
-               occ->minute = tt.minute;
-               occ->second = tt.second;
-               occ->flags = FALSE;
+       period = rdate->period;
+       if (e_cal_component_period_get_kind (period) == E_CAL_COMPONENT_PERIOD_DATETIME) {
+               ICalTime *end;
+
+               end = e_cal_component_period_get_end (period);
+               g_warn_if_fail (end != NULL);
+               if (end) {
+                       ICalTime *tt;
+
+                       tt = i_cal_time_convert_to_zone (end, zone);
+
+                       occ->year = i_cal_time_get_year (tt);
+                       occ->month = i_cal_time_get_month (tt) - 1;
+                       occ->day = i_cal_time_get_day (tt);
+                       occ->hour = i_cal_time_get_hour (tt);
+                       occ->minute = i_cal_time_get_minute (tt);
+                       occ->second = i_cal_time_get_second (tt);
+                       occ->flags = FALSE;
+
+                       g_clear_object (&tt);
+               }
        } else {
+               ICalDuration *duration;
+
+               duration = e_cal_component_period_get_duration (period);
+
                cal_obj_time_add_days (
                        occ,
-                       p->u.duration.weeks * 7 +
-                       p->u.duration.days);
-               cal_obj_time_add_hours (occ, p->u.duration.hours);
-               cal_obj_time_add_minutes (occ, p->u.duration.minutes);
-               cal_obj_time_add_seconds (occ, p->u.duration.seconds);
+                       i_cal_duration_get_weeks (duration) * 7 +
+                       i_cal_duration_get_days (duration));
+               cal_obj_time_add_hours (occ, i_cal_duration_get_hours (duration));
+               cal_obj_time_add_minutes (occ, i_cal_duration_get_minutes (duration));
+               cal_obj_time_add_seconds (occ, i_cal_duration_get_seconds (duration));
        }
 
        return TRUE;
@@ -2223,7 +2333,7 @@ cal_object_compute_duration (CalObjTime *start,
  * after the given interval.*/
 static GArray *
 cal_obj_expand_recurrence (CalObjTime *event_start,
-                           icaltimezone *zone,
+                           ICalTimezone *zone,
                            ECalRecurrence *recur,
                            CalObjTime *interval_start,
                            CalObjTime *interval_end,
@@ -4490,19 +4600,21 @@ cal_obj_time_find_first_week (CalObjTime *cotime,
 static void
 cal_object_time_from_time (CalObjTime *cotime,
                            time_t t,
-                           icaltimezone *zone)
+                           ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
 
-       tt = icaltime_from_timet_with_zone (t, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (t, FALSE, zone);
 
-       cotime->year = tt.year;
-       cotime->month = tt.month - 1;
-       cotime->day = tt.day;
-       cotime->hour = tt.hour;
-       cotime->minute = tt.minute;
-       cotime->second = tt.second;
+       cotime->year = i_cal_time_get_year (tt);
+       cotime->month = i_cal_time_get_month (tt) - 1;
+       cotime->day = i_cal_time_get_day (tt);
+       cotime->hour = i_cal_time_get_hour (tt);
+       cotime->minute = i_cal_time_get_minute (tt);
+       cotime->second = i_cal_time_get_second (tt);
        cotime->flags = FALSE;
+
+       g_clear_object (&tt);
 }
 
 /* Debugging function to convert a CalObjTime to a string. It uses a static
@@ -4533,16 +4645,17 @@ cal_obj_time_to_string (CalObjTime *cotime)
  * e_cal_recur_ensure_end_dates:
  * @comp: an #ECalComponent
  * @refresh: %TRUE to recalculate all end dates
- * @tz_cb: (closure tz_cb_data) (scope call): function to call to resolve
- * timezones
- * @tz_cb_data: (closure): data to pass to @tz_cb
+ * @tz_cb: (scope call): function to call to resolve timezones
+ * @tz_cb_data: (closure tz_cb_data): user data to pass to @tz_cb
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
  *
  * This recalculates the end dates for recurrence & exception rules which use
  * the COUNT property. If @refresh is %TRUE it will recalculate all enddates
  * for rules which use COUNT. If @refresh is %FALSE, it will only calculate
  * the enddate if it hasn't already been set. It returns %TRUE if the component
  * was changed, i.e. if the component should be saved at some point.
- * We store the enddate in the "X-EVOLUTION-ENDDATE" parameter of the RRULE
+ * We store the enddate in the %E_CAL_EVOLUTION_ENDDATE_PARAMETER parameter of the RRULE
  * or EXRULE.
  *
  * Returns: %TRUE if the component was changed, %FALSE otherwise
@@ -4551,29 +4664,32 @@ cal_obj_time_to_string (CalObjTime *cotime)
  **/
 gboolean
 e_cal_recur_ensure_end_dates (ECalComponent *comp,
-                              gboolean refresh,
-                              ECalRecurResolveTimezoneFn tz_cb,
-                              gpointer tz_cb_data)
+                             gboolean refresh,
+                             ECalRecurResolveTimezoneCb tz_cb,
+                             gpointer tz_cb_data,
+                             GCancellable *cancellable,
+                             GError **error)
 {
        GSList *rrules, *exrules, *elem;
        gboolean changed = FALSE;
 
        /* Do the RRULEs. */
-       e_cal_component_get_rrule_property_list (comp, &rrules);
-       for (elem = rrules; elem; elem = elem->next) {
+       rrules = e_cal_component_get_rrule_properties (comp);
+       for (elem = rrules; elem && !g_cancellable_is_cancelled (cancellable); elem = elem->next) {
                changed |= e_cal_recur_ensure_rule_end_date (comp, elem->data,
-                                                          FALSE, refresh,
-                                                          tz_cb, tz_cb_data);
+                       FALSE, refresh, tz_cb, tz_cb_data, cancellable, error);
        }
 
        /* Do the EXRULEs. */
-       e_cal_component_get_exrule_property_list (comp, &exrules);
-       for (elem = exrules; elem; elem = elem->next) {
+       exrules = e_cal_component_get_exrule_properties (comp);
+       for (elem = exrules; elem && !g_cancellable_is_cancelled (cancellable); elem = elem->next) {
                changed |= e_cal_recur_ensure_rule_end_date (comp, elem->data,
-                                                          TRUE, refresh,
-                                                          tz_cb, tz_cb_data);
+                       TRUE, refresh, tz_cb, tz_cb_data, cancellable, error);
        }
 
+       g_slist_free_full (rrules, g_object_unref);
+       g_slist_free_full (exrules, g_object_unref);
+
        return changed;
 }
 
@@ -4586,32 +4702,41 @@ struct _ECalRecurEnsureEndDateData {
 
 static gboolean
 e_cal_recur_ensure_rule_end_date (ECalComponent *comp,
-                                  icalproperty *prop,
+                                  ICalProperty *prop,
                                   gboolean exception,
                                   gboolean refresh,
-                                  ECalRecurResolveTimezoneFn tz_cb,
-                                  gpointer tz_cb_data)
+                                  ECalRecurResolveTimezoneCb tz_cb,
+                                  gpointer tz_cb_data,
+                                 GCancellable *cancellable,
+                                 GError **error)
 {
-       struct icalrecurrencetype rule;
+       ICalRecurrence *rule;
        ECalRecurEnsureEndDateData cb_data;
 
+       if (!prop)
+               return FALSE;
+
        if (exception)
-               rule = icalproperty_get_exrule (prop);
+               rule = i_cal_property_get_exrule (prop);
        else
-               rule = icalproperty_get_rrule (prop);
+               rule = i_cal_property_get_rrule (prop);
 
        /* If the rule doesn't use COUNT just return. */
-       if (rule.count == 0)
+       if (!rule || !i_cal_recurrence_get_count (rule)) {
+               g_clear_object (&rule);
                return FALSE;
+       }
 
        /* If refresh is FALSE, we check if the enddate is already set, and
         * if it is we just return. */
        if (!refresh) {
-               if (e_cal_recur_get_rule_end_date (prop, NULL) != -1)
+               if (e_cal_recur_get_rule_end_date (prop, NULL) != -1) {
+                       g_clear_object (&rule);
                        return FALSE;
+               }
        } else {
                /* Remove the property parameter, thus it'll not influence the regeneration */
-               icalproperty_remove_parameter_by_name (prop, EVOLUTION_END_DATE_PARAMETER);
+               i_cal_property_remove_parameter_by_name (prop, E_CAL_EVOLUTION_ENDDATE_PARAMETER);
        }
 
        /* Calculate the end date. Note that we initialize end_date to 0, so
@@ -4619,36 +4744,37 @@ e_cal_recur_ensure_rule_end_date (ECalComponent *comp,
         * Also note that we use the UTC timezone as the default timezone.
         * In get_end_date () if the DTSTART is a DATE or floating time, we will
         * convert the ENDDATE to the current timezone. */
-       cb_data.count = rule.count;
+       cb_data.count = i_cal_recurrence_get_count (rule);
        cb_data.instances = 0;
        cb_data.end_date = 0;
        e_cal_recur_generate_instances_of_rule (
                comp, prop, -1, -1,
                e_cal_recur_ensure_rule_end_date_cb,
                &cb_data, tz_cb, tz_cb_data,
-               icaltimezone_get_utc_timezone ());
+               i_cal_timezone_get_utc_timezone ());
 
-       /* Store the end date in the "X-EVOLUTION-ENDDATE" parameter of the
-        * rule. */
+       /* Store the end date in the E_CAL_EVOLUTION_ENDDATE_PARAMETER parameter of the rule. */
        e_cal_recur_set_rule_end_date (prop, cb_data.end_date);
 
+       g_clear_object (&rule);
+
        return TRUE;
 }
 
 static gboolean
-e_cal_recur_ensure_rule_end_date_cb (ECalComponent *comp,
-                                     time_t instance_start,
-                                     time_t instance_end,
-                                     gpointer data)
+e_cal_recur_ensure_rule_end_date_cb (ICalComponent *comp,
+                                    ICalTime *instance_start,
+                                    ICalTime *instance_end,
+                                    gpointer user_data,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
-       ECalRecurEnsureEndDateData *cb_data;
-
-       cb_data = (ECalRecurEnsureEndDateData *) data;
+       ECalRecurEnsureEndDateData *cb_data = user_data;
 
        cb_data->instances++;
 
        if (cb_data->instances == cb_data->count) {
-               cb_data->end_date = instance_start;
+               cb_data->end_date = i_cal_time_as_timet (instance_start);
                return FALSE;
        }
 
@@ -4660,94 +4786,88 @@ e_cal_recur_ensure_rule_end_date_cb (ECalComponent *comp,
  * value, since the RRULE end date will change depending on the timezone that
  * it is evaluated in. */
 static time_t
-e_cal_recur_get_rule_end_date (icalproperty *prop,
-                               icaltimezone *default_timezone)
+e_cal_recur_get_rule_end_date (ICalProperty *prop,
+                               ICalTimezone *default_timezone)
 {
-       icalparameter *param;
+       ICalParameter *param;
        const gchar *xname, *xvalue;
-       icalvalue *value;
-       struct icaltimetype icaltime;
-       icaltimezone *zone;
-
-       param = icalproperty_get_first_parameter (prop, ICAL_X_PARAMETER);
-       while (param) {
-               xname = icalparameter_get_xname (param);
-               if (xname && !strcmp (xname, EVOLUTION_END_DATE_PARAMETER)) {
-                       xvalue = icalparameter_get_x (param);
-                       value = icalvalue_new_from_string (
-                               ICAL_DATETIME_VALUE,
-                               xvalue);
+
+       for (param = i_cal_property_get_first_parameter (prop, I_CAL_X_PARAMETER);
+            param;
+            g_object_unref (param), param = i_cal_property_get_next_parameter (prop, I_CAL_X_PARAMETER)) {
+               xname = i_cal_parameter_get_xname (param);
+               if (xname && !strcmp (xname, E_CAL_EVOLUTION_ENDDATE_PARAMETER)) {
+                       ICalValue *value;
+
+                       xvalue = i_cal_parameter_get_x (param);
+                       value = i_cal_value_new_from_string (I_CAL_DATETIME_VALUE, xvalue);
                        if (value) {
-                               icaltime = icalvalue_get_datetime (value);
-                               icalvalue_free (value);
-
-                               zone = default_timezone ? default_timezone :
-                                       icaltimezone_get_utc_timezone ();
-                               return icaltime_as_timet_with_zone (
-                                       icaltime,
-                                       zone);
+                               ICalTime *tt;
+                               ICalTimezone *zone;
+                               time_t res;
+
+                               tt = i_cal_value_get_datetime (value);
+                               g_object_unref (value);
+
+                               zone = default_timezone;
+                               if (!zone)
+                                       zone = i_cal_timezone_get_utc_timezone ();
+
+                               res = i_cal_time_as_timet_with_zone (tt, zone);
+
+                               g_object_unref (param);
+                               g_clear_object (&tt);
+
+                               return res;
                        }
                }
-
-               param = icalproperty_get_next_parameter (
-                       prop,
-                       ICAL_X_PARAMETER);
        }
 
        return -1;
 }
 
 static void
-e_cal_recur_set_rule_end_date (icalproperty *prop,
+e_cal_recur_set_rule_end_date (ICalProperty *prop,
                                time_t end_date)
 {
-       icalparameter *param;
-       icalvalue *value;
-       icaltimezone *utc_zone;
-       struct icaltimetype icaltime;
+       ICalParameter *param;
+       ICalValue *value;
+       ICalTimezone *utc_zone;
+       ICalTime *icaltime;
        const gchar *xname;
        gchar *end_date_string;
 
        /* We save the value as a UTC DATE-TIME. */
-       utc_zone = icaltimezone_get_utc_timezone ();
-       icaltime = icaltime_from_timet_with_zone (end_date, FALSE, utc_zone);
-       value = icalvalue_new_datetime (icaltime);
-       end_date_string = icalvalue_as_ical_string_r (value);
-       icalvalue_free (value);
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+       icaltime = i_cal_time_from_timet_with_zone (end_date, FALSE, utc_zone);
+       value = i_cal_value_new_datetime (icaltime);
+       end_date_string = i_cal_value_as_ical_string_r (value);
+       g_object_unref (value);
+       g_object_unref (icaltime);
 
        /* If we already have an X-EVOLUTION-ENDDATE parameter, set the value
         * to the new date-time. */
-       param = icalproperty_get_first_parameter (prop, ICAL_X_PARAMETER);
-       while (param) {
-               xname = icalparameter_get_xname (param);
-               if (xname && !strcmp (xname, EVOLUTION_END_DATE_PARAMETER)) {
-                       icalparameter_set_x (param, end_date_string);
+       for (param = i_cal_property_get_first_parameter (prop, I_CAL_X_PARAMETER);
+            param;
+            g_object_unref (param), param = i_cal_property_get_next_parameter (prop, I_CAL_X_PARAMETER)) {
+               xname = i_cal_parameter_get_xname (param);
+               if (xname && !strcmp (xname, E_CAL_EVOLUTION_ENDDATE_PARAMETER)) {
+                       i_cal_parameter_set_x (param, end_date_string);
+                       g_free (end_date_string);
+                       g_object_unref (param);
                        return;
                }
-               param = icalproperty_get_next_parameter (prop, ICAL_X_PARAMETER);
        }
 
        /* Create a new X-EVOLUTION-ENDDATE and add it to the property. */
-       param = icalparameter_new_x (end_date_string);
-       icalparameter_set_xname (param, EVOLUTION_END_DATE_PARAMETER);
-       icalproperty_add_parameter (prop, param);
+       param = i_cal_parameter_new_x (end_date_string);
+       i_cal_parameter_set_xname (param, E_CAL_EVOLUTION_ENDDATE_PARAMETER);
+       i_cal_property_take_parameter (prop, param);
 
        g_free (end_date_string);
 }
 
-#ifdef G_OS_WIN32
-#undef e_cal_recur_nth
-static
-#endif
-/**
- * e_cal_recur_nth:
- *
- * An array of 31 translated strings for each day of the month (i.e. "1st",
- * "2nd", and so on).
- *
- * Deprecated: 3.28: Use e_cal_recur_get_localized_nth() instead
- */
-const gchar *e_cal_recur_nth[31] = {
+static const gchar *e_cal_recur_nth[31] = {
        N_("1st"),
        N_("2nd"),
        N_("3rd"),
@@ -4781,26 +4901,6 @@ const gchar *e_cal_recur_nth[31] = {
        N_("31st")
 };
 
-#ifdef G_OS_WIN32
-
-/**
- * e_cal_get_recur_nth:
- *
- * Returns an array of 31 translated strings for each day of the month
- * (i.e. "1st", "2nd", and so on).
- *
- * Returns: a pointer to an array of strings.  This array is static, do not free it.
- *
- * Deprecated: 3.28: Use e_cal_recur_get_localized_nth() instead
- */
-const gchar **
-e_cal_get_recur_nth (void)
-{
-       return e_cal_recur_nth;
-}
-
-#endif
-
 /**
  * e_cal_recur_get_localized_nth:
  * @nth: the nth index, counting from zero
@@ -4820,27 +4920,32 @@ e_cal_recur_get_localized_nth (gint nth)
 }
 
 static gint
-cal_comp_util_recurrence_count_by_xxx (gshort *field,
-                                      gint max_elements)
+cal_comp_util_recurrence_count_by_xxx_and_free (GArray *array) /* gshort */
 {
        gint ii;
 
-       for (ii = 0; ii < max_elements; ii++)
-               if (field[ii] == ICAL_RECURRENCE_ARRAY_MAX)
+       if (!array)
+               return 0;
+
+       for (ii = 0; ii < array->len; ii++) {
+               if (g_array_index (array, gshort, ii) == I_CAL_RECURRENCE_ARRAY_MAX)
                        break;
+       }
+
+       g_array_unref (array);
 
        return ii;
 }
 
 /**
  * e_cal_recur_describe_recurrence:
- * @icalcomp: an icalcomponent
+ * @icalcomp: an #ICalComponent
  * @week_start_day: a day when the week starts
  * @flags: bit-or of #ECalRecurDescribeRecurrenceFlags
  *
  * Describes some simple types of recurrences in a human-readable and localized way.
- * The @flags influence the output output format and what to do when the @icalcomp
- * contain more complicated recurrence, some which the function cannot describe.
+ * The @flags influence the output format and what to do when the @icalcomp
+ * contains more complicated recurrence, some which the function cannot describe.
  *
  * The @week_start_day is used for weekly recurrences, to start the list of selected
  * days at that day.
@@ -4855,75 +4960,76 @@ cal_comp_util_recurrence_count_by_xxx (gshort *field,
  * Since: 3.30
  **/
 gchar *
-e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
+e_cal_recur_describe_recurrence (ICalComponent *icalcomp,
                                 GDateWeekday week_start_day,
                                 guint32 flags)
 {
        gchar *prefix = NULL, *mid = NULL, *suffix = NULL, *result = NULL;
-       icalproperty *prop;
-       struct icalrecurrencetype rrule;
+       ICalProperty *prop;
+       ICalRecurrence *rrule = NULL;
+       ICalTime *until = NULL, *dtstart = NULL;
        gint n_by_second, n_by_minute, n_by_hour;
        gint n_by_day, n_by_month_day, n_by_year_day;
        gint n_by_week_no, n_by_month, n_by_set_pos;
        gboolean prefixed, fallback;
 
-       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (I_CAL_IS_COMPONENT (icalcomp), NULL);
 
        prefixed = (flags & E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_PREFIXED) != 0;
        fallback = (flags & E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_FALLBACK) != 0;
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+       prop = i_cal_component_get_first_property (icalcomp, I_CAL_RRULE_PROPERTY);
        if (!prop)
                return NULL;
 
-       switch (icalcomponent_isa (icalcomp)) {
-       case ICAL_VEVENT_COMPONENT:
-       case ICAL_VTODO_COMPONENT:
-       case ICAL_VJOURNAL_COMPONENT:
+       switch (i_cal_component_isa (icalcomp)) {
+       case I_CAL_VEVENT_COMPONENT:
+       case I_CAL_VTODO_COMPONENT:
+       case I_CAL_VJOURNAL_COMPONENT:
                break;
        default:
+               g_object_unref (prop);
                return NULL;
        }
 
-       if (icalcomponent_count_properties (icalcomp, ICAL_RRULE_PROPERTY) != 1 ||
-           icalcomponent_count_properties (icalcomp, ICAL_RDATE_PROPERTY) != 0 ||
-           icalcomponent_count_properties (icalcomp, ICAL_EXRULE_PROPERTY) != 0)
+       if (i_cal_component_count_properties (icalcomp, I_CAL_RRULE_PROPERTY) != 1 ||
+           i_cal_component_count_properties (icalcomp, I_CAL_RDATE_PROPERTY) != 0 ||
+           i_cal_component_count_properties (icalcomp, I_CAL_EXRULE_PROPERTY) != 0)
                goto custom;
 
-       rrule = icalproperty_get_rrule (prop);
+       rrule = i_cal_property_get_rrule (prop);
 
-       switch (rrule.freq) {
-       case ICAL_DAILY_RECURRENCE:
-       case ICAL_WEEKLY_RECURRENCE:
-       case ICAL_MONTHLY_RECURRENCE:
-       case ICAL_YEARLY_RECURRENCE:
+       switch (i_cal_recurrence_get_freq (rrule)) {
+       case I_CAL_DAILY_RECURRENCE:
+       case I_CAL_WEEKLY_RECURRENCE:
+       case I_CAL_MONTHLY_RECURRENCE:
+       case I_CAL_YEARLY_RECURRENCE:
                break;
        default:
                goto custom;
 
        }
 
-#define N_HAS_BY(field) (cal_comp_util_recurrence_count_by_xxx (field, G_N_ELEMENTS (field)))
+       until = i_cal_recurrence_get_until (rrule);
+       dtstart = i_cal_component_get_dtstart (icalcomp);
 
-       n_by_second = N_HAS_BY (rrule.by_second);
-       n_by_minute = N_HAS_BY (rrule.by_minute);
-       n_by_hour = N_HAS_BY (rrule.by_hour);
-       n_by_day = N_HAS_BY (rrule.by_day);
-       n_by_month_day = N_HAS_BY (rrule.by_month_day);
-       n_by_year_day = N_HAS_BY (rrule.by_year_day);
-       n_by_week_no = N_HAS_BY (rrule.by_week_no);
-       n_by_month = N_HAS_BY (rrule.by_month);
-       n_by_set_pos = N_HAS_BY (rrule.by_set_pos);
-
-#undef N_HAS_BY
+       n_by_second = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_second_array 
(rrule));
+       n_by_minute = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_minute_array 
(rrule));
+       n_by_hour = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_hour_array 
(rrule));
+       n_by_day = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_day_array (rrule));
+       n_by_month_day = cal_comp_util_recurrence_count_by_xxx_and_free 
(i_cal_recurrence_get_by_month_day_array (rrule));
+       n_by_year_day = cal_comp_util_recurrence_count_by_xxx_and_free 
(i_cal_recurrence_get_by_year_day_array (rrule));
+       n_by_week_no = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_week_no_array 
(rrule));
+       n_by_month = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_month_array 
(rrule));
+       n_by_set_pos = cal_comp_util_recurrence_count_by_xxx_and_free (i_cal_recurrence_get_by_set_pos_array 
(rrule));
 
        if (n_by_second != 0 ||
            n_by_minute != 0 ||
            n_by_hour != 0)
                goto custom;
 
-       switch (rrule.freq) {
-       case ICAL_DAILY_RECURRENCE:
+       switch (i_cal_recurrence_get_freq (rrule)) {
+       case I_CAL_DAILY_RECURRENCE:
                if (n_by_day != 0 ||
                    n_by_month_day != 0 ||
                    n_by_year_day != 0 ||
@@ -4932,20 +5038,20 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                    n_by_set_pos != 0)
                        goto custom;
 
-               if (rrule.interval > 0) {
-                       if (!rrule.count && !rrule.until.year) {
+               if (i_cal_recurrence_get_interval (rrule) > 0) {
+                       if (!i_cal_recurrence_get_count (rrule) && (!until || !i_cal_time_get_year (until))) {
                                if (prefixed) {
                                        result = g_strdup_printf (
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "every day forever",
                                                        "every %d days forever",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                } else {
                                        result = g_strdup_printf (
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "Every day forever",
                                                        "Every %d days forever",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                }
                        } else {
                                if (prefixed) {
@@ -4953,19 +5059,19 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "every day",
                                                        "every %d days",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                } else {
                                        prefix = g_strdup_printf (
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "Every day",
                                                        "Every %d days",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                }
                        }
                }
                break;
 
-       case ICAL_WEEKLY_RECURRENCE: {
+       case I_CAL_WEEKLY_RECURRENCE: {
                gint ii, ndays;
                guint8 day_mask;
                gint day_shift = week_start_day;
@@ -4983,42 +5089,42 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
 
                day_mask = 0;
 
-               for (ii = 0; ii < 8 && rrule.by_day[ii] != ICAL_RECURRENCE_ARRAY_MAX; ii++) {
-                       enum icalrecurrencetype_weekday weekday;
+               for (ii = 0; ii < 8 && i_cal_recurrence_get_by_day (rrule, ii) != I_CAL_RECURRENCE_ARRAY_MAX; 
ii++) {
+                       ICalRecurrenceWeekday weekday;
                        gint pos;
 
-                       weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[ii]);
-                       pos = icalrecurrencetype_day_position (rrule.by_day[ii]);
+                       weekday = i_cal_recurrence_day_day_of_week (i_cal_recurrence_get_by_day (rrule, ii));
+                       pos = i_cal_recurrence_day_position (i_cal_recurrence_get_by_day (rrule, ii));
 
                        if (pos != 0)
                                goto custom;
 
                        switch (weekday) {
-                       case ICAL_SUNDAY_WEEKDAY:
+                       case I_CAL_SUNDAY_WEEKDAY:
                                day_mask |= 1 << 0;
                                break;
 
-                       case ICAL_MONDAY_WEEKDAY:
+                       case I_CAL_MONDAY_WEEKDAY:
                                day_mask |= 1 << 1;
                                break;
 
-                       case ICAL_TUESDAY_WEEKDAY:
+                       case I_CAL_TUESDAY_WEEKDAY:
                                day_mask |= 1 << 2;
                                break;
 
-                       case ICAL_WEDNESDAY_WEEKDAY:
+                       case I_CAL_WEDNESDAY_WEEKDAY:
                                day_mask |= 1 << 3;
                                break;
 
-                       case ICAL_THURSDAY_WEEKDAY:
+                       case I_CAL_THURSDAY_WEEKDAY:
                                day_mask |= 1 << 4;
                                break;
 
-                       case ICAL_FRIDAY_WEEKDAY:
+                       case I_CAL_FRIDAY_WEEKDAY:
                                day_mask |= 1 << 5;
                                break;
 
-                       case ICAL_SATURDAY_WEEKDAY:
+                       case I_CAL_SATURDAY_WEEKDAY:
                                day_mask |= 1 << 6;
                                break;
 
@@ -5028,11 +5134,7 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                }
 
                if (ii == 0) {
-                       struct icaltimetype dtstart;
-
-                       dtstart = icalcomponent_get_dtstart (icalcomp);
-
-                       ii = icaltime_day_of_week (dtstart);
+                       ii = i_cal_time_day_of_week (dtstart);
                        if (ii >= 1)
                                day_mask |= 1 << (ii - 1);
                }
@@ -5049,13 +5151,13 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                                g_dngettext (GETTEXT_PACKAGE,
                                        "every week",
                                        "every %d weeks",
-                                       rrule.interval), rrule.interval);
+                                       i_cal_recurrence_get_interval (rrule)), i_cal_recurrence_get_interval 
(rrule));
                } else {
                        prefix = g_strdup_printf (
                                g_dngettext (GETTEXT_PACKAGE,
                                        "Every week",
                                        "Every %d weeks",
-                                       rrule.interval), rrule.interval);
+                                       i_cal_recurrence_get_interval (rrule)), i_cal_recurrence_get_interval 
(rrule));
                }
 
                for (ii = 0; ii < 7 && ndays; ii++) {
@@ -5169,16 +5271,12 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                        if (n_by_set_pos != 0)
                                goto custom;
 
-                       nth = rrule.by_month_day[0];
+                       nth = i_cal_recurrence_get_by_month_day (rrule, 0);
                        if (nth < 1 && nth != -1)
                                goto custom;
 
                        if (nth == -1) {
-                               struct icaltimetype dtstart;
-
-                               dtstart = icalcomponent_get_dtstart (icalcomp);
-
-                               month_index = dtstart.day;
+                               month_index = i_cal_time_get_day (dtstart);
                                month_num = MONTH_NUM_LAST;
                        } else {
                                month_index = nth;
@@ -5187,50 +5285,50 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                        month_day = MONTH_DAY_NTH;
 
                } else if (n_by_day == 1) {
-                       enum icalrecurrencetype_weekday weekday;
+                       ICalRecurrenceWeekday weekday;
                        gint pos;
 
                        /* Outlook 2000 uses BYDAY=TU;BYSETPOS=2, and will not
                         * accept BYDAY=2TU. So we now use the same as Outlook
                         * by default. */
 
-                       weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[0]);
-                       pos = icalrecurrencetype_day_position (rrule.by_day[0]);
+                       weekday = i_cal_recurrence_day_day_of_week (i_cal_recurrence_get_by_day (rrule, 0));
+                       pos = i_cal_recurrence_day_position (i_cal_recurrence_get_by_day (rrule, 0));
 
                        if (pos == 0) {
                                if (n_by_set_pos != 1)
                                        goto custom;
-                               pos = rrule.by_set_pos[0];
+                               pos = i_cal_recurrence_get_by_set_pos (rrule, 0);
                        } else if (pos < 0) {
                                goto custom;
                        }
 
                        switch (weekday) {
-                       case ICAL_MONDAY_WEEKDAY:
+                       case I_CAL_MONDAY_WEEKDAY:
                                month_day = MONTH_DAY_MON;
                                break;
 
-                       case ICAL_TUESDAY_WEEKDAY:
+                       case I_CAL_TUESDAY_WEEKDAY:
                                month_day = MONTH_DAY_TUE;
                                break;
 
-                       case ICAL_WEDNESDAY_WEEKDAY:
+                       case I_CAL_WEDNESDAY_WEEKDAY:
                                month_day = MONTH_DAY_WED;
                                break;
 
-                       case ICAL_THURSDAY_WEEKDAY:
+                       case I_CAL_THURSDAY_WEEKDAY:
                                month_day = MONTH_DAY_THU;
                                break;
 
-                       case ICAL_FRIDAY_WEEKDAY:
+                       case I_CAL_FRIDAY_WEEKDAY:
                                month_day = MONTH_DAY_FRI;
                                break;
 
-                       case ICAL_SATURDAY_WEEKDAY:
+                       case I_CAL_SATURDAY_WEEKDAY:
                                month_day = MONTH_DAY_SAT;
                                break;
 
-                       case ICAL_SUNDAY_WEEKDAY:
+                       case I_CAL_SUNDAY_WEEKDAY:
                                month_day = MONTH_DAY_SUN;
                                break;
 
@@ -5251,13 +5349,13 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                                g_dngettext (GETTEXT_PACKAGE,
                                        "every month",
                                        "every %d months",
-                                       rrule.interval), rrule.interval);
+                                       i_cal_recurrence_get_interval (rrule)), i_cal_recurrence_get_interval 
(rrule));
                } else {
                        prefix = g_strdup_printf (
                                g_dngettext (GETTEXT_PACKAGE,
                                        "Every month",
                                        "Every %d months",
-                                       rrule.interval), rrule.interval);
+                                       i_cal_recurrence_get_interval (rrule)), i_cal_recurrence_get_interval 
(rrule));
                }
 
                switch (month_day) {
@@ -5598,7 +5696,7 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                break;
        }
 
-       case ICAL_YEARLY_RECURRENCE:
+       case I_CAL_YEARLY_RECURRENCE:
                if (n_by_day != 0 ||
                    n_by_month_day != 0 ||
                    n_by_year_day != 0 ||
@@ -5607,20 +5705,20 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                    n_by_set_pos != 0)
                        goto custom;
 
-               if (rrule.interval > 0) {
-                       if (!rrule.count && !rrule.until.year) {
+               if (i_cal_recurrence_get_interval (rrule) > 0) {
+                       if (!i_cal_recurrence_get_count (rrule) && (!until || !i_cal_time_get_year (until))) {
                                if (prefixed) {
                                        result = g_strdup_printf (
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "every year forever",
                                                        "every %d years forever",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                } else {
                                        result = g_strdup_printf (
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "Every year forever",
                                                        "Every %d years forever",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                }
                        } else {
                                if (prefixed) {
@@ -5628,13 +5726,13 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "every year",
                                                        "every %d years",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                } else {
                                        prefix = g_strdup_printf (
                                                g_dngettext (GETTEXT_PACKAGE,
                                                        "Every year",
                                                        "Every %d years",
-                                                       rrule.interval), rrule.interval);
+                                                       i_cal_recurrence_get_interval (rrule)), 
i_cal_recurrence_get_interval (rrule));
                                }
                        }
                }
@@ -5645,7 +5743,7 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
        }
 
        if (prefix) {
-               if (rrule.count) {
+               if (i_cal_recurrence_get_count (rrule)) {
                        suffix = g_strdup_printf (
                                g_dngettext (GETTEXT_PACKAGE,
                                        /* Translators: This is one of the last possible parts of a 
recurrence description.
@@ -5653,32 +5751,28 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                                           for example: "Every 3 days for 10 occurrences" */
                                        "for one occurrence",
                                        "for %d occurrences",
-                                       rrule.count), rrule.count);
-               } else if (rrule.until.year) {
+                                       i_cal_recurrence_get_count (rrule)), i_cal_recurrence_get_count 
(rrule));
+               } else if (until && i_cal_time_get_year (until)) {
                        struct tm tm;
                        gchar dt_str[256];
 
                        dt_str[0] = 0;
 
-                       if (!rrule.until.is_date) {
-                               icaltimezone *from_zone, *to_zone;
-                               struct icaltimetype dtstart;
-
-                               dtstart = icalcomponent_get_dtstart (icalcomp);
+                       if (!i_cal_time_is_date (until)) {
+                               ICalTimezone *from_zone, *to_zone;
 
-                               from_zone = icaltimezone_get_utc_timezone ();
-                               to_zone = (icaltimezone *) dtstart.zone;
+                               from_zone = i_cal_timezone_get_utc_timezone ();
+                               to_zone = i_cal_time_get_timezone (dtstart);
 
                                if (to_zone)
-                                       icaltimezone_convert_time (&rrule.until, from_zone, to_zone);
+                                       i_cal_timezone_convert_time (until, from_zone, to_zone);
 
-                               rrule.until.hour = 0;
-                               rrule.until.minute = 0;
-                               rrule.until.second = 0;
-                               rrule.until.is_date = TRUE;
+                               i_cal_time_set_time (until, 0, 0, 0);
+                               i_cal_time_set_is_date (until, TRUE);
                        }
 
-                       tm = icaltimetype_to_tm (&rrule.until);
+                       tm = e_cal_util_icaltime_to_tm (until);
+
                        e_time_format_date_and_time (&tm, FALSE, FALSE, FALSE, dt_str, 255);
 
                        if (*dt_str) {
@@ -5715,7 +5809,7 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                gint n_exdates;
                gchar *tmp;
 
-               n_exdates = icalcomponent_count_properties (icalcomp, ICAL_EXDATE_PROPERTY);
+               n_exdates = i_cal_component_count_properties (icalcomp, I_CAL_EXDATE_PROPERTY);
                if (n_exdates > 0) {
                        gchar *exdates_str;
 
@@ -5740,16 +5834,16 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                if (prefixed) {
                        const gchar *comp_prefix;
 
-                       if (icalcomponent_isa (icalcomp) == ICAL_VEVENT_COMPONENT) {
-                               if (icalcomponent_count_properties (icalcomp, ICAL_ORGANIZER_PROPERTY) > 0 &&
-                                   icalcomponent_count_properties (icalcomp, ICAL_ATTENDEE_PROPERTY) > 0) {
+                       if (i_cal_component_isa (icalcomp) == I_CAL_VEVENT_COMPONENT) {
+                               if (i_cal_component_count_properties (icalcomp, I_CAL_ORGANIZER_PROPERTY) > 0 
&&
+                                   i_cal_component_count_properties (icalcomp, I_CAL_ATTENDEE_PROPERTY) > 0) 
{
                                        comp_prefix = C_("recur-description", "The meeting recurs");
                                } else {
                                        comp_prefix = C_("recur-description", "The appointment recurs");
                                }
-                       } else if (icalcomponent_isa (icalcomp) == ICAL_VTODO_COMPONENT) {
+                       } else if (i_cal_component_isa (icalcomp) == I_CAL_VTODO_COMPONENT) {
                                comp_prefix = C_("recur-description", "The task recurs");
-                       } else /* if (icalcomponent_isa (icalcomp) == ICAL_VJOURNAL_COMPONENT) */ {
+                       } else /* if (i_cal_component_isa (comp) == I_CAL_VJOURNAL_COMPONENT) */ {
                                comp_prefix = C_("recur-description", "The memo recurs");
                        }
 
@@ -5763,20 +5857,24 @@ e_cal_recur_describe_recurrence (icalcomponent *icalcomp,
                        result = tmp;
                }
        } else if (fallback) {
-               if (icalcomponent_isa (icalcomp) == ICAL_VEVENT_COMPONENT) {
-                       if (icalcomponent_count_properties (icalcomp, ICAL_ORGANIZER_PROPERTY) > 0 &&
-                           icalcomponent_count_properties (icalcomp, ICAL_ATTENDEE_PROPERTY) > 0) {
+               if (i_cal_component_isa (icalcomp) == I_CAL_VEVENT_COMPONENT) {
+                       if (i_cal_component_count_properties (icalcomp, I_CAL_ORGANIZER_PROPERTY) > 0 &&
+                           i_cal_component_count_properties (icalcomp, I_CAL_ATTENDEE_PROPERTY) > 0) {
                                result = g_strdup (C_("recur-description", "The meeting recurs"));
                        } else {
                                result = g_strdup (C_("recur-description", "The appointment recurs"));
                        }
-               } else if (icalcomponent_isa (icalcomp) == ICAL_VTODO_COMPONENT) {
+               } else if (i_cal_component_isa (icalcomp) == I_CAL_VTODO_COMPONENT) {
                        result = g_strdup (C_("recur-description", "The task recurs"));
-               } else if (icalcomponent_isa (icalcomp) == ICAL_VJOURNAL_COMPONENT) {
+               } else if (i_cal_component_isa (icalcomp) == I_CAL_VJOURNAL_COMPONENT) {
                        result = g_strdup (C_("recur-description", "The memo recurs"));
                }
        }
 
+       g_clear_object (&dtstart);
+       g_clear_object (&until);
+       g_clear_object (&rrule);
+       g_clear_object (&prop);
        g_free (prefix);
        g_free (mid);
        g_free (suffix);
diff --git a/src/calendar/libecal/e-cal-recur.h b/src/calendar/libecal/e-cal-recur.h
index 025cfdbed..dddad058b 100644
--- a/src/calendar/libecal/e-cal-recur.h
+++ b/src/calendar/libecal/e-cal-recur.h
@@ -29,99 +29,93 @@
 #include <glib.h>
 #include <gio/gio.h>
 
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
+
 #include <libecal/e-cal-component.h>
+#include <libecal/e-cal-enums.h>
 
 G_BEGIN_DECLS
 
-typedef icaltimezone * (* ECalRecurResolveTimezoneCb)  (const gchar *tzid,
+/**
+ * E_CAL_EVOLUTION_ENDDATE_PARAMETER:
+ *
+ * The X parameter name being used to store the enddate in RRULE and EXRULE properties.
+ *
+ * Since: 3.36
+ **/
+#define E_CAL_EVOLUTION_ENDDATE_PARAMETER      "X-EVOLUTION-ENDDATE"
+
+/**
+ * ECalRecurResolveTimezoneCb:
+ * @tzid: timezone ID to resolve
+ * @user_data: user data used for this callback
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Resolve timezone by its ID provided as @tzid. Free the returned object,
+ * if not %NULL, with g_object_unref(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a new #ICalTimezone object for @tzid,
+ *    or %NULL, on error or if not found.
+ *
+ * Since: 3.36
+ **/
+typedef ICalTimezone * (* ECalRecurResolveTimezoneCb)  (const gchar *tzid,
                                                         gpointer user_data,
                                                         GCancellable *cancellable,
                                                         GError **error);
 
-typedef gboolean (* ECalRecurInstanceCb)               (icalcomponent *comp,
-                                                        struct icaltimetype instance_start,
-                                                        struct icaltimetype instance_end,
+/**
+ * ECalRecurInstanceCb:
+ * @icomp: an #ICalComponent
+ * @instance_start: start time of an instance
+ * @instance_end: end time of an instance
+ * @user_data: user data used for this callback in e_cal_recur_generate_instances_sync()
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Callback used by e_cal_recur_generate_instances_sync(), called
+ * for each instance of a (recurring) component within given time range.
+ *
+ * Returns: %TRUE, to continue recurrence generation, %FALSE to stop
+ *
+ * Since: 3.36
+ **/
+typedef gboolean (* ECalRecurInstanceCb)               (ICalComponent *icomp,
+                                                        ICalTime *instance_start,
+                                                        ICalTime *instance_end,
                                                         gpointer user_data,
                                                         GCancellable *cancellable,
                                                         GError **error);
 
-gboolean       e_cal_recur_generate_instances_sync     (icalcomponent *comp,
-                                                        struct icaltimetype interval_start,
-                                                        struct icaltimetype interval_end,
+gboolean       e_cal_recur_generate_instances_sync     (ICalComponent *icalcomp,
+                                                        ICalTime *interval_start,
+                                                        ICalTime *interval_end,
                                                         ECalRecurInstanceCb callback,
                                                         gpointer callback_user_data,
                                                         ECalRecurResolveTimezoneCb get_tz_callback,
                                                         gpointer get_tz_callback_user_data,
-                                                        icaltimezone *default_timezone,
+                                                        ICalTimezone *default_timezone,
                                                         GCancellable *cancellable,
                                                         GError **error);
 
-typedef gboolean (* ECalRecurInstanceFn) (ECalComponent *comp,
-                                        time_t        instance_start,
-                                        time_t        instance_end,
-                                        gpointer      user_data);
-
-typedef icaltimezone * (* ECalRecurResolveTimezoneFn)  (const gchar   *tzid,
-                                                        gpointer      data);
-
-void   e_cal_recur_generate_instances  (ECalComponent          *comp,
-                                        time_t                  start,
-                                        time_t                  end,
-                                        ECalRecurInstanceFn     cb,
-                                        gpointer                cb_data,
-                                        ECalRecurResolveTimezoneFn tz_cb,
-                                        gpointer                  tz_cb_data,
-                                        icaltimezone           *default_timezone);
-
-time_t
-e_cal_recur_obtain_enddate (struct icalrecurrencetype *ir,
-                            icalproperty *prop,
-                            icaltimezone *zone,
-                            gboolean convert_end_date);
-
-gboolean
-e_cal_recur_ensure_end_dates (ECalComponent    *comp,
-                           gboolean             refresh,
-                           ECalRecurResolveTimezoneFn  tz_cb,
-                           gpointer             tz_cb_data);
-
-#ifndef EDS_DISABLE_DEPRECATED
-
-/* Localized nth-day-of-month strings. (Use with _() ) */
-#ifdef G_OS_WIN32
-extern const gchar **e_cal_get_recur_nth (void);
-#define e_cal_recur_nth (e_cal_get_recur_nth ())
-#else
-extern const gchar *e_cal_recur_nth[31];
-#endif
+time_t         e_cal_recur_obtain_enddate              (ICalRecurrence *ir,
+                                                        ICalProperty *prop,
+                                                        ICalTimezone *zone,
+                                                        gboolean convert_end_date);
 
-#endif /* EDS_DISABLE_DEPRECATED */
+gboolean       e_cal_recur_ensure_end_dates            (ECalComponent *comp,
+                                                        gboolean refresh,
+                                                        ECalRecurResolveTimezoneCb tz_cb,
+                                                        gpointer tz_cb_data,
+                                                        GCancellable *cancellable,
+                                                        GError **error);
 
-const gchar *          e_cal_recur_get_localized_nth           (gint nth);
+const gchar *  e_cal_recur_get_localized_nth           (gint nth);
 
-/**
- * ECalRecurDescribeRecurrenceFlags:
- * @E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_NONE: no extra flags, either returns %NULL or the recurrence 
description,
- *    something like "Every 2 weeks..."
- * @E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_PREFIXED: either returns %NULL or the recurrence description 
prefixed
- *    with text like "The meeting recurs", forming something like "The meeting recurs every 2 weeks..."
- * @E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_FALLBACK: returns %NULL only if the component doesn't recur,
- *    otherwise returns either the recurrence description or at least text like "The meeting recurs"
- *
- * Influences behaviour of e_cal_recur_describe_recurrence().
- *
- * Since: 3.30
- **/
-typedef enum {
-       E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_NONE       = 0,
-       E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_PREFIXED   = (1 << 0),
-       E_CAL_RECUR_DESCRIBE_RECURRENCE_FLAG_FALLBACK   = (1 << 1)
-} ECalRecurDescribeRecurrenceFlags;
-
-gchar *                        e_cal_recur_describe_recurrence         (icalcomponent *icalcomp,
-                                                                GDateWeekday week_start_day,
-                                                                guint32 flags);
+gchar *                e_cal_recur_describe_recurrence         (ICalComponent *icalcomp,
+                                                        GDateWeekday week_start_day,
+                                                        guint32 flags); /* bit-or of 
ECalRecurDescribeRecurrenceFlags */
 
 G_END_DECLS
 
diff --git a/src/calendar/libecal/e-cal-system-timezone.c b/src/calendar/libecal/e-cal-system-timezone.c
index b51f70e8d..09da13973 100644
--- a/src/calendar/libecal/e-cal-system-timezone.c
+++ b/src/calendar/libecal/e-cal-system-timezone.c
@@ -19,6 +19,8 @@
 #include <glib/gstdio.h>
 #include <gio/gio.h>
 #include <string.h>
+#include <libical-glib/libical-glib.h>
+
 #include "e-cal-system-timezone.h"
 
 #ifndef G_OS_WIN32
@@ -541,27 +543,29 @@ static gchar *
 system_timezone_find (void)
 {
        GHashTable *ical_zones;
-       icalarray *builtin_timezones;
-       gint ii;
+       ICalArray *builtin_timezones;
+       gint ii, nelems;
        gchar *tz, *config_tz = NULL;
 
        /* return only timezones known to libical */
        ical_zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
        g_hash_table_add (ical_zones, g_strdup ("UTC"));
 
-       builtin_timezones = icaltimezone_get_builtin_timezones ();
-       for (ii = 0; ii < builtin_timezones->num_elements; ii++) {
-               icaltimezone *zone;
+       builtin_timezones = i_cal_timezone_get_builtin_timezones ();
+       nelems = i_cal_array_size (builtin_timezones);
+
+       for (ii = 0; ii < nelems; ii++) {
+               ICalTimezone *zone;
                const gchar *location;
 
-               zone = icalarray_element_at (builtin_timezones, ii);
+               zone = i_cal_timezone_array_element_at (builtin_timezones, ii);
                if (!zone)
                        continue;
 
-               location = icaltimezone_get_location (zone);
+               location = i_cal_timezone_get_location (zone);
                if (location)
-                       g_hash_table_add (
-                               ical_zones, g_strdup (location));
+                       g_hash_table_add (ical_zones, g_strdup (location));
+               g_object_unref (zone);
        }
 
        /* softlink is the best option, it points to the correct file */
diff --git a/src/calendar/libecal/e-cal-system-timezone.h b/src/calendar/libecal/e-cal-system-timezone.h
index 49bcb9072..017dcad8f 100644
--- a/src/calendar/libecal/e-cal-system-timezone.h
+++ b/src/calendar/libecal/e-cal-system-timezone.h
@@ -23,7 +23,7 @@
 #ifndef E_CAL_SYSTEM_TIMEZONE_H
 #define E_CAL_SYSTEM_TIMEZONE_H
 
-#include <libical/ical.h>
+#include <glib.h>
 
 gchar *e_cal_system_timezone_get_location (void);
 
diff --git a/src/calendar/libecal/e-cal-time-util.c b/src/calendar/libecal/e-cal-time-util.c
index 22649c588..f89dbaf6e 100644
--- a/src/calendar/libecal/e-cal-time-util.c
+++ b/src/calendar/libecal/e-cal-time-util.c
@@ -23,7 +23,6 @@
 #include <ctype.h>
 #include "e-cal-time-util.h"
 
-
 #ifdef G_OS_WIN32
 #ifdef gmtime_r
 #undef gmtime_r
@@ -50,7 +49,7 @@ static const gint days_in_month[12] = {
  *
  * NOTE: these use the Unix timezone functions like mktime() and localtime()
  * and so should not be used in Evolution. New Evolution code should use
- * icaltimetype values rather than time_t values wherever possible.
+ * ICalTime values rather than time_t values wherever possible.
  **************************************************************************/
 
 /**
@@ -142,7 +141,7 @@ time_day_end (time_t t)
  * time_t manipulation functions, using timezones in libical.
  *
  * NOTE: these are only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values rather than
+ * functions easier. New code should use ICalTime values rather than
  * time_t values wherever possible.
  **************************************************************************/
 
@@ -155,26 +154,31 @@ time_day_end (time_t t)
  * Adds or subtracts a number of days to/from the given time_t value, using
  * the given timezone.
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: a time_t value containing @time plus the days added.
  */
 time_t
 time_add_day_with_zone (time_t time,
-                        gint days,
-                        icaltimezone *zone)
+                       gint days,
+                       const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
+       time_t res;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Add/subtract the number of days. */
-       icaltime_adjust (&tt, days, 0, 0, 0);
+       i_cal_time_adjust (tt, days, 0, 0, 0);
 
        /* Convert back to a time_t. */
-       return icaltime_as_timet_with_zone (tt, zone);
+       res = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone);
+
+       g_object_unref (tt);
+
+       return res;
 }
 
 /**
@@ -186,15 +190,15 @@ time_add_day_with_zone (time_t time,
  * Adds or subtracts a number of weeks to/from the given time_t value, using
  * the given timezone.
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: a time_t value containing @time plus the weeks added.
  */
 time_t
 time_add_week_with_zone (time_t time,
-                         gint weeks,
-                         icaltimezone *zone)
+                        gint weeks,
+                        const ICalTimezone *zone)
 {
        return time_add_day_with_zone (time, weeks * 7, zone);
 }
@@ -213,42 +217,47 @@ time_add_week_with_zone (time_t time,
  * down to the last day in the month, e.g. 28th Feb (or 29th in a leap year.)
  *
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: a time_t value containing @time plus the months added.
  */
 time_t
 time_add_month_with_zone (time_t time,
-                          gint months,
-                          icaltimezone *zone)
+                         gint months,
+                         const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
        gint day, days_in_month;
+       time_t res;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Add on the number of months. */
-       tt.month += months;
+       i_cal_time_set_month (tt, i_cal_time_get_month (tt) + months);
 
        /* Save the day, and set it to 1, so we don't overflow into the next
         * month. */
-       day = tt.day;
-       tt.day = 1;
+       day = i_cal_time_get_day (tt);
+       i_cal_time_set_day (tt, 1);
 
        /* Normalize it, fixing any month overflow. */
-       tt = icaltime_normalize (tt);
+       i_cal_time_normalize_inplace (tt);
 
        /* If we go past the end of a month, set it to the last day. */
-       days_in_month = time_days_in_month (tt.year, tt.month - 1);
+       days_in_month = time_days_in_month (i_cal_time_get_year (tt), i_cal_time_get_month (tt) - 1);
        if (day > days_in_month)
                day = days_in_month;
 
-       tt.day = day;
+       i_cal_time_set_day (tt, day);
 
        /* Convert back to a time_t. */
-       return icaltime_as_timet_with_zone (tt, zone);
+       res = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone);
+
+       g_object_unref (tt);
+
+       return res;
 }
 
 /**
@@ -259,29 +268,34 @@ time_add_month_with_zone (time_t time,
  * Returns the start of the year containing the given time_t, using the given
  * timezone.
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: the beginning of the year.
  */
 time_t
 time_year_begin_with_zone (time_t time,
-                           icaltimezone *zone)
+                          const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
+       time_t res;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Set it to the start of the year. */
-       tt.month = 1;
-       tt.day = 1;
-       tt.hour = 0;
-       tt.minute = 0;
-       tt.second = 0;
+       i_cal_time_set_month (tt, 1);
+       i_cal_time_set_day (tt, 1);
+       i_cal_time_set_hour (tt, 0);
+       i_cal_time_set_minute (tt, 0);
+       i_cal_time_set_second (tt, 0);
 
        /* Convert back to a time_t. */
-       return icaltime_as_timet_with_zone (tt, zone);
+       res = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone);
+
+       g_object_unref (tt);
+
+       return res;
 }
 
 /**
@@ -292,28 +306,33 @@ time_year_begin_with_zone (time_t time,
  * Returns the start of the month containing the given time_t, using the given
  * timezone.
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: the beginning of the month.
  */
 time_t
 time_month_begin_with_zone (time_t time,
-                            icaltimezone *zone)
+                           const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
+       time_t res;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Set it to the start of the month. */
-       tt.day = 1;
-       tt.hour = 0;
-       tt.minute = 0;
-       tt.second = 0;
+       i_cal_time_set_day (tt, 1);
+       i_cal_time_set_hour (tt, 0);
+       i_cal_time_set_minute (tt, 0);
+       i_cal_time_set_second (tt, 0);
 
        /* Convert back to a time_t. */
-       return icaltime_as_timet_with_zone (tt, zone);
+       res = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone);
+
+       g_object_unref (tt);
+
+       return res;
 }
 
 /**
@@ -326,39 +345,44 @@ time_month_begin_with_zone (time_t time,
  * timezone. week_start_day should use the same values as mktime(),
  * i.e. 0 (Sun) to 6 (Sat).
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: the beginning of the week.
  */
 time_t
 time_week_begin_with_zone (time_t time,
-                           gint week_start_day,
-                           icaltimezone *zone)
+                          gint week_start_day,
+                          const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
        gint weekday, offset;
+       time_t res;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Get the weekday. */
-       weekday = time_day_of_week (tt.day, tt.month - 1, tt.year);
+       weekday = time_day_of_week (i_cal_time_get_day (tt), i_cal_time_get_month (tt) - 1, 
i_cal_time_get_year (tt));
 
        /* Calculate the current offset from the week start day. */
        offset = (weekday + 7 - week_start_day) % 7;
 
        /* Set it to the start of the month. */
-       tt.day -= offset;
-       tt.hour = 0;
-       tt.minute = 0;
-       tt.second = 0;
+       i_cal_time_set_day (tt, i_cal_time_get_day (tt) - offset);
+       i_cal_time_set_hour (tt, 0);
+       i_cal_time_set_minute (tt, 0);
+       i_cal_time_set_second (tt, 0);
 
        /* Normalize it, to fix any overflow. */
-       tt = icaltime_normalize (tt);
+       i_cal_time_normalize_inplace (tt);
 
        /* Convert back to a time_t. */
-       return icaltime_as_timet_with_zone (tt, zone);
+       res = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone);
+
+       g_object_unref (tt);
+
+       return res;
 }
 
 /**
@@ -369,31 +393,33 @@ time_week_begin_with_zone (time_t time,
  * Returns the start of the day containing the given time_t, using the given
  * timezone.
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: the beginning of the day.
  */
 time_t
 time_day_begin_with_zone (time_t time,
-                          icaltimezone *zone)
+                         const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
        time_t new_time;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Set it to the start of the day. */
-       tt.hour = 0;
-       tt.minute = 0;
-       tt.second = 0;
+       i_cal_time_set_hour (tt, 0);
+       i_cal_time_set_minute (tt, 0);
+       i_cal_time_set_second (tt, 0);
 
        /* Convert back to a time_t and make sure the time is in the past. */
-       while (new_time = icaltime_as_timet_with_zone (tt, zone), new_time > time) {
-               icaltime_adjust (&tt, 0, -1, 0, 0);
+       while (new_time = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone), new_time > time) {
+               i_cal_time_adjust (tt, 0, -1, 0, 0);
        }
 
+       g_object_unref (tt);
+
        return new_time;
 }
 
@@ -405,33 +431,35 @@ time_day_begin_with_zone (time_t time,
  * Returns the end of the day containing the given time_t, using the given
  * timezone. (The end of the day is the start of the next day.)
  * NOTE: this function is only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values and
- * icaltime_adjust() to add or subtract days, hours, minutes & seconds.
+ * functions easier. New code should use ICalTime values and
+ * i_cal_time_adjust() to add or subtract days, hours, minutes & seconds.
  *
  * Returns: the end of the day.
  */
 time_t
 time_day_end_with_zone (time_t time,
-                        icaltimezone *zone)
+                       const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
        time_t new_time;
 
        /* Convert to an icaltimetype. */
-       tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+       tt = i_cal_time_from_timet_with_zone (time, FALSE, (ICalTimezone *) zone);
 
        /* Set it to the start of the next day. */
-       tt.hour = 0;
-       tt.minute = 0;
-       tt.second = 0;
+       i_cal_time_set_hour (tt, 0);
+       i_cal_time_set_minute (tt, 0);
+       i_cal_time_set_second (tt, 0);
 
-       icaltime_adjust (&tt, 1, 0, 0, 0);
+       i_cal_time_adjust (tt, 1, 0, 0, 0);
 
        /* Convert back to a time_t and make sure the time is in the future. */
-       while (new_time = icaltime_as_timet_with_zone (tt, zone), new_time <= time) {
-               icaltime_adjust (&tt, 0, 1, 0, 0);
+       while (new_time = i_cal_time_as_timet_with_zone (tt, (ICalTimezone *) zone), new_time <= time) {
+               i_cal_time_adjust (tt, 0, 1, 0, 0);
        }
 
+       g_object_unref (tt);
+
        return new_time;
 }
 
@@ -439,27 +467,29 @@ time_day_end_with_zone (time_t time,
  * time_to_gdate_with_zone:
  * @date: Destination #GDate value.
  * @time: A time value.
- * @zone: Desired timezone for destination @date, or NULL if the UTC timezone
- * is desired.
+ * @zone: (nullable): Desired timezone for destination @date, or %NULL if
+ *    the UTC timezone is desired.
  *
  * Converts a time_t value to a #GDate structure using the specified timezone.
  * This is analogous to g_date_set_time() but takes the timezone into account.
  **/
 void
 time_to_gdate_with_zone (GDate *date,
-                         time_t time,
-                         icaltimezone *zone)
+                        time_t time,
+                        const ICalTimezone *zone)
 {
-       struct icaltimetype tt;
+       ICalTime *tt;
 
        g_return_if_fail (date != NULL);
        g_return_if_fail (time != -1);
 
-       tt = icaltime_from_timet_with_zone (
+       tt = i_cal_time_from_timet_with_zone (
                time, FALSE,
-               zone ? zone : icaltimezone_get_utc_timezone ());
+               zone ? (ICalTimezone *) zone : i_cal_timezone_get_utc_timezone ());
+
+       g_date_set_dmy (date, i_cal_time_get_day (tt), i_cal_time_get_month (tt), i_cal_time_get_year (tt));
 
-       g_date_set_dmy (date, tt.day, tt.month, tt.year);
+       g_object_unref (tt);
 }
 
 /**************************************************************************
@@ -630,9 +660,10 @@ isodate_from_time_t (time_t t)
 time_t
 time_from_isodate (const gchar *str)
 {
-       struct icaltimetype tt = icaltime_null_time ();
-       icaltimezone *utc_zone;
+       ICalTime *tt;
+       ICalTimezone *utc_zone;
        gint len, i;
+       time_t res;
 
        g_return_val_if_fail (str != NULL, -1);
 
@@ -651,66 +682,75 @@ time_from_isodate (const gchar *str)
 
 #define digit_at(x,y) (x[y] - '0')
 
-       tt.year = digit_at (str, 0) * 1000
-               + digit_at (str, 1) * 100
-               + digit_at (str, 2) * 10
-               + digit_at (str, 3);
+       tt = i_cal_time_null_time ();
 
-       tt.month = digit_at (str, 4) * 10
-                + digit_at (str, 5);
+       i_cal_time_set_year (tt, digit_at (str, 0) * 1000 +
+                                    digit_at (str, 1) * 100 +
+                                    digit_at (str, 2) * 10 +
+                                    digit_at (str, 3));
 
-       tt.day = digit_at (str, 6) * 10
-              + digit_at (str, 7);
+       i_cal_time_set_month (tt, digit_at (str, 4) * 10 +
+                                     digit_at (str, 5));
+
+       i_cal_time_set_day (tt, digit_at (str, 6) * 10 +
+                                   digit_at (str, 7));
 
        if (len > 8) {
-               tt.hour = digit_at (str, 9) * 10
-                       + digit_at (str, 10);
-               tt.minute = digit_at (str, 11) * 10
-                          + digit_at (str, 12);
-               tt.second = digit_at (str, 13) * 10
-                          + digit_at (str, 14);
+               i_cal_time_set_hour (tt, digit_at (str, 9) * 10 +
+                                            digit_at (str, 10));
+               i_cal_time_set_minute (tt, digit_at (str, 11) * 10 +
+                                              digit_at (str, 12));
+               i_cal_time_set_second (tt, digit_at (str, 13) * 10 +
+                                              digit_at (str, 14));
        }
 
-       utc_zone = icaltimezone_get_utc_timezone ();
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+
+       res = i_cal_time_as_timet_with_zone (tt, utc_zone);
 
-       return icaltime_as_timet_with_zone (tt, utc_zone);
+       g_object_unref (tt);
+
+       return res;
 }
 
 /**
- * icaltimetype_to_tm:
- * @itt: An icaltimetype structure.
+ * e_cal_util_icaltime_to_tm:
+ * @itt: An #ICalTime
  *
- * Convers an icaltimetype structure into a GLibc's struct tm.
+ * Converts an #ICalTime into a GLibc's struct tm.
  *
- * Returns: (transfer full): The converted time as a struct tm. All fields will be
- * set properly except for tm.tm_yday.
+ * Returns: The converted time as a struct tm. All fields will be
+ *    set properly except for tm.tm_yday.
  *
  * Since: 2.22
  */
 struct tm
-icaltimetype_to_tm (struct icaltimetype *itt)
+e_cal_util_icaltime_to_tm (const ICalTime *itt)
 {
        struct tm tm;
+       ICalTime *tt = (ICalTime *) itt;
 
        memset (&tm, 0, sizeof (struct tm));
 
-       if (!itt->is_date) {
-               tm.tm_sec = itt->second;
-               tm.tm_min = itt->minute;
-               tm.tm_hour = itt->hour;
+       g_return_val_if_fail (itt != NULL, tm);
+
+       if (!i_cal_time_is_date (tt)) {
+               tm.tm_sec = i_cal_time_get_second (tt);
+               tm.tm_min = i_cal_time_get_minute (tt);
+               tm.tm_hour = i_cal_time_get_hour (tt);
        }
 
-       tm.tm_mday = itt->day;
-       tm.tm_mon = itt->month - 1;
-       tm.tm_year = itt->year - 1900;
-       tm.tm_wday = time_day_of_week (itt->day, itt->month - 1, itt->year);
+       tm.tm_mday = i_cal_time_get_day (tt);
+       tm.tm_mon = i_cal_time_get_month (tt) - 1;
+       tm.tm_year = i_cal_time_get_year (tt) - 1900;
+       tm.tm_wday = time_day_of_week (i_cal_time_get_day (tt), i_cal_time_get_month (tt) - 1, 
i_cal_time_get_year (tt));
        tm.tm_isdst = -1;
 
        return tm;
 }
 
 /**
- * icaltimetype_to_tm_with_zone:
+ * e_cal_util_icaltime_to_tm_with_zone:
  * @itt: A time value.
  * @from_zone: Source timezone.
  * @to_zone: Destination timezone.
@@ -718,63 +758,60 @@ icaltimetype_to_tm (struct icaltimetype *itt)
  * Converts a time value from one timezone to another, and returns a struct tm
  * representation of the time.
  *
- * Returns: (transfer full): The converted time as a struct tm. All fields will be
- * set properly except for tm.tm_yday.
+ * Returns: The converted time as a struct tm. All fields will be
+ *    set properly except for tm.tm_yday.
  *
  * Since: 2.22
  **/
 struct tm
-icaltimetype_to_tm_with_zone (struct icaltimetype *itt,
-                              icaltimezone *from_zone,
-                              icaltimezone *to_zone)
+e_cal_util_icaltime_to_tm_with_zone (const ICalTime *itt,
+                                    const ICalTimezone *from_zone,
+                                    const ICalTimezone *to_zone)
 {
        struct tm tm;
-       struct icaltimetype itt_copy;
+       ICalTime *itt_copy;
 
        memset (&tm, 0, sizeof (tm));
        tm.tm_isdst = -1;
 
        g_return_val_if_fail (itt != NULL, tm);
 
-       itt_copy = *itt;
+       itt_copy = i_cal_time_new_clone (itt);
 
-       icaltimezone_convert_time (&itt_copy, from_zone, to_zone);
-       tm = icaltimetype_to_tm (&itt_copy);
+       i_cal_timezone_convert_time (itt_copy, (ICalTimezone *) from_zone, (ICalTimezone *) to_zone);
+       tm = e_cal_util_icaltime_to_tm (itt_copy);
+       g_object_unref (itt_copy);
 
        return tm;
 }
 
 /**
- * tm_to_icaltimetype:
+ * e_cal_util_tm_to_icaltime:
  * @tm: A struct tm.
  * @is_date: Whether the given time is a date only or not.
  *
- * Converts a struct tm into an icaltimetype.
+ * Converts a struct tm into an #ICalTime. Free the returned object
+ * with g_object_unref(), when no longe needed.
  *
- * Returns: (transfer full): The converted time as an icaltimetype.
+ * Returns: (transfer full): The converted time as an #ICalTime.
  *
  * Since: 2.22
  */
-struct icaltimetype
-tm_to_icaltimetype (struct tm *tm,
-                    gboolean is_date)
+ICalTime *
+e_cal_util_tm_to_icaltime (struct tm *tm,
+                          gboolean is_date)
 {
-       struct icaltimetype itt;
+       ICalTime *itt;
 
-       memset (&itt, 0, sizeof (struct icaltimetype));
+       g_return_val_if_fail (tm != NULL, NULL);
 
-       if (!is_date) {
-               itt.second = tm->tm_sec;
-               itt.minute = tm->tm_min;
-               itt.hour = tm->tm_hour;
-       }
+       itt = i_cal_time_null_time ();
 
-       itt.day = tm->tm_mday;
-       itt.month = tm->tm_mon + 1;
-       itt.year = tm->tm_year + 1900;
+       if (!is_date)
+               i_cal_time_set_time (itt, tm->tm_hour, tm->tm_min, tm->tm_sec);
 
-       itt.is_date = is_date;
+       i_cal_time_set_date (itt, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
+       i_cal_time_set_is_date (itt, is_date);
 
        return itt;
 }
-
diff --git a/src/calendar/libecal/e-cal-time-util.h b/src/calendar/libecal/e-cal-time-util.h
index 550a90145..8acb13061 100644
--- a/src/calendar/libecal/e-cal-time-util.h
+++ b/src/calendar/libecal/e-cal-time-util.h
@@ -28,7 +28,7 @@
 #define TIMEUTIL_H
 
 #include <time.h>
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 #include <glib.h>
 
 G_BEGIN_DECLS
@@ -39,99 +39,126 @@ G_BEGIN_DECLS
 
 /* Returns the number of days in the month. Year is the normal year, e.g. 2001.
  * Month is 0 (Jan) to 11 (Dec). */
-gint   time_days_in_month      (gint year, gint month);
+gint           time_days_in_month      (gint year,
+                                        gint month);
 
 /* Returns the 1-based day number within the year of the specified date.
  * Year is the normal year, e.g. 2001. Month is 0 to 11. */
-gint   time_day_of_year        (gint day, gint month, gint year);
+gint           time_day_of_year        (gint day,
+                                        gint month,
+                                        gint year);
 
 /* Returns the day of the week for the specified date, 0 (Sun) to 6 (Sat).
  * For the days that were removed on the Gregorian reformation, it returns
  * Thursday. Year is the normal year, e.g. 2001. Month is 0 to 11. */
-gint   time_day_of_week        (gint day, gint month, gint year);
+gint           time_day_of_week        (gint day,
+                                        gint month,
+                                        gint year);
 
 /* Returns whether the specified year is a leap year. Year is the normal year,
  * e.g. 2001. */
-gboolean time_is_leap_year     (gint year);
+gboolean       time_is_leap_year       (gint year);
 
 /* Returns the number of leap years since year 1 up to (but not including) the
  * specified year. Year is the normal year, e.g. 2001. */
-gint   time_leap_years_up_to   (gint year);
+gint           time_leap_years_up_to   (gint year);
 
 /* Convert to or from an ISO 8601 representation of a time, in UTC,
  * e.g. "20010708T183000Z". */
-gchar   *isodate_from_time_t     (time_t t);
-time_t time_from_isodate       (const gchar *str);
+gchar *                isodate_from_time_t     (time_t t);
+time_t         time_from_isodate       (const gchar *str);
 
 /**************************************************************************
  * time_t manipulation functions.
  *
  * NOTE: these use the Unix timezone functions like mktime() and localtime()
  * and so should not be used in Evolution. New Evolution code should use
- * icaltimetype values rather than time_t values wherever possible.
+ * ICalTime values rather than time_t values wherever possible.
  **************************************************************************/
 
 /* Add or subtract a number of days, weeks or months. */
-time_t time_add_day            (time_t time, gint days);
-time_t time_add_week           (time_t time, gint weeks);
+time_t         time_add_day            (time_t time,
+                                        gint days);
+time_t         time_add_week           (time_t time,
+                                        gint weeks);
 
 /* Returns the beginning or end of the day. */
-time_t time_day_begin          (time_t t);
-time_t time_day_end            (time_t t);
+time_t         time_day_begin          (time_t t);
+time_t         time_day_end            (time_t t);
 
 /**************************************************************************
  * time_t manipulation functions, using timezones in libical.
  *
  * NOTE: these are only here to make the transition to the timezone
- * functions easier. New code should use icaltimetype values rather than
+ * functions easier. New code should use ICalTime values rather than
  * time_t values wherever possible.
  **************************************************************************/
 
 /* Adds or subtracts a number of days to/from the given time_t value, using
  * the given timezone. */
-time_t time_add_day_with_zone (time_t time, gint days, icaltimezone *zone);
+time_t         time_add_day_with_zone  (time_t time,
+                                        gint days,
+                                        const ICalTimezone *zone);
 
 /* Adds or subtracts a number of weeks to/from the given time_t value, using
  * the given timezone. */
-time_t time_add_week_with_zone (time_t time, gint weeks, icaltimezone *zone);
+time_t         time_add_week_with_zone (time_t time,
+                                        gint weeks,
+                                        const ICalTimezone *zone);
 
 /* Adds or subtracts a number of months to/from the given time_t value, using
  * the given timezone. */
-time_t time_add_month_with_zone (time_t time, gint months, icaltimezone *zone);
+time_t         time_add_month_with_zone(time_t time,
+                                        gint months,
+                                        const ICalTimezone *zone);
 
 /* Returns the start of the year containing the given time_t, using the given
  * timezone. */
-time_t time_year_begin_with_zone (time_t time, icaltimezone *zone);
+time_t         time_year_begin_with_zone
+                                       (time_t time,
+                                        const ICalTimezone *zone);
 
 /* Returns the start of the month containing the given time_t, using the given
  * timezone. */
-time_t time_month_begin_with_zone (time_t time, icaltimezone *zone);
+time_t         time_month_begin_with_zone
+                                       (time_t time,
+                                        const ICalTimezone *zone);
 
 /* Returns the start of the week containing the given time_t, using the given
  * timezone. week_start_day should use the same values as mktime (),
  * i.e. 0 (Sun) to 6 (Sat). */
-time_t time_week_begin_with_zone (time_t time, gint week_start_day,
-                                  icaltimezone *zone);
+time_t         time_week_begin_with_zone
+                                       (time_t time,
+                                        gint week_start_day,
+                                        const ICalTimezone *zone);
 
 /* Returns the start of the day containing the given time_t, using the given
  * timezone. */
-time_t time_day_begin_with_zone (time_t time, icaltimezone *zone);
+time_t         time_day_begin_with_zone(time_t time,
+                                        const ICalTimezone *zone);
 
 /* Returns the end of the day containing the given time_t, using the given
  * timezone. (The end of the day is the start of the next day.) */
-time_t time_day_end_with_zone (time_t time, icaltimezone *zone);
+time_t         time_day_end_with_zone  (time_t time,
+                                        const ICalTimezone *zone);
 
-void time_to_gdate_with_zone (GDate *date, time_t time, icaltimezone *zone);
+void           time_to_gdate_with_zone (GDate *date,
+                                        time_t time,
+                                        const ICalTimezone *zone);
 
 /**************************************************************************
  * struct tm manipulation
  **************************************************************************/
 
-struct tm icaltimetype_to_tm (struct icaltimetype *itt);
-struct tm icaltimetype_to_tm_with_zone (struct icaltimetype *itt,
-                                       icaltimezone *from_zone,
-                                       icaltimezone *to_zone);
-struct icaltimetype tm_to_icaltimetype (struct tm *tm, gboolean is_date);
+struct tm      e_cal_util_icaltime_to_tm
+                                       (const ICalTime *itt);
+struct tm      e_cal_util_icaltime_to_tm_with_zone
+                                       (const ICalTime *itt,
+                                        const ICalTimezone *from_zone,
+                                        const ICalTimezone *to_zone);
+ICalTime *     e_cal_util_tm_to_icaltime
+                                       (struct tm *tm,
+                                        gboolean is_date);
 
 G_END_DECLS
 
diff --git a/src/calendar/libecal/e-cal-util.c b/src/calendar/libecal/e-cal-util.c
index 71f25fa29..cef07e73f 100644
--- a/src/calendar/libecal/e-cal-util.c
+++ b/src/calendar/libecal/e-cal-util.c
@@ -26,106 +26,111 @@
 
 #include <libedataserver/libedataserver.h>
 
-#include "e-cal-util.h"
+#include "e-cal-check-timezones.h"
 #include "e-cal-client.h"
 #include "e-cal-system-timezone.h"
+#include "e-cal-recur.h"
+
+#include "e-cal-util.h"
 
 #define _TIME_MIN      ((time_t) 0)            /* Min valid time_t     */
 #define _TIME_MAX      ((time_t) INT_MAX)
 
-/**
- * cal_obj_instance_list_free:
- * @list: (element-type CalObjInstance): List of #CalObjInstance structures.
- *
- * Frees a list of #CalObjInstance structures.
- **/
-void
-cal_obj_instance_list_free (GList *list)
-{
-       CalObjInstance *i;
-       GList *l;
-
-       for (l = list; l; l = l->next) {
-               i = l->data;
-
-               if (i != NULL && i->uid != NULL) {
-                       g_free (i->uid);
-                       g_free (i);
-               } else
-                       g_warn_if_reached ();
-       }
-
-       g_list_free (list);
-}
-
-/**
- * cal_obj_uid_list_free:
- * @list: (element-type utf8): List of strings with unique identifiers.
- *
- * Frees a list of unique identifiers for calendar objects.
- **/
-void
-cal_obj_uid_list_free (GList *list)
-{
-       g_list_foreach (list, (GFunc) g_free, NULL);
-       g_list_free (list);
-}
-
 /**
  * e_cal_util_new_top_level:
  *
- * Creates a new VCALENDAR component.
+ * Creates a new VCALENDAR component. Free it with g_object_unref(),
+ * when no longer needed.
  *
- * Returns: the newly created top level component.
+ * Returns: (transfer full): the newly created top level component.
  */
-icalcomponent *
+ICalComponent *
 e_cal_util_new_top_level (void)
 {
-       icalcomponent *icalcomp;
-       icalproperty *prop;
+       ICalComponent *icalcomp;
+       ICalProperty *prop;
 
-       icalcomp = icalcomponent_new (ICAL_VCALENDAR_COMPONENT);
+       icalcomp = i_cal_component_new (I_CAL_VCALENDAR_COMPONENT);
 
        /* RFC 2445, section 4.7.1 */
-       prop = icalproperty_new_calscale ("GREGORIAN");
-       icalcomponent_add_property (icalcomp, prop);
+       prop = i_cal_property_new_calscale ("GREGORIAN");
+       i_cal_component_take_property (icalcomp, prop);
 
        /* RFC 2445, section 4.7.3 */
-       prop = icalproperty_new_prodid ("-//Ximian//NONSGML Evolution Calendar//EN");
-       icalcomponent_add_property (icalcomp, prop);
+       prop = i_cal_property_new_prodid ("-//Ximian//NONSGML Evolution Calendar//EN");
+       i_cal_component_take_property (icalcomp, prop);
 
        /* RFC 2445, section 4.7.4.  This is the iCalendar spec version, *NOT*
         * the product version!  Do not change this!
         */
-       prop = icalproperty_new_version ("2.0");
-       icalcomponent_add_property (icalcomp, prop);
+       prop = i_cal_property_new_version ("2.0");
+       i_cal_component_take_property (icalcomp, prop);
 
        return icalcomp;
 }
 
 /**
  * e_cal_util_new_component:
- * @kind: Kind of the component to create.
+ * @kind: Kind of the component to create, as #ICalComponentKind.
  *
- * Creates a new #icalcomponent of the specified kind.
+ * Creates a new #ICalComponent of the specified kind. Free it
+ * with g_object_unref(), when no longer needed.
  *
- * Returns: the newly created component.
+ * Returns: (transfer full): the newly created component.
  */
-icalcomponent *
-e_cal_util_new_component (icalcomponent_kind kind)
+ICalComponent *
+e_cal_util_new_component (ICalComponentKind kind)
 {
-       icalcomponent *comp;
-       struct icaltimetype dtstamp;
+       ICalComponent *icalcomp;
+       ICalTime *dtstamp;
        gchar *uid;
 
-       comp = icalcomponent_new (kind);
+       icalcomp = i_cal_component_new (kind);
        uid = e_util_generate_uid ();
-       icalcomponent_set_uid (comp, uid);
+       i_cal_component_set_uid (icalcomp, uid);
        g_free (uid);
-       dtstamp = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomponent_set_dtstamp (comp, dtstamp);
+       dtstamp = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       i_cal_component_set_dtstamp (icalcomp, dtstamp);
+       g_object_unref (dtstamp);
+
+       return icalcomp;
+}
+
+/**
+ * e_cal_util_copy_timezone:
+ * @zone: an ICalTimezone
+ *
+ * Copies the @zone together with its inner component and
+ * returns it as a new #ICalTimezone object. Free it with
+ * g_object_unref(), when no longer needed.
+ *
+ * Returns: (transfer full): a copy of the @zone
+ *
+ * Since: 3.36
+ **/
+ICalTimezone *
+e_cal_util_copy_timezone (const ICalTimezone *zone)
+{
+       ICalComponent *comp;
+       ICalTimezone *zone_copy;
+
+       g_return_val_if_fail (zone != NULL, NULL);
+
+       zone_copy = i_cal_timezone_copy (zone);
+       if (!zone_copy)
+               return NULL;
+
+       comp = i_cal_timezone_get_component (zone);
+       if (comp) {
+               ICalComponent *comp_copy;
 
-       return comp;
+               comp_copy = i_cal_component_new_clone (comp);
+               i_cal_timezone_set_component (zone_copy, comp_copy);
+               g_object_unref (comp_copy);
+               g_object_unref (comp);
+       }
+
+       return zone_copy;
 }
 
 static gchar *
@@ -149,20 +154,22 @@ read_line (const gchar *string)
  * e_cal_util_parse_ics_string:
  * @string: iCalendar string to be parsed.
  *
- * Parses an iCalendar string and returns a new #icalcomponent representing
+ * Parses an iCalendar string and returns a new #ICalComponent representing
  * that string. Note that this function deals with multiple VCALENDAR's in the
  * string, something that Mozilla used to do and which libical does not
  * support.
  *
- * Returns: a newly created #icalcomponent or NULL if the string isn't a
- * valid iCalendar string.
+ * Free the returned non-NULL component with g_object_unref(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly created #ICalComponent, or %NULL,
+ *    if the string isn't a valid iCalendar string.
  */
-icalcomponent *
+ICalComponent *
 e_cal_util_parse_ics_string (const gchar *string)
 {
        GString *comp_str = NULL;
        gchar *s;
-       icalcomponent *icalcomp = NULL;
+       ICalComponent *icalcomp = NULL;
 
        g_return_val_if_fail (string != NULL, NULL);
 
@@ -170,7 +177,7 @@ e_cal_util_parse_ics_string (const gchar *string)
        s = g_strstr_len (string, strlen (string), "BEGIN:VCALENDAR");
 
        if (s == NULL)
-               return icalparser_parse_string (string);
+               return i_cal_parser_parse_string (string);
 
        while (*s != '\0') {
                gchar *line = read_line (s);
@@ -181,13 +188,14 @@ e_cal_util_parse_ics_string (const gchar *string)
                        comp_str = g_string_append (comp_str, line);
 
                if (strncmp (line, "END:VCALENDAR", 13) == 0) {
-                       icalcomponent *tmp;
-
-                       tmp = icalparser_parse_string (comp_str->str);
-                       if (tmp && icalcomponent_isa (tmp) == ICAL_VCALENDAR_COMPONENT) {
-                               if (icalcomp)
-                                       icalcomponent_merge_component (icalcomp, tmp);
-                               else
+                       ICalComponent *tmp;
+
+                       tmp = i_cal_parser_parse_string (comp_str->str);
+                       if (tmp && i_cal_component_isa (tmp) == I_CAL_VCALENDAR_COMPONENT) {
+                               if (icalcomp) {
+                                       i_cal_component_merge_component (icalcomp, tmp);
+                                       g_object_unref (tmp);
+                               } else
                                        icalcomp = tmp;
                        } else {
                                g_warning (
@@ -257,16 +265,18 @@ get_line_fn (gchar *buf,
  * @filename: Name of the file to be parsed.
  *
  * Parses the given file, and, if it contains a valid iCalendar object,
- * parse it and return a new #icalcomponent.
+ * parse it and return a new #ICalComponent.
+ *
+ * Free the returned non-NULL component with g_object_unref(), when no longer needed.
  *
- * Returns: a newly created #icalcomponent or NULL if the file doesn't
- * contain a valid iCalendar object.
+ * Returns: (transfer full) (nullable): a newly created #ICalComponent, or %NULL,
+ *    if the file doesn't contain a valid iCalendar object.
  */
-icalcomponent *
+ICalComponent *
 e_cal_util_parse_ics_file (const gchar *filename)
 {
-       icalparser *parser;
-       icalcomponent *icalcomp;
+       ICalParser *parser;
+       ICalComponent *icalcomp;
        struct ics_file fl;
 
        fl.file = g_fopen (filename, "rb");
@@ -275,11 +285,11 @@ e_cal_util_parse_ics_file (const gchar *filename)
 
        fl.bof = TRUE;
 
-       parser = icalparser_new ();
-       icalparser_set_gen_data (parser, &fl);
+       parser = i_cal_parser_new ();
+       i_cal_parser_set_gen_data (parser, &fl);
 
-       icalcomp = icalparser_parse (parser, get_line_fn);
-       icalparser_free (parser);
+       icalcomp = i_cal_parser_parse (parser, get_line_fn);
+       g_object_unref (parser);
        fclose (fl.file);
 
        return icalcomp;
@@ -290,13 +300,13 @@ e_cal_util_parse_ics_file (const gchar *filename)
  */
 static void
 compute_alarm_range (ECalComponent *comp,
-                     GList *alarm_uids,
+                     GSList *alarm_uids,
                      time_t start,
                      time_t end,
                      time_t *alarm_start,
                      time_t *alarm_end)
 {
-       GList *l;
+       GSList *link;
        time_t repeat_time;
 
        *alarm_start = start;
@@ -304,41 +314,45 @@ compute_alarm_range (ECalComponent *comp,
 
        repeat_time = 0;
 
-       for (l = alarm_uids; l; l = l->next) {
+       for (link = alarm_uids; link; link = g_slist_next (link)) {
                const gchar *auid;
                ECalComponentAlarm *alarm;
-               ECalComponentAlarmTrigger trigger;
-               struct icaldurationtype *dur;
+               ECalComponentAlarmTrigger *trigger;
+               ICalDuration *dur;
                time_t dur_time;
-               ECalComponentAlarmRepeat repeat;
+               ECalComponentAlarmRepeat *repeat;
 
-               auid = l->data;
+               auid = link->data;
                alarm = e_cal_component_get_alarm (comp, auid);
                g_return_if_fail (alarm != NULL);
 
-               e_cal_component_alarm_get_trigger (alarm, &trigger);
-               e_cal_component_alarm_get_repeat (alarm, &repeat);
-               e_cal_component_alarm_free (alarm);
+               trigger = e_cal_component_alarm_get_trigger (alarm);
+               repeat = e_cal_component_alarm_get_repeat (alarm);
+
+               if (!trigger) {
+                       e_cal_component_alarm_free (alarm);
+                       continue;
+               }
 
-               switch (trigger.type) {
+               switch (e_cal_component_alarm_trigger_get_kind (trigger)) {
                case E_CAL_COMPONENT_ALARM_TRIGGER_NONE:
                case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
                        break;
 
                case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
                case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
-                       dur = &trigger.u.rel_duration;
-                       dur_time = icaldurationtype_as_int (*dur);
+                       dur = e_cal_component_alarm_trigger_get_duration (trigger);
+                       dur_time = i_cal_duration_as_int (dur);
 
-                       if (repeat.repetitions != 0) {
+                       if (repeat && e_cal_component_alarm_repeat_get_repetitions (repeat) != 0) {
                                gint rdur;
 
-                               rdur = repeat.repetitions *
-                                       icaldurationtype_as_int (repeat.duration);
+                               rdur = e_cal_component_alarm_repeat_get_repetitions (repeat) *
+                                       e_cal_component_alarm_repeat_get_interval_seconds (repeat);
                                repeat_time = MAX (repeat_time, rdur);
                        }
 
-                       if (dur->is_neg)
+                       if (i_cal_duration_is_neg (dur))
                                /* If the duration is negative then dur_time
                                 * will be negative as well; that is why we
                                 * subtract to expand the range.
@@ -348,10 +362,9 @@ compute_alarm_range (ECalComponent *comp,
                                *alarm_start = MIN (*alarm_start, start - dur_time);
 
                        break;
-
-               default:
-                       g_return_if_reached ();
                }
+
+               e_cal_component_alarm_free (alarm);
        }
 
        *alarm_start -= repeat_time;
@@ -360,31 +373,29 @@ compute_alarm_range (ECalComponent *comp,
 
 /* Closure data to generate alarm occurrences */
 struct alarm_occurrence_data {
+       ECalComponent *comp;
+
        /* These are the info we have */
-       GList *alarm_uids;
+       GSList *alarm_uids; /* gchar * */
        time_t start;
        time_t end;
        ECalComponentAlarmAction *omit;
 
        /* This is what we compute */
-       GSList *triggers;
+       GSList *triggers; /* ECalComponentAlarmInstance * */
        gint n_triggers;
 };
 
 static void
 add_trigger (struct alarm_occurrence_data *aod,
              const gchar *auid,
-             time_t trigger,
+             time_t instance_time,
              time_t occur_start,
              time_t occur_end)
 {
        ECalComponentAlarmInstance *instance;
 
-       instance = g_new (ECalComponentAlarmInstance, 1);
-       instance->auid = g_strdup (auid);
-       instance->trigger = trigger;
-       instance->occur_start = occur_start;
-       instance->occur_end = occur_end;
+       instance = e_cal_component_alarm_instance_new (auid, instance_time, occur_start, occur_end);
 
        aod->triggers = g_slist_prepend (aod->triggers, instance);
        aod->n_triggers++;
@@ -394,51 +405,65 @@ add_trigger (struct alarm_occurrence_data *aod,
  * of a component's RELATIVE alarms.
  */
 static gboolean
-add_alarm_occurrences_cb (ECalComponent *comp,
-                          time_t start,
-                          time_t end,
-                          gpointer data)
+add_alarm_occurrences_cb (ICalComponent *icalcomp,
+                         ICalTime *instance_start,
+                         ICalTime *instance_end,
+                         gpointer user_data,
+                         GCancellable *cancellable,
+                         GError **error)
 {
        struct alarm_occurrence_data *aod;
-       GList *l;
+       time_t start, end;
+       GSList *link;
 
-       aod = data;
+       aod = user_data;
+       start = i_cal_time_as_timet (instance_start);
+       end = i_cal_time_as_timet (instance_end);
 
-       for (l = aod->alarm_uids; l; l = l->next) {
+       for (link = aod->alarm_uids; link; link = g_slist_next (link)) {
                const gchar *auid;
                ECalComponentAlarm *alarm;
                ECalComponentAlarmAction action;
-               ECalComponentAlarmTrigger trigger;
-               ECalComponentAlarmRepeat repeat;
-               struct icaldurationtype *dur;
+               ECalComponentAlarmTrigger *trigger;
+               ECalComponentAlarmRepeat *repeat;
+               ICalDuration *dur;
                time_t dur_time;
                time_t occur_time, trigger_time;
                gint i;
 
-               auid = l->data;
-               alarm = e_cal_component_get_alarm (comp, auid);
+               auid = link->data;
+               alarm = e_cal_component_get_alarm (aod->comp, auid);
                g_return_val_if_fail (alarm != NULL, FALSE);
 
-               e_cal_component_alarm_get_action (alarm, &action);
-               e_cal_component_alarm_get_trigger (alarm, &trigger);
-               e_cal_component_alarm_get_repeat (alarm, &repeat);
-               e_cal_component_alarm_free (alarm);
+               action = e_cal_component_alarm_get_action (alarm);
+               trigger = e_cal_component_alarm_get_trigger (alarm);
+               repeat = e_cal_component_alarm_get_repeat (alarm);
+
+               if (!trigger) {
+                       e_cal_component_alarm_free (alarm);
+                       continue;
+               }
 
                for (i = 0; aod->omit[i] != -1; i++) {
                        if (aod->omit[i] == action)
                                break;
                }
-               if (aod->omit[i] != -1)
+
+               if (aod->omit[i] != -1) {
+                       e_cal_component_alarm_free (alarm);
                        continue;
+               }
 
-               if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START
-                   && trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END)
+               if (e_cal_component_alarm_trigger_get_kind (trigger) != 
E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START &&
+                   e_cal_component_alarm_trigger_get_kind (trigger) != 
E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END) {
+                       e_cal_component_alarm_free (alarm);
                        continue;
+               }
 
-               dur = &trigger.u.rel_duration;
-               dur_time = icaldurationtype_as_int (*dur);
+               dur = e_cal_component_alarm_trigger_get_duration (trigger);
+               dur_time = i_cal_duration_as_int (dur);
 
-               if (trigger.type == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START)
+               if (e_cal_component_alarm_trigger_get_kind (trigger) == 
E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START)
                        occur_time = start;
                else
                        occur_time = end;
@@ -453,16 +478,17 @@ add_alarm_occurrences_cb (ECalComponent *comp,
 
                /* Add repeating alarms */
 
-               if (repeat.repetitions != 0) {
-                       gint i;
+               if (repeat && e_cal_component_alarm_repeat_get_repetitions (repeat) != 0) {
+                       gint ii, repetitions;
                        time_t repeat_time;
 
-                       repeat_time = icaldurationtype_as_int (repeat.duration);
+                       repeat_time = e_cal_component_alarm_repeat_get_interval_seconds (repeat);
+                       repetitions = e_cal_component_alarm_repeat_get_repetitions (repeat);
 
-                       for (i = 0; i < repeat.repetitions; i++) {
+                       for (ii = 0; ii < repetitions; ii++) {
                                time_t t;
 
-                               t = trigger_time + (i + 1) * repeat_time;
+                               t = trigger_time + (ii + 1) * repeat_time;
 
                                if (t >= aod->start && t < aod->end)
                                        add_trigger (aod, auid, t, start, end);
@@ -473,6 +499,8 @@ add_alarm_occurrences_cb (ECalComponent *comp,
 
                if (trigger_time >= aod->start && trigger_time < aod->end)
                        add_trigger (aod, auid, trigger_time, start, end);
+
+               e_cal_component_alarm_free (alarm);
        }
 
        return TRUE;
@@ -482,93 +510,105 @@ add_alarm_occurrences_cb (ECalComponent *comp,
 static void
 generate_absolute_triggers (ECalComponent *comp,
                             struct alarm_occurrence_data *aod,
-                            ECalRecurResolveTimezoneFn resolve_tzid,
+                            ECalRecurResolveTimezoneCb resolve_tzid,
                             gpointer user_data,
-                            icaltimezone *default_timezone)
+                            ICalTimezone *default_timezone)
 {
-       GList *l;
-       ECalComponentDateTime dt_start, dt_end;
+       GSList *link;
+       ECalComponentDateTime *dtstart, *dtend;
+       time_t occur_start, occur_end;
+
+       dtstart = e_cal_component_get_dtstart (comp);
+       dtend = e_cal_component_get_dtend (comp);
+
+       /* No particular occurrence, so just use the times from the
+        * component */
+
+       if (dtstart && e_cal_component_datetime_get_value (dtstart)) {
+               ICalTimezone *zone;
+               const gchar *tzid = e_cal_component_datetime_get_tzid (dtstart);
+
+               if (tzid && !i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)))
+                       zone = (* resolve_tzid) (tzid, user_data, NULL, NULL);
+               else
+                       zone = default_timezone ? g_object_ref (default_timezone) : NULL;
+
+               occur_start = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value (dtstart), 
zone);
+
+               g_clear_object (&zone);
+       } else
+               occur_start = -1;
+
+       if (dtend && e_cal_component_datetime_get_value (dtend)) {
+               ICalTimezone *zone;
+               const gchar *tzid = e_cal_component_datetime_get_tzid (dtend);
 
-       e_cal_component_get_dtstart (comp, &dt_start);
-       e_cal_component_get_dtend (comp, &dt_end);
+               if (tzid && !i_cal_time_is_date (e_cal_component_datetime_get_value (dtend)))
+                       zone = (* resolve_tzid) (tzid, user_data, NULL, NULL);
+               else
+                       zone = default_timezone ? g_object_ref (default_timezone) : NULL;
+
+               occur_end = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value (dtend), zone);
+
+               g_clear_object (&zone);
+       } else
+               occur_end = -1;
 
-       for (l = aod->alarm_uids; l; l = l->next) {
+       for (link = aod->alarm_uids; link; link = g_slist_next (link)) {
                const gchar *auid;
                ECalComponentAlarm *alarm;
                ECalComponentAlarmAction action;
-               ECalComponentAlarmRepeat repeat;
-               ECalComponentAlarmTrigger trigger;
+               ECalComponentAlarmRepeat *repeat;
+               ECalComponentAlarmTrigger *trigger;
                time_t abs_time;
-               time_t occur_start, occur_end;
-               icaltimezone *zone;
+               ICalTimezone *zone;
                gint i;
 
-               auid = l->data;
+               auid = link->data;
                alarm = e_cal_component_get_alarm (comp, auid);
                g_return_if_fail (alarm != NULL);
 
-               e_cal_component_alarm_get_action (alarm, &action);
-               e_cal_component_alarm_get_trigger (alarm, &trigger);
-               e_cal_component_alarm_get_repeat (alarm, &repeat);
-               e_cal_component_alarm_free (alarm);
+               action = e_cal_component_alarm_get_action (alarm);
+               trigger = e_cal_component_alarm_get_trigger (alarm);
+               repeat = e_cal_component_alarm_get_repeat (alarm);
 
                for (i = 0; aod->omit[i] != -1; i++) {
                        if (aod->omit[i] == action)
                                break;
                }
-               if (aod->omit[i] != -1)
+
+               if (aod->omit[i] != -1) {
+                       e_cal_component_alarm_free (alarm);
                        continue;
+               }
 
-               if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE)
+               if (e_cal_component_alarm_trigger_get_kind (trigger) != 
E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                       e_cal_component_alarm_free (alarm);
                        continue;
+               }
 
                /* Absolute triggers are always in UTC;
                 * see RFC 2445 section 4.8.6.3 */
-               zone = icaltimezone_get_utc_timezone ();
-
-               abs_time = icaltime_as_timet_with_zone (trigger.u.abs_time, zone);
+               zone = i_cal_timezone_get_utc_timezone ();
 
-               /* No particular occurrence, so just use the times from the
-                * component */
-
-               if (dt_start.value) {
-                       if (dt_start.tzid && !dt_start.value->is_date)
-                               zone = (* resolve_tzid) (dt_start.tzid, user_data);
-                       else
-                               zone = default_timezone;
-
-                       occur_start = icaltime_as_timet_with_zone (
-                               *dt_start.value, zone);
-               } else
-                       occur_start = -1;
-
-               if (dt_end.value) {
-                       if (dt_end.tzid && !dt_end.value->is_date)
-                               zone = (* resolve_tzid) (dt_end.tzid, user_data);
-                       else
-                               zone = default_timezone;
-
-                       occur_end = icaltime_as_timet_with_zone (*dt_end.value, zone);
-               } else
-                       occur_end = -1;
+               abs_time = i_cal_time_as_timet_with_zone (e_cal_component_alarm_trigger_get_absolute_time 
(trigger), zone);
 
                /* Add repeating alarms */
 
-               if (repeat.repetitions != 0) {
-                       gint i;
+               if (repeat && e_cal_component_alarm_repeat_get_repetitions (repeat) > 0) {
+                       gint ii, repetitions;
                        time_t repeat_time;
 
-                       repeat_time = icaldurationtype_as_int (repeat.duration);
+                       repeat_time = e_cal_component_alarm_repeat_get_interval_seconds (repeat);
+                       repetitions = e_cal_component_alarm_repeat_get_repetitions (repeat);
 
-                       for (i = 0; i < repeat.repetitions; i++) {
-                               time_t t;
+                       for (ii = 0; ii < repetitions; ii++) {
+                               time_t tt;
 
-                               t = abs_time + (i + 1) * repeat_time;
+                               tt = abs_time + (ii + 1) * repeat_time;
 
-                               if (t >= aod->start && t < aod->end)
-                                       add_trigger (
-                                               aod, auid, t,
-                                               occur_start, occur_end);
+                               if (tt >= aod->start && tt < aod->end)
+                                       add_trigger (aod, auid, tt, occur_start, occur_end);
                        }
                }
 
@@ -576,10 +616,12 @@ generate_absolute_triggers (ECalComponent *comp,
 
                if (abs_time >= aod->start && abs_time < aod->end)
                        add_trigger (aod, auid, abs_time, occur_start, occur_end);
+
+               e_cal_component_alarm_free (alarm);
        }
 
-       e_cal_component_free_datetime (&dt_start);
-       e_cal_component_free_datetime (&dt_end);
+       e_cal_component_datetime_free (dtstart);
+       e_cal_component_datetime_free (dtend);
 }
 
 /* Compares two alarm instances; called from g_slist_sort() */
@@ -588,13 +630,17 @@ compare_alarm_instance (gconstpointer a,
                         gconstpointer b)
 {
        const ECalComponentAlarmInstance *aia, *aib;
+       time_t atime, btime;
 
        aia = a;
        aib = b;
 
-       if (aia->trigger < aib->trigger)
+       atime = e_cal_component_alarm_instance_get_time (aia);
+       btime = e_cal_component_alarm_instance_get_time (aib);
+
+       if (atime < btime)
                return -1;
-       else if (aia->trigger > aib->trigger)
+       else if (atime > btime)
                return 1;
        else
                return 0;
@@ -612,35 +658,36 @@ compare_alarm_instance (gconstpointer a,
  * @default_timezone: The timezone used to resolve DATE and floating DATE-TIME
  * values.
  *
- * Generates alarm instances for a calendar component.  Returns the instances
+ * Generates alarm instances for a calendar component. Returns the instances
  * structure, or %NULL if no alarm instances occurred in the specified time
- * range.
+ * range. Free the returned structure with e_cal_component_alarms_free(),
+ * when no longer needed.
  *
- * Returns: (allow-none) (transfer full): a list of all the alarms found for the
- * given component in the given time range. The list of alarms should be freed
- * by using e_cal_component_alarms_free().
+ * Returns: (transfer full) (nullable): a list of all the alarms found
+ *    for the given component in the given time range.
  */
 ECalComponentAlarms *
 e_cal_util_generate_alarms_for_comp (ECalComponent *comp,
                                      time_t start,
                                      time_t end,
                                      ECalComponentAlarmAction *omit,
-                                     ECalRecurResolveTimezoneFn resolve_tzid,
+                                     ECalRecurResolveTimezoneCb resolve_tzid,
                                      gpointer user_data,
-                                     icaltimezone *default_timezone)
+                                     ICalTimezone *default_timezone)
 {
-       GList *alarm_uids;
+       GSList *alarm_uids;
        time_t alarm_start, alarm_end;
        struct alarm_occurrence_data aod;
+       ICalTime *alarm_start_tt, *alarm_end_tt;
        ECalComponentAlarms *alarms;
 
        if (!e_cal_component_has_alarms (comp))
                return NULL;
 
        alarm_uids = e_cal_component_get_alarm_uids (comp);
-       compute_alarm_range (
-               comp, alarm_uids, start, end, &alarm_start, &alarm_end);
+       compute_alarm_range (comp, alarm_uids, start, end, &alarm_start, &alarm_end);
 
+       aod.comp = comp;
        aod.alarm_uids = alarm_uids;
        aod.start = start;
        aod.end = end;
@@ -648,27 +695,30 @@ e_cal_util_generate_alarms_for_comp (ECalComponent *comp,
        aod.triggers = NULL;
        aod.n_triggers = 0;
 
-       e_cal_recur_generate_instances (
-               comp, alarm_start, alarm_end,
+       alarm_start_tt = i_cal_time_from_timet_with_zone (alarm_start, FALSE, i_cal_timezone_get_utc_timezone 
());
+       alarm_end_tt = i_cal_time_from_timet_with_zone (alarm_end, FALSE, i_cal_timezone_get_utc_timezone ());
+
+       e_cal_recur_generate_instances_sync (e_cal_component_get_icalcomponent (comp),
+               alarm_start_tt, alarm_end_tt,
                add_alarm_occurrences_cb, &aod,
                resolve_tzid, user_data,
-               default_timezone);
+               default_timezone, NULL, NULL);
+
+       g_clear_object (&alarm_start_tt);
+       g_clear_object (&alarm_end_tt);
 
        /* We add the ABSOLUTE triggers separately */
-       generate_absolute_triggers (
-               comp, &aod, resolve_tzid, user_data, default_timezone);
+       generate_absolute_triggers (comp, &aod, resolve_tzid, user_data, default_timezone);
 
-       cal_obj_uid_list_free (alarm_uids);
+       g_slist_free_full (alarm_uids, g_free);
 
        if (aod.n_triggers == 0)
                return NULL;
 
        /* Create the component alarm instances structure */
 
-       alarms = g_new (ECalComponentAlarms, 1);
-       alarms->comp = comp;
-       g_object_ref (G_OBJECT (alarms->comp));
-       alarms->alarms = g_slist_sort (aod.triggers, compare_alarm_instance);
+       alarms = e_cal_component_alarms_new (comp);
+       e_cal_component_alarms_take_instances (alarms, g_slist_sort (aod.triggers, compare_alarm_instance));
 
        return alarms;
 }
@@ -688,7 +738,9 @@ e_cal_util_generate_alarms_for_comp (ECalComponent *comp,
  * values.
  *
  * Iterates through all the components in the @comps list and generates alarm
- * instances for them; putting them in the @comp_alarms list.
+ * instances for them; putting them in the @comp_alarms list. Free the @comp_alarms
+ * with g_slist_free_full (comp_alarms, e_cal_component_alarms_free);, when
+ * no longer neeed.
  *
  * Returns: the number of elements it added to the list
  */
@@ -698,9 +750,9 @@ e_cal_util_generate_alarms_for_list (GList *comps,
                                      time_t end,
                                      ECalComponentAlarmAction *omit,
                                      GSList **comp_alarms,
-                                     ECalRecurResolveTimezoneFn resolve_tzid,
+                                     ECalRecurResolveTimezoneCb resolve_tzid,
                                      gpointer user_data,
-                                     icaltimezone *default_timezone)
+                                     ICalTimezone *default_timezone)
 {
        GList *l;
        gint n;
@@ -856,41 +908,45 @@ e_cal_util_seconds_to_string (gint64 seconds)
 
 /* callback for icalcomponent_foreach_tzid */
 typedef struct {
-       icalcomponent *vcal_comp;
-       icalcomponent *icalcomp;
+       ICalComponent *vcal_comp;
+       ICalComponent *icalcomp;
 } ForeachTzidData;
 
 static void
-add_timezone_cb (icalparameter *param,
-                 gpointer data)
+add_timezone_cb (ICalParameter *param,
+                 gpointer user_data)
 {
-       icaltimezone *tz;
+       ICalTimezone *tz;
        const gchar *tzid;
-       icalcomponent *vtz_comp;
-       ForeachTzidData *f_data = (ForeachTzidData *) data;
+       ICalComponent *vtz_comp;
+       ForeachTzidData *f_data = user_data;
 
-       tzid = icalparameter_get_tzid (param);
+       tzid = i_cal_parameter_get_tzid (param);
        if (!tzid)
                return;
 
-       tz = icalcomponent_get_timezone (f_data->vcal_comp, tzid);
-       if (tz)
+       tz = i_cal_component_get_timezone (f_data->vcal_comp, tzid);
+       if (tz) {
+               g_object_unref (tz);
                return;
+       }
 
-       tz = icalcomponent_get_timezone (f_data->icalcomp, tzid);
+       tz = i_cal_component_get_timezone (f_data->icalcomp, tzid);
        if (!tz) {
-               tz = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+               tz = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
                if (!tz)
                        return;
+
+               g_object_ref (tz);
        }
 
-       vtz_comp = icaltimezone_get_component (tz);
-       if (!vtz_comp)
-               return;
+       vtz_comp = i_cal_timezone_get_component (tz);
+       if (vtz_comp) {
+               i_cal_component_take_component (f_data->vcal_comp, i_cal_component_new_clone (vtz_comp));
+               g_object_unref (vtz_comp);
+       }
 
-       icalcomponent_add_component (
-               f_data->vcal_comp,
-               icalcomponent_new_clone (vtz_comp));
+       g_object_unref (tz);
 }
 
 /**
@@ -902,8 +958,8 @@ add_timezone_cb (icalparameter *param,
  * in the given @icalcomp.
  */
 void
-e_cal_util_add_timezones_from_component (icalcomponent *vcal_comp,
-                                         icalcomponent *icalcomp)
+e_cal_util_add_timezones_from_component (ICalComponent *vcal_comp,
+                                        ICalComponent *icalcomp)
 {
        ForeachTzidData f_data;
 
@@ -912,103 +968,189 @@ e_cal_util_add_timezones_from_component (icalcomponent *vcal_comp,
 
        f_data.vcal_comp = vcal_comp;
        f_data.icalcomp = icalcomp;
-       icalcomponent_foreach_tzid (icalcomp, add_timezone_cb, &f_data);
+       i_cal_component_foreach_tzid (icalcomp, add_timezone_cb, &f_data);
+}
+
+/**
+ * e_cal_util_property_has_parameter:
+ * @prop: an #ICalProperty
+ * @param_kind: a parameter kind to look for, as an %ICalParameterKind
+ *
+ * Returns, whether the @prop has a parameter of @param_kind.
+ *
+ * Returns: whether the @prop has a parameter of @prop_kind
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_util_property_has_parameter (ICalProperty *prop,
+                                  ICalParameterKind param_kind)
+{
+       ICalParameter *param;
+
+       g_return_val_if_fail (I_CAL_IS_PROPERTY (prop), FALSE);
+
+       param = i_cal_property_get_first_parameter (prop, param_kind);
+
+       if (!param)
+               return FALSE;
+
+       g_object_unref (param);
+
+       return TRUE;
+}
+
+/**
+ * e_cal_util_component_has_property:
+ * @icalcomp: an #ICalComponent
+ * @prop_kind: a property kind to look for, as an %ICalPropertyKind
+ *
+ * Returns, whether the @icalcomp has a property of @prop_kind. To check
+ * for a specific X property use e_cal_util_component_has_x_property().
+ *
+ * Returns: whether the @icalcomp has a property of @prop_kind
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_util_component_has_property (ICalComponent *icalcomp,
+                                  ICalPropertyKind prop_kind)
+{
+       ICalProperty *prop;
+
+       g_return_val_if_fail (I_CAL_IS_COMPONENT (icalcomp), FALSE);
+
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+
+       if (!prop)
+               return FALSE;
+
+       g_object_unref (prop);
+
+       return TRUE;
 }
 
 /**
  * e_cal_util_component_is_instance:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks whether an #icalcomponent is an instance of a recurring appointment.
+ * Checks whether an #ICalComponent is an instance of a recurring appointment.
  *
  * Returns: TRUE if it is an instance, FALSE if not.
  */
 gboolean
-e_cal_util_component_is_instance (icalcomponent *icalcomp)
+e_cal_util_component_is_instance (ICalComponent *icalcomp)
 {
-       icalproperty *prop;
-
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_RECURRENCEID_PROPERTY);
-
-       return (prop != NULL);
+       return e_cal_util_component_has_property (icalcomp, I_CAL_RECURRENCEID_PROPERTY);
 }
 
 /**
  * e_cal_util_component_has_alarms:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks whether an #icalcomponent has any alarm.
+ * Checks whether an #ICalComponent has any alarm.
  *
  * Returns: TRUE if it has alarms, FALSE otherwise.
  */
 gboolean
-e_cal_util_component_has_alarms (icalcomponent *icalcomp)
+e_cal_util_component_has_alarms (ICalComponent *icalcomp)
 {
-       icalcomponent *alarm;
+       ICalComponent *alarm;
 
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
-       alarm = icalcomponent_get_first_component (
-               icalcomp, ICAL_VALARM_COMPONENT);
+       alarm = i_cal_component_get_first_component (icalcomp, I_CAL_VALARM_COMPONENT);
 
-       return (alarm != NULL);
+       if (!alarm)
+               return FALSE;
+
+       g_object_unref (alarm);
+
+       return TRUE;
 }
 
 /**
  * e_cal_util_component_has_organizer:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks whether an #icalcomponent has an organizer.
+ * Checks whether an #ICalComponent has an organizer.
  *
  * Returns: TRUE if there is an organizer, FALSE if not.
  */
 gboolean
-e_cal_util_component_has_organizer (icalcomponent *icalcomp)
+e_cal_util_component_has_organizer (ICalComponent *icalcomp)
 {
-       icalproperty *prop;
-
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_ORGANIZER_PROPERTY);
-
-       return (prop != NULL);
+       return e_cal_util_component_has_property (icalcomp, I_CAL_ORGANIZER_PROPERTY);
 }
 
 /**
  * e_cal_util_component_has_attendee:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks if an #icalcomponent has any attendees.
+ * Checks if an #ICalComponent has any attendees.
  *
  * Returns: TRUE if there are attendees, FALSE if not.
  */
 gboolean
-e_cal_util_component_has_attendee (icalcomponent *icalcomp)
+e_cal_util_component_has_attendee (ICalComponent *icalcomp)
 {
-       icalproperty *prop;
-
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_ATTENDEE_PROPERTY);
+       return e_cal_util_component_has_property (icalcomp, I_CAL_ATTENDEE_PROPERTY);
+}
+
+/**
+ * e_cal_util_component_get_recurid_as_string:
+ * @icalcomp: an #ICalComponent
+ *
+ * Returns: (transfer full) (nullable): a RECURRENCEID property as string,
+ *    or %NULL, when the @icalcomp is not an instance. Free the returned
+ *    string with g_free(), when no longer needed.
+ *
+ * Since: 3.36
+ **/
+gchar *
+e_cal_util_component_get_recurid_as_string (ICalComponent *icalcomp)
+{
+       ICalProperty *prop;
+       ICalTime *recurid;
+       gchar *rid;
+
+       g_return_val_if_fail (icalcomp != NULL, NULL);
+
+       prop = i_cal_component_get_first_property (icalcomp, I_CAL_RECURRENCEID_PROPERTY);
+       if (!prop)
+               return NULL;
+
+       recurid = i_cal_property_get_recurrenceid (prop);
+       if (!recurid ||
+           !i_cal_time_is_valid_time (recurid) ||
+           i_cal_time_is_null_time (recurid)) {
+               rid = g_strdup ("0");
+       } else {
+               rid = i_cal_time_as_ical_string_r (recurid);
+       }
 
-       return (prop != NULL);
+       g_clear_object (&recurid);
+       g_object_unref (prop);
+
+       return rid;
 }
 
 /**
  * e_cal_util_component_has_recurrences:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks if an #icalcomponent has recurrence dates or rules.
+ * Checks if an #ICalComponent has recurrence dates or rules.
  *
  * Returns: TRUE if there are recurrence dates/rules, FALSE if not.
  */
 gboolean
-e_cal_util_component_has_recurrences (icalcomponent *icalcomp)
+e_cal_util_component_has_recurrences (ICalComponent *icalcomp)
 {
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
@@ -1018,100 +1160,34 @@ e_cal_util_component_has_recurrences (icalcomponent *icalcomp)
 
 /**
  * e_cal_util_component_has_rdates:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks if an #icalcomponent has recurrence dates.
+ * Checks if an #ICalComponent has recurrence dates.
  *
  * Returns: TRUE if there are recurrence dates, FALSE if not.
  */
 gboolean
-e_cal_util_component_has_rdates (icalcomponent *icalcomp)
+e_cal_util_component_has_rdates (ICalComponent *icalcomp)
 {
-       icalproperty *prop;
-
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_RDATE_PROPERTY);
-
-       return (prop != NULL);
+       return e_cal_util_component_has_property (icalcomp, I_CAL_RDATE_PROPERTY);
 }
 
 /**
  * e_cal_util_component_has_rrules:
- * @icalcomp: An #icalcomponent.
+ * @icalcomp: An #ICalComponent.
  *
- * Checks if an #icalcomponent has recurrence rules.
+ * Checks if an #ICalComponent has recurrence rules.
  *
  * Returns: TRUE if there are recurrence rules, FALSE if not.
  */
 gboolean
-e_cal_util_component_has_rrules (icalcomponent *icalcomp)
+e_cal_util_component_has_rrules (ICalComponent *icalcomp)
 {
-       icalproperty *prop;
-
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_RRULE_PROPERTY);
-
-       return (prop != NULL);
-}
-
-/**
- * e_cal_util_event_dates_match:
- * @icalcomp1: An #icalcomponent.
- * @icalcomp2: An #icalcomponent.
- *
- * Compare the dates of two #icalcomponent's to check if they match.
- *
- * Returns: TRUE if the dates of both components match, FALSE otherwise.
- */
-gboolean
-e_cal_util_event_dates_match (icalcomponent *icalcomp1,
-                              icalcomponent *icalcomp2)
-{
-       struct icaltimetype c1_dtstart, c1_dtend, c2_dtstart, c2_dtend;
-
-       g_return_val_if_fail (icalcomp1 != NULL, FALSE);
-       g_return_val_if_fail (icalcomp2 != NULL, FALSE);
-
-       c1_dtstart = icalcomponent_get_dtstart (icalcomp1);
-       c1_dtend = icalcomponent_get_dtend (icalcomp1);
-       c2_dtstart = icalcomponent_get_dtstart (icalcomp2);
-       c2_dtend = icalcomponent_get_dtend (icalcomp2);
-
-       /* if either value is NULL, they must both be NULL to match */
-       if (icaltime_is_valid_time (c1_dtstart) || icaltime_is_valid_time (c2_dtstart)) {
-               if (!(icaltime_is_valid_time (c1_dtstart) && icaltime_is_valid_time (c2_dtstart)))
-                       return FALSE;
-       } else {
-               if (icaltime_compare (c1_dtstart, c2_dtstart))
-                       return FALSE;
-       }
-
-       if (icaltime_is_valid_time (c1_dtend) || icaltime_is_valid_time (c2_dtend)) {
-               if (!(icaltime_is_valid_time (c1_dtend) && icaltime_is_valid_time (c2_dtend)))
-                       return FALSE;
-       } else {
-               if (icaltime_compare (c1_dtend, c2_dtend))
-                       return FALSE;
-       }
-
-       /* now match the timezones */
-       if (!(!c1_dtstart.zone && !c2_dtstart.zone) ||
-           (c1_dtstart.zone && c2_dtstart.zone &&
-            !strcmp (icaltimezone_get_tzid ((icaltimezone *) c1_dtstart.zone),
-                     icaltimezone_get_tzid ((icaltimezone *) c2_dtstart.zone))))
-               return FALSE;
-
-       if (!(!c1_dtend.zone && !c2_dtend.zone) ||
-           (c1_dtend.zone && c2_dtend.zone &&
-            !strcmp (icaltimezone_get_tzid ((icaltimezone *) c1_dtend.zone),
-                     icaltimezone_get_tzid ((icaltimezone *) c2_dtend.zone))))
-               return FALSE;
-
-       return TRUE;
+       return e_cal_util_component_has_property (icalcomp, I_CAL_RRULE_PROPERTY);
 }
 
 /* Individual instances management */
@@ -1122,67 +1198,72 @@ struct instance_data {
 };
 
 static void
-check_instance (icalcomponent *comp,
-                struct icaltime_span *span,
-                gpointer data)
+check_instance (ICalComponent *comp,
+               ICalTimeSpan *span,
+               gpointer user_data)
 {
-       struct instance_data *instance = data;
+       struct instance_data *instance = user_data;
 
-       if (span->start == instance->start)
+       if (i_cal_time_span_get_start (span) == instance->start)
                instance->found = TRUE;
 }
 
 /**
  * e_cal_util_construct_instance:
- * @icalcomp: A recurring #icalcomponent
+ * @icalcomp: A recurring #ICalComponent
  * @rid: The RECURRENCE-ID to construct a component for
  *
  * This checks that @rid indicates a valid recurrence of @icalcomp, and
- * if so, generates a copy of @comp containing a RECURRENCE-ID of @rid.
+ * if so, generates a copy of @icalcomp containing a RECURRENCE-ID of @rid.
+ *
+ * Free the returned non-NULL component with g_object_unref(), when
+ * no longer needed.
  *
- * Returns: the instance, or %NULL.
+ * Returns: (transfer full) (nullable): the instance as a new #ICalComponent, or %NULL.
  **/
-icalcomponent *
-e_cal_util_construct_instance (icalcomponent *icalcomp,
-                               struct icaltimetype rid)
+ICalComponent *
+e_cal_util_construct_instance (ICalComponent *icalcomp,
+                              const ICalTime *rid)
 {
        struct instance_data instance;
-       struct icaltimetype start, end;
+       ICalTime *start, *end;
 
        g_return_val_if_fail (icalcomp != NULL, NULL);
 
        /* Make sure this is really recurring */
-       if (!icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY) &&
-           !icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY))
+       if (!e_cal_util_component_has_recurrences (icalcomp))
                return NULL;
 
        /* Make sure the specified instance really exists */
-       start = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ());
-       end = start;
-       icaltime_adjust (&end, 0, 0, 0, 1);
+       start = i_cal_time_convert_to_zone ((ICalTime *) rid, i_cal_timezone_get_utc_timezone ());
+       end = i_cal_time_new_clone (start);
+       i_cal_time_adjust (end, 0, 0, 0, 1);
 
-       instance.start = icaltime_as_timet (start);
+       instance.start = i_cal_time_as_timet (start);
        instance.found = FALSE;
-       icalcomponent_foreach_recurrence (icalcomp, start, end,
-                                         check_instance, &instance);
+       i_cal_component_foreach_recurrence (icalcomp, start, end, check_instance, &instance);
+
+       g_object_unref (start);
+       g_object_unref (end);
+
        if (!instance.found)
                return NULL;
 
        /* Make the instance */
-       icalcomp = icalcomponent_new_clone (icalcomp);
-       icalcomponent_set_recurrenceid (icalcomp, rid);
+       icalcomp = i_cal_component_new_clone (icalcomp);
+       i_cal_component_set_recurrenceid (icalcomp, (ICalTime *) rid);
 
        return icalcomp;
 }
 
 static inline gboolean
-time_matches_rid (struct icaltimetype itt,
-                  struct icaltimetype rid,
+time_matches_rid (const ICalTime *itt,
+                  const ICalTime *rid,
                   ECalObjModType mod)
 {
        gint compare;
 
-       compare = icaltime_compare (itt, rid);
+       compare = i_cal_time_compare ((ICalTime *) itt, (ICalTime *) rid);
        if (compare == 0)
                return TRUE;
        else if (compare < 0 && (mod & E_CAL_OBJ_MOD_THIS_AND_PRIOR))
@@ -1194,169 +1275,220 @@ time_matches_rid (struct icaltimetype itt,
 }
 
 static void
-e_cal_util_remove_instances_ex (icalcomponent *icalcomp,
-                               struct icaltimetype rid,
+e_cal_util_remove_instances_ex (ICalComponent *icalcomp,
+                               const ICalTime *rid,
                                ECalObjModType mod,
                                gboolean keep_rid,
                                gboolean can_add_exrule)
 {
-       icalproperty *prop;
-       struct icaltimetype itt, recur;
-       struct icalrecurrencetype rule;
-       icalrecur_iterator *iter;
+       ICalProperty *prop;
+       ICalTime *itt, *recur;
+       ICalRecurrence *rule;
+       ICalRecurIterator *iter;
        GSList *remove_props = NULL, *rrules = NULL, *link;
 
        g_return_if_fail (icalcomp != NULL);
        g_return_if_fail (mod != E_CAL_OBJ_MOD_ALL);
 
        /* First remove RDATEs and EXDATEs in the indicated range. */
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_RDATE_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_RDATE_PROPERTY)) {
-               struct icaldatetimeperiodtype period;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_RDATE_PROPERTY)) {
+               ICalDatetimeperiod *period;
+               ICalTime *period_time;
+
+               period = i_cal_property_get_rdate (prop);
+               if (!period)
+                       continue;
+
+               period_time = i_cal_datetimeperiod_get_time (period);
 
-               period = icalproperty_get_rdate (prop);
-               if (time_matches_rid (period.time, rid, mod) && (!keep_rid ||
-                   icaltime_compare (period.time, rid) != 0))
-                       remove_props = g_slist_prepend (remove_props, prop);
+               if (time_matches_rid (period_time, rid, mod) && (!keep_rid ||
+                   i_cal_time_compare (period_time, (ICalTime *) rid) != 0))
+                       remove_props = g_slist_prepend (remove_props, g_object_ref (prop));
+
+               g_clear_object (&period_time);
+               g_object_unref (period);
        }
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_EXDATE_PROPERTY);
+
+       for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_EXDATE_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_EXDATE_PROPERTY)) {
-               itt = icalproperty_get_exdate (prop);
-               if (time_matches_rid (itt, rid, mod) && (!keep_rid ||
-                   icaltime_compare (itt, rid) != 0))
-                       remove_props = g_slist_prepend (remove_props, prop);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_EXDATE_PROPERTY)) {
+               itt = i_cal_property_get_exdate (prop);
+               if (!itt)
+                       continue;
+
+               if (time_matches_rid (itt, rid, mod) && (!keep_rid || i_cal_time_compare (itt, (ICalTime *) 
rid) != 0))
+                       remove_props = g_slist_prepend (remove_props, g_object_ref (prop));
+
+               g_object_unref (itt);
        }
 
        for (link = remove_props; link; link = g_slist_next (link)) {
                prop = link->data;
 
-               icalcomponent_remove_property (icalcomp, prop);
+               i_cal_component_remove_property (icalcomp, prop);
        }
 
-       g_slist_free (remove_props);
+       g_slist_free_full (remove_props, g_object_unref);
        remove_props = NULL;
 
        /* If we're only removing one instance, just add an EXDATE. */
        if (mod == E_CAL_OBJ_MOD_THIS) {
-               prop = icalproperty_new_exdate (rid);
-               icalcomponent_add_property (icalcomp, prop);
+               prop = i_cal_property_new_exdate ((ICalTime *) rid);
+               i_cal_component_take_property (icalcomp, prop);
                return;
        }
 
        /* Otherwise, iterate through RRULEs */
        /* FIXME: this may generate duplicate EXRULEs */
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_RRULE_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) {
-               rrules = g_slist_prepend (rrules, prop);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_RRULE_PROPERTY)) {
+               rrules = g_slist_prepend (rrules, g_object_ref (prop));
        }
 
        for (link = rrules; link; link = g_slist_next (link)) {
                prop = link->data;
-               rule = icalproperty_get_rrule (prop);
 
-               iter = icalrecur_iterator_new (rule, rid);
-               recur = icalrecur_iterator_next (iter);
+               rule = i_cal_property_get_rrule (prop);
+               if (!rule)
+                       continue;
+
+               iter = i_cal_recur_iterator_new (rule, (ICalTime *) rid);
+               recur = i_cal_recur_iterator_next (iter);
+
+               if (!recur) {
+                       g_object_unref (rule);
+                       g_object_unref (iter);
+                       continue;
+               }
 
                if (mod & E_CAL_OBJ_MOD_THIS_AND_FUTURE) {
                        /* Truncate the rule at rid. */
-                       if (!icaltime_is_null_time (recur)) {
+                       if (!i_cal_time_is_null_time (recur)) {
+                               gint rule_count = i_cal_recurrence_get_count (rule);
+
                                /* Use count if it was used */
-                               if (rule.count > 0) {
+                               if (rule_count > 0) {
                                        gint occurrences_count = 0;
-                                       icalrecur_iterator *count_iter;
-                                       struct icaltimetype count_recur;
-
-                                       count_iter = icalrecur_iterator_new (rule, icalcomponent_get_dtstart 
(icalcomp));
-                                       while (count_recur = icalrecur_iterator_next (count_iter), 
!icaltime_is_null_time (count_recur) && occurrences_count < rule.count) {
-                                               if (icaltime_compare (count_recur, rid) >= 0)
+                                       ICalRecurIterator *count_iter;
+                                       ICalTime *count_recur, *dtstart;
+
+                                       dtstart = i_cal_component_get_dtstart (icalcomp);
+                                       count_iter = i_cal_recur_iterator_new (rule, dtstart);
+                                       while (count_recur = i_cal_recur_iterator_next (count_iter),
+                                              count_recur && !i_cal_time_is_null_time (count_recur) && 
occurrences_count < rule_count) {
+                                               if (i_cal_time_compare (count_recur, (ICalTime *) rid) >= 0)
                                                        break;
 
                                                occurrences_count++;
+                                               g_object_unref (count_recur);
                                        }
 
-                                       icalrecur_iterator_free (count_iter);
-
-                                       if (keep_rid && icaltime_compare (count_recur, rid) == 0)
+                                       if (keep_rid && count_recur && i_cal_time_compare (count_recur, 
(ICalTime *) rid) == 0)
                                                occurrences_count++;
 
                                        /* The caller should make sure that the remove will keep at least one 
instance */
                                        g_warn_if_fail (occurrences_count > 0);
 
-                                       rule.count = occurrences_count;
+                                       i_cal_recurrence_set_count (rule, occurrences_count);
+
+                                       g_clear_object (&count_recur);
+                                       g_clear_object (&count_iter);
+                                       g_clear_object (&dtstart);
                                } else {
-                                       if (keep_rid && icaltime_compare (recur, rid) == 0)
-                                               rule.until = icaltime_add (rid, icalcomponent_get_duration 
(icalcomp));
-                                       else
-                                               rule.until = rid;
-                                       icaltime_adjust (&rule.until, 0, 0, 0, -1);
+                                       ICalTime *ttuntil;
+
+                                       if (keep_rid && i_cal_time_compare (recur, (ICalTime *) rid) == 0) {
+                                               ICalDuration *dur;
+
+                                               dur = i_cal_component_get_duration (icalcomp);
+                                               ttuntil = i_cal_time_add ((ICalTime *) rid, dur);
+                                               g_clear_object (&dur);
+                                       } else {
+                                               ttuntil = i_cal_time_new_clone (rid);
+                                       }
+                                       i_cal_time_adjust (ttuntil, 0, 0, 0, -1);
+                                       i_cal_recurrence_set_until (rule, ttuntil);
+                                       g_object_unref (ttuntil);
                                }
 
-                               icalproperty_set_rrule (prop, rule);
-                               icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE");
+                               i_cal_property_set_rrule (prop, rule);
+                               i_cal_property_remove_parameter_by_name (prop, 
E_CAL_EVOLUTION_ENDDATE_PARAMETER);
                        }
                } else {
                        /* (If recur == rid, skip to the next occurrence) */
-                       if (!keep_rid && icaltime_compare (recur, rid) == 0)
-                               recur = icalrecur_iterator_next (iter);
+                       if (!keep_rid && i_cal_time_compare (recur, (ICalTime *) rid) == 0) {
+                               g_object_unref (recur);
+                               recur = i_cal_recur_iterator_next (iter);
+                       }
 
                        /* If there is a recurrence after rid, add
                         * an EXRULE to block instances up to rid.
                         * Otherwise, just remove the RRULE.
                         */
-                       if (!icaltime_is_null_time (recur)) {
+                       if (!i_cal_time_is_null_time (recur)) {
                                if (can_add_exrule) {
-                                       rule.count = 0;
+                                       ICalTime *ttuntil;
+                                       ICalDuration *dur = i_cal_component_get_duration (icalcomp);
+
+                                       i_cal_recurrence_set_count (rule, 0);
+
                                        /* iCalendar says we should just use rid
                                         * here, but Outlook/Exchange handle
                                         * UNTIL incorrectly.
                                         */
-                                       if (keep_rid && icaltime_compare (recur, rid) == 0) {
-                                               struct icaldurationtype duration = icalcomponent_get_duration 
(icalcomp);
-                                               duration.is_neg = !duration.is_neg;
-                                               rule.until = icaltime_add (rid, duration);
-                                       } else
-                                               rule.until = icaltime_add (rid, icalcomponent_get_duration 
(icalcomp));
-                                       prop = icalproperty_new_exrule (rule);
-                                       icalcomponent_add_property (icalcomp, prop);
+                                       if (keep_rid && i_cal_time_compare (recur, (ICalTime *) rid) == 0) {
+                                               i_cal_duration_set_is_neg (dur, !i_cal_duration_is_neg (dur));
+                                               ttuntil = i_cal_time_add ((ICalTime *) rid, dur);
+                                       } else {
+                                               ttuntil = i_cal_time_add ((ICalTime *) rid, dur);
+                                       }
+
+                                       i_cal_recurrence_set_until (rule, ttuntil);
+
+                                       g_clear_object (&ttuntil);
+                                       g_clear_object (&dur);
+
+                                       prop = i_cal_property_new_exrule (rule);
+                                       i_cal_component_take_property (icalcomp, prop);
                                }
                        } else {
-                               remove_props = g_slist_prepend (remove_props, prop);
+                               remove_props = g_slist_prepend (remove_props, g_object_ref (prop));
                        }
                }
 
-               icalrecur_iterator_free (iter);
+               g_object_unref (recur);
+               g_object_unref (rule);
+               g_object_unref (iter);
        }
 
        for (link = remove_props; link; link = g_slist_next (link)) {
                prop = link->data;
 
-               icalcomponent_remove_property (icalcomp, prop);
+               i_cal_component_remove_property (icalcomp, prop);
        }
 
-       g_slist_free (remove_props);
-       g_slist_free (rrules);
+       g_slist_free_full (remove_props, g_object_unref);
+       g_slist_free_full (rrules, g_object_unref);
 }
 
 /**
  * e_cal_util_remove_instances:
- * @icalcomp: A (recurring) #icalcomponent
+ * @icalcomp: A (recurring) #ICalComponent
  * @rid: The base RECURRENCE-ID to remove
  * @mod: How to interpret @rid
  *
- * Removes one or more instances from @comp according to @rid and @mod.
- *
- * FIXME: should probably have a return value indicating whether @icalcomp
- *        still has any instances
+ * Removes one or more instances from @icalcomp according to @rid and @mod.
  **/
 void
-e_cal_util_remove_instances (icalcomponent *icalcomp,
-                             struct icaltimetype rid,
+e_cal_util_remove_instances (ICalComponent *icalcomp,
+                             const ICalTime *rid,
                              ECalObjModType mod)
 {
        g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (rid != NULL);
        g_return_if_fail (mod != E_CAL_OBJ_MOD_ALL);
 
        e_cal_util_remove_instances_ex (icalcomp, rid, mod, FALSE, TRUE);
@@ -1364,11 +1496,11 @@ e_cal_util_remove_instances (icalcomponent *icalcomp,
 
 /**
  * e_cal_util_split_at_instance:
- * @icalcomp: A (recurring) #icalcomponent
+ * @icalcomp: A (recurring) #ICalComponent
  * @rid: The base RECURRENCE-ID to remove
- * @master_dtstart: The DTSTART of the master object
+ * @master_dtstart: (nullable): The DTSTART of the master object
  *
- * Splits a recurring @icalcomp into two at time @rid. The returned icalcomponent
+ * Splits a recurring @icalcomp into two at time @rid. The returned #ICalComponent
  * is modified @icalcomp which contains recurrences beginning at @rid, inclusive.
  * The instance identified by @rid should exist. The @master_dtstart can be
  * a null time, then it is read from the @icalcomp.
@@ -1376,136 +1508,186 @@ e_cal_util_remove_instances (icalcomponent *icalcomp,
  * Use e_cal_util_remove_instances() with E_CAL_OBJ_MOD_THIS_AND_FUTURE mode
  * on the @icalcomp to remove the overlapping interval from it, if needed.
  *
- * Returns: the split icalcomponent, or %NULL.
+ * Free the returned non-NULL component with g_object_unref(), when
+ * done with it.
+ *
+ * Returns: (transfer full) (nullable): the split @icalcom, or %NULL.
  *
  * Since: 3.16
  **/
-icalcomponent *
-e_cal_util_split_at_instance (icalcomponent *icalcomp,
-                             struct icaltimetype rid,
-                             struct icaltimetype master_dtstart)
+ICalComponent *
+e_cal_util_split_at_instance (ICalComponent *icalcomp,
+                             const ICalTime *rid,
+                             const ICalTime *master_dtstart)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
        struct instance_data instance;
-       struct icaltimetype start, end;
-       struct icaldurationtype duration;
+       ICalTime *start, *end, *dtstart = NULL;
+       ICalDuration *duration;
        GSList *remove_props = NULL, *link;
 
        g_return_val_if_fail (icalcomp != NULL, NULL);
-       g_return_val_if_fail (!icaltime_is_null_time (rid), NULL);
+       g_return_val_if_fail (rid != NULL, NULL);
+       g_return_val_if_fail (!i_cal_time_is_null_time ((ICalTime *) rid), NULL);
 
        /* Make sure this is really recurring */
-       if (!icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY) &&
-           !icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY))
+       if (!e_cal_util_component_has_recurrences (icalcomp))
                return NULL;
 
        /* Make sure the specified instance really exists */
-       start = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ());
-       end = start;
-       icaltime_adjust (&end, 0, 0, 0, 1);
+       start = i_cal_time_convert_to_zone ((ICalTime *) rid, i_cal_timezone_get_utc_timezone ());
+       end = i_cal_time_new_clone (start);
+       i_cal_time_adjust (end, 0, 0, 0, 1);
 
-       instance.start = icaltime_as_timet (start);
+       instance.start = i_cal_time_as_timet (start);
        instance.found = FALSE;
-       icalcomponent_foreach_recurrence (icalcomp, start, end,
-                                         check_instance, &instance);
+       i_cal_component_foreach_recurrence (icalcomp, start, end, check_instance, &instance);
+       g_clear_object (&start);
+       g_clear_object (&end);
+
        /* Make the copy */
-       icalcomp = icalcomponent_new_clone (icalcomp);
+       icalcomp = i_cal_component_new_clone (icalcomp);
 
        e_cal_util_remove_instances_ex (icalcomp, rid, E_CAL_OBJ_MOD_THIS_AND_PRIOR, TRUE, FALSE);
 
-       start = rid;
-       if (icaltime_is_null_time (master_dtstart))
-               master_dtstart = icalcomponent_get_dtstart (icalcomp);
-       duration = icalcomponent_get_duration (icalcomp);
+       start = i_cal_time_new_clone ((ICalTime *) rid);
+
+       if (!master_dtstart || i_cal_time_is_null_time ((ICalTime *) master_dtstart)) {
+               dtstart = i_cal_component_get_dtstart (icalcomp);
+               master_dtstart = dtstart;
+       }
+
+       duration = i_cal_component_get_duration (icalcomp);
 
        /* Expect that DTSTART and DTEND are already set when the instance could not be found */
        if (instance.found) {
-               icalcomponent_set_dtstart (icalcomp, start);
+               ICalTime *dtend;
+
+               dtend = i_cal_component_get_dtend (icalcomp);
+
+               i_cal_component_set_dtstart (icalcomp, start);
+
                /* Update either DURATION or DTEND */
-               if (icaltime_is_null_time (icalcomponent_get_dtend (icalcomp))) {
-                       icalcomponent_set_duration (icalcomp, duration);
+               if (i_cal_time_is_null_time (dtend)) {
+                       i_cal_component_set_duration (icalcomp, duration);
                } else {
-                       end = start;
-                       if (duration.is_neg)
-                               icaltime_adjust (&end, -duration.days - 7 * duration.weeks, -duration.hours, 
-duration.minutes, -duration.seconds);
+                       end = i_cal_time_new_clone (start);
+                       if (i_cal_duration_is_neg (duration))
+                               i_cal_time_adjust (end, -i_cal_duration_get_days (duration)
+                                                       - 7 * i_cal_duration_get_weeks (duration),
+                                                       -i_cal_duration_get_hours (duration),
+                                                       -i_cal_duration_get_minutes (duration),
+                                                       -i_cal_duration_get_seconds (duration));
                        else
-                               icaltime_adjust (&end, duration.days + 7 * duration.weeks, duration.hours, 
duration.minutes, duration.seconds);
-                       icalcomponent_set_dtend (icalcomp, end);
+                               i_cal_time_adjust (end, i_cal_duration_get_days (duration)
+                                                       + 7 * i_cal_duration_get_weeks (duration),
+                                                       i_cal_duration_get_hours (duration),
+                                                       i_cal_duration_get_minutes (duration),
+                                                       i_cal_duration_get_seconds (duration));
+
+                       i_cal_component_set_dtend (icalcomp, end);
                }
+
+               g_clear_object (&dtend);
        }
 
+       g_clear_object (&start);
+       g_clear_object (&end);
+       g_clear_object (&duration);
+
        /* any RRULE with 'count' should be shortened */
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) {
-               struct icaltimetype recur;
-               struct icalrecurrencetype rule;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) 
{
+               ICalTime *recur;
+               ICalRecurrence *rule;
+               gint rule_count;
+
+               rule = i_cal_property_get_rrule (prop);
+               if (!rule)
+                       continue;
 
-               rule = icalproperty_get_rrule (prop);
+               rule_count = i_cal_recurrence_get_count (rule);
 
-               if (rule.count != 0) {
+               if (rule_count != 0) {
                        gint occurrences_count = 0;
-                       icalrecur_iterator *iter;
+                       ICalRecurIterator *iter;
 
-                       iter = icalrecur_iterator_new (rule, master_dtstart);
-                       while (recur = icalrecur_iterator_next (iter), !icaltime_is_null_time (recur) && 
occurrences_count < rule.count) {
-                               if (icaltime_compare (recur, rid) >= 0)
+                       iter = i_cal_recur_iterator_new (rule, (ICalTime *) master_dtstart);
+                       while (recur = i_cal_recur_iterator_next (iter),
+                              recur && !i_cal_time_is_null_time (recur) && occurrences_count < rule_count) {
+                               if (i_cal_time_compare (recur, (ICalTime *) rid) >= 0)
                                        break;
 
                                occurrences_count++;
+                               g_object_unref (recur);
                        }
 
-                       icalrecur_iterator_free (iter);
-
-                       if (icaltime_is_null_time (recur)) {
-                               remove_props = g_slist_prepend (remove_props, prop);
+                       if (!recur || i_cal_time_is_null_time (recur)) {
+                               remove_props = g_slist_prepend (remove_props, g_object_ref (prop));
                        } else {
-                               rule.count -= occurrences_count;
-                               icalproperty_set_rrule (prop, rule);
-                               icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE");
+                               i_cal_recurrence_set_count (rule, rule_count - occurrences_count);
+                               i_cal_property_set_rrule (prop, rule);
+                               i_cal_property_remove_parameter_by_name (prop, 
E_CAL_EVOLUTION_ENDDATE_PARAMETER);
                        }
+
+                       g_clear_object (&iter);
+                       g_clear_object (&recur);
                }
+
+               g_object_unref (rule);
        }
 
        for (link = remove_props; link; link = g_slist_next (link)) {
                prop = link->data;
 
-               icalcomponent_remove_property (icalcomp, prop);
+               i_cal_component_remove_property (icalcomp, prop);
        }
 
-       g_slist_free (remove_props);
+       g_slist_free_full (remove_props, g_object_unref);
+       g_clear_object (&dtstart);
 
        return icalcomp;
 }
 
 typedef struct {
-       struct icaltimetype rid;
+       const ICalTime *rid;
        gboolean matches;
 } CheckFirstInstanceData;
 
 static gboolean
-check_first_instance_cb (ECalComponent *comp,
-                        time_t instance_start,
-                        time_t instance_end,
-                        gpointer user_data)
+check_first_instance_cb (ICalComponent *icalcomp,
+                        ICalTime *instance_start,
+                        ICalTime *instance_end,
+                        gpointer user_data,
+                        GCancellable *cancellable,
+                        GError **error)
 {
        CheckFirstInstanceData *ifs = user_data;
-       icalcomponent *icalcomp;
-       struct icaltimetype rid;
+       ICalProperty *prop;
+       ICalTime *rid;
 
        g_return_val_if_fail (ifs != NULL, FALSE);
 
-       icalcomp = e_cal_component_get_icalcomponent (comp);
-       if (icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY) != NULL) {
-               rid = icalcomponent_get_recurrenceid (icalcomp);
+       prop = i_cal_component_get_first_property (icalcomp, I_CAL_RECURRENCEID_PROPERTY);
+       if (prop) {
+               rid = i_cal_property_get_recurrenceid (prop);
+               g_object_unref (prop);
        } else {
-               struct icaltimetype dtstart;
+               ICalTime *dtstart;
+               ICalTimezone *zone;
+
+               dtstart = i_cal_component_get_dtstart (icalcomp);
+               zone = i_cal_time_get_timezone (dtstart);
+
+               rid = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (instance_start), 
i_cal_time_is_date (dtstart), zone);
 
-               dtstart = icalcomponent_get_dtstart (icalcomp);
-               rid = icaltime_from_timet_with_zone (instance_start, dtstart.is_date, dtstart.zone);
+               g_clear_object (&dtstart);
        }
 
-       ifs->matches = icaltime_compare (ifs->rid, rid) == 0;
+       ifs->matches = i_cal_time_compare ((ICalTime *) ifs->rid, rid) == 0;
+
+       g_clear_object (&rid);
 
        return FALSE;
 }
@@ -1514,7 +1696,7 @@ check_first_instance_cb (ECalComponent *comp,
  * e_cal_util_is_first_instance:
  * @comp: an #ECalComponent instance
  * @rid: a recurrence ID
- * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneFn to call
+ * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneCb to call
  * @tz_cb_data: (closure): User data to be passed to the @tz_cb callback
  *
  * Returns whether the given @rid is the first instance of
@@ -1526,26 +1708,36 @@ check_first_instance_cb (ECalComponent *comp,
  **/
 gboolean
 e_cal_util_is_first_instance (ECalComponent *comp,
-                             struct icaltimetype rid,
-                             ECalRecurResolveTimezoneFn tz_cb,
+                             const ICalTime *rid,
+                             ECalRecurResolveTimezoneCb tz_cb,
                              gpointer tz_cb_data)
 {
        CheckFirstInstanceData ifs;
-       icalcomponent *icalcomp;
-       time_t start, end;
+       ICalComponent *icalcomp;
+       ICalTime *start, *end;
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-       g_return_val_if_fail (!icaltime_is_null_time (rid), FALSE);
+       g_return_val_if_fail (rid && !i_cal_time_is_null_time ((ICalTime *) rid), FALSE);
 
        ifs.rid = rid;
        ifs.matches = FALSE;
 
        icalcomp = e_cal_component_get_icalcomponent (comp);
-       start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)) - 24 * 60 * 60;
-       end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)) + 24 * 60 * 60;
 
-       e_cal_recur_generate_instances (comp, start, end, check_first_instance_cb, &ifs,
-               tz_cb, tz_cb_data, icaltimezone_get_utc_timezone ());
+       start = i_cal_component_get_dtstart (icalcomp);
+       i_cal_time_adjust (start, -1, 0, 0, 0);
+
+       end = i_cal_component_get_dtend (icalcomp);
+       i_cal_time_adjust (end, +1, 0, 0, 0);
+
+       e_cal_recur_generate_instances_sync (e_cal_component_get_icalcomponent (comp),
+               start, end,
+               check_first_instance_cb, &ifs,
+               tz_cb, tz_cb_data, i_cal_timezone_get_utc_timezone (),
+               NULL, NULL);
+
+       g_clear_object (&start);
+       g_clear_object (&end);
 
        return ifs.matches;
 }
@@ -1568,19 +1760,19 @@ e_cal_util_get_system_timezone_location (void)
 /**
  * e_cal_util_get_system_timezone:
  *
- * Fetches system timezone icaltimezone object.
+ * Fetches system timezone ICalTimezone object.
  *
  * The returned pointer is part of the built-in timezones and should not be freed.
  *
- * Returns: (transfer none): The icaltimezone object of the system timezone, or %NULL on an error.
+ * Returns: (transfer none) (nullable): The ICalTimezone object of the system timezone, or %NULL on an error.
  *
  * Since: 2.28
  **/
-icaltimezone *
+ICalTimezone *
 e_cal_util_get_system_timezone (void)
 {
        gchar *location;
-       icaltimezone *zone;
+       ICalTimezone *zone;
 
        location = e_cal_system_timezone_get_location ();
 
@@ -1588,7 +1780,7 @@ e_cal_util_get_system_timezone (void)
        if (!location)
                return NULL;
 
-       zone = icaltimezone_get_builtin_timezone (location);
+       zone = i_cal_timezone_get_builtin_timezone (location);
 
        g_free (location);
 
@@ -1597,21 +1789,24 @@ e_cal_util_get_system_timezone (void)
 
 static time_t
 componenttime_to_utc_timet (const ECalComponentDateTime *dt_time,
-                            ECalRecurResolveTimezoneFn tz_cb,
+                            ECalRecurResolveTimezoneCb tz_cb,
                             gpointer tz_cb_data,
-                            const icaltimezone *default_zone)
+                            const ICalTimezone *default_zone)
 {
+       ICalTime *value = NULL;
        time_t timet = -1;
-       icaltimezone *zone = NULL;
 
-       g_return_val_if_fail (dt_time != NULL, -1);
+       if (dt_time)
+               value = e_cal_component_datetime_get_value (dt_time);
 
-       if (dt_time->value) {
-               if (dt_time->tzid)
-                       zone = tz_cb (dt_time->tzid, tz_cb_data);
+       if (value) {
+               ICalTimezone *zone = NULL;
+               const gchar *tzid = e_cal_component_datetime_get_tzid (dt_time);
 
-               timet = icaltime_as_timet_with_zone (
-                       *dt_time->value, zone ? zone : default_zone);
+               if (tzid)
+                       zone = tz_cb (tzid, tz_cb_data, NULL, NULL);
+
+               timet = i_cal_time_as_timet_with_zone (value, zone ? zone : (ICalTimezone *) default_zone);
        }
 
        return timet;
@@ -1620,12 +1815,12 @@ componenttime_to_utc_timet (const ECalComponentDateTime *dt_time,
 /**
  * e_cal_util_get_component_occur_times:
  * @comp: an #ECalComponent
- * @start: (out): Location to store the start time
- * @end: (out): Location to store the end time
- * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneFn to call
+ * @out_start: (out): Location to store the start time
+ * @out_end: (out): Location to store the end time
+ * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneCb to call
  * @tz_cb_data: (closure): User data to be passed to the @tz_cb callback
  * @default_timezone: The default timezone
- * @kind: the type of component, indicated with an icalcomponent_kind
+ * @kind: the type of component, indicated with an #ICalComponentKind
  *
  * Find out when the component starts and stops, being careful about
  * recurrences.
@@ -1634,68 +1829,66 @@ componenttime_to_utc_timet (const ECalComponentDateTime *dt_time,
  **/
 void
 e_cal_util_get_component_occur_times (ECalComponent *comp,
-                                      time_t *start,
-                                      time_t *end,
-                                      ECalRecurResolveTimezoneFn tz_cb,
+                                      time_t *out_start,
+                                      time_t *out_end,
+                                      ECalRecurResolveTimezoneCb tz_cb,
                                       gpointer tz_cb_data,
-                                      const icaltimezone *default_timezone,
-                                      icalcomponent_kind kind)
+                                      const ICalTimezone *default_timezone,
+                                      ICalComponentKind kind)
 {
-       struct icalrecurrencetype ir;
-       ECalComponentDateTime dt_start, dt_end;
+       ICalTimezone *utc_zone;
+       ECalComponentDateTime *dtstart, *dtend;
        time_t duration;
 
        g_return_if_fail (comp != NULL);
-       g_return_if_fail (start != NULL);
-       g_return_if_fail (end != NULL);
+       g_return_if_fail (out_start != NULL);
+       g_return_if_fail (out_end != NULL);
 
-       e_cal_recur_ensure_end_dates (comp, FALSE, tz_cb, tz_cb_data);
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+       e_cal_recur_ensure_end_dates (comp, FALSE, tz_cb, tz_cb_data, NULL, NULL);
 
        /* Get dtstart of the component and convert it to UTC */
-       e_cal_component_get_dtstart (comp, &dt_start);
+       dtstart = e_cal_component_get_dtstart (comp);
 
-       if ((*start = componenttime_to_utc_timet (&dt_start, tz_cb, tz_cb_data, default_timezone)) == -1)
-               *start = _TIME_MIN;
+       if ((*out_start = componenttime_to_utc_timet (dtstart, tz_cb, tz_cb_data, default_timezone)) == -1)
+               *out_start = _TIME_MIN;
 
-       e_cal_component_free_datetime (&dt_start);
+       e_cal_component_datetime_free (dtstart);
 
-       e_cal_component_get_dtend (comp, &dt_end);
-       duration = componenttime_to_utc_timet (&dt_end, tz_cb, tz_cb_data, default_timezone);
-       if (duration <= 0 || *start == _TIME_MIN || *start > duration)
+       dtend = e_cal_component_get_dtend (comp);
+       duration = componenttime_to_utc_timet (dtend, tz_cb, tz_cb_data, default_timezone);
+       if (duration <= 0 || *out_start == _TIME_MIN || *out_start > duration)
                duration = 0;
        else
-               duration = duration - *start;
-       e_cal_component_free_datetime (&dt_end);
+               duration = duration - *out_start;
+       e_cal_component_datetime_free (dtend);
 
        /* find out end date of component */
-       *end = _TIME_MAX;
+       *out_end = _TIME_MAX;
 
-       if (kind == ICAL_VTODO_COMPONENT) {
+       if (kind == I_CAL_VTODO_COMPONENT) {
                /* max from COMPLETED and DUE properties */
-               struct icaltimetype *tt = NULL;
+               ICalTime *tt;
                time_t completed_time = -1, due_time = -1, max_time;
-               ECalComponentDateTime dt_due;
+               ECalComponentDateTime *dtdue;
 
-               e_cal_component_get_completed (comp, &tt);
+               tt = e_cal_component_get_completed (comp);
                if (tt) {
                        /* COMPLETED must be in UTC. */
-                       completed_time = icaltime_as_timet_with_zone (
-                               *tt, icaltimezone_get_utc_timezone ());
-                       e_cal_component_free_icaltimetype (tt);
+                       completed_time = i_cal_time_as_timet_with_zone (tt, utc_zone);
+                       g_object_unref (tt);
                }
 
-               e_cal_component_get_due (comp, &dt_due);
-               if (dt_due.value != NULL)
-                       due_time = componenttime_to_utc_timet (
-                               &dt_due, tz_cb, tz_cb_data,
-                               default_timezone);
+               dtdue = e_cal_component_get_due (comp);
+               if (dtdue)
+                       due_time = componenttime_to_utc_timet (dtdue, tz_cb, tz_cb_data, default_timezone);
 
-               e_cal_component_free_datetime (&dt_due);
+               e_cal_component_datetime_free (dtdue);
 
                max_time = MAX (completed_time, due_time);
 
                if (max_time != -1)
-                       *end = max_time;
+                       *out_end = max_time;
 
        } else {
                /* ALARMS, EVENTS: DTEND and reccurences */
@@ -1705,62 +1898,67 @@ e_cal_util_get_component_occur_times (ECalComponent *comp,
                if (e_cal_component_has_recurrences (comp)) {
                        GSList *rrules = NULL;
                        GSList *exrules = NULL;
-                       GSList *elem;
                        GSList *rdates = NULL;
+                       GSList *elem;
 
                        /* Do the RRULEs, EXRULEs and RDATEs*/
-                       e_cal_component_get_rrule_property_list (comp, &rrules);
-                       e_cal_component_get_exrule_property_list (comp, &exrules);
-                       e_cal_component_get_rdate_list (comp, &rdates);
+                       rrules = e_cal_component_get_rrule_properties (comp);
+                       exrules = e_cal_component_get_exrule_properties (comp);
+                       rdates = e_cal_component_get_rdates (comp);
 
-                       for (elem = rrules; elem; elem = elem->next) {
+                       for (elem = rrules; elem; elem = g_slist_next (elem)) {
+                               ICalProperty *prop = elem->data;
+                               ICalRecurrence *ir;
                                time_t rule_end;
-                               icaltimezone *utc_zone;
-                               icalproperty *prop = elem->data;
-                               ir = icalproperty_get_rrule (prop);
 
-                               utc_zone = icaltimezone_get_utc_timezone ();
-                               rule_end = e_cal_recur_obtain_enddate (
-                                       &ir, prop, utc_zone, TRUE);
+                               ir = i_cal_property_get_rrule (prop);
+                               rule_end = e_cal_recur_obtain_enddate (ir, prop, utc_zone, TRUE);
 
                                if (rule_end == -1) /* repeats forever */
                                        may_end = _TIME_MAX;
                                else if (rule_end + duration > may_end) /* new maximum */
                                        may_end = rule_end + duration;
+
+                               g_clear_object (&ir);
                        }
 
                        /* Do the EXRULEs. */
-                       for (elem = exrules; elem; elem = elem->next) {
-                               icalproperty *prop = elem->data;
+                       for (elem = exrules; elem; elem = g_slist_next (elem)) {
+                               ICalProperty *prop = elem->data;
+                               ICalRecurrence *ir;
                                time_t rule_end;
-                               icaltimezone *utc_zone;
-                               ir = icalproperty_get_exrule (prop);
 
-                               utc_zone = icaltimezone_get_utc_timezone ();
-                               rule_end = e_cal_recur_obtain_enddate (
-                                       &ir, prop, utc_zone, TRUE);
+                               ir = i_cal_property_get_exrule (prop);
+
+                               rule_end = e_cal_recur_obtain_enddate (ir, prop, utc_zone, TRUE);
 
                                if (rule_end == -1) /* repeats forever */
                                        may_end = _TIME_MAX;
                                else if (rule_end + duration > may_end)
                                        may_end = rule_end + duration;
+
+                               g_clear_object (&ir);
                        }
 
                        /* Do the RDATEs */
-                       for (elem = rdates; elem; elem = elem->next) {
-                               ECalComponentPeriod *p = elem->data;
+                       for (elem = rdates; elem; elem = g_slist_next (elem)) {
+                               const ECalComponentPeriod *period = elem->data;
                                time_t rdate_end = _TIME_MAX;
 
                                /* FIXME: We currently assume RDATEs are in the same timezone
                                 * as DTSTART. We should get the RDATE timezone and convert
                                 * to the DTSTART timezone first. */
 
-                               /* Check if the end date or duration is set, libical seems to set
-                                * second to -1 to denote an unset time */
-                               if (p->type != E_CAL_COMPONENT_PERIOD_DATETIME || p->u.end.second != -1)
-                                       rdate_end = icaltime_as_timet (icaltime_add (p->start, 
p->u.duration));
-                               else
-                                       rdate_end = icaltime_as_timet (p->u.end);
+                               if (e_cal_component_period_get_kind (period) != 
E_CAL_COMPONENT_PERIOD_DATETIME) {
+                                       ICalTime *tt;
+                                       tt = i_cal_time_add (e_cal_component_period_get_start (period), 
e_cal_component_period_get_duration (period));
+                                       rdate_end = i_cal_time_as_timet (tt);
+                                       g_object_unref (tt);
+                               } else if (e_cal_component_period_get_end (period)) {
+                                       rdate_end = i_cal_time_as_timet (e_cal_component_period_get_end 
(period));
+                               } else {
+                                       rdate_end = (time_t) -1;
+                               }
 
                                if (rdate_end == -1) /* repeats forever */
                                        may_end = _TIME_MAX;
@@ -1768,19 +1966,20 @@ e_cal_util_get_component_occur_times (ECalComponent *comp,
                                        may_end = rdate_end;
                        }
 
-                       e_cal_component_free_period_list (rdates);
-               } else if (*start != _TIME_MIN) {
-                       may_end = *start;
+                       g_slist_free_full (rrules, g_object_unref);
+                       g_slist_free_full (exrules, g_object_unref);
+                       g_slist_free_full (rdates, e_cal_component_period_free);
+               } else if (*out_start != _TIME_MIN) {
+                       may_end = *out_start;
                }
 
                /* Get dtend of the component and convert it to UTC */
-               e_cal_component_get_dtend (comp, &dt_end);
+               dtend = e_cal_component_get_dtend (comp);
 
-               if (dt_end.value) {
+               if (dtend) {
                        time_t dtend_time;
 
-                       dtend_time = componenttime_to_utc_timet (
-                               &dt_end, tz_cb, tz_cb_data, default_timezone);
+                       dtend_time = componenttime_to_utc_timet (dtend, tz_cb, tz_cb_data, default_timezone);
 
                        if (dtend_time == -1 || (dtend_time > may_end))
                                may_end = dtend_time;
@@ -1788,180 +1987,187 @@ e_cal_util_get_component_occur_times (ECalComponent *comp,
                        may_end = _TIME_MAX;
                }
 
-               e_cal_component_free_datetime (&dt_end);
+               e_cal_component_datetime_free (dtend);
 
-               *end = may_end == _TIME_MIN ? _TIME_MAX : may_end;
+               *out_end = may_end == _TIME_MIN ? _TIME_MAX : may_end;
        }
 }
 
 /**
- * e_cal_util_find_x_property:
- * @icalcomp: an icalcomponent
+ * e_cal_util_component_has_x_property:
+ * @icalcomp: an #ICalComponent
  * @x_name: name of the X property
  *
- * Searches for an X property named @x_name within X properties
- * of @icalcomp and returns it.
+ * Returns, whether the @icalcomp contains X property named @x_name. To check
+ * for standard property use e_cal_util_component_has_property().
  *
- * Returns: (nullable) (transfer none): the first X icalproperty named
- *    @x_name, or %NULL, when none found. The returned structure is owned
- *    by @icalcomp.
+ * Returns: whether the @icalcomp contains X property named @x_name
  *
- * Since: 3.26
+ * Since: 3.36
  **/
-icalproperty *
-e_cal_util_find_x_property (icalcomponent *icalcomp,
-                           const gchar *x_name)
+gboolean
+e_cal_util_component_has_x_property (ICalComponent *icalcomp,
+                                    const gchar *x_name)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
-       g_return_val_if_fail (icalcomp != NULL, NULL);
-       g_return_val_if_fail (x_name != NULL, NULL);
+       g_return_val_if_fail (I_CAL_IS_COMPONENT (icalcomp), FALSE);
+       g_return_val_if_fail (x_name != NULL, FALSE);
 
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY)) {
-               const gchar *prop_name = icalproperty_get_x_name (prop);
+       prop = e_cal_util_component_find_x_property (icalcomp, x_name);
 
-               if (g_strcmp0 (prop_name, x_name) == 0)
-                       break;
-       }
+       if (!prop)
+               return FALSE;
 
-       return prop;
+       g_object_unref (prop);
+
+       return TRUE;
 }
 
+
 /**
- * e_cal_util_dup_x_property:
- * @icalcomp: an icalcomponent
+ * e_cal_util_component_find_x_property:
+ * @icalcomp: an #ICalComponent
  * @x_name: name of the X property
  *
  * Searches for an X property named @x_name within X properties
- * of @icalcomp and returns its value as a newly allocated string.
- * Free it with g_free(), when no longer needed.
+ * of @icalcomp and returns it. Free the non-NULL object
+ * with g_object_unref(), when no longer needed.
  *
- * Returns: (nullable) (transfer full): Newly allocated value of the first @x_name
- *    X property in @icalcomp, or %NULL, if not found.
+ * Returns: (transfer full) (nullable): the first X ICalProperty named
+ *    @x_name, or %NULL, when none found.
  *
- * Since: 3.26
+ * Since: 3.36
  **/
-gchar *
-e_cal_util_dup_x_property (icalcomponent *icalcomp,
-                          const gchar *x_name)
+ICalProperty *
+e_cal_util_component_find_x_property (ICalComponent *icalcomp,
+                                     const gchar *x_name)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
        g_return_val_if_fail (icalcomp != NULL, NULL);
        g_return_val_if_fail (x_name != NULL, NULL);
 
-       prop = e_cal_util_find_x_property (icalcomp, x_name);
+       for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_X_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, I_CAL_X_PROPERTY)) {
+               const gchar *prop_name = i_cal_property_get_x_name (prop);
 
-       if (!prop)
-               return NULL;
+               if (g_strcmp0 (prop_name, x_name) == 0)
+                       break;
+       }
 
-       return icalproperty_get_value_as_string_r (prop);
+       return prop;
 }
 
 /**
- * e_cal_util_get_x_property:
- * @icalcomp: an icalcomponent
+ * e_cal_util_component_dup_x_property:
+ * @icalcomp: an #ICalComponent
  * @x_name: name of the X property
  *
  * Searches for an X property named @x_name within X properties
- * of @icalcomp and returns its value. The returned string is
- * owned by libical. See e_cal_util_dup_x_property().
+ * of @icalcomp and returns its value as a newly allocated string.
+ * Free it with g_free(), when no longer needed.
  *
- * Returns: (nullable) (transfer none): Value of the first @x_name
+ * Returns: (nullable) (transfer full): Newly allocated value of the first @x_name
  *    X property in @icalcomp, or %NULL, if not found.
  *
- * Since: 3.26
+ * Since: 3.36
  **/
-const gchar *
-e_cal_util_get_x_property (icalcomponent *icalcomp,
-                          const gchar *x_name)
+gchar *
+e_cal_util_component_dup_x_property (ICalComponent *icalcomp,
+                                    const gchar *x_name)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
+       gchar *x_value;
 
        g_return_val_if_fail (icalcomp != NULL, NULL);
        g_return_val_if_fail (x_name != NULL, NULL);
 
-       prop = e_cal_util_find_x_property (icalcomp, x_name);
+       prop = e_cal_util_component_find_x_property (icalcomp, x_name);
 
        if (!prop)
                return NULL;
 
-       return icalproperty_get_value_as_string (prop);
+       x_value = i_cal_property_get_value_as_string_r (prop);
+
+       g_object_unref (prop);
+
+       return x_value;
 }
 
 /**
- * e_cal_util_set_x_property:
- * @icalcomp: an icalcomponent
+ * e_cal_util_component_set_x_property:
+ * @icalcomp: an #ICalComponent
  * @x_name: name of the X property
  * @value: (nullable): a value to set, or %NULL
  *
  * Sets a value of the first X property named @x_name in @icalcomp,
  * if any such already exists, or adds a new property with this name
  * and value. As a special case, if @value is %NULL, then removes
- * the first X property names @x_name from @icalcomp instead.
+ * the first X property named @x_name from @icalcomp instead.
  *
- * Since: 3.26
+ * Since: 3.36
  **/
 void
-e_cal_util_set_x_property (icalcomponent *icalcomp,
-                          const gchar *x_name,
-                          const gchar *value)
+e_cal_util_component_set_x_property (ICalComponent *icalcomp,
+                                    const gchar *x_name,
+                                    const gchar *value)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
        g_return_if_fail (icalcomp != NULL);
        g_return_if_fail (x_name != NULL);
 
        if (!value) {
-               e_cal_util_remove_x_property (icalcomp, x_name);
+               e_cal_util_component_remove_x_property (icalcomp, x_name);
                return;
        }
 
-       prop = e_cal_util_find_x_property (icalcomp, x_name);
+       prop = e_cal_util_component_find_x_property (icalcomp, x_name);
        if (prop) {
-               icalproperty_set_value_from_string (prop, value, "NO");
+               i_cal_property_set_value_from_string (prop, value, "NO");
+               g_object_unref (prop);
        } else {
-               prop = icalproperty_new_x (value);
-               icalproperty_set_x_name (prop, x_name);
-               icalcomponent_add_property (icalcomp, prop);
+               prop = i_cal_property_new_x (value);
+               i_cal_property_set_x_name (prop, x_name);
+               i_cal_component_take_property (icalcomp, prop);
        }
 }
 
 /**
- * e_cal_util_remove_x_property:
- * @icalcomp: an icalcomponent
+ * e_cal_util_component_remove_x_property:
+ * @icalcomp: an #ICalComponent
  * @x_name: name of the X property
  *
  * Removes the first X property named @x_name in @icalcomp.
  *
  * Returns: %TRUE, when any such had been found and removed, %FALSE otherwise.
  *
- * Since: 3.26
+ * Since: 3.36
  **/
 gboolean
-e_cal_util_remove_x_property (icalcomponent *icalcomp,
-                             const gchar *x_name)
+e_cal_util_component_remove_x_property (ICalComponent *icalcomp,
+                                       const gchar *x_name)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
        g_return_val_if_fail (icalcomp != NULL, FALSE);
        g_return_val_if_fail (x_name != NULL, FALSE);
 
-       prop = e_cal_util_find_x_property (icalcomp, x_name);
+       prop = e_cal_util_component_find_x_property (icalcomp, x_name);
        if (!prop)
                return FALSE;
 
-       icalcomponent_remove_property (icalcomp, prop);
-       icalproperty_free (prop);
+       i_cal_component_remove_property (icalcomp, prop);
+       g_object_unref (prop);
 
        return TRUE;
 }
 
 /**
- * e_cal_util_remove_property_by_kind:
- * @icalcomp: an icalcomponent
+ * e_cal_util_component_remove_property_by_kind:
+ * @icalcomp: an #ICalComponent
  * @kind: the kind of the property to remove
  * @all: %TRUE to remove all, or %FALSE to remove only the first property of the @kind
  *
@@ -1972,18 +2178,18 @@ e_cal_util_remove_x_property (icalcomponent *icalcomp,
  * Since: 3.30
  **/
 guint
-e_cal_util_remove_property_by_kind (icalcomponent *icalcomp,
-                                   icalproperty_kind kind,
-                                   gboolean all)
+e_cal_util_component_remove_property_by_kind (ICalComponent *icalcomp,
+                                             ICalPropertyKind kind,
+                                             gboolean all)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
        guint count = 0;
 
        g_return_val_if_fail (icalcomp != NULL, 0);
 
-       while (prop = icalcomponent_get_first_property (icalcomp, kind), prop) {
-               icalcomponent_remove_property (icalcomp, prop);
-               icalproperty_free (prop);
+       while (prop = i_cal_component_get_first_property (icalcomp, kind), prop) {
+               i_cal_component_remove_property (icalcomp, prop);
+               g_object_unref (prop);
 
                count++;
 
@@ -1995,16 +2201,16 @@ e_cal_util_remove_property_by_kind (icalcomponent *icalcomp,
 }
 
 typedef struct _NextOccurrenceData {
-       struct icaltimetype interval_start;
-       struct icaltimetype next;
+       ICalTime *interval_start;
+       ICalTime *next;
        gboolean found_next;
        gboolean any_hit;
 } NextOccurrenceData;
 
 static gboolean
-ecu_find_next_occurrence_cb (icalcomponent *comp,
-                            struct icaltimetype instance_start,
-                            struct icaltimetype instance_end,
+ecu_find_next_occurrence_cb (ICalComponent *comp,
+                            ICalTime *instance_start,
+                            ICalTime *instance_end,
                             gpointer user_data,
                             GCancellable *cancellable,
                             GError **error)
@@ -2015,8 +2221,9 @@ ecu_find_next_occurrence_cb (icalcomponent *comp,
 
        nod->any_hit = TRUE;
 
-       if (icaltime_compare (nod->interval_start, instance_start) < 0) {
-               nod->next = instance_start;
+       if (i_cal_time_compare (nod->interval_start, instance_start) < 0) {
+               g_clear_object (&nod->next);
+               nod->next = g_object_ref (instance_start);
                nod->found_next = TRUE;
                return FALSE;
        }
@@ -2026,17 +2233,17 @@ ecu_find_next_occurrence_cb (icalcomponent *comp,
 
 /* the returned FALSE means failure in timezone resolution, not in @out_time */
 static gboolean
-e_cal_util_find_next_occurrence (icalcomponent *vtodo,
-                                struct icaltimetype for_time,
-                                struct icaltimetype *out_time, /* set to icaltime_null_time() on failure */
+e_cal_util_find_next_occurrence (ICalComponent *vtodo,
+                                ICalTime *for_time,
+                                ICalTime **out_time, /* set to NULL on failure */
                                 ECalClient *cal_client,
                                 GCancellable *cancellable,
                                 GError **error)
 {
        NextOccurrenceData nod;
-       struct icaltimetype interval_start = for_time, interval_end, orig_dtstart, orig_due;
+       ICalTime *interval_start, *interval_end = NULL, *orig_dtstart, *orig_due;
        gint advance_days = 8;
-       icalproperty *prop;
+       ICalProperty *prop;
        gboolean success;
        GError *local_error = NULL;
 
@@ -2044,70 +2251,89 @@ e_cal_util_find_next_occurrence (icalcomponent *vtodo,
        g_return_val_if_fail (out_time != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
 
-       orig_dtstart = icalcomponent_get_dtstart (vtodo);
-       orig_due = icalcomponent_get_due (vtodo);
+       orig_dtstart = i_cal_component_get_dtstart (vtodo);
+       orig_due = i_cal_component_get_due (vtodo);
 
-       e_cal_util_remove_property_by_kind (vtodo, ICAL_DUE_PROPERTY, TRUE);
+       e_cal_util_component_remove_property_by_kind (vtodo, I_CAL_DUE_PROPERTY, TRUE);
 
-       if (!icaltime_is_null_time (for_time) && icaltime_is_valid_time (for_time)) {
-               icalcomponent_set_dtstart (vtodo, for_time);
+       if (for_time && !i_cal_time_is_null_time (for_time) && i_cal_time_is_valid_time (for_time)) {
+               i_cal_component_set_dtstart (vtodo, for_time);
        }
 
-       interval_start = icalcomponent_get_dtstart (vtodo);
-       if (icaltime_is_null_time (interval_start) || !icaltime_is_valid_time (interval_start))
-               interval_start = icaltime_current_time_with_zone (e_cal_client_get_default_timezone 
(cal_client));
+       interval_start = i_cal_component_get_dtstart (vtodo);
+       if (!interval_start || i_cal_time_is_null_time (interval_start) || !i_cal_time_is_valid_time 
(interval_start)) {
+               g_clear_object (&interval_start);
+               interval_start = i_cal_time_current_time_with_zone (e_cal_client_get_default_timezone 
(cal_client));
+       }
 
-       prop = icalcomponent_get_first_property (vtodo, ICAL_RRULE_PROPERTY);
+       prop = i_cal_component_get_first_property (vtodo, I_CAL_RRULE_PROPERTY);
        if (prop) {
-               struct icalrecurrencetype rrule;
+               ICalRecurrence *rrule;
 
-               rrule = icalproperty_get_rrule (prop);
+               rrule = i_cal_property_get_rrule (prop);
+
+               if (rrule) {
+                       if (i_cal_recurrence_get_freq (rrule) == I_CAL_WEEKLY_RECURRENCE && 
i_cal_recurrence_get_interval (rrule) > 1)
+                               advance_days = (i_cal_recurrence_get_interval (rrule) * 7) + 1;
+                       else if (i_cal_recurrence_get_freq (rrule) == I_CAL_MONTHLY_RECURRENCE)
+                               advance_days = (i_cal_recurrence_get_interval (rrule) >= 1 ? 
i_cal_recurrence_get_interval (rrule) * 31 : 31) + 1;
+                       else if (i_cal_recurrence_get_freq (rrule) == I_CAL_YEARLY_RECURRENCE)
+                               advance_days = (i_cal_recurrence_get_interval (rrule) >= 1 ? 
i_cal_recurrence_get_interval (rrule) * 365 : 365) + 2;
+               }
 
-               if (rrule.freq == ICAL_WEEKLY_RECURRENCE && rrule.interval > 1)
-                       advance_days = (rrule.interval * 7) + 1;
-               else if (rrule.freq == ICAL_MONTHLY_RECURRENCE)
-                       advance_days = (rrule.interval >= 1 ? rrule.interval * 31 : 31) + 1;
-               else if (rrule.freq == ICAL_YEARLY_RECURRENCE)
-                       advance_days = (rrule.interval >= 1 ? rrule.interval * 365 : 365) + 2;
+               g_clear_object (&rrule);
+               g_clear_object (&prop);
        }
 
+       nod.next = NULL;
+
        do {
-               interval_end = interval_start;
-               icaltime_adjust (&interval_end, advance_days, 0, 0, 0);
+               interval_end = i_cal_time_new_clone (interval_start);
+               i_cal_time_adjust (interval_end, advance_days, 0, 0, 0);
+
+               g_clear_object (&(nod.next));
 
                nod.interval_start = interval_start;
-               nod.next = icaltime_null_time ();
+               nod.next = i_cal_time_null_time ();
                nod.found_next = FALSE;
                nod.any_hit = FALSE;
 
                success = e_cal_recur_generate_instances_sync (vtodo, interval_start, interval_end,
                        ecu_find_next_occurrence_cb, &nod,
-                       e_cal_client_resolve_tzid_sync, cal_client,
+                       e_cal_client_tzlookup_cb, cal_client,
                        e_cal_client_get_default_timezone (cal_client),
                        cancellable, &local_error) || nod.found_next;
 
+               g_object_unref (interval_start);
                interval_start = interval_end;
-               icaltime_adjust (&interval_start, -1, 0, 0, 0);
+               interval_end = NULL;
+               i_cal_time_adjust (interval_start, -1, 0, 0, 0);
 
        } while (!local_error && !g_cancellable_is_cancelled (cancellable) && !nod.found_next && nod.any_hit);
 
        if (success)
-               *out_time = nod.next;
+               *out_time = (nod.next && !i_cal_time_is_null_time (nod.next)) ? g_object_ref (nod.next) : 
NULL;
 
        if (local_error)
                g_propagate_error (error, local_error);
 
-       if (!icaltime_is_null_time (for_time) && icaltime_is_valid_time (for_time)) {
-               if (icaltime_is_null_time (orig_dtstart) || !icaltime_is_valid_time (orig_dtstart))
-                       e_cal_util_remove_property_by_kind (vtodo, ICAL_DTSTART_PROPERTY, FALSE);
+       if (for_time && !i_cal_time_is_null_time (for_time) && i_cal_time_is_valid_time (for_time)) {
+               if (!orig_dtstart || i_cal_time_is_null_time (orig_dtstart) || !i_cal_time_is_valid_time 
(orig_dtstart))
+                       e_cal_util_component_remove_property_by_kind (vtodo, I_CAL_DTSTART_PROPERTY, FALSE);
                else
-                       icalcomponent_set_dtstart (vtodo, orig_dtstart);
+                       i_cal_component_set_dtstart (vtodo, orig_dtstart);
        }
 
-       if (icaltime_is_null_time (orig_due) || !icaltime_is_valid_time (orig_due))
-               e_cal_util_remove_property_by_kind (vtodo, ICAL_DUE_PROPERTY, FALSE);
+       if (!orig_due || i_cal_time_is_null_time (orig_due) || !i_cal_time_is_valid_time (orig_due))
+               e_cal_util_component_remove_property_by_kind (vtodo, I_CAL_DUE_PROPERTY, FALSE);
        else
-               icalcomponent_set_due (vtodo, orig_due);
+               i_cal_component_set_due (vtodo, orig_due);
+
+       g_clear_object (&interval_start);
+       g_clear_object (&interval_end);
+       g_clear_object (&orig_dtstart);
+       g_clear_object (&orig_due);
+       g_clear_object (&(nod.next));
 
        return success;
 }
@@ -2135,37 +2361,44 @@ e_cal_util_find_next_occurrence (icalcomponent *vtodo,
  * Since: 3.30
  **/
 gboolean
-e_cal_util_init_recur_task_sync (icalcomponent *vtodo,
+e_cal_util_init_recur_task_sync (ICalComponent *vtodo,
                                 ECalClient *cal_client,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       struct icaltimetype dtstart, due;
+       ICalTime *dtstart, *due;
        gboolean success = TRUE;
 
        g_return_val_if_fail (vtodo != NULL, FALSE);
-       g_return_val_if_fail (icalcomponent_isa (vtodo) == ICAL_VTODO_COMPONENT, FALSE);
+       g_return_val_if_fail (i_cal_component_isa (vtodo) == I_CAL_VTODO_COMPONENT, FALSE);
        g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
 
        if (!e_cal_util_component_has_recurrences (vtodo))
                return TRUE;
 
        /* DTSTART is required for recurring components */
-       dtstart = icalcomponent_get_dtstart (vtodo);
-       if (icaltime_is_null_time (dtstart) || !icaltime_is_valid_time (dtstart)) {
-               dtstart = icaltime_current_time_with_zone (e_cal_client_get_default_timezone (cal_client));
-               icalcomponent_set_dtstart (vtodo, dtstart);
+       dtstart = i_cal_component_get_dtstart (vtodo);
+       if (!dtstart || i_cal_time_is_null_time (dtstart) || !i_cal_time_is_valid_time (dtstart)) {
+               g_clear_object (&dtstart);
+
+               dtstart = i_cal_time_current_time_with_zone (e_cal_client_get_default_timezone (cal_client));
+               i_cal_component_set_dtstart (vtodo, dtstart);
        }
 
-       due = icalcomponent_get_due (vtodo);
-       if (icaltime_is_null_time (due) || !icaltime_is_valid_time (due) ||
-           icaltime_compare (dtstart, due) < 0) {
-               success = e_cal_util_find_next_occurrence (vtodo, icaltime_null_time (), &due, cal_client, 
cancellable, error);
+       due = i_cal_component_get_due (vtodo);
+       if (!due || i_cal_time_is_null_time (due) || !i_cal_time_is_valid_time (due) ||
+           i_cal_time_compare (dtstart, due) < 0) {
+               g_clear_object (&due);
+
+               success = e_cal_util_find_next_occurrence (vtodo, NULL, &due, cal_client, cancellable, error);
 
-               if (!icaltime_is_null_time (due) && icaltime_is_valid_time (due))
-                       icalcomponent_set_due (vtodo, due);
+               if (due && !i_cal_time_is_null_time (due) && i_cal_time_is_valid_time (due))
+                       i_cal_component_set_due (vtodo, due);
        }
 
+       g_clear_object (&dtstart);
+       g_clear_object (&due);
+
        return success;
 }
 
@@ -2198,128 +2431,225 @@ e_cal_util_init_recur_task_sync (icalcomponent *vtodo,
  * Since: 3.30
  **/
 gboolean
-e_cal_util_mark_task_complete_sync (icalcomponent *vtodo,
+e_cal_util_mark_task_complete_sync (ICalComponent *vtodo,
                                    time_t completed_time,
                                    ECalClient *cal_client,
                                    GCancellable *cancellable,
                                    GError **error)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
 
        g_return_val_if_fail (vtodo != NULL, FALSE);
-       g_return_val_if_fail (icalcomponent_isa (vtodo) == ICAL_VTODO_COMPONENT, FALSE);
+       g_return_val_if_fail (i_cal_component_isa (vtodo) == I_CAL_VTODO_COMPONENT, FALSE);
        g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
 
        if (e_cal_util_component_has_recurrences (vtodo) &&
-           !e_client_check_capability (E_CLIENT (cal_client), CAL_STATIC_CAPABILITY_TASK_HANDLE_RECUR)) {
+           !e_client_check_capability (E_CLIENT (cal_client), E_CAL_STATIC_CAPABILITY_TASK_HANDLE_RECUR)) {
                gboolean is_last = FALSE, change_count = FALSE;
-               struct icaltimetype new_dtstart = icaltime_null_time (), new_due = icaltime_null_time ();
+               ICalTime *new_dtstart = NULL, *new_due = NULL;
 
-               for (prop = icalcomponent_get_first_property (vtodo, ICAL_RRULE_PROPERTY);
+               for (prop = i_cal_component_get_first_property (vtodo, I_CAL_RRULE_PROPERTY);
                     prop && !is_last;
-                    prop = icalcomponent_get_next_property (vtodo, ICAL_RRULE_PROPERTY)) {
-                       struct icalrecurrencetype rrule;
+                    g_object_unref (prop), prop = i_cal_component_get_next_property (vtodo, 
I_CAL_RRULE_PROPERTY)) {
+                       ICalRecurrence *rrule;
+
+                       rrule = i_cal_property_get_rrule (prop);
 
-                       rrule = icalproperty_get_rrule (prop);
+                       if (rrule && i_cal_recurrence_get_interval (rrule) > 0) {
+                               gint count = i_cal_recurrence_get_count (rrule);
 
-                       if (rrule.interval > 0) {
-                               if (rrule.count > 0) {
-                                       is_last = rrule.count == 1;
+                               if (count > 0) {
+                                       is_last = count == 1;
                                        change_count = TRUE;
                                }
                        }
+
+                       g_clear_object (&rrule);
                }
 
+               g_clear_object (&prop);
+
                if (!is_last) {
-                       if (!e_cal_util_find_next_occurrence (vtodo, icaltime_null_time (), &new_dtstart, 
cal_client, cancellable, error))
+                       if (!e_cal_util_find_next_occurrence (vtodo, NULL, &new_dtstart, cal_client, 
cancellable, error)) {
+                               g_clear_object (&new_dtstart);
                                return FALSE;
+                       }
 
-                       if (!icaltime_is_null_time (new_dtstart) && icaltime_is_valid_time (new_dtstart)) {
-                               struct icaltimetype old_due;
+                       if (new_dtstart && !i_cal_time_is_null_time (new_dtstart) && i_cal_time_is_valid_time 
(new_dtstart)) {
+                               ICalTime *old_due;
 
-                               old_due = icalcomponent_get_due (vtodo);
+                               old_due = i_cal_component_get_due (vtodo);
 
                                /* When the previous DUE is before new DTSTART, then move relatively also the 
DUE
                                   date, to keep the difference... */
-                               if (!icaltime_is_null_time (old_due) && icaltime_is_valid_time (old_due) &&
-                                   icaltime_compare (old_due, new_dtstart) < 0) {
-                                       if (!e_cal_util_find_next_occurrence (vtodo, old_due, &new_due, 
cal_client, cancellable, error))
+                               if (old_due && !i_cal_time_is_null_time (old_due) && i_cal_time_is_valid_time 
(old_due) &&
+                                   i_cal_time_compare (old_due, new_dtstart) < 0) {
+                                       if (!e_cal_util_find_next_occurrence (vtodo, old_due, &new_due, 
cal_client, cancellable, error)) {
+                                               g_clear_object (&new_dtstart);
+                                               g_clear_object (&new_due);
+                                               g_clear_object (&old_due);
                                                return FALSE;
+                                       }
                                }
 
                                /* ...  otherwise set the new DUE as the next-next-DTSTART ... */
-                               if (icaltime_is_null_time (new_due) || !icaltime_is_valid_time (new_due)) {
-                                       if (!e_cal_util_find_next_occurrence (vtodo, new_dtstart, &new_due, 
cal_client, cancellable, error))
+                               if (!new_due || i_cal_time_is_null_time (new_due) || 
!i_cal_time_is_valid_time (new_due)) {
+                                       g_clear_object (&new_due);
+
+                                       if (!e_cal_util_find_next_occurrence (vtodo, new_dtstart, &new_due, 
cal_client, cancellable, error)) {
+                                               g_clear_object (&new_dtstart);
+                                               g_clear_object (&new_due);
+                                               g_clear_object (&old_due);
                                                return FALSE;
+                                       }
                                }
 
                                /* ... eventually fallback to the new DTSTART for the new DUE */
-                               if (icaltime_is_null_time (new_due) || !icaltime_is_valid_time (new_due))
-                                       new_due = new_dtstart;
+                               if (!new_due || i_cal_time_is_null_time (new_due) || 
!i_cal_time_is_valid_time (new_due)) {
+                                       g_clear_object (&new_due);
+                                       new_due = i_cal_time_new_clone (new_dtstart);
+                               }
+
+                               g_clear_object (&old_due);
                        }
                }
 
-               if (!is_last &&
-                   !icaltime_is_null_time (new_dtstart) && icaltime_is_valid_time (new_dtstart) &&
-                   !icaltime_is_null_time (new_due) && icaltime_is_valid_time (new_due)) {
+               if (!is_last && new_dtstart && new_due &&
+                   !i_cal_time_is_null_time (new_dtstart) && i_cal_time_is_valid_time (new_dtstart) &&
+                   !i_cal_time_is_null_time (new_due) && i_cal_time_is_valid_time (new_due)) {
                        /* Move to the next occurrence */
                        if (change_count) {
-                               for (prop = icalcomponent_get_first_property (vtodo, ICAL_RRULE_PROPERTY);
+                               for (prop = i_cal_component_get_first_property (vtodo, I_CAL_RRULE_PROPERTY);
                                     prop;
-                                    prop = icalcomponent_get_next_property (vtodo, ICAL_RRULE_PROPERTY)) {
-                                       struct icalrecurrencetype rrule;
+                                    g_object_unref (prop), prop = i_cal_component_get_next_property (vtodo, 
I_CAL_RRULE_PROPERTY)) {
+                                       ICalRecurrence *rrule;
 
-                                       rrule = icalproperty_get_rrule (prop);
+                                       rrule = i_cal_property_get_rrule (prop);
 
-                                       if (rrule.interval > 0) {
-                                               if (rrule.count > 0) {
-                                                       rrule.count--;
-                                                       icalproperty_set_rrule (prop, rrule);
+                                       if (rrule && i_cal_recurrence_get_interval (rrule) > 0) {
+                                               gint count = i_cal_recurrence_get_count (rrule);
+
+                                               if (count > 0) {
+                                                       i_cal_recurrence_set_count (rrule, count - 1);
+                                                       i_cal_property_set_rrule (prop, rrule);
                                                }
                                        }
+
+                                       g_clear_object (&rrule);
                                }
                        }
 
-                       icalcomponent_set_dtstart (vtodo, new_dtstart);
-                       icalcomponent_set_due (vtodo, new_due);
+                       i_cal_component_set_dtstart (vtodo, new_dtstart);
+                       i_cal_component_set_due (vtodo, new_due);
 
-                       e_cal_util_remove_property_by_kind (vtodo, ICAL_COMPLETED_PROPERTY, TRUE);
+                       e_cal_util_component_remove_property_by_kind (vtodo, I_CAL_COMPLETED_PROPERTY, TRUE);
 
-                       prop = icalcomponent_get_first_property (vtodo, ICAL_PERCENTCOMPLETE_PROPERTY);
-                       if (prop)
-                               icalproperty_set_percentcomplete (prop, 0);
+                       prop = i_cal_component_get_first_property (vtodo, I_CAL_PERCENTCOMPLETE_PROPERTY);
+                       if (prop) {
+                               i_cal_property_set_percentcomplete (prop, 0);
+                               g_object_unref (prop);
+                       }
+
+                       prop = i_cal_component_get_first_property (vtodo, I_CAL_STATUS_PROPERTY);
+                       if (prop) {
+                               i_cal_property_set_status (prop, I_CAL_STATUS_NEEDSACTION);
+                               g_object_unref (prop);
+                       }
 
-                       prop = icalcomponent_get_first_property (vtodo, ICAL_STATUS_PROPERTY);
-                       if (prop)
-                               icalproperty_set_status (prop, ICAL_STATUS_NEEDSACTION);
+                       g_clear_object (&new_dtstart);
+                       g_clear_object (&new_due);
 
                        return TRUE;
                }
        }
 
-       prop = icalcomponent_get_first_property (vtodo, ICAL_COMPLETED_PROPERTY);
-       if (!prop) {
-               prop = icalproperty_new_completed (completed_time != (time_t) -1 ?
-                       icaltime_from_timet_with_zone (completed_time, FALSE, icaltimezone_get_utc_timezone 
()) :
-                       icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()));
-               icalcomponent_add_property (vtodo, prop);
+       prop = i_cal_component_get_first_property (vtodo, I_CAL_COMPLETED_PROPERTY);
+       if (prop) {
+               g_object_unref (prop);
+       } else {
+               ICalTime *tt;
+
+               tt = completed_time != (time_t) -1 ?
+                       i_cal_time_from_timet_with_zone (completed_time, FALSE, 
i_cal_timezone_get_utc_timezone ()) :
+                       i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+               prop = i_cal_property_new_completed (tt);
+               i_cal_component_take_property (vtodo, prop);
+               g_object_unref (tt);
        }
 
-       prop = icalcomponent_get_first_property (vtodo, ICAL_PERCENTCOMPLETE_PROPERTY);
+       prop = i_cal_component_get_first_property (vtodo, I_CAL_PERCENTCOMPLETE_PROPERTY);
        if (prop) {
-               icalproperty_set_percentcomplete (prop, 100);
+               i_cal_property_set_percentcomplete (prop, 100);
+               g_object_unref (prop);
        } else {
-               prop = icalproperty_new_percentcomplete (100);
-               icalcomponent_add_property (vtodo, prop);
+               prop = i_cal_property_new_percentcomplete (100);
+               i_cal_component_take_property (vtodo, prop);
        }
 
-       prop = icalcomponent_get_first_property (vtodo, ICAL_STATUS_PROPERTY);
+       prop = i_cal_component_get_first_property (vtodo, I_CAL_STATUS_PROPERTY);
        if (prop) {
-               icalproperty_set_status (prop, ICAL_STATUS_COMPLETED);
+               i_cal_property_set_status (prop, I_CAL_STATUS_COMPLETED);
+               g_object_unref (prop);
        } else {
-               prop = icalproperty_new_status (ICAL_STATUS_COMPLETED);
-               icalcomponent_add_property (vtodo, prop);
+               prop = i_cal_property_new_status (I_CAL_STATUS_COMPLETED);
+               i_cal_component_take_property (vtodo, prop);
        }
 
        return TRUE;
 }
+
+/**
+ * e_cal_util_operation_flags_to_conflict_resolution:
+ * @flags: bit-or of #ECalOperationFlags
+ *
+ * Decodes the #EConflictResolution from the bit-or of #ECalOperationFlags.
+ *
+ * Returns: an #EConflictResolution as stored in the @flags
+ *
+ * Since: 3.36
+ **/
+EConflictResolution
+e_cal_util_operation_flags_to_conflict_resolution (guint32 flags)
+{
+       if ((flags & E_CAL_OPERATION_FLAG_CONFLICT_FAIL) != 0)
+               return E_CONFLICT_RESOLUTION_FAIL;
+       else if ((flags & E_CAL_OPERATION_FLAG_CONFLICT_USE_NEWER) != 0)
+               return E_CONFLICT_RESOLUTION_USE_NEWER;
+       else if ((flags & E_CAL_OPERATION_FLAG_CONFLICT_KEEP_SERVER) != 0)
+               return E_CONFLICT_RESOLUTION_KEEP_SERVER;
+       else if ((flags & E_CAL_OPERATION_FLAG_CONFLICT_WRITE_COPY) != 0)
+               return E_CONFLICT_RESOLUTION_WRITE_COPY;
+
+       /* E_CAL_OPERATION_FLAG_CONFLICT_KEEP_LOCAL is the default */
+       return E_CONFLICT_RESOLUTION_KEEP_LOCAL;
+}
+
+/**
+ * e_cal_util_conflict_resolution_to_operation_flags:
+ * @conflict_resolution: an #EConflictResolution
+ *
+ * Encodes the #EConflictResolution into the bit-or of #ECalOperationFlags.
+ * The returned value can be bit-or-ed with other #ECalOperationFlags values.
+ *
+ * Returns: a bit-or of #ECalOperationFlags, corresponding to the @conflict_resolution
+ *
+ * Since: 3.36
+ **/
+guint32
+e_cal_util_conflict_resolution_to_operation_flags (EConflictResolution conflict_resolution)
+{
+       switch (conflict_resolution) {
+       case E_CONFLICT_RESOLUTION_FAIL:
+               return E_CAL_OPERATION_FLAG_CONFLICT_FAIL;
+       case E_CONFLICT_RESOLUTION_USE_NEWER:
+               return E_CAL_OPERATION_FLAG_CONFLICT_USE_NEWER;
+       case E_CONFLICT_RESOLUTION_KEEP_SERVER:
+               return E_CAL_OPERATION_FLAG_CONFLICT_KEEP_SERVER;
+       case E_CONFLICT_RESOLUTION_KEEP_LOCAL:
+               return E_CAL_OPERATION_FLAG_CONFLICT_KEEP_LOCAL;
+       case E_CONFLICT_RESOLUTION_WRITE_COPY:
+               return E_CAL_OPERATION_FLAG_CONFLICT_WRITE_COPY;
+       }
+
+       return E_CAL_OPERATION_FLAG_CONFLICT_KEEP_LOCAL;
+}
diff --git a/src/calendar/libecal/e-cal-util.h b/src/calendar/libecal/e-cal-util.h
index ae0609544..e9f66f1d2 100644
--- a/src/calendar/libecal/e-cal-util.h
+++ b/src/calendar/libecal/e-cal-util.h
@@ -24,200 +24,132 @@
 #ifndef E_CAL_UTIL_H
 #define E_CAL_UTIL_H
 
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 #include <time.h>
+#include <libedataserver/libedataserver.h>
 #include <libecal/e-cal-component.h>
 #include <libecal/e-cal-recur.h>
-#include <libecal/e-cal-types.h>
+#include <libecal/e-cal-enums.h>
 
 G_BEGIN_DECLS
 
-struct _ECalClient;
-
-/**
- * CalObjInstance:
- * @uid: UID of the object
- * @start: Start time of instance
- * @end: End time of instance
- *
- * Instance of a calendar object.  This can be an actual occurrence, a
- * recurrence, or an alarm trigger of a `real' calendar object.
- **/
-typedef struct {
-       gchar *uid;                     /* UID of the object */
-       time_t start;                   /* Start time of instance */
-       time_t end;                     /* End time of instance */
-} CalObjInstance;
-
-void cal_obj_instance_list_free (GList *list);
-
-void cal_obj_uid_list_free (GList *list);
-
-icalcomponent *        e_cal_util_new_top_level        (void);
-icalcomponent *        e_cal_util_new_component        (icalcomponent_kind kind);
-
-icalcomponent *        e_cal_util_parse_ics_string     (const gchar *string);
-icalcomponent *        e_cal_util_parse_ics_file       (const gchar *filename);
-
-ECalComponentAlarms *
-               e_cal_util_generate_alarms_for_comp
-                                               (ECalComponent *comp,
-                                                time_t start,
-                                                time_t end,
-                                                ECalComponentAlarmAction *omit,
-                                                ECalRecurResolveTimezoneFn resolve_tzid,
-                                                gpointer user_data,
-                                                icaltimezone *default_timezone);
-gint           e_cal_util_generate_alarms_for_list
-                                               (GList *comps,
-                                                time_t start,
-                                                time_t end,
-                                                ECalComponentAlarmAction *omit,
-                                                GSList **comp_alarms,
-                                                ECalRecurResolveTimezoneFn resolve_tzid,
-                                                gpointer user_data,
-                                                icaltimezone *default_timezone);
-
-const gchar *  e_cal_util_priority_to_string   (gint priority);
-gint           e_cal_util_priority_from_string (const gchar *string);
-
-gchar *                e_cal_util_seconds_to_string    (gint64 seconds);
-
-void           e_cal_util_add_timezones_from_component
-                                               (icalcomponent *vcal_comp,
-                                                icalcomponent *icalcomp);
-
-gboolean       e_cal_util_component_is_instance
-                                               (icalcomponent *icalcomp);
-gboolean       e_cal_util_component_has_alarms (icalcomponent *icalcomp);
-gboolean       e_cal_util_component_has_organizer
-                                               (icalcomponent *icalcomp);
-gboolean       e_cal_util_component_has_recurrences
-                                               (icalcomponent *icalcomp);
-gboolean       e_cal_util_component_has_rdates (icalcomponent *icalcomp);
-gboolean       e_cal_util_component_has_rrules (icalcomponent *icalcomp);
-gboolean       e_cal_util_component_has_attendee
-                                               (icalcomponent *icalcomp);
-gboolean       e_cal_util_event_dates_match    (icalcomponent *icalcomp1,
-                                                icalcomponent *icalcomp2);
-
 /* The static capabilities to be supported by backends */
-#define CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT          "no-alarm-repeat"
-#define CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS          "no-audio-alarms"
-#define CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS                "no-display-alarms"
-#define CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS          "no-email-alarms"
-#define CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS      "no-procedure-alarms"
-#define CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT       "no-task-assignment"
-#define CAL_STATIC_CAPABILITY_NO_THISANDFUTURE         "no-thisandfuture"
-#define CAL_STATIC_CAPABILITY_NO_THISANDPRIOR          "no-thisandprior"
-#define CAL_STATIC_CAPABILITY_NO_TRANSPARENCY          "no-transparency"
+#define E_CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT                "no-alarm-repeat"
+#define E_CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS                "no-audio-alarms"
+#define E_CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS      "no-display-alarms"
+#define E_CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS                "no-email-alarms"
+#define E_CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS    "no-procedure-alarms"
+#define E_CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT     "no-task-assignment"
+#define E_CAL_STATIC_CAPABILITY_NO_THISANDFUTURE       "no-thisandfuture"
+#define E_CAL_STATIC_CAPABILITY_NO_THISANDPRIOR                "no-thisandprior"
+#define E_CAL_STATIC_CAPABILITY_NO_TRANSPARENCY                "no-transparency"
 
 /**
- * CAL_STATIC_CAPABILITY_MEMO_START_DATE:
+ * E_CAL_STATIC_CAPABILITY_MEMO_START_DATE:
  *
  * Flag indicating that the backend does not support memo's start date
  *
  * Since: 3.12
  */
-#define CAL_STATIC_CAPABILITY_NO_MEMO_START_DATE       "no-memo-start-date"
+#define E_CAL_STATIC_CAPABILITY_NO_MEMO_START_DATE     "no-memo-start-date"
 
 /**
- * CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION:
+ * E_CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION:
  *
  * Flag indicating that the backend supports alarm description
  *
  * Since: 3.8
  */
-#define CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION                "alarm-description"
+#define E_CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION      "alarm-description"
 
 /**
- * CAL_STATIC_CAPABILITY_NO_ALARM_AFTER_START:
+ * E_CAL_STATIC_CAPABILITY_NO_ALARM_AFTER_START:
  *
  * Flag indicating that the backend does not support alarm after start the event
  *
  * Since: 3.8
  */
-#define CAL_STATIC_CAPABILITY_NO_ALARM_AFTER_START     "no-alarm-after-start"
+#define E_CAL_STATIC_CAPABILITY_NO_ALARM_AFTER_START   "no-alarm-after-start"
 
 /**
- * CAL_STATIC_CAPABILITY_BULK_ADDS:
+ * E_CAL_STATIC_CAPABILITY_BULK_ADDS:
  *
  * Flag indicating that the backend supports bulk additions.
  *
  * Since: 3.6
  */
-#define CAL_STATIC_CAPABILITY_BULK_ADDS                        "bulk-adds"
+#define E_CAL_STATIC_CAPABILITY_BULK_ADDS              "bulk-adds"
 
 /**
- * CAL_STATIC_CAPABILITY_BULK_MODIFIES:
+ * E_CAL_STATIC_CAPABILITY_BULK_MODIFIES:
  *
  * Flag indicating that the backend supports bulk modifications.
  *
  * Since: 3.6
  */
-#define CAL_STATIC_CAPABILITY_BULK_MODIFIES            "bulk-modifies"
+#define E_CAL_STATIC_CAPABILITY_BULK_MODIFIES          "bulk-modifies"
 
 /**
- * CAL_STATIC_CAPABILITY_BULK_REMOVES:
+ * E_CAL_STATIC_CAPABILITY_BULK_REMOVES:
  *
  * Flag indicating that the backend supports bulk removals.
  *
  * Since: 3.6
  */
-#define CAL_STATIC_CAPABILITY_BULK_REMOVES             "bulk-removes"
+#define E_CAL_STATIC_CAPABILITY_BULK_REMOVES           "bulk-removes"
 
 /**
- * CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS:
+ * E_CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS:
  *
  * FIXME: Document me.
  *
  * Since: 3.2
  **/
-#define CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS         "remove-only-this"
+#define E_CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS       "remove-only-this"
 
-#define CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY           "one-alarm-only"
-#define CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND    "organizer-must-attend"
-#define CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS      "organizer-not-email-address"
-#define CAL_STATIC_CAPABILITY_REMOVE_ALARMS            "remove-alarms"
+#define E_CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY         "one-alarm-only"
+#define E_CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND  "organizer-must-attend"
+#define E_CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS    "organizer-not-email-address"
+#define E_CAL_STATIC_CAPABILITY_REMOVE_ALARMS          "remove-alarms"
 
 /**
- * CAL_STATIC_CAPABILITY_CREATE_MESSAGES:
+ * E_CAL_STATIC_CAPABILITY_CREATE_MESSAGES:
  *
  * Since: 2.26
  **/
-#define CAL_STATIC_CAPABILITY_CREATE_MESSAGES          "create-messages"
-
-#define CAL_STATIC_CAPABILITY_SAVE_SCHEDULES           "save-schedules"
-#define CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK   "no-conv-to-assign-task"
-#define CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR         "no-conv-to-recur"
-#define CAL_STATIC_CAPABILITY_NO_GEN_OPTIONS           "no-general-options"
-#define CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS         "require-send-options"
-#define CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER    "recurrences-no-master-object"
-#define CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT    "organizer-must-accept"
-#define CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED       "delegate-support"
-#define CAL_STATIC_CAPABILITY_NO_ORGANIZER             "no-organizer"
-#define CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY         "delegate-to-many"
-#define CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING   "has-unaccepted-meeting"
+#define E_CAL_STATIC_CAPABILITY_CREATE_MESSAGES                "create-messages"
+
+#define E_CAL_STATIC_CAPABILITY_SAVE_SCHEDULES         "save-schedules"
+#define E_CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK "no-conv-to-assign-task"
+#define E_CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR       "no-conv-to-recur"
+#define E_CAL_STATIC_CAPABILITY_NO_GEN_OPTIONS         "no-general-options"
+#define E_CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS       "require-send-options"
+#define E_CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER  "recurrences-no-master-object"
+#define E_CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT  "organizer-must-accept"
+#define E_CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED     "delegate-support"
+#define E_CAL_STATIC_CAPABILITY_NO_ORGANIZER           "no-organizer"
+#define E_CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY       "delegate-to-many"
+#define E_CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING "has-unaccepted-meeting"
 
 /**
- * CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED:
+ * E_CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED:
  *
  * Since: 2.30
  **/
-#define CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED                "refresh-supported"
+#define E_CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED      "refresh-supported"
 
 /**
- * CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME:
+ * E_CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME:
  *
  * Let the client know that it should store All Day event times as time
  * with a time zone, rather than as a date.
  *
  * Since: 3.18
  **/
-#define CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME    "all-day-event-as-time"
+#define E_CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME  "all-day-event-as-time"
 
 /**
- * CAL_STATIC_CAPABILITY_TASK_DATE_ONLY:
+ * E_CAL_STATIC_CAPABILITY_TASK_DATE_ONLY:
  *
  * Let the client know that the Task Start date, Due date and Completed date
  * can be entered only as dates. When the capability is not set, then these
@@ -225,114 +157,164 @@ gboolean        e_cal_util_event_dates_match    (icalcomponent *icalcomp1,
  *
  * Since: 3.24
  **/
-#define CAL_STATIC_CAPABILITY_TASK_DATE_ONLY           "task-date-only"
+#define E_CAL_STATIC_CAPABILITY_TASK_DATE_ONLY         "task-date-only"
 
 /**
- * CAL_STATIC_CAPABILITY_TASK_CAN_RECUR:
+ * E_CAL_STATIC_CAPABILITY_TASK_CAN_RECUR:
  *
  * When the capability is set, the client can store and provide recurring
  * tasks, otherwise it cannot.
  *
  * Since: 3.30
  **/
-#define CAL_STATIC_CAPABILITY_TASK_CAN_RECUR           "task-can-recur"
+#define E_CAL_STATIC_CAPABILITY_TASK_CAN_RECUR         "task-can-recur"
 
 /**
- * CAL_STATIC_CAPABILITY_TASK_NO_ALARM:
+ * E_CAL_STATIC_CAPABILITY_TASK_NO_ALARM:
  *
  * When the capability is set, the client cannot store reminders
  * on tasks, otherwise it can.
  *
  * Since: 3.30
  **/
-#define CAL_STATIC_CAPABILITY_TASK_NO_ALARM            "task-no-alarm"
+#define E_CAL_STATIC_CAPABILITY_TASK_NO_ALARM          "task-no-alarm"
 
 /**
- * CAL_STATIC_CAPABILITY_COMPONENT_COLOR:
+ * E_CAL_STATIC_CAPABILITY_COMPONENT_COLOR:
  *
  * When the capability is set, the client supports storing color
  * for individual components.
  *
  * Since: 3.30
  **/
-#define CAL_STATIC_CAPABILITY_COMPONENT_COLOR          "component-color"
+#define E_CAL_STATIC_CAPABILITY_COMPONENT_COLOR                "component-color"
 
 /**
- * CAL_STATIC_CAPABILITY_TASK_HANDLE_RECUR:
+ * E_CAL_STATIC_CAPABILITY_TASK_HANDLE_RECUR:
  *
  * When the capability is set, the backend handles task recurrence
- * completion on its own. This does not imply CAL_STATIC_CAPABILITY_TASK_CAN_RECUR.
+ * completion on its own. This does not imply E_CAL_STATIC_CAPABILITY_TASK_CAN_RECUR.
  *
  * Since: 3.34
  **/
-#define CAL_STATIC_CAPABILITY_TASK_HANDLE_RECUR                "task-handle-recur"
+#define E_CAL_STATIC_CAPABILITY_TASK_HANDLE_RECUR      "task-handle-recur"
+
+struct _ECalClient;
+
+ICalComponent *        e_cal_util_new_top_level        (void);
+ICalComponent *        e_cal_util_new_component        (ICalComponentKind kind);
+ICalTimezone * e_cal_util_copy_timezone        (const ICalTimezone *zone);
+
+ICalComponent *        e_cal_util_parse_ics_string     (const gchar *string);
+ICalComponent *        e_cal_util_parse_ics_file       (const gchar *filename);
+
+ECalComponentAlarms *
+               e_cal_util_generate_alarms_for_comp
+                                               (ECalComponent *comp,
+                                                time_t start,
+                                                time_t end,
+                                                ECalComponentAlarmAction *omit,
+                                                ECalRecurResolveTimezoneCb resolve_tzid,
+                                                gpointer user_data,
+                                                ICalTimezone *default_timezone);
+gint           e_cal_util_generate_alarms_for_list
+                                               (GList *comps, /* ECalComponent * */
+                                                time_t start,
+                                                time_t end,
+                                                ECalComponentAlarmAction *omit,
+                                                GSList **comp_alarms,
+                                                ECalRecurResolveTimezoneCb resolve_tzid,
+                                                gpointer user_data,
+                                                ICalTimezone *default_timezone);
+
+const gchar *  e_cal_util_priority_to_string   (gint priority);
+gint           e_cal_util_priority_from_string (const gchar *string);
 
-/* Recurrent events. Management for instances */
-icalcomponent *        e_cal_util_construct_instance   (icalcomponent *icalcomp,
-                                                struct icaltimetype rid);
-void           e_cal_util_remove_instances     (icalcomponent *icalcomp,
-                                                struct icaltimetype rid,
+gchar *                e_cal_util_seconds_to_string    (gint64 seconds);
+
+void           e_cal_util_add_timezones_from_component
+                                               (ICalComponent *vcal_comp,
+                                                ICalComponent *icalcomp);
+
+gboolean       e_cal_util_property_has_parameter
+                                               (ICalProperty *prop,
+                                                ICalParameterKind param_kind);
+gboolean       e_cal_util_component_has_property
+                                               (ICalComponent *icalcomp,
+                                                ICalPropertyKind prop_kind);
+gboolean       e_cal_util_component_is_instance
+                                               (ICalComponent *icalcomp);
+gboolean       e_cal_util_component_has_alarms (ICalComponent *icalcomp);
+gboolean       e_cal_util_component_has_organizer
+                                               (ICalComponent *icalcomp);
+gboolean       e_cal_util_component_has_recurrences
+                                               (ICalComponent *icalcomp);
+gboolean       e_cal_util_component_has_rdates (ICalComponent *icalcomp);
+gboolean       e_cal_util_component_has_rrules (ICalComponent *icalcomp);
+gboolean       e_cal_util_component_has_attendee
+                                               (ICalComponent *icalcomp);
+gchar *                e_cal_util_component_get_recurid_as_string
+                                               (ICalComponent *icalcomp);
+ICalComponent *        e_cal_util_construct_instance   (ICalComponent *icalcomp,
+                                                const ICalTime *rid);
+void           e_cal_util_remove_instances     (ICalComponent *icalcomp,
+                                                const ICalTime *rid,
                                                 ECalObjModType mod);
-icalcomponent *        e_cal_util_split_at_instance    (icalcomponent *icalcomp,
-                                                struct icaltimetype rid,
-                                                struct icaltimetype master_dtstart);
+ICalComponent *        e_cal_util_split_at_instance    (ICalComponent *icalcomp,
+                                                const ICalTime *rid,
+                                                const ICalTime *master_dtstart);
 gboolean       e_cal_util_is_first_instance    (ECalComponent *comp,
-                                                struct icaltimetype rid,
-                                                ECalRecurResolveTimezoneFn tz_cb,
+                                                const ICalTime *rid,
+                                                ECalRecurResolveTimezoneCb tz_cb,
                                                 gpointer tz_cb_data);
 
 gchar *                e_cal_util_get_system_timezone_location (void);
-icaltimezone * e_cal_util_get_system_timezone (void);
+ICalTimezone * e_cal_util_get_system_timezone (void);
 void           e_cal_util_get_component_occur_times
                                                (ECalComponent *comp,
-                                                time_t * start,
-                                                time_t * end,
-                                                ECalRecurResolveTimezoneFn tz_cb,
+                                                time_t *out_start,
+                                                time_t *out_end,
+                                                ECalRecurResolveTimezoneCb tz_cb,
                                                 gpointer tz_cb_data,
-                                                const icaltimezone *default_timezone,
-                                                icalcomponent_kind kind);
+                                                const ICalTimezone *default_timezone,
+                                                ICalComponentKind kind);
 
-icalproperty * e_cal_util_find_x_property      (icalcomponent *icalcomp,
+gboolean       e_cal_util_component_has_x_property
+                                               (ICalComponent *icalcomp,
                                                 const gchar *x_name);
-gchar *                e_cal_util_dup_x_property       (icalcomponent *icalcomp,
+ICalProperty * e_cal_util_component_find_x_property
+                                               (ICalComponent *icalcomp,
                                                 const gchar *x_name);
-const gchar *  e_cal_util_get_x_property       (icalcomponent *icalcomp,
+gchar *                e_cal_util_component_dup_x_property
+                                               (ICalComponent *icalcomp,
                                                 const gchar *x_name);
-void           e_cal_util_set_x_property       (icalcomponent *icalcomp,
+void           e_cal_util_component_set_x_property
+                                               (ICalComponent *icalcomp,
                                                 const gchar *x_name,
                                                 const gchar *value);
-gboolean       e_cal_util_remove_x_property    (icalcomponent *icalcomp,
+gboolean       e_cal_util_component_remove_x_property
+                                               (ICalComponent *icalcomp,
                                                 const gchar *x_name);
-guint          e_cal_util_remove_property_by_kind
-                                               (icalcomponent *icalcomp,
-                                                icalproperty_kind kind,
+guint          e_cal_util_component_remove_property_by_kind
+                                               (ICalComponent *icalcomp,
+                                                ICalPropertyKind kind,
                                                 gboolean all);
 
-gboolean       e_cal_util_init_recur_task_sync (icalcomponent *vtodo,
+gboolean       e_cal_util_init_recur_task_sync (ICalComponent *vtodo,
                                                 struct _ECalClient *cal_client,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_util_mark_task_complete_sync
-                                               (icalcomponent *vtodo,
+                                               (ICalComponent *vtodo,
                                                 time_t completed_time,
                                                 struct _ECalClient *cal_client,
                                                 GCancellable *cancellable,
                                                 GError **error);
-
-#ifndef EDS_DISABLE_DEPRECATED
-/* Used for mode stuff */
-typedef enum {
-       CAL_MODE_INVALID = -1,
-       CAL_MODE_LOCAL = 1 << 0,
-       CAL_MODE_REMOTE = 1 << 1,
-       CAL_MODE_ANY = 0x07
-} CalMode;
-
-#define cal_mode_to_corba(mode) \
-       (mode == CAL_MODE_LOCAL ? Local : \
-        mode == CAL_MODE_REMOTE ? Remote : \
-        AnyMode)
-#endif /* EDS_DISABLE_DEPRECATED */
+EConflictResolution
+               e_cal_util_operation_flags_to_conflict_resolution
+                                               (guint32 flags); /* bit-or of ECalOperationFlags */
+guint32                e_cal_util_conflict_resolution_to_operation_flags /* bit-or of ECalOperationFlags */
+                                               (EConflictResolution conflict_resolution);
 
 G_END_DECLS
 
diff --git a/src/calendar/libecal/e-reminder-watcher.c b/src/calendar/libecal/e-reminder-watcher.c
index b08a7f301..aa10cdcf3 100644
--- a/src/calendar/libecal/e-reminder-watcher.c
+++ b/src/calendar/libecal/e-reminder-watcher.c
@@ -36,6 +36,7 @@
 
 #include "libedataserver/libedataserver.h"
 
+#include "e-cal-check-timezones.h"
 #include "e-cal-client.h"
 #include "e-cal-system-timezone.h"
 #include "e-cal-time-util.h"
@@ -62,7 +63,7 @@ struct _EReminderWatcherPrivate {
        guint expected_past_changes;
        guint expected_snoozed_changes;
 
-       icaltimezone *default_zone;
+       ICalTimezone *default_zone;
 
        GSList *clients; /* ClientData * */
        GSList *snoozed; /* EReminderData * */
@@ -97,15 +98,20 @@ static guint signals[LAST_SIGNAL];
 G_DEFINE_TYPE (EReminderWatcher, e_reminder_watcher, G_TYPE_OBJECT)
 
 G_DEFINE_BOXED_TYPE (EReminderData, e_reminder_data, e_reminder_data_copy, e_reminder_data_free)
-G_DEFINE_BOXED_TYPE (EReminderWatcherZone, e_reminder_watcher_zone, e_reminder_watcher_zone_copy, 
e_reminder_watcher_zone_free)
+
+struct _EReminderData {
+       gchar *source_uid;
+       ECalComponent *component;
+       ECalComponentAlarmInstance *instance;
+};
 
 static void
 e_reminder_watcher_objects_added_cb (ECalClientView *view,
-                                    const GSList *objects, /* icalcomponent * */
+                                    const GSList *objects, /* ICalComponent * */
                                     gpointer user_data);
 static void
 e_reminder_watcher_objects_modified_cb (ECalClientView *view,
-                                       const GSList *objects, /* icalcomponent * */
+                                       const GSList *objects, /* ICalComponent * */
                                        gpointer user_data);
 static void
 e_reminder_watcher_objects_removed_cb (ECalClientView *view,
@@ -147,7 +153,7 @@ e_reminder_watcher_timet_as_string (gint64 tt)
        static gchar buffers[10][32 + 1];
        static volatile gint curr_index = 0;
        gint counter = 0, index;
-       struct icaltimetype itt;
+       ICalTime *itt;
 
        while (index = (curr_index + 1) % 10, !g_atomic_int_compare_and_exchange (&curr_index, curr_index, 
index)) {
                counter++;
@@ -155,11 +161,13 @@ e_reminder_watcher_timet_as_string (gint64 tt)
                        break;
        }
 
-       itt = icaltime_from_timet_with_zone ((time_t) tt, 0, icaltimezone_get_utc_timezone ());
+       itt = i_cal_time_from_timet_with_zone ((time_t) tt, 0, i_cal_timezone_get_utc_timezone ());
 
        g_snprintf (buffers[index], 32, "%04d%02d%02dT%02d%02d%02d",
-               itt.year, itt.month, itt.day,
-               itt.hour, itt.minute, itt.second);
+               i_cal_time_get_year (itt), i_cal_time_get_month (itt), i_cal_time_get_day (itt),
+               i_cal_time_get_hour (itt), i_cal_time_get_minute (itt), i_cal_time_get_second (itt));
+
+       g_clear_object (&itt);
 
        return buffers[index];
 }
@@ -416,10 +424,7 @@ e_reminder_data_new_take_component (const gchar *source_uid,
        rd = g_new0 (EReminderData, 1);
        rd->source_uid = g_strdup (source_uid);
        rd->component = component;
-       rd->instance.auid = g_strdup (instance->auid);
-       rd->instance.trigger = instance->trigger;
-       rd->instance.occur_start = instance->occur_start;
-       rd->instance.occur_end = instance->occur_end;
+       rd->instance = e_cal_component_alarm_instance_copy (instance);
 
        return rd;
 }
@@ -464,7 +469,7 @@ e_reminder_data_copy (const EReminderData *rd)
        if (!rd)
                return NULL;
 
-       return e_reminder_data_new_take_component (rd->source_uid, g_object_ref (rd->component), 
&(rd->instance));
+       return e_reminder_data_new_take_component (rd->source_uid, g_object_ref (rd->component), 
rd->instance);
 }
 
 /**
@@ -483,44 +488,127 @@ e_reminder_data_free (gpointer rd)
 
        if (ptr) {
                g_clear_object (&ptr->component);
+               e_cal_component_alarm_instance_free (ptr->instance);
                g_free (ptr->source_uid);
-               g_free (ptr->instance.auid);
                g_free (ptr);
        }
 }
 
 /**
- * e_reminder_watcher_zone_copy:
- * @watcher_zone: (nullable): an #EReminderWatcherZone to copy, or %NULL
+ * e_reminder_data_get_source_uid:
+ * @rd: an #EReminderData
  *
- * Returns: (transfer full): copy of @watcher_zone, or %NULL, when it's also %NULL.
- *    Free returned instance with e_reminder_watcher_zone_free(), when no longer needed.
+ * Returns: an #ESource UID for @rd
  *
- * Since: 3.30
+ * Since: 3.36
  **/
-EReminderWatcherZone *
-e_reminder_watcher_zone_copy (const EReminderWatcherZone *watcher_zone)
+const gchar *
+e_reminder_data_get_source_uid (const EReminderData *rd)
 {
-       if (!watcher_zone)
-               return NULL;
+       g_return_val_if_fail (rd != NULL, NULL);
 
-       return (EReminderWatcherZone *) icaltimezone_copy ((icaltimezone *) watcher_zone);
+       return rd->source_uid;
 }
 
 /**
- * e_reminder_watcher_zone_free:
- * @watcher_zone: (nullable): an #EReminderWatcherZone to free
+ * e_reminder_data_set_source_uid:
+ * @rd: an #EReminderData
+ * @source_uid: an #ESource UID
  *
- * Frees @watcher_zone, previously allocated with e_reminder_watcher_zone_copy().
- * The function does nothing when the @watcher_zone is %NULL.
+ * Set an #ESource UID for @rd.
  *
- * Since: 3.30
+ * Since: 3.36
  **/
 void
-e_reminder_watcher_zone_free (EReminderWatcherZone *watcher_zone)
+e_reminder_data_set_source_uid (EReminderData *rd,
+                               const gchar *source_uid)
 {
-       if (watcher_zone)
-               icaltimezone_free ((icaltimezone *) watcher_zone, 1);
+       g_return_if_fail (rd != NULL);
+
+       if (g_strcmp0 (rd->source_uid, source_uid) != 0) {
+               g_free (rd->source_uid);
+               rd->source_uid = g_strdup (source_uid);
+       }
+}
+
+/**
+ * e_reminder_data_get_component:
+ * @rd: an #EReminderData
+ *
+ * Returns: (transfer none): an #ECalComponent for @rd. It is owned by @rd,
+ *    thus do not free it.
+ *
+ * Since: 3.36
+ **/
+ECalComponent *
+e_reminder_data_get_component (const EReminderData *rd)
+{
+       g_return_val_if_fail (rd != NULL, NULL);
+
+       return rd->component;
+}
+
+/**
+ * e_reminder_data_set_component:
+ * @rd: an #EReminderData
+ * @component: an #ECalComponent
+ *
+ * Set an #ECalComponent @component as associated with this @rd.
+ * The @rd creates a copy of the @component.
+ *
+ * Since: 3.36
+ **/
+void
+e_reminder_data_set_component (EReminderData *rd,
+                              const ECalComponent *component)
+{
+       g_return_if_fail (rd != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (component));
+
+       if (rd->component != component) {
+               g_clear_object (&rd->component);
+               rd->component = e_cal_component_clone ((ECalComponent *) component);
+       }
+}
+
+/**
+ * e_reminder_data_get_instance:
+ * @rd: an #EReminderData
+ *
+ * Returns: (transfer none): an #ECalComponentAlarmInstance for @rd.
+ *    It is owned by @rd, thus do not free it.
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmInstance *
+e_reminder_data_get_instance (const EReminderData *rd)
+{
+       g_return_val_if_fail (rd != NULL, NULL);
+
+       return rd->instance;
+}
+
+/**
+ * e_reminder_data_set_instance:
+ * @rd: an #EReminderData
+ * @instance: an #ECalComponentAlarmInstance
+ *
+ * Set an #ECalComponentAlarmInstance @instance as associated with this @rd.
+ * The @rd creates a copy of the @instance.
+ *
+ * Since: 3.36
+ **/
+void
+e_reminder_data_set_instance (EReminderData *rd,
+                             const ECalComponentAlarmInstance *instance)
+{
+       g_return_if_fail (rd != NULL);
+       g_return_if_fail (instance != NULL);
+
+       if (rd->instance != instance) {
+               e_cal_component_alarm_instance_free (rd->instance);
+               rd->instance = e_cal_component_alarm_instance_copy (instance);
+       }
 }
 
 static gchar *
@@ -540,17 +628,17 @@ e_reminder_data_to_string (const EReminderData *rd)
        g_string_append (str, rd->source_uid);
        g_string_append_c (str, '\n');
 
-       if (rd->instance.auid)
-               g_string_append (str, rd->instance.auid);
+       if (rd->instance && e_cal_component_alarm_instance_get_uid (rd->instance))
+               g_string_append (str, e_cal_component_alarm_instance_get_uid (rd->instance));
        g_string_append_c (str, '\n');
 
-       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) rd->instance.trigger);
+       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) (rd->instance ? 
e_cal_component_alarm_instance_get_time (rd->instance) : -1));
        g_string_append_c (str, '\n');
 
-       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) rd->instance.occur_start);
+       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) (rd->instance ? 
e_cal_component_alarm_instance_get_occur_start (rd->instance) : -1));
        g_string_append_c (str, '\n');
 
-       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) rd->instance.occur_end);
+       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) (rd->instance ? 
e_cal_component_alarm_instance_get_occur_end (rd->instance) : -1));
        g_string_append_c (str, '\n');
 
        g_string_append (str, icalstr);
@@ -566,7 +654,7 @@ e_reminder_data_from_string (const gchar *str)
        gchar **strv;
        EReminderData *rd;
        ECalComponent *component;
-       ECalComponentAlarmInstance instance;
+       ECalComponentAlarmInstance *instance;
 
        g_return_val_if_fail (str != NULL, NULL);
 
@@ -585,13 +673,15 @@ e_reminder_data_from_string (const gchar *str)
                return NULL;
        }
 
-       instance.auid = (*(strv[1])) ? strv[1] : NULL;
-       instance.trigger = g_ascii_strtoll (strv[2], NULL, 10);
-       instance.occur_start = g_ascii_strtoll (strv[3], NULL, 10);
-       instance.occur_end = g_ascii_strtoll (strv[4], NULL, 10);
+       instance = e_cal_component_alarm_instance_new (
+               (*(strv[1])) ? strv[1] : NULL,
+               g_ascii_strtoll (strv[2], NULL, 10),
+               g_ascii_strtoll (strv[3], NULL, 10),
+               g_ascii_strtoll (strv[4], NULL, 10));
 
-       rd = e_reminder_data_new_take_component (strv[0], component, &instance);
+       rd = e_reminder_data_new_take_component (strv[0], component, instance);
 
+       e_cal_component_alarm_instance_free (instance);
        g_strfreev (strv);
 
        return rd;
@@ -602,6 +692,7 @@ e_reminder_data_compare (gconstpointer ptr1,
                         gconstpointer ptr2)
 {
        const EReminderData *rd1 = ptr1, *rd2 = ptr2;
+       time_t trigger1, trigger2;
 
        if (!rd1 || !rd2) {
                if (rd1 == rd2)
@@ -609,10 +700,13 @@ e_reminder_data_compare (gconstpointer ptr1,
                return !rd1 ? -1 : 1;
        }
 
-       if (rd1->instance.trigger == rd2->instance.trigger)
+       trigger1 = rd1->instance ? e_cal_component_alarm_instance_get_time (rd1->instance) : -1;
+       trigger2 = rd2->instance ? e_cal_component_alarm_instance_get_time (rd2->instance) : -1;
+
+       if (trigger1 == trigger2)
                return 0;
 
-       return rd1->instance.trigger < rd2->instance.trigger ? -1 : 1;
+       return trigger1 < trigger2 ? -1 : 1;
 }
 
 static void
@@ -658,8 +752,8 @@ match_not_component_id_cb (gpointer data,
                return FALSE;
 
        rd_id = e_cal_component_get_id (rd->component);
-       match = rd_id && g_strcmp0 (rd_id->uid, id->uid) == 0;
-       e_cal_component_free_id (rd_id);
+       match = rd_id && g_strcmp0 (e_cal_component_id_get_uid (rd_id), e_cal_component_id_get_uid (id)) == 0;
+       e_cal_component_id_free (rd_id);
 
        return !match;
 }
@@ -669,7 +763,7 @@ typedef struct _ObjectsChangedData {
        GSList *ids; /* ECalComponentId * */
        time_t interval_start;
        time_t interval_end;
-       icaltimezone *zone;
+       ICalTimezone *zone;
 } ObjectsChangedData;
 
 static void
@@ -679,9 +773,8 @@ objects_changed_data_free (gpointer ptr)
 
        if (ocd) {
                g_clear_object (&ocd->client);
-               g_slist_free_full (ocd->ids, (GDestroyNotify) e_cal_component_free_id);
-               if (ocd->zone)
-                       e_reminder_watcher_zone_free (ocd->zone);
+               g_slist_free_full (ocd->ids, (GDestroyNotify) e_cal_component_id_free);
+               g_clear_object (&ocd->zone);
                g_free (ocd);
        }
 }
@@ -707,13 +800,14 @@ e_reminder_watcher_objects_changed_thread (GTask *task,
 
        for (link = ocd->ids; link && !g_cancellable_is_cancelled (cancellable); link = g_slist_next (link)) {
                const ECalComponentId *id = link->data;
-               icalcomponent *icalcomp = NULL;
+               ICalComponent *icalcomp = NULL;
                GError *local_error = NULL;
 
-               if (!id || !id->uid || !*id->uid)
+               if (!id || !e_cal_component_id_get_uid (id))
                        continue;
 
-               if (e_cal_client_get_object_sync (ocd->client, id->uid, id->rid, &icalcomp, cancellable, 
&local_error) && !local_error && icalcomp) {
+               if (e_cal_client_get_object_sync (ocd->client, e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id),
+                   &icalcomp, cancellable, &local_error) && !local_error && icalcomp) {
                        ECalComponent *ecomp;
 
                        ecomp = e_cal_component_new_from_icalcomponent (icalcomp);
@@ -722,40 +816,45 @@ e_reminder_watcher_objects_changed_thread (GTask *task,
                                ECalComponentAlarms *alarms;
 
                                alarms = e_cal_util_generate_alarms_for_comp (
-                                       ecomp, ocd->interval_start, ocd->interval_end, omit, 
e_cal_client_resolve_tzid_cb,
+                                       ecomp, ocd->interval_start, ocd->interval_end, omit, 
e_cal_client_tzlookup_cb,
                                        ocd->client, ocd->zone);
 
-                               if (alarms && alarms->alarms) {
-                                       GSList *alink;
+                               if (alarms && e_cal_component_alarms_get_instances (alarms)) {
+                                       ECalComponent *alarms_comp = e_cal_component_alarms_get_component 
(alarms);
+                                       GSList *alink, *instances;
+
+                                       instances = e_cal_component_alarms_get_instances (alarms);
 
-                                       e_reminder_watcher_debug_print ("Source %s: Got %d alarms for object 
'%s':'%s' at interval %s .. %s\n", source_uid,
-                                               g_slist_length (alarms->alarms), id->uid, id->rid ? id->rid : 
"",
+                                       e_reminder_watcher_debug_print ("Source %s: Got %d alarms for object 
'%s':'%s' at interval %s .. %s\n",
+                                               source_uid, g_slist_length (instances), 
e_cal_component_id_get_uid (id),
+                                               e_cal_component_id_get_rid (id) ? e_cal_component_id_get_rid 
(id) : "",
                                                e_reminder_watcher_timet_as_string (ocd->interval_start),
                                                e_reminder_watcher_timet_as_string (ocd->interval_end));
 
-                                       for (alink = alarms->alarms; alink; alink = g_slist_next (alink)) {
+                                       for (alink = instances; alink; alink = g_slist_next (alink)) {
                                                const ECalComponentAlarmInstance *instance = alink->data;
 
                                                if (instance) {
                                                        reminders = g_slist_prepend (reminders, 
e_reminder_data_new_take_component (
-                                                               source_uid, g_object_ref (alarms->comp), 
instance));
+                                                               source_uid, g_object_ref (alarms_comp), 
instance));
                                                }
                                        }
                                } else {
-                                       e_reminder_watcher_debug_print ("Source %s: Got no alarms for object 
'%s':'%s' at interval %s .. %s\n", source_uid,
-                                               id->uid, id->rid ? id->rid : "",
+                                       e_reminder_watcher_debug_print ("Source %s: Got no alarms for object 
'%s':'%s' at interval %s .. %s\n",
+                                               source_uid, e_cal_component_id_get_uid (id),
+                                               e_cal_component_id_get_rid (id) ? e_cal_component_id_get_rid 
(id) : "",
                                                e_reminder_watcher_timet_as_string (ocd->interval_start),
                                                e_reminder_watcher_timet_as_string (ocd->interval_end));
                                }
 
-                               if (alarms)
-                                       e_cal_component_alarms_free (alarms);
-
+                               e_cal_component_alarms_free (alarms);
                                g_object_unref (ecomp);
                        }
                } else {
-                       e_reminder_watcher_debug_print ("Source %s: Failed to get object '%s':'%s': %s\n", 
source_uid,
-                               id->uid, id->rid ? id->rid : "", local_error ? local_error->message : 
"Unknown error");
+                       e_reminder_watcher_debug_print ("Source %s: Failed to get object '%s':'%s': %s\n",
+                               source_uid, e_cal_component_id_get_uid (id),
+                               e_cal_component_id_get_rid (id) ? e_cal_component_id_get_rid (id) : "",
+                               local_error ? local_error->message : "Unknown error");
                        g_clear_error (&local_error);
                }
 
@@ -781,7 +880,7 @@ e_reminder_watcher_objects_changed_thread (GTask *task,
                                ECalComponentId *id = link->data;
                                GSList *new_scheduled;
 
-                               if (!id || !id->uid)
+                               if (!id || !e_cal_component_id_get_uid (id))
                                        continue;
 
                                new_scheduled = e_reminder_watcher_move_matched (scheduled, 
match_not_component_id_cb, id);
@@ -831,7 +930,7 @@ e_reminder_watcher_objects_changed_done_cb (GObject *source_object,
 static void
 e_reminder_watcher_objects_changed (EReminderWatcher *watcher,
                                    ECalClient *client,
-                                   const GSList *objects) /* icalcomponent * */
+                                   const GSList *objects) /* ICalComponent * */
 {
        GSList *link, *ids = NULL;
 
@@ -846,23 +945,25 @@ e_reminder_watcher_objects_changed (EReminderWatcher *watcher,
        }
 
        for (link = (GSList *) objects; link; link = g_slist_next (link)) {
-               icalcomponent *icalcomp = link->data;
+               ICalComponent *icalcomp = link->data;
                ECalComponentId *id;
                const gchar *uid;
                gchar *rid = NULL;
 
-               uid = icalcomponent_get_uid (icalcomp);
+               uid = i_cal_component_get_uid (icalcomp);
                if (!uid || !*uid)
                        continue;
 
                if (e_cal_util_component_is_instance (icalcomp)) {
-                       struct icaltimetype itt;
+                       ICalTime *itt;
 
-                       itt = icalcomponent_get_recurrenceid (icalcomp);
-                       if (icaltime_is_valid_time (itt) && !icaltime_is_null_time (itt))
-                               rid = icaltime_as_ical_string_r (itt);
+                       itt = i_cal_component_get_recurrenceid (icalcomp);
+                       if (i_cal_time_is_valid_time (itt) && !i_cal_time_is_null_time (itt))
+                               rid = i_cal_time_as_ical_string_r (itt);
                        else
                                rid = g_strdup ("0");
+
+                       g_clear_object (&itt);
                }
 
                id = e_cal_component_id_new (uid, rid && *rid ? rid : NULL);
@@ -929,7 +1030,7 @@ e_reminder_watcher_objects_removed (EReminderWatcher *watcher,
                ECalComponentId *id = link->data;
                GSList *new_scheduled;
 
-               if (!id || !id->uid)
+               if (!id || e_cal_component_id_get_uid (id))
                        continue;
 
                new_scheduled = e_reminder_watcher_move_matched (scheduled, match_not_component_id_cb, id);
@@ -949,7 +1050,7 @@ e_reminder_watcher_objects_removed (EReminderWatcher *watcher,
 
 static void
 e_reminder_watcher_objects_added_cb (ECalClientView *view,
-                                    const GSList *objects, /* icalcomponent * */
+                                    const GSList *objects, /* ICalComponent * */
                                     gpointer user_data)
 {
        EReminderWatcher *watcher = user_data;
@@ -973,7 +1074,7 @@ e_reminder_watcher_objects_added_cb (ECalClientView *view,
 
 static void
 e_reminder_watcher_objects_modified_cb (ECalClientView *view,
-                                       const GSList *objects, /* icalcomponent * */
+                                       const GSList *objects, /* ICalComponent * */
                                        gpointer user_data)
 {
        EReminderWatcher *watcher = user_data;
@@ -1094,7 +1195,7 @@ e_reminder_watcher_schedule_timer_impl (EReminderWatcher *watcher,
 static void
 e_reminder_watcher_format_time_impl (EReminderWatcher *watcher,
                                     const EReminderData *rd,
-                                    struct icaltimetype *itt,
+                                    ICalTime *itt,
                                     gchar **inout_buffer,
                                     gint buffer_size)
 {
@@ -1107,7 +1208,7 @@ e_reminder_watcher_format_time_impl (EReminderWatcher *watcher,
        g_return_if_fail (*inout_buffer != NULL);
        g_return_if_fail (buffer_size > 0);
 
-       tm = icaltimetype_to_tm (itt);
+       tm = e_cal_util_icaltime_to_tm (itt);
        e_time_format_date_and_time (&tm, FALSE, FALSE, FALSE, *inout_buffer, buffer_size);
 }
 
@@ -1197,19 +1298,29 @@ e_reminder_watcher_find (GSList *reminders, /* EReminderData * */
                id2 = e_cal_component_get_id (rd2->component);
 
                if (id2) {
-                       if (g_strcmp0 (id1->uid, id2->uid) == 0 && (
-                           (g_strcmp0 (id1->rid, id2->rid) == 0 ||
-                           ((!id1->rid || !*(id1->rid)) && (!id2->rid || !*(id2->rid))))) &&
-                           g_strcmp0 (rd->instance.auid, rd2->instance.auid) == 0 &&
-                           rd->instance.trigger == rd2->instance.trigger)
+                       const gchar *uid1, *uid2, *rid1, *rid2, *auid1, *auid2;
+
+                       uid1 = e_cal_component_id_get_uid (id1);
+                       rid1 = e_cal_component_id_get_rid (id1);
+                       uid2 = e_cal_component_id_get_uid (id2);
+                       rid2 = e_cal_component_id_get_rid (id2);
+                       auid1 = e_cal_component_alarm_instance_get_uid (e_reminder_data_get_instance (rd));
+                       auid2 = e_cal_component_alarm_instance_get_uid (e_reminder_data_get_instance (rd2));
+
+                       if (g_strcmp0 (uid1, uid2) == 0 && (
+                           (g_strcmp0 (rid1, rid2) == 0 ||
+                           ((!rid1 || !*rid1) && (!rid2 || !*rid2)))) &&
+                           g_strcmp0 (auid1, auid2) == 0 &&
+                           e_cal_component_alarm_instance_get_time (e_reminder_data_get_instance (rd)) ==
+                           e_cal_component_alarm_instance_get_time (e_reminder_data_get_instance (rd2)))
                                found = rd2;
 
-                       e_cal_component_free_id (id2);
+                       e_cal_component_id_free (id2);
                }
        }
 
        if (id1)
-               e_cal_component_free_id (id1);
+               e_cal_component_id_free (id1);
 
        return found;
 }
@@ -1333,9 +1444,9 @@ e_reminder_watcher_remove_from_past (EReminderWatcher *watcher,
                e_reminder_watcher_save_past (watcher, reminders);
 
                e_reminder_watcher_debug_print ("Removed reminder from past for '%s' from %s at %s\n",
-                       icalcomponent_get_summary (e_cal_component_get_icalcomponent (found->component)),
+                       i_cal_component_get_summary (e_cal_component_get_icalcomponent (found->component)),
                        found->source_uid,
-                       e_reminder_watcher_timet_as_string (found->instance.trigger));
+                       e_reminder_watcher_timet_as_string (e_cal_component_alarm_instance_get_time 
(found->instance)));
 
                e_reminder_data_free (found);
        }
@@ -1368,9 +1479,9 @@ e_reminder_watcher_remove_from_snoozed (EReminderWatcher *watcher,
                        e_reminder_watcher_save_snoozed (watcher);
 
                e_reminder_watcher_debug_print ("Removed reminder from snoozed for '%s' from %s at %s\n",
-                       icalcomponent_get_summary (e_cal_component_get_icalcomponent (found->component)),
+                       i_cal_component_get_summary (e_cal_component_get_icalcomponent (found->component)),
                        found->source_uid,
-                       e_reminder_watcher_timet_as_string (found->instance.trigger));
+                       e_reminder_watcher_timet_as_string (e_cal_component_alarm_instance_get_time 
(found->instance)));
 
                e_reminder_data_free (found);
        }
@@ -1492,8 +1603,8 @@ e_reminder_watcher_gather_nearest_scheduled_cb (gpointer key,
        gint *out_nearest = user_data;
        EReminderData *rd = reminders ? reminders->data : NULL;
 
-       if (rd && out_nearest && (!*out_nearest || rd->instance.trigger < *out_nearest))
-               *out_nearest = rd->instance.trigger;
+       if (rd && out_nearest && (!*out_nearest || e_cal_component_alarm_instance_get_time (rd->instance) < 
*out_nearest))
+               *out_nearest = e_cal_component_alarm_instance_get_time (rd->instance);
 }
 
 static gint64
@@ -1527,8 +1638,8 @@ e_reminder_watcher_maybe_schedule_next_trigger (EReminderWatcher *watcher,
        if (watcher->priv->snoozed && watcher->priv->snoozed->data) {
                const EReminderData *rd = watcher->priv->snoozed->data;
 
-               if (next_trigger <= 0 || rd->instance.trigger < next_trigger)
-                       next_trigger = rd->instance.trigger;
+               if (next_trigger <= 0 || e_cal_component_alarm_instance_get_time (rd->instance) < 
next_trigger)
+                       next_trigger = e_cal_component_alarm_instance_get_time (rd->instance);
        }
 
        if (watcher->priv->scheduled) {
@@ -1622,9 +1733,9 @@ e_reminder_watcher_reminders_snoozed_changed_cb (GSettings *settings,
                                changed = TRUE;
 
                                e_reminder_watcher_debug_print ("Removed reminder from snoozed for '%s' from 
%s at %s\n",
-                                       icalcomponent_get_summary (e_cal_component_get_icalcomponent 
(rd->component)),
+                                       i_cal_component_get_summary (e_cal_component_get_icalcomponent 
(rd->component)),
                                        rd->source_uid,
-                                       e_reminder_watcher_timet_as_string (rd->instance.trigger));
+                                       e_reminder_watcher_timet_as_string 
(e_cal_component_alarm_instance_get_time (rd->instance)));
                        }
                }
 
@@ -1635,9 +1746,9 @@ e_reminder_watcher_reminders_snoozed_changed_cb (GSettings *settings,
                                changed = TRUE;
 
                                e_reminder_watcher_debug_print ("Added reminder to snoozed for '%s' from %s 
at %s\n",
-                                       icalcomponent_get_summary (e_cal_component_get_icalcomponent 
(rd->component)),
+                                       i_cal_component_get_summary (e_cal_component_get_icalcomponent 
(rd->component)),
                                        rd->source_uid,
-                                       e_reminder_watcher_timet_as_string (rd->instance.trigger));
+                                       e_reminder_watcher_timet_as_string 
(e_cal_component_alarm_instance_get_time (rd->instance)));
                        }
                }
 
@@ -1655,9 +1766,9 @@ e_reminder_watcher_reminders_snoozed_changed_cb (GSettings *settings,
                                continue;
 
                        e_reminder_watcher_debug_print ("Removed reminder from snoozed for '%s' from %s at 
%s\n",
-                               icalcomponent_get_summary (e_cal_component_get_icalcomponent (rd->component)),
+                               i_cal_component_get_summary (e_cal_component_get_icalcomponent 
(rd->component)),
                                rd->source_uid,
-                               e_reminder_watcher_timet_as_string (rd->instance.trigger));
+                               e_reminder_watcher_timet_as_string (e_cal_component_alarm_instance_get_time 
(rd->instance)));
                }
 
                g_slist_free_full (old_snoozed, e_reminder_data_free);
@@ -2024,7 +2135,7 @@ e_reminder_watcher_finalize (GObject *object)
 {
        EReminderWatcher *watcher = E_REMINDER_WATCHER (object);
 
-       e_reminder_watcher_zone_free ((EReminderWatcherZone *) watcher->priv->default_zone);
+       g_clear_object (&watcher->priv->default_zone);
        g_rec_mutex_clear (&watcher->priv->lock);
 
        /* Chain up to parent's method. */
@@ -2073,19 +2184,18 @@ e_reminder_watcher_class_init (EReminderWatcherClass *klass)
        /**
         * EReminderWatcher:default-zone:
         *
-        * An icaltimezone to be used as the default time zone.
-        * It's encapsulated in a boxed type #EReminderWatcherZone.
+        * An #ICalTimezone to be used as the default time zone.
         *
         * Since: 3.30
         **/
        g_object_class_install_property (
                object_class,
                PROP_DEFAULT_ZONE,
-               g_param_spec_boxed (
+               g_param_spec_object (
                        "default-zone",
                        "Default Zone",
                        "The default time zone",
-                       E_TYPE_REMINDER_WATCHER_ZONE,
+                       I_CAL_TYPE_TIMEZONE,
                        G_PARAM_READWRITE |
                        G_PARAM_EXPLICIT_NOTIFY |
                        G_PARAM_STATIC_STRINGS));
@@ -2117,8 +2227,8 @@ e_reminder_watcher_class_init (EReminderWatcherClass *klass)
         * EReminderWatcher::format-time:
         * @watcher: an #EReminderWatcher
         * @rd: an #EReminderData
-        * @itt: a pointer to struct icaltimetype
-        * @inout_buffer: (caller allocates) (inout): a pointer to a buffer to fill with formatted @itt
+        * @itt: an #ICalTime
+        * @inout_buffer: (inout): a pointer to a buffer to fill with formatted @itt
         * @buffer_size: size of inout_buffer
         *
         * Formats time @itt to a string and writes it to @inout_buffer, which can hold
@@ -2144,7 +2254,7 @@ e_reminder_watcher_class_init (EReminderWatcherClass *klass)
        /**
         * EReminderWatcher::triggered:
         * @watcher: an #EReminderWatcher
-        * @reminders: (element-type EReminderData): a #GSList of #EReminderData
+        * @reminders: (type GSList) (element-type EReminderData): a #GSList of #EReminderData
         * @snoozed: %TRUE, when the @reminders had been snoozed, %FALSE otherwise
         *
         * Signal is emitted when any reminder is either overdue or triggered.
@@ -2188,23 +2298,23 @@ e_reminder_watcher_class_init (EReminderWatcherClass *klass)
 static void
 e_reminder_watcher_init (EReminderWatcher *watcher)
 {
-       icaltimezone *zone = NULL;
+       ICalTimezone *zone = NULL;
        gchar *location;
 
        location = e_cal_system_timezone_get_location ();
        if (location) {
-               zone = icaltimezone_get_builtin_timezone (location);
+               zone = i_cal_timezone_get_builtin_timezone (location);
                g_free (location);
        }
 
        if (!zone)
-               zone = icaltimezone_get_utc_timezone ();
+               zone = i_cal_timezone_get_utc_timezone ();
 
        watcher->priv = G_TYPE_INSTANCE_GET_PRIVATE (watcher, E_TYPE_REMINDER_WATCHER, 
EReminderWatcherPrivate);
        watcher->priv->cancellable = g_cancellable_new ();
        watcher->priv->settings = g_settings_new ("org.gnome.evolution-data-server.calendar");
        watcher->priv->scheduled = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
e_reminder_watcher_free_rd_slist);
-       watcher->priv->default_zone = icaltimezone_copy (zone);
+       watcher->priv->default_zone = e_cal_util_copy_timezone (zone);
        watcher->priv->timers_enabled = TRUE;
 
        g_rec_mutex_init (&watcher->priv->lock);
@@ -2248,11 +2358,11 @@ e_reminder_watcher_get_registry (EReminderWatcher *watcher)
 }
 
 /**
- * e_reminders_widget_ref_opened_client:
+ * e_reminder_watcher_ref_opened_client:
  * @watcher: an #EReminderWatcher
  * @source_uid: an #ESource UID of the calendar to return
  *
- * Returns: (nullable) (transfer full): a referenced #ECalClient for the @source_uid,
+ * Returns: (transfer full) (nullable): a referenced #ECalClient for the @source_uid,
  *    if any such is opened; %NULL otherwise.
  *
  * Since: 3.30
@@ -2270,7 +2380,7 @@ e_reminder_watcher_ref_opened_client (EReminderWatcher *watcher,
 /**
  * e_reminder_watcher_set_default_zone:
  * @watcher: an #EReminderWatcher
- * @zone: (nullable): an icaltimezone or #EReminderWatcherZone structure
+ * @zone: (nullable): an #ICalTimezone
  *
  * Sets the default zone for the @watcher. This is used when calculating
  * trigger times for floating component times. When the @zone is %NULL,
@@ -2280,27 +2390,27 @@ e_reminder_watcher_ref_opened_client (EReminderWatcher *watcher,
  **/
 void
 e_reminder_watcher_set_default_zone (EReminderWatcher *watcher,
-                                    const icaltimezone *zone)
+                                    const ICalTimezone *zone)
 {
        const gchar *new_location;
 
        g_return_if_fail (E_IS_REMINDER_WATCHER (watcher));
 
        if (!zone)
-               zone = icaltimezone_get_utc_timezone ();
+               zone = i_cal_timezone_get_utc_timezone ();
 
        g_rec_mutex_lock (&watcher->priv->lock);
 
-       new_location = icaltimezone_get_location ((icaltimezone *) zone);
+       new_location = i_cal_timezone_get_location ((ICalTimezone *) zone);
 
        if (new_location && g_strcmp0 (new_location,
-           icaltimezone_get_location (watcher->priv->default_zone)) == 0) {
+           i_cal_timezone_get_location (watcher->priv->default_zone)) == 0) {
                g_rec_mutex_unlock (&watcher->priv->lock);
                return;
        }
 
-       e_reminder_watcher_zone_free ((EReminderWatcherZone *) watcher->priv->default_zone);
-       watcher->priv->default_zone = (icaltimezone *) e_reminder_watcher_zone_copy ((const 
EReminderWatcherZone *) zone);
+       g_clear_object (&watcher->priv->default_zone);
+       watcher->priv->default_zone = e_cal_util_copy_timezone (zone);
 
        g_rec_mutex_unlock (&watcher->priv->lock);
 
@@ -2312,20 +2422,20 @@ e_reminder_watcher_set_default_zone (EReminderWatcher *watcher,
  * @watcher: an #EReminderWatcher
  *
  * Returns: (transfer full): A copy of the currently set default time zone.
- *    Use e_reminder_watcher_zone_free() to free it, when no longer needed.
+ *    Free it with g_object_unref(), when no longer needed.
  *
  * Since: 3.30
  **/
-icaltimezone *
+ICalTimezone *
 e_reminder_watcher_dup_default_zone (EReminderWatcher *watcher)
 {
-       icaltimezone *zone;
+       ICalTimezone *zone;
 
        g_return_val_if_fail (E_IS_REMINDER_WATCHER (watcher), NULL);
 
        g_rec_mutex_lock (&watcher->priv->lock);
 
-       zone = (icaltimezone *) e_reminder_watcher_zone_copy ((EReminderWatcherZone *) 
watcher->priv->default_zone);
+       zone = e_cal_util_copy_timezone (watcher->priv->default_zone);
 
        g_rec_mutex_unlock (&watcher->priv->lock);
 
@@ -2401,50 +2511,72 @@ static gchar *
 e_reminder_watcher_get_alarm_summary (EReminderWatcher *watcher,
                                      const EReminderData *rd)
 {
-       ECalComponentText summary_text, alarm_text;
+       ECalComponentText *summary_text, *alarm_text;
        ECalComponentAlarm *alarm;
        gchar *alarm_summary;
+       const gchar *summary_text_value, *alarm_text_value;
 
        g_return_val_if_fail (watcher != NULL, NULL);
        g_return_val_if_fail (rd != NULL, NULL);
 
-       summary_text.value = NULL;
-       alarm_text.value = NULL;
+       alarm_text = NULL;
 
-       e_cal_component_get_summary (rd->component, &summary_text);
+       summary_text = e_cal_component_get_summary (rd->component);
+       if (summary_text) {
+               const gchar *value;
 
-       alarm = e_cal_component_get_alarm (rd->component, rd->instance.auid);
+               value = e_cal_component_text_get_value (summary_text);
+               if (!value || !*value) {
+                       e_cal_component_text_free (summary_text);
+                       summary_text = NULL;
+               }
+       }
+
+       alarm = e_cal_component_get_alarm (rd->component, e_cal_component_alarm_instance_get_uid 
(rd->instance));
        if (alarm) {
                ECalClient *client;
 
                client = e_reminder_watcher_ref_opened_client (watcher, rd->source_uid);
 
-               if (client && e_client_check_capability (E_CLIENT (client), 
CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION)) {
-                       e_cal_component_alarm_get_description (alarm, &alarm_text);
-                       if (!alarm_text.value || !*alarm_text.value)
-                               alarm_text.value = NULL;
+               if (client && e_client_check_capability (E_CLIENT (client), 
E_CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION)) {
+                       alarm_text = e_cal_component_alarm_get_description (alarm);
+                       if (alarm_text) {
+                               const gchar *value;
+
+                               value = e_cal_component_text_get_value (alarm_text);
+                               if (!value || !*value) {
+                                       e_cal_component_text_free (alarm_text);
+                                       alarm_text = NULL;
+                               }
+                       }
                }
 
                g_clear_object (&client);
        }
 
-       if (alarm_text.value && summary_text.value &&
-           e_util_utf8_strcasecmp (alarm_text.value, summary_text.value) == 0)
-               alarm_text.value = NULL;
+       summary_text_value = summary_text ? e_cal_component_text_get_value (summary_text) : NULL;
+       alarm_text_value = alarm_text ? e_cal_component_text_get_value (alarm_text) : NULL;
+
+       if (alarm_text_value && summary_text_value &&
+           e_util_utf8_strcasecmp (alarm_text_value, summary_text_value) == 0) {
+               alarm_text_value = NULL;
+       }
 
-       if (summary_text.value && *summary_text.value &&
-           alarm_text.value && *alarm_text.value)
-               alarm_summary = g_strconcat (summary_text.value, "\n", alarm_text.value, NULL);
-       else if (summary_text.value && *summary_text.value)
-               alarm_summary = g_strdup (summary_text.value);
-       else if (alarm_text.value && *alarm_text.value)
-               alarm_summary = g_strdup (alarm_text.value);
+       if (summary_text_value && *summary_text_value &&
+           alarm_text_value && *alarm_text_value)
+               alarm_summary = g_strconcat (summary_text_value, "\n", alarm_text_value, NULL);
+       else if (summary_text_value && *summary_text_value)
+               alarm_summary = g_strdup (summary_text_value);
+       else if (alarm_text_value && *alarm_text_value)
+               alarm_summary = g_strdup (alarm_text_value);
        else
                alarm_summary = NULL;
 
        if (alarm)
                e_cal_component_alarm_free (alarm);
 
+       e_cal_component_text_free (summary_text);
+
        return alarm_summary;
 }
 
@@ -2468,7 +2600,7 @@ e_reminder_watcher_describe_data (EReminderWatcher *watcher,
                                  const EReminderData *rd,
                                  guint32 flags)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icalcomp;
        gchar *description = NULL;
        gboolean use_markup;
 
@@ -2488,37 +2620,39 @@ e_reminder_watcher_describe_data (EReminderWatcher *watcher,
                timestr[0] = 0;
                markup = g_string_sized_new (256);
                summary = e_reminder_watcher_get_alarm_summary (watcher, rd);
-               location = icalcomponent_get_location (icalcomp);
+               location = i_cal_component_get_location (icalcomp);
 
-               if (rd->instance.occur_start > 0) {
+               if (e_cal_component_alarm_instance_get_occur_start (rd->instance) > 0) {
                        gchar *timestrptr = timestr;
-                       icaltimezone *zone;
-                       struct icaltimetype itt;
+                       ICalTimezone *zone;
+                       ICalTime *itt;
                        gboolean is_date = FALSE;
 
-                       if (rd->instance.occur_end > rd->instance.occur_start) {
-                               timediff = e_cal_util_seconds_to_string (rd->instance.occur_end - 
rd->instance.occur_start);
+                       if (e_cal_component_alarm_instance_get_occur_end (rd->instance) > 
e_cal_component_alarm_instance_get_occur_start (rd->instance)) {
+                               timediff = e_cal_util_seconds_to_string (
+                                       e_cal_component_alarm_instance_get_occur_end (rd->instance) -
+                                       e_cal_component_alarm_instance_get_occur_start (rd->instance));
                        }
 
                        zone = e_reminder_watcher_dup_default_zone (watcher);
-                       if (zone && (!icaltimezone_get_location (zone) || g_strcmp0 
(icaltimezone_get_location (zone), "UTC") == 0)) {
-                               icaltimezone_free (zone, 1);
-                               zone = NULL;
+                       if (zone && (!i_cal_timezone_get_location (zone) || g_strcmp0 
(i_cal_timezone_get_location (zone), "UTC") == 0)) {
+                               g_clear_object (&zone);
                        }
 
-                       itt = icalcomponent_get_dtstart (icalcomp);
-                       if (icaltime_is_valid_time (itt) && !icaltime_is_null_time (itt))
-                               is_date = itt.is_date;
+                       itt = i_cal_component_get_dtstart (icalcomp);
+                       if (itt && i_cal_time_is_valid_time (itt) && !i_cal_time_is_null_time (itt))
+                               is_date = i_cal_time_is_date (itt);
+                       g_clear_object (&itt);
 
-                       itt = icaltime_from_timet_with_zone (rd->instance.occur_start, is_date, zone);
+                       itt = i_cal_time_from_timet_with_zone (e_cal_component_alarm_instance_get_occur_start 
(rd->instance), is_date, zone);
 
-                       g_signal_emit (watcher, signals[FORMAT_TIME], 0, rd, &itt, &timestrptr, 254, NULL);
+                       g_signal_emit (watcher, signals[FORMAT_TIME], 0, rd, itt, &timestrptr, 254, NULL);
 
                        if (!*timestr)
-                               e_reminder_watcher_format_time_impl (watcher, rd, &itt, &timestrptr, 254);
+                               e_reminder_watcher_format_time_impl (watcher, rd, itt, &timestrptr, 254);
 
-                       if (zone)
-                               icaltimezone_free (zone, 1);
+                       g_clear_object (&zone);
+                       g_clear_object (&itt);
                }
 
                if (!summary || !*summary) {
@@ -2627,7 +2761,7 @@ foreach_trigger_cb (gpointer key,
        for (link = reminders; link; link = g_slist_next (link)) {
                rd = link->data;
 
-               if (!rd || rd->instance.trigger > ftd->current_time)
+               if (!rd || e_cal_component_alarm_instance_get_time (rd->instance) > ftd->current_time)
                        break;
        }
 
@@ -2718,7 +2852,7 @@ e_reminder_watcher_timer_elapsed (EReminderWatcher *watcher)
        for (link = snoozed; link; link = g_slist_next (link)) {
                EReminderData *rd = link->data;
 
-               if (rd && rd->instance.trigger <= ftd.current_time) {
+               if (rd && e_cal_component_alarm_instance_get_time (rd->instance) <= ftd.current_time) {
                        link->data = NULL;
 
                        changed = e_reminder_watcher_remove_from_snoozed (watcher, rd, FALSE) || changed;
@@ -2748,11 +2882,11 @@ e_reminder_watcher_timer_elapsed (EReminderWatcher *watcher)
 
                                        ptrigger = g_hash_table_lookup (last_notifies, rd->source_uid);
                                        if (ptrigger) {
-                                               if (*ptrigger < rd->instance.trigger)
-                                                       *ptrigger = rd->instance.trigger;
+                                               if (*ptrigger < e_cal_component_alarm_instance_get_time 
(rd->instance))
+                                                       *ptrigger = e_cal_component_alarm_instance_get_time 
(rd->instance);
                                        } else {
                                                ptrigger = g_new0 (time_t, 1);
-                                               *ptrigger = rd->instance.trigger;
+                                               *ptrigger = e_cal_component_alarm_instance_get_time 
(rd->instance);
                                                g_hash_table_insert (last_notifies, rd->source_uid, ptrigger);
                                        }
                                }
@@ -2768,11 +2902,11 @@ e_reminder_watcher_timer_elapsed (EReminderWatcher *watcher)
 
                                        ptrigger = g_hash_table_lookup (last_notifies, rd->source_uid);
                                        if (ptrigger) {
-                                               if (*ptrigger < rd->instance.trigger)
-                                                       *ptrigger = rd->instance.trigger;
+                                               if (*ptrigger < e_cal_component_alarm_instance_get_time 
(rd->instance))
+                                                       *ptrigger = e_cal_component_alarm_instance_get_time 
(rd->instance);
                                        } else {
                                                ptrigger = g_new0 (time_t, 1);
-                                               *ptrigger = rd->instance.trigger;
+                                               *ptrigger = e_cal_component_alarm_instance_get_time 
(rd->instance);
                                                g_hash_table_insert (last_notifies, rd->source_uid, ptrigger);
                                        }
                                }
@@ -2922,14 +3056,14 @@ e_reminder_watcher_snooze (EReminderWatcher *watcher,
        changed = e_reminder_watcher_remove_from_past (watcher, rd_copy);
        changed = e_reminder_watcher_remove_from_snoozed (watcher, rd_copy, FALSE) || changed;
 
-       rd_copy->instance.trigger = (time_t) until;
+       e_cal_component_alarm_instance_set_time (rd_copy->instance, (time_t) until);
 
        changed = e_reminder_watcher_add (&watcher->priv->snoozed, rd_copy, FALSE, TRUE) || changed;
 
        e_reminder_watcher_debug_print ("Added reminder to snoozed for '%s' from %s at %s\n",
-               icalcomponent_get_summary (e_cal_component_get_icalcomponent (rd_copy->component)),
+               i_cal_component_get_summary (e_cal_component_get_icalcomponent (rd_copy->component)),
                rd_copy->source_uid,
-               e_reminder_watcher_timet_as_string (rd_copy->instance.trigger));
+               e_reminder_watcher_timet_as_string (e_cal_component_alarm_instance_get_time 
(rd_copy->instance)));
 
        e_reminder_watcher_save_snoozed (watcher);
        e_reminder_watcher_maybe_schedule_next_trigger (watcher, until);
@@ -3038,11 +3172,18 @@ e_reminder_watcher_dismiss_one_sync (ECalClient *client,
        if (id) {
                GError *local_error = NULL;
 
-               success = e_cal_client_discard_alarm_sync (client, id->uid, id->rid, rd->instance.auid, 
cancellable, &local_error);
+               success = e_cal_client_discard_alarm_sync (client,
+                       e_cal_component_id_get_uid (id),
+                       e_cal_component_id_get_rid (id),
+                       e_cal_component_alarm_instance_get_uid (rd->instance),
+                       E_CAL_OPERATION_FLAG_NONE,
+                       cancellable, &local_error);
 
                e_reminder_watcher_debug_print ("Discard alarm for '%s' from %s (uid:%s rid:%s auid:%s) 
%s%s%s%s\n",
-                       icalcomponent_get_summary (e_cal_component_get_icalcomponent (rd->component)),
-                       rd->source_uid, id->uid, id->rid ? id->rid : "null", rd->instance.auid,
+                       i_cal_component_get_summary (e_cal_component_get_icalcomponent (rd->component)),
+                       rd->source_uid, e_cal_component_id_get_uid (id),
+                       e_cal_component_id_get_rid (id) ? e_cal_component_id_get_rid (id) : "null",
+                       e_cal_component_alarm_instance_get_uid (rd->instance),
                        success ? "succeeded" : "failed",
                        (!success || local_error) ? " (" : "",
                        local_error ? local_error->message : success ? "" : "Unknown error",
@@ -3052,7 +3193,7 @@ e_reminder_watcher_dismiss_one_sync (ECalClient *client,
                success = TRUE;
                g_clear_error (&local_error);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
        }
 
        return success;
diff --git a/src/calendar/libecal/e-reminder-watcher.h b/src/calendar/libecal/e-reminder-watcher.h
index 285d6cc67..ddc16b727 100644
--- a/src/calendar/libecal/e-reminder-watcher.h
+++ b/src/calendar/libecal/e-reminder-watcher.h
@@ -59,11 +59,7 @@ G_BEGIN_DECLS
  *
  * Since: 3.30
  **/
-typedef struct _EReminderData {
-       gchar *source_uid;
-       ECalComponent *component;
-       ECalComponentAlarmInstance instance;
-} EReminderData;
+typedef struct _EReminderData EReminderData;
 
 GType          e_reminder_data_get_type        (void) G_GNUC_CONST;
 EReminderData *        e_reminder_data_new             (const gchar *source_uid,
@@ -71,21 +67,16 @@ EReminderData *     e_reminder_data_new             (const gchar *source_uid,
                                                 const ECalComponentAlarmInstance *instance);
 EReminderData *        e_reminder_data_copy            (const EReminderData *rd);
 void           e_reminder_data_free            (gpointer rd); /* EReminderData * */
-
-/**
- * EReminderWatcherZone:
- *
- * A libical's icaltimezone encapsulated as a GBoxed type.
- * It can be retyped into icaltimezone directly.
- *
- * Since: 3.30
- **/
-typedef icaltimezone EReminderWatcherZone;
-
-GType          e_reminder_watcher_zone_get_type(void) G_GNUC_CONST;
-EReminderWatcherZone *
-               e_reminder_watcher_zone_copy    (const EReminderWatcherZone *watcher_zone);
-void           e_reminder_watcher_zone_free    (EReminderWatcherZone *watcher_zone);
+const gchar *  e_reminder_data_get_source_uid  (const EReminderData *rd);
+void           e_reminder_data_set_source_uid  (EReminderData *rd,
+                                                const gchar *source_uid);
+ECalComponent *        e_reminder_data_get_component   (const EReminderData *rd);
+void           e_reminder_data_set_component   (EReminderData *rd,
+                                                const ECalComponent *component);
+ECalComponentAlarmInstance *
+               e_reminder_data_get_instance    (const EReminderData *rd);
+void           e_reminder_data_set_instance    (EReminderData *rd,
+                                                const ECalComponentAlarmInstance *instance);
 
 typedef struct _EReminderWatcher EReminderWatcher;
 typedef struct _EReminderWatcherClass EReminderWatcherClass;
@@ -128,7 +119,7 @@ struct _EReminderWatcherClass {
                                                 gint64 at_time);
        void            (* format_time)         (EReminderWatcher *watcher,
                                                 const EReminderData *rd,
-                                                struct icaltimetype *itt,
+                                                ICalTime *itt,
                                                 gchar **inout_buffer,
                                                 gint buffer_size);
        void            (* triggered)           (EReminderWatcher *watcher,
@@ -166,8 +157,8 @@ ESourceRegistry *
 ECalClient *   e_reminder_watcher_ref_opened_client    (EReminderWatcher *watcher,
                                                         const gchar *source_uid);
 void           e_reminder_watcher_set_default_zone     (EReminderWatcher *watcher,
-                                                        const icaltimezone *zone);
-icaltimezone * e_reminder_watcher_dup_default_zone     (EReminderWatcher *watcher);
+                                                        const ICalTimezone *zone);
+ICalTimezone * e_reminder_watcher_dup_default_zone     (EReminderWatcher *watcher);
 gboolean       e_reminder_watcher_get_timers_enabled   (EReminderWatcher *watcher);
 void           e_reminder_watcher_set_timers_enabled   (EReminderWatcher *watcher,
                                                         gboolean enabled);
diff --git a/src/calendar/libecal/e-timezone-cache.c b/src/calendar/libecal/e-timezone-cache.c
index 0f0f86a75..dee781ac5 100644
--- a/src/calendar/libecal/e-timezone-cache.c
+++ b/src/calendar/libecal/e-timezone-cache.c
@@ -20,7 +20,7 @@
  * @include: libecal/libecal.h
  * @short_description: An interface for caching time zone data
  *
- * Several classes (both client-side and server-side) cache #icaltimezone
+ * Several classes (both client-side and server-side) cache #ICalTimezone
  * instances internally, indexed by their TZID strings.  Classes which do
  * this should implement #ETimezoneCacheInterface to provide a consistent
  * API for accessing time zone data.
@@ -39,7 +39,7 @@ e_timezone_cache_default_init (ETimezoneCacheInterface *iface)
        /**
         * ETimezoneCache::timezone-added:
         * @cache: the #ETimezoneCache which emitted the signal
-        * @zone: the newly-added #icaltimezone
+        * @zone: the newly-added #ICalTimezone
         *
         * Emitted when a new #icaltimezone is added to @cache.
         **/
@@ -50,29 +50,29 @@ e_timezone_cache_default_init (ETimezoneCacheInterface *iface)
                G_STRUCT_OFFSET (ETimezoneCacheInterface, timezone_added),
                NULL, NULL, NULL,
                G_TYPE_NONE, 1,
-               G_TYPE_POINTER);
+               I_CAL_TYPE_TIMEZONE);
 }
 
 /**
  * e_timezone_cache_add_timezone:
  * @cache: an #ETimezoneCache
- * @zone: an #icaltimezone
+ * @zone: an #ICalTimezone
  *
  * Adds a copy of @zone to @cache and emits a
  * #ETimezoneCache::timezone-added signal.  The @cache will use the TZID
- * string returned by icaltimezone_get_tzid() as the lookup key, which can
+ * string returned by i_cal_timezone_get_tzid() as the lookup key, which can
  * be passed to e_timezone_cache_get_timezone() to obtain @zone again.
  *
- * If the @cache already has an #icaltimezone with the same TZID string
+ * If the @cache already has an #ICalTimezone with the same TZID string
  * as @zone, the @cache will remain unchanged to avoid invalidating any
- * #icaltimezone pointers which may have already been returned through
+ * #ICalTimezone pointers which may have already been returned through
  * e_timezone_cache_get_timezone().
  *
  * Since: 3.8
  **/
 void
 e_timezone_cache_add_timezone (ETimezoneCache *cache,
-                               icaltimezone *zone)
+                              ICalTimezone *zone)
 {
        ETimezoneCacheInterface *iface;
 
@@ -90,15 +90,15 @@ e_timezone_cache_add_timezone (ETimezoneCache *cache,
  * @cache: an #ETimezoneCache
  * @tzid: the TZID of a timezone
  *
- * Obtains an #icaltimezone by its TZID string.  If no match is found,
- * the function returns %NULL.  The returned #icaltimezone is owned by
+ * Obtains an #ICalTimezone by its TZID string.  If no match is found,
+ * the function returns %NULL.  The returned #ICalTimezone is owned by
  * the @cache and should not be modified or freed.
  *
- * Returns: an #icaltimezone, or %NULL
+ * Returns: (transfer none) (nullable): an #ICalTimezone, or %NULL
  *
  * Since: 3.8
  **/
-icaltimezone *
+ICalTimezone *
 e_timezone_cache_get_timezone (ETimezoneCache *cache,
                                const gchar *tzid)
 {
@@ -117,7 +117,7 @@ e_timezone_cache_get_timezone (ETimezoneCache *cache,
  * e_timezone_cache_list_timezones:
  * @cache: an #ETimezoneCache
  *
- * Returns a list of #icaltimezone instances that were explicitly added to
+ * Returns a list of #ICalTimezone instances that were explicitly added to
  * the @cache through e_timezone_cache_add_timezone().  In particular, any
  * built-in time zone data that e_timezone_cache_get_timezone() may use to
  * match a TZID string is excluded from the returned list.
@@ -125,8 +125,8 @@ e_timezone_cache_get_timezone (ETimezoneCache *cache,
  * Free the returned list with g_list_free().  The list elements are owned
  * by the @cache and should not be modified or freed.
  *
- * Returns: (transfer container) (element-type icaltimezone): a #GList of
- *          #icaltimezone instances
+ * Returns: (transfer container) (element-type ICalTimezone): a #GList of
+ *    #ICalTimezone instances
  *
  * Since: 3.8
  **/
@@ -142,4 +142,3 @@ e_timezone_cache_list_timezones (ETimezoneCache *cache)
 
        return iface->list_timezones (cache);
 }
-
diff --git a/src/calendar/libecal/e-timezone-cache.h b/src/calendar/libecal/e-timezone-cache.h
index fb5dfe0b9..91240bd80 100644
--- a/src/calendar/libecal/e-timezone-cache.h
+++ b/src/calendar/libecal/e-timezone-cache.h
@@ -23,7 +23,7 @@
 #define E_TIMEZONE_CACHE_H
 
 #include <glib-object.h>
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 
 /* Standard GObject macros */
 #define E_TYPE_TIMEZONE_CACHE \
@@ -64,22 +64,25 @@ struct _ETimezoneCacheInterface {
        /*< public >*/
        /* Methods */
        void            (*add_timezone)         (ETimezoneCache *cache,
-                                                icaltimezone *zone);
-       icaltimezone *  (*get_timezone)         (ETimezoneCache *cache,
+                                                ICalTimezone *zone);
+       ICalTimezone *  (*get_timezone)         (ETimezoneCache *cache,
                                                 const gchar *tzid);
-       GList *         (*list_timezones)       (ETimezoneCache *cache);
+       GList *         (*list_timezones)       (ETimezoneCache *cache); /* ICalTimezone * */
 
        /* Signals */
        void            (*timezone_added)       (ETimezoneCache *cache,
-                                                icaltimezone *zone);
+                                                ICalTimezone *zone);
+
+       /* Padding for future expansion */
+       gpointer reserved_signals[4];
 };
 
 GType          e_timezone_cache_get_type       (void) G_GNUC_CONST;
 void           e_timezone_cache_add_timezone   (ETimezoneCache *cache,
-                                                icaltimezone *zone);
-icaltimezone * e_timezone_cache_get_timezone   (ETimezoneCache *cache,
+                                                ICalTimezone *zone);
+ICalTimezone * e_timezone_cache_get_timezone   (ETimezoneCache *cache,
                                                 const gchar *tzid);
-GList *                e_timezone_cache_list_timezones (ETimezoneCache *cache);
+GList *                e_timezone_cache_list_timezones (ETimezoneCache *cache); /* ICalTimezone * */
 
 G_END_DECLS
 
diff --git a/src/calendar/libecal/libecal.h b/src/calendar/libecal/libecal.h
index e14eb9d4b..5f9b09183 100644
--- a/src/calendar/libecal/libecal.h
+++ b/src/calendar/libecal/libecal.h
@@ -20,24 +20,40 @@
 
 #define __LIBECAL_H_INSIDE__
 
+#define LIBICAL_GLIB_UNSTABLE_API 1
+
+#include <libical-glib/libical-glib.h>
 #include <libedataserver/libedataserver.h>
 
-#include <libecal/e-cal.h>
 #include <libecal/e-cal-check-timezones.h>
 #include <libecal/e-cal-client-view.h>
 #include <libecal/e-cal-client.h>
 #include <libecal/e-cal-component.h>
+#include <libecal/e-cal-component-alarm.h>
+#include <libecal/e-cal-component-alarm-instance.h>
+#include <libecal/e-cal-component-alarm-repeat.h>
+#include <libecal/e-cal-component-alarm-trigger.h>
+#include <libecal/e-cal-component-alarms.h>
+#include <libecal/e-cal-component-attendee.h>
+#include <libecal/e-cal-component-datetime.h>
+#include <libecal/e-cal-component-id.h>
+#include <libecal/e-cal-component-organizer.h>
+#include <libecal/e-cal-component-parameter-bag.h>
+#include <libecal/e-cal-component-period.h>
+#include <libecal/e-cal-component-property-bag.h>
+#include <libecal/e-cal-component-range.h>
+#include <libecal/e-cal-component-text.h>
+#include <libecal/e-cal-enums.h>
 #include <libecal/e-cal-enumtypes.h>
 #include <libecal/e-cal-recur.h>
 #include <libecal/e-cal-system-timezone.h>
 #include <libecal/e-cal-time-util.h>
-#include <libecal/e-cal-types.h>
 #include <libecal/e-cal-util.h>
-#include <libecal/e-cal-view.h>
 #include <libecal/e-reminder-watcher.h>
 #include <libecal/e-timezone-cache.h>
 
+#undef LIBICAL_GLIB_UNSTABLE_API
+
 #undef __LIBECAL_H_INSIDE__
 
 #endif /* LIBECAL_H */
-
diff --git a/src/calendar/libecal/libecal.pc.in b/src/calendar/libecal/libecal.pc.in
index ac2f07499..a71e414f6 100644
--- a/src/calendar/libecal/libecal.pc.in
+++ b/src/calendar/libecal/libecal.pc.in
@@ -9,6 +9,6 @@ privincludedir=@privincludedir@
 Name: libecal
 Description: Client library for evolution calendars
 Version: @PROJECT_VERSION@
-Requires: libical libedataserver-@API_VERSION@
-Libs: -L${libdir} -lecal-@API_VERSION@
-Cflags: -I${privincludedir} @LIBICAL_EXTRA_CFLAGS@
+Requires: libical-glib libedataserver-@API_VERSION@
+Libs: -L${libdir} -lecal-@CAL_API_VERSION@
+Cflags: -I${privincludedir}
diff --git a/src/calendar/libedata-cal/CMakeLists.txt b/src/calendar/libedata-cal/CMakeLists.txt
index 749fdf68d..213de6178 100644
--- a/src/calendar/libedata-cal/CMakeLists.txt
+++ b/src/calendar/libedata-cal/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_pkgconfig_file(libedata-cal.pc.in libedata-cal-${API_VERSION}.pc)
+add_pkgconfig_file(libedata-cal.pc.in libedata-cal-${CAL_API_VERSION}.pc)
 
 set(DEPENDENCIES
        ebackend
@@ -9,13 +9,11 @@ set(DEPENDENCIES
 
 set(SOURCES
        e-cal-backend.c
-       e-cal-backend-cache.c
        e-cal-backend-factory.c
        e-cal-backend-intervaltree.c
        e-cal-backend-sexp.c
        e-cal-backend-sync.c
        e-cal-backend-util.c
-       e-cal-backend-store.c
        e-cal-cache.c
        e-cal-meta-backend.c
        e-data-cal.c
@@ -27,13 +25,11 @@ set(SOURCES
 set(HEADERS
        libedata-cal.h
        e-cal-backend.h
-       e-cal-backend-cache.h
        e-cal-backend-factory.h
        e-cal-backend-intervaltree.h
        e-cal-backend-sync.h
        e-cal-backend-util.h
        e-cal-backend-sexp.h
-       e-cal-backend-store.h
        e-cal-cache.h
        e-cal-meta-backend.h
        e-data-cal.h
@@ -54,7 +50,7 @@ add_dependencies(edata-cal
 set_target_properties(edata-cal PROPERTIES
        VERSION "${LIBEDATACAL_CURRENT}.${LIBEDATACAL_REVISION}.${LIBEDATACAL_AGE}"
        SOVERSION ${LIBEDATACAL_CURRENT}
-       OUTPUT_NAME edata-cal-${API_VERSION}
+       OUTPUT_NAME edata-cal-${CAL_API_VERSION}
 )
 
 target_compile_definitions(edata-cal PRIVATE
@@ -93,6 +89,48 @@ install(FILES ${HEADERS}
        DESTINATION ${privincludedir}/libedata-cal
 )
 
+set(gir_sources ${SOURCES} ${HEADERS})
+set(gir_identifies_prefixes EDataCal E)
+set(gir_includes GObject-2.0 Gio-2.0 Soup-2.4 libxml2-2.0 ICalGLib-3.0)
+set(gir_cflags
+       -DLIBEDATA_CAL_COMPILATION
+       -I${CMAKE_BINARY_DIR}/src/calendar
+       -I${CMAKE_SOURCE_DIR}/src/calendar
+)
+set(gir_libdirs
+       ${CMAKE_BINARY_DIR}/src/camel
+       ${CMAKE_BINARY_DIR}/src/libebackend
+       ${CMAKE_BINARY_DIR}/src/libedataserver
+       ${CMAKE_BINARY_DIR}/src/calendar/libecal
+       ${CMAKE_BINARY_DIR}/src/calendar/libedata-cal
+)
+set(gir_libs
+       ebackend
+       ecal
+       edata-cal
+       edataserver
+)
+set(gir_deps
+       ${CMAKE_BINARY_DIR}/src/camel/Camel-${API_VERSION}.gir
+       ${CMAKE_BINARY_DIR}/src/libedataserver/EDataServer-${API_VERSION}.gir
+       ${CMAKE_BINARY_DIR}/src/libebackend/EBackend-${API_VERSION}.gir
+       ${CMAKE_BINARY_DIR}/src/calendar/libecal/ECal-${CAL_API_VERSION}.gir
+)
+
+gir_add_introspection_simple(
+       EDataCal
+       libedata-cal
+       ${CAL_API_VERSION}
+       "libedata-cal/libedata-cal.h"
+       gir_identifies_prefixes
+       gir_includes
+       gir_cflags
+       gir_libdirs
+       gir_libs
+       gir_deps
+       gir_sources
+)
+
 set(DEPENDENCIES
        ebackend
        edataserver
@@ -101,7 +139,8 @@ set(DEPENDENCIES
 )
 
 add_executable(evolution-calendar-factory-subprocess
-       evolution-calendar-factory-subprocess.c)
+       evolution-calendar-factory-subprocess.c
+)
 
 target_compile_definitions(evolution-calendar-factory-subprocess PRIVATE
        -DG_LOG_DOMAIN=\"evolution-calendar-factory-subprocess\"
diff --git a/src/calendar/libedata-cal/e-cal-backend-factory.h 
b/src/calendar/libedata-cal/e-cal-backend-factory.h
index 8d46685c6..7a2b06ed4 100644
--- a/src/calendar/libedata-cal/e-cal-backend-factory.h
+++ b/src/calendar/libedata-cal/e-cal-backend-factory.h
@@ -25,7 +25,7 @@
 #ifndef E_CAL_BACKEND_FACTORY_H
 #define E_CAL_BACKEND_FACTORY_H
 
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 #include <libebackend/libebackend.h>
 
 /* Standard GObject macros */
@@ -85,7 +85,7 @@ struct _ECalBackendFactoryClass {
        /* Subclasses just need to set these
         * class members, we handle the rest. */
        const gchar *factory_name;
-       icalcomponent_kind component_kind;
+       ICalComponentKind component_kind;
        GType backend_type;
 };
 
diff --git a/src/calendar/libedata-cal/e-cal-backend-intervaltree.c 
b/src/calendar/libedata-cal/e-cal-backend-intervaltree.c
index b94cea02b..2a5b16fa7 100644
--- a/src/calendar/libedata-cal/e-cal-backend-intervaltree.c
+++ b/src/calendar/libedata-cal/e-cal-backend-intervaltree.c
@@ -380,7 +380,7 @@ intervaltree_fixup_deletion (EIntervalTree *tree,
        x->red = 0;
 }
 
-/** Caller should hold the lock. **/
+/* * Caller should hold the lock. * */
 static EIntervalNode *
 intervaltree_search_component (EIntervalTree *tree,
                                const gchar *searched_uid,
@@ -508,7 +508,7 @@ e_intervaltree_insert (EIntervalTree *tree,
 
        g_rec_mutex_lock (&tree->priv->mutex);
 
-       e_cal_component_get_uid (comp, &uid);
+       uid = e_cal_component_get_uid (comp);
        rid = e_cal_component_get_recurid_as_string (comp);
        e_intervaltree_remove (tree, uid, rid);
 
@@ -678,7 +678,8 @@ e_intervaltree_remove (EIntervalTree *tree,
  * @start: start of the interval
  * @end: end of the interval
  * 
- * Returns: list of nodes that overlaps given interval or %NULL.
+ * Returns: (element-type ECalComponent) (nullable) (transfer full): list of #ECalComponent-s
+ *    that overlap given interval, or %NULL.
  *
  * Since: 2.32
  **/
diff --git a/src/calendar/libedata-cal/e-cal-backend-sexp.c b/src/calendar/libedata-cal/e-cal-backend-sexp.c
index faa2faf9e..46884d35a 100644
--- a/src/calendar/libedata-cal/e-cal-backend-sexp.c
+++ b/src/calendar/libedata-cal/e-cal-backend-sexp.c
@@ -72,7 +72,7 @@ func_uid (ESExp *esexp,
           gpointer data)
 {
        SearchContext *ctx = data;
-       const gchar *uid = NULL, *arg_uid;
+       const gchar *uid, *arg_uid;
        gboolean equal;
        ESExpResult *result;
 
@@ -94,7 +94,7 @@ func_uid (ESExp *esexp,
        }
 
        arg_uid = argv[0]->value.string;
-       e_cal_component_get_uid (ctx->comp, &uid);
+       uid = e_cal_component_get_uid (ctx->comp);
 
        if (!arg_uid && !uid)
                equal = TRUE;
@@ -112,12 +112,14 @@ func_uid (ESExp *esexp,
 }
 
 static gboolean
-check_instance_time_range_cb (ECalComponent *comp,
-                              time_t instance_start,
-                              time_t instance_end,
-                              gpointer data)
+check_instance_time_range_cb (ICalComponent *comp,
+                             ICalTime *instance_start,
+                             ICalTime *instance_end,
+                             gpointer user_data,
+                             GCancellable *cancellable,
+                             GError **error)
 {
-       SearchContext *ctx = data;
+       SearchContext *ctx = user_data;
 
        /* if we get called, the event has an occurrence in the given time range */
        ctx->occurs = TRUE;
@@ -125,9 +127,11 @@ check_instance_time_range_cb (ECalComponent *comp,
        return FALSE;
 }
 
-static icaltimezone *
+static ICalTimezone *
 resolve_tzid (const gchar *tzid,
-              gpointer user_data)
+             gpointer user_data,
+             GCancellable *cancellable,
+             GError **error)
 {
        SearchContext *ctx = user_data;
 
@@ -156,7 +160,8 @@ func_occur_in_time_range (ESExp *esexp,
        SearchContext *ctx = data;
        time_t start, end;
        ESExpResult *result;
-       icaltimezone *default_zone = NULL;
+       ICalTimezone *default_zone = NULL, *utc_zone;
+       ICalTime *starttt, *endtt;
 
        /* Check argument types */
 
@@ -194,19 +199,28 @@ func_occur_in_time_range (ESExp *esexp,
                        return NULL;
                }
 
-               default_zone = resolve_tzid (argv[2]->value.string, ctx);
+               default_zone = resolve_tzid (argv[2]->value.string, ctx, NULL, NULL);
        }
 
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+
        if (!default_zone)
-               default_zone = icaltimezone_get_utc_timezone ();
+               default_zone = utc_zone;
 
        /* See if the object occurs in the specified time range */
        ctx->occurs = FALSE;
-       e_cal_recur_generate_instances (
-               ctx->comp, start, end,
-               (ECalRecurInstanceFn) check_instance_time_range_cb,
+
+       starttt = i_cal_time_from_timet_with_zone (start, FALSE, utc_zone);
+       endtt = i_cal_time_from_timet_with_zone (end, FALSE, utc_zone);
+
+       e_cal_recur_generate_instances_sync (
+               e_cal_component_get_icalcomponent (ctx->comp), starttt, endtt,
+               check_instance_time_range_cb,
                ctx, resolve_tzid, ctx,
-               default_zone);
+               default_zone, NULL, NULL);
+
+       g_clear_object (&starttt);
+       g_clear_object (&endtt);
 
        result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
        result->value.boolean = ctx->occurs;
@@ -215,12 +229,14 @@ func_occur_in_time_range (ESExp *esexp,
 }
 
 static gboolean
-count_instances_time_range_cb (ECalComponent *comp,
-                               time_t instance_start,
-                               time_t instance_end,
-                               gpointer data)
+count_instances_time_range_cb (ICalComponent *comp,
+                              ICalTime *instance_start,
+                              ICalTime *instance_end,
+                              gpointer user_data,
+                              GCancellable *cancellable,
+                              GError **error)
 {
-       SearchContext *ctx = data;
+       SearchContext *ctx = user_data;
 
        ctx->occurrences_count++;
 
@@ -244,7 +260,8 @@ func_occurrences_count (ESExp *esexp,
        SearchContext *ctx = data;
        time_t start, end;
        ESExpResult *result;
-       icaltimezone *default_zone;
+       ICalTimezone *default_zone;
+       ICalTime *starttt, *endtt;
 
        /* Check argument types */
 
@@ -281,13 +298,19 @@ func_occurrences_count (ESExp *esexp,
                return result;
        }
 
-       default_zone = icaltimezone_get_utc_timezone ();
+       default_zone = i_cal_timezone_get_utc_timezone ();
+
+       starttt = i_cal_time_from_timet_with_zone (start, FALSE, default_zone);
+       endtt = i_cal_time_from_timet_with_zone (end, FALSE, default_zone);
 
        ctx->occurrences_count = 0;
-       e_cal_recur_generate_instances (
-               ctx->comp, start, end,
+       e_cal_recur_generate_instances_sync (
+               e_cal_component_get_icalcomponent (ctx->comp), starttt, endtt,
                count_instances_time_range_cb, ctx,
-               resolve_tzid, ctx, default_zone);
+               resolve_tzid, ctx, default_zone, NULL, NULL);
+
+       g_clear_object (&starttt);
+       g_clear_object (&endtt);
 
        result = e_sexp_result_new (esexp, ESEXP_RES_INT);
        result->value.number = ctx->occurrences_count;
@@ -304,8 +327,8 @@ func_due_in_time_range (ESExp *esexp,
        SearchContext *ctx = data;
        time_t start, end;
        ESExpResult *result;
-       icaltimezone *zone;
-       ECalComponentDateTime dt;
+       ICalTimezone *zone;
+       ECalComponentDateTime *dt;
        time_t due_t;
        gboolean retval;
 
@@ -337,17 +360,19 @@ func_due_in_time_range (ESExp *esexp,
        }
 
        end = argv[1]->value.time;
-       e_cal_component_get_due (ctx->comp, &dt);
+       dt = e_cal_component_get_due (ctx->comp);
 
-       if (dt.value != NULL) {
-               zone = resolve_tzid (dt.tzid, ctx);
+       if (dt && e_cal_component_datetime_get_value (dt)) {
+               zone = resolve_tzid (e_cal_component_datetime_get_tzid (dt), ctx, NULL, NULL);
                if (zone)
-                       due_t = icaltime_as_timet_with_zone (*dt.value,zone);
+                       due_t = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value (dt), zone);
                else
-                       due_t = icaltime_as_timet (*dt.value);
+                       due_t = i_cal_time_as_timet (e_cal_component_datetime_get_value (dt));
+       } else {
+               due_t = (time_t) 0;
        }
 
-       if (dt.value != NULL && (due_t <= end && due_t >= start))
+       if (dt && e_cal_component_datetime_get_value (dt) && (due_t <= end && due_t >= start))
                retval = TRUE;
        else
                retval = FALSE;
@@ -355,7 +380,7 @@ func_due_in_time_range (ESExp *esexp,
        result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
        result->value.boolean = retval;
 
-       e_cal_component_free_datetime (&dt);
+       e_cal_component_datetime_free (dt);
 
        return result;
 }
@@ -366,16 +391,13 @@ matches_text_list (GSList *text_list,
                    const gchar *str)
 {
        GSList *l;
-       gboolean matches;
-
-       matches = FALSE;
+       gboolean matches = FALSE;
 
        for (l = text_list; l; l = l->next) {
-               ECalComponentText *text;
-
-               text = l->data;
+               ECalComponentText *text = l->data;
 
-               if (text && e_util_utf8_strstrcasedecomp (text->value, str) != NULL) {
+               if (text && e_cal_component_text_get_value (text) &&
+                   e_util_utf8_strstrcasedecomp (e_cal_component_text_get_value (text), str) != NULL) {
                        matches = TRUE;
                        break;
                }
@@ -392,9 +414,9 @@ matches_comment (ECalComponent *comp,
        GSList *list;
        gboolean matches;
 
-       e_cal_component_get_comment_list (comp, &list);
+       list = e_cal_component_get_comments (comp);
        matches = matches_text_list (list, str);
-       e_cal_component_free_text_list (list);
+       g_slist_free_full (list, e_cal_component_text_free);
 
        return matches;
 }
@@ -407,9 +429,9 @@ matches_description (ECalComponent *comp,
        GSList *list;
        gboolean matches;
 
-       e_cal_component_get_description_list (comp, &list);
+       list = e_cal_component_get_descriptions (comp);
        matches = matches_text_list (list, str);
-       e_cal_component_free_text_list (list);
+       g_slist_free_full (list, e_cal_component_text_free);
 
        return matches;
 }
@@ -421,22 +443,24 @@ matches_attendee (ECalComponent *comp,
        GSList *a_list = NULL, *l;
        gboolean matches = FALSE;
 
-       e_cal_component_get_attendee_list (comp, &a_list);
+       a_list = e_cal_component_get_attendees (comp);
 
        for (l = a_list; l; l = l->next) {
                ECalComponentAttendee *att = l->data;
 
-               if ((att->value && e_util_utf8_strstrcasedecomp (att->value, str)) ||
-                   (att->cn != NULL && e_util_utf8_strstrcasedecomp (att->cn, str))) {
+               if (!att)
+                       continue;
+
+               if ((e_cal_component_attendee_get_value (att) && e_util_utf8_strstrcasedecomp 
(e_cal_component_attendee_get_value (att), str)) ||
+                   (e_cal_component_attendee_get_cn (att) && e_util_utf8_strstrcasedecomp 
(e_cal_component_attendee_get_cn (att), str))) {
                        matches = TRUE;
                        break;
                }
        }
 
-       e_cal_component_free_attendee_list (a_list);
+       g_slist_free_full (a_list, e_cal_component_attendee_free);
 
        return matches;
-
 }
 
 static gboolean
@@ -444,17 +468,22 @@ matches_organizer (ECalComponent *comp,
                    const gchar *str)
 {
 
-       ECalComponentOrganizer org;
+       ECalComponentOrganizer *org;
+       gboolean matches;
 
-       e_cal_component_get_organizer (comp, &org);
        if (str && !*str)
                return TRUE;
 
-       if ((org.value && e_util_utf8_strstrcasedecomp (org.value, str)) ||
-           (org.cn && e_util_utf8_strstrcasedecomp (org.cn, str)))
-               return TRUE;
+       org = e_cal_component_get_organizer (comp);
+       if (!org)
+               return FALSE;
 
-       return FALSE;
+       matches = (e_cal_component_organizer_get_value (org) && e_util_utf8_strstrcasedecomp 
(e_cal_component_organizer_get_value (org), str)) ||
+                 (e_cal_component_organizer_get_cn (org) && e_util_utf8_strstrcasedecomp 
(e_cal_component_organizer_get_cn (org), str));
+
+       e_cal_component_organizer_free (org);
+
+       return matches;
 }
 
 static gboolean
@@ -476,7 +505,7 @@ matches_classification (ECalComponent *comp,
        else
                classification1 = E_CAL_COMPONENT_CLASS_UNKNOWN;
 
-       e_cal_component_get_classification (comp, &classification);
+       classification = e_cal_component_get_classification (comp);
 
        return (classification == classification1 ? TRUE : FALSE);
 }
@@ -486,17 +515,20 @@ static gboolean
 matches_summary (ECalComponent *comp,
                  const gchar *str)
 {
-       ECalComponentText text;
-
-       e_cal_component_get_summary (comp, &text);
+       ECalComponentText *text;
+       gboolean matches;
 
        if (!*str)
                return TRUE;
 
-       if (!text.value)
-               return FALSE;
+       text = e_cal_component_get_summary (comp);
+
+       matches = text && e_cal_component_text_get_value (text) &&
+                 e_util_utf8_strstrcasedecomp (e_cal_component_text_get_value (text), str) != NULL;
+
+       e_cal_component_text_free (text);
 
-       return e_util_utf8_strstrcasedecomp (text.value, str) != NULL;
+       return matches;
 }
 
 /* Returns whether the location in a component matches the specified string */
@@ -504,14 +536,16 @@ static gboolean
 matches_location (ECalComponent *comp,
                   const gchar *str)
 {
-       const gchar *location = NULL;
+       gchar *location;
+       gboolean matches;
 
-       e_cal_component_get_location (comp, &location);
+       location = e_cal_component_get_location (comp);
 
-       if (!location)
-               return FALSE;
+       matches = location && e_util_utf8_strstrcasedecomp (location, str) != NULL;
+
+       g_free (location);
 
-       return e_util_utf8_strstrcasedecomp (location, str) != NULL;
+       return matches;
 }
 
 /* Returns whether any text field in a component matches the specified string */
@@ -536,65 +570,61 @@ static gboolean
 matches_priority (ECalComponent *comp ,const gchar *pr)
 {
        gboolean res = FALSE;
-       gint *priority = NULL;
+       gint priority;
 
-       e_cal_component_get_priority (comp, &priority);
+       priority = e_cal_component_get_priority (comp);
 
-       if (!priority)
+       if (priority == -1)
                return g_str_equal (pr, "UNDEFINED");
 
-       if (g_str_equal (pr, "HIGH") && *priority <= 4)
+       if (g_str_equal (pr, "HIGH") && priority <= 4)
                res = TRUE;
-       else if (g_str_equal (pr, "NORMAL") && *priority == 5)
+       else if (g_str_equal (pr, "NORMAL") && priority == 5)
                res = TRUE;
-       else if (g_str_equal (pr, "LOW") && *priority > 5)
+       else if (g_str_equal (pr, "LOW") && priority > 5)
                res = TRUE;
 
-       e_cal_component_free_priority (priority);
-
        return res;
 }
 
 static gboolean
 matches_status (ECalComponent *comp ,const gchar *str)
 {
-       icalproperty_status status;
+       ICalPropertyStatus status;
 
        if (!*str)
                return FALSE;
 
-       e_cal_component_get_status (comp, &status);
+       status = e_cal_component_get_status (comp);
 
        switch (status) {
-       case ICAL_STATUS_NONE:
+       case I_CAL_STATUS_NONE:
                return g_str_equal (str, "NOT STARTED");
-       case ICAL_STATUS_COMPLETED:
+       case I_CAL_STATUS_COMPLETED:
                return g_str_equal (str, "COMPLETED");
-       case ICAL_STATUS_CANCELLED:
+       case I_CAL_STATUS_CANCELLED:
                return g_str_equal (str, "CANCELLED");
-       case ICAL_STATUS_INPROCESS:
+       case I_CAL_STATUS_INPROCESS:
                return g_str_equal (str, "IN PROGRESS");
-       case ICAL_STATUS_NEEDSACTION:
+       case I_CAL_STATUS_NEEDSACTION:
                return g_str_equal (str, "NEEDS ACTION");
-       case ICAL_STATUS_TENTATIVE:
+       case I_CAL_STATUS_TENTATIVE:
                return g_str_equal (str, "TENTATIVE");
-       case ICAL_STATUS_CONFIRMED:
+       case I_CAL_STATUS_CONFIRMED:
                return g_str_equal (str, "CONFIRMED");
-       case ICAL_STATUS_DRAFT:
+       case I_CAL_STATUS_DRAFT:
                return g_str_equal (str, "DRAFT");
-       case ICAL_STATUS_FINAL:
+       case I_CAL_STATUS_FINAL:
                return g_str_equal (str, "FINAL");
-       case ICAL_STATUS_SUBMITTED:
+       case I_CAL_STATUS_SUBMITTED:
                return g_str_equal (str, "SUBMITTED");
-       case ICAL_STATUS_PENDING:
+       case I_CAL_STATUS_PENDING:
                return g_str_equal (str, "PENDING");
-       case ICAL_STATUS_FAILED:
+       case I_CAL_STATUS_FAILED:
                return g_str_equal (str, "FAILED");
-#ifdef HAVE_ICAL_STATUS_DELETED
-       case ICAL_STATUS_DELETED:
+       case I_CAL_STATUS_DELETED:
                return g_str_equal (str, "DELETED");
-#endif
-       case ICAL_STATUS_X:
+       case I_CAL_STATUS_X:
                break;
        }
 
@@ -631,7 +661,7 @@ func_percent_complete (ESExp *esexp,
 {
        SearchContext *ctx = data;
        ESExpResult *result = NULL;
-       gint *percent;
+       gint percent;
 
        if (argc != 0) {
                e_sexp_fatal_error (
@@ -640,16 +670,10 @@ func_percent_complete (ESExp *esexp,
                return NULL;
        }
 
-       e_cal_component_get_percent (ctx->comp, &percent);
+       percent = e_cal_component_get_percent_complete (ctx->comp);
 
        result = e_sexp_result_new (esexp, ESEXP_RES_INT);
-
-       if (percent) {
-               result->value.number = *percent;
-               e_cal_component_free_percent (percent);
-       } else {
-               result->value.number = -1;
-       }
+       result->value.number = percent;
 
        return result;
 }
@@ -755,7 +779,7 @@ func_has_start (ESExp *esexp,
 {
        SearchContext *ctx = data;
        ESExpResult *result;
-       ECalComponentDateTime dt;
+       ECalComponentDateTime *dt;
 
        /* Check argument types */
 
@@ -766,10 +790,10 @@ func_has_start (ESExp *esexp,
                return NULL;
        }
 
-       e_cal_component_get_dtstart (ctx->comp, &dt);
+       dt = e_cal_component_get_dtstart (ctx->comp);
        result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
-       result->value.boolean = dt.value != NULL;
-       e_cal_component_free_datetime (&dt);
+       result->value.boolean = dt && e_cal_component_datetime_get_value (dt);
+       e_cal_component_datetime_free (dt);
 
        return result;
 }
@@ -820,7 +844,7 @@ func_has_alarms_in_range (ESExp *esexp,
 {
        time_t start, end;
        ESExpResult *result;
-       icaltimezone *default_zone;
+       ICalTimezone *default_zone;
        ECalComponentAlarms *alarms;
        ECalComponentAlarmAction omit[] = {-1};
        SearchContext *ctx = data;
@@ -853,7 +877,7 @@ func_has_alarms_in_range (ESExp *esexp,
        end = argv[1]->value.time;
 
        /* See if the object has alarms in the given time range */
-       default_zone = icaltimezone_get_utc_timezone ();
+       default_zone = i_cal_timezone_get_utc_timezone ();
 
        alarms = e_cal_util_generate_alarms_for_comp (
                ctx->comp, start, end,
@@ -927,7 +951,7 @@ func_has_categories (ESExp *esexp,
         * whether unfiled components are supposed to match.
         */
 
-       e_cal_component_get_categories_list (ctx->comp, &categories);
+       categories = e_cal_component_get_categories_list (ctx->comp);
        if (!categories) {
                result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
                result->value.boolean = unfiled;
@@ -942,7 +966,7 @@ func_has_categories (ESExp *esexp,
                result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
                result->value.boolean = FALSE;
 
-               e_cal_component_free_categories_list (categories);
+               g_slist_free_full (categories, g_free);
 
                return result;
        }
@@ -975,7 +999,7 @@ func_has_categories (ESExp *esexp,
                }
        }
 
-       e_cal_component_free_categories_list (categories);
+       g_slist_free_full (categories, g_free);
 
        result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
        result->value.boolean = matches;
@@ -1028,7 +1052,7 @@ func_is_completed (ESExp *esexp,
 {
        SearchContext *ctx = data;
        ESExpResult *result;
-       struct icaltimetype *t;
+       ICalTime *itt;
        gboolean complete = FALSE;
 
        /* Check argument types */
@@ -1040,16 +1064,16 @@ func_is_completed (ESExp *esexp,
                return NULL;
        }
 
-       e_cal_component_get_completed (ctx->comp, &t);
-       if (t) {
+       itt = e_cal_component_get_completed (ctx->comp);
+       if (itt) {
                complete = TRUE;
-               e_cal_component_free_icaltimetype (t);
+               g_object_unref (itt);
        } else {
-               icalproperty_status status = ICAL_STATUS_NONE;
+               ICalPropertyStatus status;
 
-               e_cal_component_get_status (ctx->comp, &status);
+               status = e_cal_component_get_status (ctx->comp);
 
-               complete = status == ICAL_STATUS_COMPLETED;
+               complete = status == I_CAL_STATUS_COMPLETED;
        }
 
        result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
@@ -1074,8 +1098,8 @@ func_completed_before (ESExp *esexp,
 {
        SearchContext *ctx = data;
        ESExpResult *result;
-       struct icaltimetype *tt;
-       icaltimezone *zone;
+       ICalTime *itt;
+       ICalTimezone *zone;
        gboolean retval = FALSE;
        time_t before_time, completed_time;
 
@@ -1095,13 +1119,14 @@ func_completed_before (ESExp *esexp,
                        "completed-before");
                return NULL;
        }
+
        before_time = argv[0]->value.time;
 
-       e_cal_component_get_completed (ctx->comp, &tt);
-       if (tt) {
+       itt = e_cal_component_get_completed (ctx->comp);
+       if (itt) {
                /* COMPLETED must be in UTC. */
-               zone = icaltimezone_get_utc_timezone ();
-               completed_time = icaltime_as_timet_with_zone (*tt, zone);
+               zone = i_cal_timezone_get_utc_timezone ();
+               completed_time = i_cal_time_as_timet_with_zone (itt, zone);
 
                /* We want to return TRUE if before_time is after
                 * completed_time. */
@@ -1109,7 +1134,7 @@ func_completed_before (ESExp *esexp,
                        retval = TRUE;
                }
 
-               e_cal_component_free_icaltimetype (tt);
+               g_object_unref (itt);
        }
 
        result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
@@ -1313,20 +1338,16 @@ e_cal_backend_sexp_match_object (ECalBackendSExp *sexp,
                                  ETimezoneCache *cache)
 {
        ECalComponent *comp;
-       icalcomponent *icalcomp;
        gboolean retval;
 
        g_return_val_if_fail (E_IS_CAL_BACKEND_SEXP (sexp), FALSE);
        g_return_val_if_fail (object != NULL, FALSE);
        g_return_val_if_fail (E_IS_TIMEZONE_CACHE (cache), FALSE);
 
-       icalcomp = icalcomponent_new_from_string ((gchar *) object);
-       if (!icalcomp)
+       comp = e_cal_component_new_from_string (object);
+       if (!comp)
                return FALSE;
 
-       comp = e_cal_component_new ();
-       e_cal_component_set_icalcomponent (comp, icalcomp);
-
        retval = e_cal_backend_sexp_match_comp (sexp, comp, cache);
 
        g_object_unref (comp);
diff --git a/src/calendar/libedata-cal/e-cal-backend-sync.c b/src/calendar/libedata-cal/e-cal-backend-sync.c
index 0ca680ea7..4bf602adf 100644
--- a/src/calendar/libedata-cal/e-cal-backend-sync.c
+++ b/src/calendar/libedata-cal/e-cal-backend-sync.c
@@ -32,7 +32,6 @@
 #include <libedataserver/libedataserver.h>
 
 #include "e-cal-backend-sync.h"
-#include <libical/icaltz-util.h>
 
 #define E_CAL_BACKEND_SYNC_GET_PRIVATE(obj) \
        (G_TYPE_INSTANCE_GET_PRIVATE \
@@ -120,7 +119,7 @@ e_cal_backend_sync_refresh (ECalBackendSync *backend,
  * @uid: UID of the object to get.
  * @rid: Recurrence ID of the specific instance to get, or NULL if getting the
  * master object.
- * @calobj: Placeholder for returned object.
+ * @calobj: (out) (transfer full): Placeholder for returned object.
  * @error: Out parameter for a #GError.
  *
  * Calls the get_object_sync method on the given backend.
@@ -160,7 +159,7 @@ e_cal_backend_sync_get_object (ECalBackendSync *backend,
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
  * @sexp: Search query.
- * @calobjs: Placeholder for list of returned objects.
+ * @calobjs: (out) (transfer full) (element-type utf8): Placeholder for list of returned objects.
  * @error: Out parameter for a #GError.
  *
  * Calls the get_object_list_sync method on the given backend.
@@ -198,10 +197,10 @@ e_cal_backend_sync_get_object_list (ECalBackendSync *backend,
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @users: List of users to get F/B info from.
+ * @users: (element-type utf8): List of users to get F/B info from.
  * @start: Time range start.
  * @end: Time range end.
- * @freebusyobjects: Placeholder for F/B information.
+ * @freebusyobjects: (out) (transfer full) (element-type utf8): Placeholder for F/B information.
  * @error: Out parameter for a #GError.
  *
  * Calls the get_free_busy_sync method on the given backend.
@@ -241,9 +240,10 @@ e_cal_backend_sync_get_free_busy (ECalBackendSync *backend,
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @calobjs: The objects to be added.
- * @uids: Placeholder for server-generated UIDs.
- * @new_components: (out) (transfer full): Placeholder for returned #ECalComponent objects.
+ * @calobjs: (element-type utf8): The objects to be added.
+ * @opflags: bit-or of #ECalOperationFlags
+ * @uids: (out) (transfer full) (element-type utf8): Placeholder for server-generated UIDs.
+ * @new_components: (out) (transfer full) (element-type ECalComponent): Placeholder for returned 
#ECalComponent objects.
  * @error: Out parameter for a #GError.
  *
  * Calls the create_objects_sync method on the given backend.
@@ -255,6 +255,7 @@ e_cal_backend_sync_create_objects (ECalBackendSync *backend,
                                    EDataCal *cal,
                                    GCancellable *cancellable,
                                    const GSList *calobjs,
+                                  guint32 opflags,
                                    GSList **uids,
                                    GSList **new_components,
                                    GError **error)
@@ -269,7 +270,7 @@ e_cal_backend_sync_create_objects (ECalBackendSync *backend,
        if (class->create_objects_sync != NULL) {
                class->create_objects_sync (
                        backend, cal, cancellable,
-                       calobjs, uids, new_components, error);
+                       calobjs, opflags, uids, new_components, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -284,12 +285,13 @@ e_cal_backend_sync_create_objects (ECalBackendSync *backend,
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @calobjs: Objects to be modified.
+ * @calobjs: (element-type utf8): Objects to be modified.
  * @mod: Type of modification to be done.
- * @old_components: (out) (transfer full): Placeholder for returning the old components as they were stored 
on the
- * backend.
- * @new_components: (out) (transfer full): Placeholder for returning the new components as they have been 
stored
- * on the backend.
+ * @opflags: bit-or of #ECalOperationFlags
+ * @old_components: (out) (transfer full) (element-type ECalComponent): Placeholder for
+ *    returning the old components as they were stored on the backend.
+ * @new_components: (out) (transfer full) (element-type ECalComponent): Placeholder for
+ *    returning the new components as they have been stored on the backend.
  * @error: Out parameter for a #GError.
  *
  * Calls the modify_objects_sync method on the given backend.
@@ -302,6 +304,7 @@ e_cal_backend_sync_modify_objects (ECalBackendSync *backend,
                                    GCancellable *cancellable,
                                    const GSList *calobjs,
                                    ECalObjModType mod,
+                                  guint32 opflags,
                                    GSList **old_components,
                                    GSList **new_components,
                                    GError **error)
@@ -316,7 +319,7 @@ e_cal_backend_sync_modify_objects (ECalBackendSync *backend,
        if (class->modify_objects_sync != NULL) {
                class->modify_objects_sync (
                        backend, cal, cancellable,
-                       calobjs, mod, old_components, new_components, error);
+                       calobjs, mod, opflags, old_components, new_components, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -331,13 +334,14 @@ e_cal_backend_sync_modify_objects (ECalBackendSync *backend,
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @ids: List of #ECalComponentId objects identifying the objects to remove.
+ * @ids: (element-type ECalComponentId): List of #ECalComponentId objects identifying the objects to remove.
  * @mod: Type of removal.
- * @old_components: (out) (transfer full): Placeholder for returning the old components as they were stored 
on the
- * backend.
- * @new_components: (out) (transfer full): Placeholder for returning the new components as they have been 
stored
- * on the backend (when removing individual instances). If removing whole objects,
- * they will be set to %NULL.
+ * @opflags: bit-or of #ECalOperationFlags
+ * @old_components: (out) (transfer full) (element-type ECalComponent): Placeholder for returning the old
+ *    components as they were stored on the backend.
+ * @new_components: (out) (transfer full) (element-type ECalComponent): Placeholder for returning the new
+ *    components as they have been stored on the backend (when removing individual instances). If removing
+ *    whole objects, they will be set to %NULL.
  * @error: Out parameter for a #GError.
  *
  * Calls the remove_objects_sync method on the given backend.
@@ -350,6 +354,7 @@ e_cal_backend_sync_remove_objects (ECalBackendSync *backend,
                                    GCancellable *cancellable,
                                    const GSList *ids,
                                    ECalObjModType mod,
+                                  guint32 opflags,
                                    GSList **old_components,
                                    GSList **new_components,
                                    GError **error)
@@ -364,7 +369,7 @@ e_cal_backend_sync_remove_objects (ECalBackendSync *backend,
        if (class->remove_objects_sync != NULL) {
                class->remove_objects_sync (
                        backend, cal, cancellable,
-                       ids, mod, old_components, new_components, error);
+                       ids, mod, opflags, old_components, new_components, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -378,6 +383,7 @@ e_cal_backend_sync_remove_objects (ECalBackendSync *backend,
  * e_cal_backend_sync_receive_objects:
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: a #GCancellable for the operation
  * @calobj: iCalendar object to receive.
  * @error: Out parameter for a #GError.
@@ -389,6 +395,7 @@ e_cal_backend_sync_receive_objects (ECalBackendSync *backend,
                                     EDataCal *cal,
                                     GCancellable *cancellable,
                                     const gchar *calobj,
+                                   guint32 opflags,
                                     GError **error)
 {
        ECalBackendSyncClass *class;
@@ -400,7 +407,7 @@ e_cal_backend_sync_receive_objects (ECalBackendSync *backend,
 
        if (class->receive_objects_sync != NULL) {
                class->receive_objects_sync (
-                       backend, cal, cancellable, calobj, error);
+                       backend, cal, cancellable, calobj, opflags, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -416,8 +423,9 @@ e_cal_backend_sync_receive_objects (ECalBackendSync *backend,
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
  * @calobj: The iCalendar object to send.
- * @users: List of users to send notifications to.
- * @modified_calobj: Placeholder for the iCalendar object after being modified.
+ * @opflags: bit-or of #ECalOperationFlags
+ * @users: (element-type utf8): List of users to send notifications to.
+ * @modified_calobj: (out) (transfer full): Placeholder for the iCalendar object after being modified.
  * @error: Out parameter for a #GError.
  *
  * Calls the send_objects_sync method on the given backend.
@@ -427,6 +435,7 @@ e_cal_backend_sync_send_objects (ECalBackendSync *backend,
                                  EDataCal *cal,
                                  GCancellable *cancellable,
                                  const gchar *calobj,
+                                guint32 opflags,
                                  GSList **users,
                                  gchar **modified_calobj,
                                  GError **error)
@@ -441,7 +450,7 @@ e_cal_backend_sync_send_objects (ECalBackendSync *backend,
        if (class->send_objects_sync != NULL) {
                class->send_objects_sync (
                        backend, cal, cancellable,
-                       calobj, users, modified_calobj, error);
+                       calobj, opflags, users, modified_calobj, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -458,7 +467,7 @@ e_cal_backend_sync_send_objects (ECalBackendSync *backend,
  * @cancellable: a #GCancellable for the operation
  * @uid: Unique id of the calendar object.
  * @rid: Recurrence id of the calendar object.
- * @attachments: Placeholder for list of returned attachment uris.
+ * @attachments: (element-type utf8): Placeholder for list of returned attachment uris.
  * @error: Out parameter for a #GError.
  *
  * Calls the get_attachment_uris_sync method on the given backend.
@@ -503,6 +512,7 @@ e_cal_backend_sync_get_attachment_uris (ECalBackendSync *backend,
  * @uid: Unique id of the calendar object.
  * @rid: Recurrence id of the calendar object.
  * @auid: Alarm ID to remove.
+ * @opflags: bit-or of #ECalOperationFlags
  * @error: Out parameter for a #GError.
  *
  * Calls the discard_alarm_sync method on the given backend.
@@ -514,6 +524,7 @@ e_cal_backend_sync_discard_alarm (ECalBackendSync *backend,
                                   const gchar *uid,
                                   const gchar *rid,
                                   const gchar *auid,
+                                 guint32 opflags,
                                   GError **error)
 {
        ECalBackendSyncClass *class;
@@ -528,7 +539,7 @@ e_cal_backend_sync_discard_alarm (ECalBackendSync *backend,
        if (class->discard_alarm_sync != NULL) {
                class->discard_alarm_sync (
                        backend, cal, cancellable,
-                       uid, rid, auid, error);
+                       uid, rid, auid, opflags, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -577,24 +588,25 @@ e_cal_backend_sync_get_timezone (ECalBackendSync *backend,
        }
 
        if (tzobject && !*tzobject) {
-               icaltimezone *zone = NULL;
+               ICalTimezone *zone;
 
-               zone = e_timezone_cache_get_timezone (
-                       E_TIMEZONE_CACHE (backend), tzid);
+               zone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (backend), tzid);
 
                if (!zone) {
                        if (error && !*error)
-                               g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+                               g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL));
                } else {
-                       icalcomponent *icalcomp;
+                       ICalComponent *icomp;
 
-                       icalcomp = icaltimezone_get_component (zone);
+                       icomp = i_cal_timezone_get_component (zone);
 
-                       if (!icalcomp) {
+                       if (!icomp) {
                                if (error && !*error)
-                                       g_propagate_error (error, e_data_cal_create_error (InvalidObject, 
NULL));
+                                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, NULL));
                        } else {
-                               *tzobject = icalcomponent_as_ical_string_r (icalcomp);
+                               *tzobject = i_cal_component_as_ical_string_r (icomp);
+
+                               g_object_unref (icomp);
                        }
                }
        }
@@ -740,13 +752,14 @@ cal_backend_create_objects (ECalBackend *backend,
                             EDataCal *cal,
                             guint32 opid,
                             GCancellable *cancellable,
-                            const GSList *calobjs)
+                            const GSList *calobjs,
+                           guint32 opflags)
 {
        GError *error = NULL;
        GSList *uids = NULL;
        GSList *new_components = NULL;
 
-       e_cal_backend_sync_create_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobjs, &uids, 
&new_components, &error);
+       e_cal_backend_sync_create_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobjs, opflags, 
&uids, &new_components, &error);
 
        if (!new_components)
                new_components = ecalcomponent_slist_from_strings (calobjs);
@@ -763,12 +776,13 @@ cal_backend_modify_objects (ECalBackend *backend,
                             guint32 opid,
                             GCancellable *cancellable,
                             const GSList *calobjs,
-                            ECalObjModType mod)
+                            ECalObjModType mod,
+                           guint32 opflags)
 {
        GError *error = NULL;
        GSList *old_components = NULL, *new_components = NULL;
 
-       e_cal_backend_sync_modify_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobjs, mod, 
&old_components, &new_components, &error);
+       e_cal_backend_sync_modify_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobjs, mod, 
opflags, &old_components, &new_components, &error);
 
        if (!old_components)
                old_components = ecalcomponent_slist_from_strings (calobjs);
@@ -785,12 +799,13 @@ cal_backend_remove_objects (ECalBackend *backend,
                             guint32 opid,
                             GCancellable *cancellable,
                             const GSList *ids,
-                            ECalObjModType mod)
+                            ECalObjModType mod,
+                           guint32 opflags)
 {
        GError *error = NULL;
        GSList *old_components = NULL, *new_components = NULL;
 
-       e_cal_backend_sync_remove_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, ids, mod, 
&old_components, &new_components, &error);
+       e_cal_backend_sync_remove_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, ids, mod, opflags, 
&old_components, &new_components, &error);
 
        e_data_cal_respond_remove_objects (cal, opid, error, ids, old_components, new_components);
 
@@ -803,11 +818,12 @@ cal_backend_receive_objects (ECalBackend *backend,
                              EDataCal *cal,
                              guint32 opid,
                              GCancellable *cancellable,
-                             const gchar *calobj)
+                             const gchar *calobj,
+                            guint32 opflags)
 {
        GError *error = NULL;
 
-       e_cal_backend_sync_receive_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, &error);
+       e_cal_backend_sync_receive_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, opflags, 
&error);
 
        e_data_cal_respond_receive_objects (cal, opid, error);
 }
@@ -817,13 +833,14 @@ cal_backend_send_objects (ECalBackend *backend,
                           EDataCal *cal,
                           guint32 opid,
                           GCancellable *cancellable,
-                          const gchar *calobj)
+                          const gchar *calobj,
+                         guint32 opflags)
 {
        GError *error = NULL;
        GSList *users = NULL;
        gchar *modified_calobj = NULL;
 
-       e_cal_backend_sync_send_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, &users, 
&modified_calobj, &error);
+       e_cal_backend_sync_send_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, opflags, 
&users, &modified_calobj, &error);
 
        e_data_cal_respond_send_objects (cal, opid, error, users, modified_calobj ? modified_calobj : calobj);
 
@@ -858,11 +875,12 @@ cal_backend_discard_alarm (ECalBackend *backend,
                            GCancellable *cancellable,
                            const gchar *uid,
                            const gchar *rid,
-                           const gchar *auid)
+                           const gchar *auid,
+                          guint32 opflags)
 {
        GError *error = NULL;
 
-       e_cal_backend_sync_discard_alarm (E_CAL_BACKEND_SYNC (backend), cal, cancellable, uid, rid, auid, 
&error);
+       e_cal_backend_sync_discard_alarm (E_CAL_BACKEND_SYNC (backend), cal, cancellable, uid, rid, auid, 
opflags, &error);
 
        e_data_cal_respond_discard_alarm (cal, opid, error);
 }
@@ -889,38 +907,33 @@ cal_backend_get_timezone (ECalBackend *backend,
                }
 
                if (slashes == 1) {
-                       icalcomponent *icalcomp = NULL, *free_comp = NULL;
-
-                       icaltimezone *zone = icaltimezone_get_builtin_timezone (tzid);
-                       if (!zone) {
-                               /* Try fetching the timezone from zone
-                                * directory. There are some timezones like
-                                * MST, US/Pacific etc. which do not appear
-                                * in zone.tab, so they will not be available
-                                * in the libical builtin timezone */
-                               icalcomp = free_comp = icaltzutil_fetch_timezone (tzid);
-                       }
+                       ICalComponent *icomp = NULL;
+                       ICalTimezone *zone;
+
+                       zone = i_cal_timezone_get_builtin_timezone (tzid);
 
                        if (zone)
-                               icalcomp = icaltimezone_get_component (zone);
+                               icomp = i_cal_timezone_get_component (zone);
 
-                       if (icalcomp) {
-                               icalcomponent *clone = icalcomponent_new_clone (icalcomp);
-                               icalproperty *prop;
+                       if (icomp) {
+                               ICalComponent *clone = i_cal_component_new_clone (icomp);
+                               ICalProperty *prop;
 
-                               prop = icalcomponent_get_first_property (clone, ICAL_TZID_PROPERTY);
+                               prop = i_cal_component_get_first_property (clone, I_CAL_TZID_PROPERTY);
                                if (prop) {
                                        /* change tzid to our, because the component has the buildin tzid */
-                                       icalproperty_set_tzid (prop, tzid);
+                                       i_cal_property_set_tzid (prop, tzid);
+
+                                       object = i_cal_component_as_ical_string_r (clone);
 
-                                       object = icalcomponent_as_ical_string_r (clone);
                                        g_clear_error (&error);
+                                       g_object_unref (prop);
                                }
-                               icalcomponent_free (clone);
+
+                               g_clear_object (&clone);
                        }
 
-                       if (free_comp)
-                               icalcomponent_free (free_comp);
+                       g_clear_object (&icomp);
                }
 
                /* also cache this timezone to backend */
diff --git a/src/calendar/libedata-cal/e-cal-backend-sync.h b/src/calendar/libedata-cal/e-cal-backend-sync.h
index 5dc6ae32c..b0f8b85e1 100644
--- a/src/calendar/libedata-cal/e-cal-backend-sync.h
+++ b/src/calendar/libedata-cal/e-cal-backend-sync.h
@@ -64,7 +64,6 @@ struct _ECalBackendSync {
  * ECalBackendSyncClass:
  * @open_sync: Open the calendar
  * @refresh_sync: Refresh the calendar
- * @set_backend_property_sync: Deprecated: Set backend property
  * @get_object_sync: Get single object
  * @get_object_list_sync: Get multiple objects at once
  * @get_free_busy_sync: Get Free/Busy objects
@@ -98,15 +97,6 @@ struct _ECalBackendSyncClass {
                                                 GCancellable *cancellable,
                                                 GError **error);
 
-       /* This method is deprecated. */
-       gboolean        (*set_backend_property_sync)
-                                               (ECalBackendSync *backend,
-                                                EDataCal *cal,
-                                                GCancellable *cancellable,
-                                                const gchar *prop_name,
-                                                const gchar *prop_value,
-                                                GError **error);
-
        void            (*get_object_sync)      (ECalBackendSync *backend,
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
@@ -132,6 +122,7 @@ struct _ECalBackendSyncClass {
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
                                                 const GSList *calobjs,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **uids,
                                                 GSList **new_components,
                                                 GError **error);
@@ -140,6 +131,7 @@ struct _ECalBackendSyncClass {
                                                 GCancellable *cancellable,
                                                 const GSList *calobjs,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **old_components,
                                                 GSList **new_components,
                                                 GError **error);
@@ -148,6 +140,7 @@ struct _ECalBackendSyncClass {
                                                 GCancellable *cancellable,
                                                 const GSList *ids,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **old_components,
                                                 GSList **new_components,
                                                 GError **error);
@@ -155,11 +148,13 @@ struct _ECalBackendSyncClass {
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GError **error);
        void            (*send_objects_sync)    (ECalBackendSync *backend,
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **users,
                                                 gchar **modified_calobj,
                                                 GError **error);
@@ -177,6 +172,7 @@ struct _ECalBackendSyncClass {
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 const gchar *auid,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GError **error);
        void            (*get_timezone_sync)    (ECalBackendSync *backend,
                                                 EDataCal *cal,
@@ -189,6 +185,9 @@ struct _ECalBackendSyncClass {
                                                 GCancellable *cancellable,
                                                 const gchar *tzobject,
                                                 GError **error);
+
+       /* Padding for future expansion */
+       gpointer reserved_padding[20];
 };
 
 GType          e_cal_backend_sync_get_type     (void) G_GNUC_CONST;
@@ -229,6 +228,7 @@ void                e_cal_backend_sync_create_objects
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
                                                 const GSList *calobjs,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **uids,
                                                 GSList **new_components,
                                                 GError **error);
@@ -238,6 +238,7 @@ void                e_cal_backend_sync_modify_objects
                                                 GCancellable *cancellable,
                                                 const GSList *calobjs,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **old_components,
                                                 GSList **new_components,
                                                 GError **error);
@@ -247,6 +248,7 @@ void                e_cal_backend_sync_remove_objects
                                                 GCancellable *cancellable,
                                                 const GSList *ids,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **old_components,
                                                 GSList **new_components,
                                                 GError **error);
@@ -255,11 +257,13 @@ void              e_cal_backend_sync_receive_objects
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GError **error);
 void           e_cal_backend_sync_send_objects (ECalBackendSync *backend,
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GSList **users,
                                                 gchar **modified_calobj,
                                                 GError **error);
@@ -278,6 +282,7 @@ void                e_cal_backend_sync_discard_alarm
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 const gchar *auid,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GError **error);
 void           e_cal_backend_sync_get_timezone (ECalBackendSync *backend,
                                                 EDataCal *cal,
diff --git a/src/calendar/libedata-cal/e-cal-backend-util.c b/src/calendar/libedata-cal/e-cal-backend-util.c
index 7bea2387e..078835461 100644
--- a/src/calendar/libedata-cal/e-cal-backend-util.c
+++ b/src/calendar/libedata-cal/e-cal-backend-util.c
@@ -189,28 +189,28 @@ is_attendee_declined (GSList *declined_attendees,
  **/
 gboolean
 e_cal_backend_user_declined (ESourceRegistry *registry,
-                             icalcomponent *icalcomp)
+                            ICalComponent *icalcomp)
 {
        GList *list, *iter;
        GSList *declined_attendees = NULL;
        gboolean declined = FALSE;
-       icalproperty *prop;
-       icalparameter *param;
+       ICalProperty *prop;
+       ICalParameter *param;
 
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
        g_return_val_if_fail (icalcomp != NULL, FALSE);
 
        /* First test whether there is any declined attendee at all and remember his/her address */
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icalcomp, I_CAL_ATTENDEE_PROPERTY);
             prop != NULL;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
-               param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, 
I_CAL_ATTENDEE_PROPERTY)) {
+               param = i_cal_property_get_first_parameter (prop, I_CAL_PARTSTAT_PARAMETER);
 
-               if (param && icalparameter_get_partstat (param) == ICAL_PARTSTAT_DECLINED) {
+               if (param && i_cal_parameter_get_partstat (param) == I_CAL_PARTSTAT_DECLINED) {
                        gchar *attendee;
                        gchar *address;
 
-                       attendee = icalproperty_get_value_as_string_r (prop);
+                       attendee = i_cal_property_get_value_as_string_r (prop);
                        if (attendee) {
                                if (!g_ascii_strncasecmp (attendee, "mailto:";, 7))
                                        address = g_strdup (attendee + 7);
@@ -227,6 +227,8 @@ e_cal_backend_user_declined (ESourceRegistry *registry,
                                g_free (attendee);
                        }
                }
+
+               g_clear_object (&param);
        }
 
        if (!declined_attendees)
diff --git a/src/calendar/libedata-cal/e-cal-backend-util.h b/src/calendar/libedata-cal/e-cal-backend-util.h
index 730b70426..ae9f2ad2c 100644
--- a/src/calendar/libedata-cal/e-cal-backend-util.h
+++ b/src/calendar/libedata-cal/e-cal-backend-util.h
@@ -44,7 +44,7 @@ gboolean      e_cal_backend_mail_account_is_valid
                                                 const gchar *user,
                                                 gchar **name);
 gboolean       e_cal_backend_user_declined     (ESourceRegistry *registry,
-                                                 icalcomponent *icalcomp);
+                                                 ICalComponent *icalcomp);
 
 G_END_DECLS
 
diff --git a/src/calendar/libedata-cal/e-cal-backend.c b/src/calendar/libedata-cal/e-cal-backend.c
index 20b47d399..01bda3efc 100644
--- a/src/calendar/libedata-cal/e-cal-backend.c
+++ b/src/calendar/libedata-cal/e-cal-backend.c
@@ -29,7 +29,6 @@
 #include <glib/gi18n-lib.h>
 
 #include "e-cal-backend.h"
-#include "e-cal-backend-cache.h"
 
 #define E_CAL_BACKEND_GET_PRIVATE(obj) \
        (G_TYPE_INSTANCE_GET_PRIVATE \
@@ -46,7 +45,7 @@ struct _ECalBackendPrivate {
        gboolean opened;
 
        /* The kind of components for this backend */
-       icalcomponent_kind kind;
+       ICalComponentKind kind;
 
        GMutex views_mutex;
        GList *views;
@@ -85,6 +84,7 @@ struct _AsyncContext {
        time_t end;
        GSList *compid_list;
        GSList *string_list;
+       guint32 opflags;
 
        /* Outputs */
        GQueue result_queue;
@@ -112,7 +112,7 @@ struct _DispatchNode {
 
 struct _SignalClosure {
        GWeakRef backend;
-       icaltimezone *cached_zone;
+       ICalTimezone *cached_zone;
 };
 
 enum {
@@ -159,7 +159,7 @@ async_context_free (AsyncContext *async_context)
 
        g_slist_free_full (
                async_context->compid_list,
-               (GDestroyNotify) e_cal_component_free_id);
+               (GDestroyNotify) e_cal_component_id_free);
 
        g_slist_free_full (
                async_context->string_list,
@@ -195,19 +195,11 @@ static void
 signal_closure_free (SignalClosure *signal_closure)
 {
        g_weak_ref_clear (&signal_closure->backend);
-
-       /* The icaltimezone is cached in ECalBackend's internal
-        * "zone_cache" hash table and must not be freed here. */
+       g_clear_object (&signal_closure->cached_zone);
 
        g_slice_free (SignalClosure, signal_closure);
 }
 
-static void
-cal_backend_free_zone (icaltimezone *zone)
-{
-       icaltimezone_free (zone, 1);
-}
-
 static void
 cal_backend_push_operation (ECalBackend *backend,
                             GSimpleAsyncResult *simple,
@@ -390,7 +382,7 @@ static void
 cal_backend_set_default_cache_dir (ECalBackend *backend)
 {
        ESource *source;
-       icalcomponent_kind kind;
+       ICalComponentKind kind;
        const gchar *component_type;
        const gchar *user_cache_dir;
        const gchar *uid;
@@ -405,13 +397,13 @@ cal_backend_set_default_cache_dir (ECalBackend *backend)
        g_return_if_fail (uid != NULL);
 
        switch (kind) {
-               case ICAL_VEVENT_COMPONENT:
+               case I_CAL_VEVENT_COMPONENT:
                        component_type = "calendar";
                        break;
-               case ICAL_VTODO_COMPONENT:
+               case I_CAL_VTODO_COMPONENT:
                        component_type = "tasks";
                        break;
-               case ICAL_VJOURNAL_COMPONENT:
+               case I_CAL_VJOURNAL_COMPONENT:
                        component_type = "memos";
                        break;
                default:
@@ -547,7 +539,7 @@ cal_backend_emit_timezone_added_idle_cb (gpointer user_data)
 
 static void
 cal_backend_set_kind (ECalBackend *backend,
-                      icalcomponent_kind kind)
+                     ICalComponentKind kind)
 {
        backend->priv->kind = kind;
 }
@@ -797,7 +789,7 @@ _e_cal_backend_remove_cached_timezones (ECalBackend *cal_backend)
 
 static void
 cal_backend_add_cached_timezone (ETimezoneCache *cache,
-                                 icaltimezone *zone)
+                                ICalTimezone *zone)
 {
        ECalBackendPrivate *priv;
        const gchar *tzid;
@@ -806,38 +798,34 @@ cal_backend_add_cached_timezone (ETimezoneCache *cache,
 
        /* XXX Apparently this function can sometimes return NULL.
         *     I'm not sure when or why that happens, but we can't
-        *     cache the icaltimezone if it has no tzid string. */
-       tzid = icaltimezone_get_tzid (zone);
+        *     cache the ICalTimezone if it has no tzid string. */
+       tzid = i_cal_timezone_get_tzid (zone);
        if (tzid == NULL)
                return;
 
        g_mutex_lock (&priv->zone_cache_lock);
 
        /* Avoid replacing an existing cache entry.  We don't want to
-        * invalidate any icaltimezone pointers that may have already
+        * invalidate any ICalTimezone pointers that may have already
         * been returned through e_timezone_cache_get_timezone(). */
        if (!g_hash_table_contains (priv->zone_cache, tzid)) {
                GSource *idle_source;
                GMainContext *main_context;
                SignalClosure *signal_closure;
-               icalcomponent *icalcomp;
-               icaltimezone *cached_zone;
+               ICalTimezone *cached_zone;
 
-               cached_zone = icaltimezone_new ();
-               icalcomp = icaltimezone_get_component (zone);
-               icalcomp = icalcomponent_new_clone (icalcomp);
-               icaltimezone_set_component (cached_zone, icalcomp);
+               cached_zone = e_cal_util_copy_timezone (zone);
 
                g_hash_table_insert (
                        priv->zone_cache,
                        g_strdup (tzid), cached_zone);
 
                /* The closure's backend reference will keep the
-                * internally cached icaltimezone alive for the
+                * internally cached ICalTimezone alive for the
                 * duration of the idle callback. */
                signal_closure = g_slice_new0 (SignalClosure);
                g_weak_ref_init (&signal_closure->backend, cache);
-               signal_closure->cached_zone = cached_zone;
+               signal_closure->cached_zone = g_object_ref (cached_zone);
 
                main_context = e_backend_ref_main_context (E_BACKEND (cache));
 
@@ -856,21 +844,21 @@ cal_backend_add_cached_timezone (ETimezoneCache *cache,
        g_mutex_unlock (&priv->zone_cache_lock);
 }
 
-static icaltimezone *
+static ICalTimezone *
 cal_backend_get_cached_timezone (ETimezoneCache *cache,
                                  const gchar *tzid)
 {
        ECalBackendPrivate *priv;
-       icaltimezone *zone = NULL;
-       icaltimezone *builtin_zone = NULL;
-       icalcomponent *icalcomp;
-       icalproperty *prop;
+       ICalTimezone *zone = NULL;
+       ICalTimezone *builtin_zone = NULL;
+       ICalComponent *icomp, *clone;
+       ICalProperty *prop;
        const gchar *builtin_tzid;
 
        priv = E_CAL_BACKEND_GET_PRIVATE (cache);
 
        if (g_str_equal (tzid, "UTC"))
-               return icaltimezone_get_utc_timezone ();
+               return i_cal_timezone_get_utc_timezone ();
 
        g_mutex_lock (&priv->zone_cache_lock);
 
@@ -883,53 +871,46 @@ cal_backend_get_cached_timezone (ETimezoneCache *cache,
        /* Try to replace the original time zone with a more complete
         * and/or potentially updated built-in time zone.  Note this also
         * applies to TZIDs which match built-in time zones exactly: they
-        * are extracted via icaltimezone_get_builtin_timezone_from_tzid(). */
+        * are extracted via i_cal_timezone_get_builtin_timezone_from_tzid(). */
 
        builtin_tzid = e_cal_match_tzid (tzid);
 
        if (builtin_tzid != NULL)
-               builtin_zone = icaltimezone_get_builtin_timezone_from_tzid (
-                       builtin_tzid);
+               builtin_zone = i_cal_timezone_get_builtin_timezone_from_tzid (builtin_tzid);
 
        if (builtin_zone == NULL)
                goto exit;
 
        /* Use the built-in time zone *and* rename it.  Likely the caller
         * is asking for a specific TZID because it has an event with such
-        * a TZID.  Returning an icaltimezone with a different TZID would
+        * a TZID.  Returning an ICalTimezone with a different TZID would
         * lead to broken VCALENDARs in the caller. */
 
-       icalcomp = icaltimezone_get_component (builtin_zone);
-       icalcomp = icalcomponent_new_clone (icalcomp);
-
-       prop = icalcomponent_get_first_property (
-               icalcomp, ICAL_ANY_PROPERTY);
-
-       while (prop != NULL) {
-               if (icalproperty_isa (prop) == ICAL_TZID_PROPERTY) {
-                       icalproperty_set_value_from_string (prop, tzid, "NO");
+       icomp = i_cal_timezone_get_component (builtin_zone);
+       clone = i_cal_component_new_clone (icomp);
+       g_object_unref (icomp);
+       icomp = clone;
+
+       for (prop = i_cal_component_get_first_property (icomp, I_CAL_ANY_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icomp, I_CAL_ANY_PROPERTY)) {
+               if (i_cal_property_isa (prop) == I_CAL_TZID_PROPERTY) {
+                       i_cal_property_set_value_from_string (prop, tzid, "NO");
+                       g_object_unref (prop);
                        break;
                }
-
-               prop = icalcomponent_get_next_property (
-                       icalcomp, ICAL_ANY_PROPERTY);
        }
 
-       if (icalcomp != NULL) {
-               zone = icaltimezone_new ();
-               if (icaltimezone_set_component (zone, icalcomp)) {
-                       tzid = icaltimezone_get_tzid (zone);
-                       g_hash_table_insert (
-                               priv->zone_cache,
-                               g_strdup (tzid), zone);
-               } else {
-                       icalcomponent_free (icalcomp);
-                       icaltimezone_free (zone, 1);
-                       zone = NULL;
-               }
+       zone = i_cal_timezone_new ();
+       if (i_cal_timezone_set_component (zone, icomp)) {
+               tzid = i_cal_timezone_get_tzid (zone);
+               g_hash_table_insert (priv->zone_cache, g_strdup (tzid), zone);
+       } else {
+               g_clear_object (&zone);
        }
+       g_clear_object (&icomp);
 
-exit:
+ exit:
        g_mutex_unlock (&priv->zone_cache_lock);
 
        return zone;
@@ -1090,7 +1071,7 @@ e_cal_backend_init (ECalBackend *backend)
                (GHashFunc) g_str_hash,
                (GEqualFunc) g_str_equal,
                (GDestroyNotify) g_free,
-               (GDestroyNotify) cal_backend_free_zone);
+               (GDestroyNotify) g_object_unref);
 
        backend->priv = E_CAL_BACKEND_GET_PRIVATE (backend);
 
@@ -1117,7 +1098,7 @@ e_cal_backend_init (ECalBackend *backend)
  *
  * Returns: The kind of components for this backend.
  */
-icalcomponent_kind
+ICalComponentKind
 e_cal_backend_get_kind (ECalBackend *backend)
 {
        g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
@@ -1138,7 +1119,7 @@ e_cal_backend_get_kind (ECalBackend *backend)
  * The returned #EDataCal is referenced for thread-safety and must be
  * unreferenced with g_object_unref() when finished with it.
  *
- * Returns: an #EDataCal, or %NULL
+ * Returns: (transfer full): an #EDataCal, or %NULL
  *
  * Since: 3.10
  **/
@@ -1165,6 +1146,8 @@ e_cal_backend_ref_data_cal (ECalBackend *backend)
  *
  * An #EDataCal should be set only once after @backend is first created.
  *
+ * The @backend adds its own reference on the @data_cal.
+ *
  * Since: 3.10
  **/
 void
@@ -1191,7 +1174,7 @@ e_cal_backend_set_data_cal (ECalBackend *backend,
  * The returned #GProxyResolver is referenced for thread-safety and must
  * be unreferenced with g_object_unref() when finished with it.
  *
- * Returns: a #GProxyResolver, or %NULL
+ * Returns: (transfer full) (nullable): a #GProxyResolver, or %NULL
  *
  * Since: 3.12
  **/
@@ -1218,7 +1201,7 @@ e_cal_backend_ref_proxy_resolver (ECalBackend *backend)
  *
  * Returns the data source registry to which #EBackend:source belongs.
  *
- * Returns: an #ESourceRegistry
+ * Returns: (transfer none): an #ESourceRegistry
  *
  * Since: 3.6
  **/
@@ -1475,7 +1458,7 @@ e_cal_backend_add_view (ECalBackend *backend,
 }
 
 /**
- * e_cal_backend_remove_view
+ * e_cal_backend_remove_view:
  * @backend: an #ECalBackend
  * @view: An #EDataCalView object, previously added with @ref e_cal_backend_add_view.
  *
@@ -1529,7 +1512,7 @@ e_cal_backend_remove_view (ECalBackend *backend,
  *   g_list_free_full (list, g_object_unref);
  * ]|
  *
- * Returns: (element-type EDataCalView): a list of cal views
+ * Returns: (element-type EDataCalView) (transfer full): a list of cal views
  *
  * Since: 3.8
  **/
@@ -2075,7 +2058,7 @@ e_cal_backend_get_object_finish (ECalBackend *backend,
  * e_cal_backend_get_object_list_sync:
  * @backend: an #ECalBackend
  * @query: a search query in S-expression format
- * @out_objects: a #GQueue in which to deposit results
+ * @out_objects: (element-type utf8): a #GQueue in which to deposit results
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -2219,7 +2202,7 @@ e_cal_backend_get_object_list (ECalBackend *backend,
  * e_cal_backend_get_object_list_finish:
  * @backend: an #ECalBackend
  * @result: a #GAsyncResult
- * @out_objects: a #GQueue in which to deposit results
+ * @out_objects: (element-type utf8): a #GQueue in which to deposit results
  * @error: return location for a #GError, or %NULL
  *
  * Finishes the operation started with e_cal_backend_get_object_list().
@@ -2267,8 +2250,8 @@ e_cal_backend_get_object_list_finish (ECalBackend *backend,
  * @backend: an #ECalBackend
  * @start: start time
  * @end: end time
- * @users: a %NULL-terminated array of user strings
- * @out_freebusy: iCalendar strings with overall returned Free/Busy data
+ * @users: (array zero-terminated=1): a %NULL-terminated array of user strings
+ * @out_freebusy: (element-type utf8): iCalendar strings with overall returned Free/Busy data
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -2367,7 +2350,7 @@ cal_backend_get_free_busy_thread (GSimpleAsyncResult *simple,
  * @backend: an #ECalBackend
  * @start: start time
  * @end: end time
- * @users: a %NULL-terminated array of user strings
+ * @users: (array zero-terminated=1): a %NULL-terminated array of user strings
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -2430,7 +2413,7 @@ e_cal_backend_get_free_busy (ECalBackend *backend,
  * e_cal_backend_get_free_busy_finish:
  * @backend: an #ECalBackend
  * @result: a #GAsyncResult
- * @out_freebusy: iCalendar strings with overall returned Free/Busy data
+ * @out_freebusy: (element-type utf8): iCalendar strings with overall returned Free/Busy data
  * @error: return location for a #GError, or %NULL
  *
  * Finishes the operation started with e_cal_backend_get_free_busy().
@@ -2490,6 +2473,7 @@ e_cal_backend_get_free_busy_finish (ECalBackend *backend,
  * e_cal_backend_create_objects_sync:
  * @backend: an #ECalBackend
  * @calobjs: a %NULL-terminated array of iCalendar strings
+ * @opflags: bit-or of #ECalOperationFlags
  * @out_uids: a #GQueue in which to deposit results
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -2508,6 +2492,7 @@ e_cal_backend_get_free_busy_finish (ECalBackend *backend,
 gboolean
 e_cal_backend_create_objects_sync (ECalBackend *backend,
                                    const gchar * const *calobjs,
+                                  guint32 opflags,
                                    GQueue *out_uids,
                                    GCancellable *cancellable,
                                    GError **error)
@@ -2522,7 +2507,7 @@ e_cal_backend_create_objects_sync (ECalBackend *backend,
        closure = e_async_closure_new ();
 
        e_cal_backend_create_objects (
-               backend, calobjs, cancellable,
+               backend, calobjs, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -2579,7 +2564,7 @@ cal_backend_create_objects_thread (GSimpleAsyncResult *simple,
 
                class->create_objects (
                        backend, data_cal, opid, cancellable,
-                       async_context->string_list);
+                       async_context->string_list, async_context->opflags);
        }
 
        g_object_unref (data_cal);
@@ -2589,6 +2574,7 @@ cal_backend_create_objects_thread (GSimpleAsyncResult *simple,
  * e_cal_backend_create_objects:
  * @backend: an #ECalBackend
  * @calobjs: a %NULL-terminated array of iCalendar strings
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisifed
  * @user_data: data to pass to the callback function
@@ -2604,6 +2590,7 @@ cal_backend_create_objects_thread (GSimpleAsyncResult *simple,
 void
 e_cal_backend_create_objects (ECalBackend *backend,
                               const gchar * const *calobjs,
+                             guint32 opflags,
                               GCancellable *cancellable,
                               GAsyncReadyCallback callback,
                               gpointer user_data)
@@ -2621,6 +2608,7 @@ e_cal_backend_create_objects (ECalBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->string_list = g_slist_reverse (list);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (backend), callback, user_data,
@@ -2712,10 +2700,11 @@ e_cal_backend_create_objects_finish (ECalBackend *backend,
 }
 
 /**
- * e_cal_backend_modify_objects:
+ * e_cal_backend_modify_objects_sync:
  * @backend: an #ECalBackend
  * @calobjs: a %NULL-terminated array of iCalendar strings
  * @mod: modification type for recurrences
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -2731,6 +2720,7 @@ gboolean
 e_cal_backend_modify_objects_sync (ECalBackend *backend,
                                    const gchar * const *calobjs,
                                    ECalObjModType mod,
+                                  guint32 opflags,
                                    GCancellable *cancellable,
                                    GError **error)
 {
@@ -2744,7 +2734,7 @@ e_cal_backend_modify_objects_sync (ECalBackend *backend,
        closure = e_async_closure_new ();
 
        e_cal_backend_modify_objects (
-               backend, calobjs, mod, cancellable,
+               backend, calobjs, mod, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -2802,7 +2792,8 @@ cal_backend_modify_objects_thread (GSimpleAsyncResult *simple,
                class->modify_objects (
                        backend, data_cal, opid, cancellable,
                        async_context->string_list,
-                       async_context->mod);
+                       async_context->mod,
+                       async_context->opflags);
        }
 
        g_object_unref (data_cal);
@@ -2813,6 +2804,7 @@ cal_backend_modify_objects_thread (GSimpleAsyncResult *simple,
  * @backend: an #ECalBackend
  * @calobjs: a %NULL-terminated array of iCalendar strings
  * @mod: modification type for recurrences
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -2830,6 +2822,7 @@ void
 e_cal_backend_modify_objects (ECalBackend *backend,
                               const gchar * const *calobjs,
                               ECalObjModType mod,
+                             guint32 opflags,
                               GCancellable *cancellable,
                               GAsyncReadyCallback callback,
                               gpointer user_data)
@@ -2848,6 +2841,7 @@ e_cal_backend_modify_objects (ECalBackend *backend,
        async_context = g_slice_new0 (AsyncContext);
        async_context->string_list = g_slist_reverse (list);
        async_context->mod = mod;
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (backend), callback, user_data,
@@ -2947,8 +2941,9 @@ e_cal_backend_modify_objects_finish (ECalBackend *backend,
 /**
  * e_cal_backend_remove_objects_sync:
  * @backend: an #ECalBackend
- * @component_ids: a #GList of #ECalComponentId structs
+ * @component_ids: (element-type ECalComponentId): a #GList of #ECalComponentId structs
  * @mod: modification type for recurrences
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -2964,6 +2959,7 @@ gboolean
 e_cal_backend_remove_objects_sync (ECalBackend *backend,
                                    GList *component_ids,
                                    ECalObjModType mod,
+                                  guint32 opflags,
                                    GCancellable *cancellable,
                                    GError **error)
 {
@@ -2977,7 +2973,7 @@ e_cal_backend_remove_objects_sync (ECalBackend *backend,
        closure = e_async_closure_new ();
 
        e_cal_backend_remove_objects (
-               backend, component_ids, mod, cancellable,
+               backend, component_ids, mod, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -3028,7 +3024,8 @@ cal_backend_remove_objects_thread (GSimpleAsyncResult *simple,
                class->remove_objects (
                        backend, data_cal, opid, cancellable,
                        async_context->compid_list,
-                       async_context->mod);
+                       async_context->mod,
+                       async_context->opflags);
        }
 
        g_object_unref (data_cal);
@@ -3037,8 +3034,9 @@ cal_backend_remove_objects_thread (GSimpleAsyncResult *simple,
 /**
  * e_cal_backend_remove_objects:
  * @backend: an #ECalBackend
- * @component_ids: a #GList of #ECalComponentId structs
+ * @component_ids: (element-type ECalComponentId): a #GList of #ECalComponentId structs
  * @mod: modification type for recurrences
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -3056,6 +3054,7 @@ void
 e_cal_backend_remove_objects (ECalBackend *backend,
                               GList *component_ids,
                               ECalObjModType mod,
+                             guint32 opflags,
                               GCancellable *cancellable,
                               GAsyncReadyCallback callback,
                               gpointer user_data)
@@ -3076,6 +3075,7 @@ e_cal_backend_remove_objects (ECalBackend *backend,
        async_context = g_slice_new0 (AsyncContext);
        async_context->compid_list = g_slist_reverse (list);
        async_context->mod = mod;
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (backend), callback, user_data,
@@ -3165,7 +3165,7 @@ e_cal_backend_remove_objects_finish (ECalBackend *backend,
                e_cal_backend_notify_component_removed (
                        backend, component_id, old_component, new_component);
 
-               e_cal_component_free_id (component_id);
+               e_cal_component_id_free (component_id);
                g_clear_object (&old_component);
                g_clear_object (&new_component);
        }
@@ -3188,6 +3188,7 @@ e_cal_backend_remove_objects_finish (ECalBackend *backend,
  * e_cal_backend_receive_objects_sync:
  * @backend: an #ECalBackend
  * @calobj: an iCalendar string
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -3203,6 +3204,7 @@ e_cal_backend_remove_objects_finish (ECalBackend *backend,
 gboolean
 e_cal_backend_receive_objects_sync (ECalBackend *backend,
                                     const gchar *calobj,
+                                   guint32 opflags,
                                     GCancellable *cancellable,
                                     GError **error)
 {
@@ -3216,7 +3218,7 @@ e_cal_backend_receive_objects_sync (ECalBackend *backend,
        closure = e_async_closure_new ();
 
        e_cal_backend_receive_objects (
-               backend, calobj, cancellable,
+               backend, calobj, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -3266,7 +3268,8 @@ cal_backend_receive_objects_thread (GSimpleAsyncResult *simple,
 
                class->receive_objects (
                        backend, data_cal, opid, cancellable,
-                       async_context->calobj);
+                       async_context->calobj,
+                       async_context->opflags);
        }
 
        g_object_unref (data_cal);
@@ -3276,6 +3279,7 @@ cal_backend_receive_objects_thread (GSimpleAsyncResult *simple,
  * e_cal_backend_receive_objects:
  * @backend: an #ECalBackend
  * @calobj: an iCalendar string
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -3293,6 +3297,7 @@ cal_backend_receive_objects_thread (GSimpleAsyncResult *simple,
 void
 e_cal_backend_receive_objects (ECalBackend *backend,
                                const gchar *calobj,
+                              guint32 opflags,
                                GCancellable *cancellable,
                                GAsyncReadyCallback callback,
                                gpointer user_data)
@@ -3305,6 +3310,7 @@ e_cal_backend_receive_objects (ECalBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->calobj = g_strdup (calobj);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (backend), callback, user_data,
@@ -3362,6 +3368,7 @@ e_cal_backend_receive_objects_finish (ECalBackend *backend,
  * e_cal_backend_send_objects_sync:
  * @backend: an #ECalBackend
  * @calobj: an iCalendar string
+ * @opflags: bit-or of #ECalOperationFlags
  * @out_users: a #GQueue in which to deposit results
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -3382,6 +3389,7 @@ e_cal_backend_receive_objects_finish (ECalBackend *backend,
 gchar *
 e_cal_backend_send_objects_sync (ECalBackend *backend,
                                  const gchar *calobj,
+                                guint32 opflags,
                                  GQueue *out_users,
                                  GCancellable *cancellable,
                                  GError **error)
@@ -3396,7 +3404,7 @@ e_cal_backend_send_objects_sync (ECalBackend *backend,
        closure = e_async_closure_new ();
 
        e_cal_backend_send_objects (
-               backend, calobj, cancellable,
+               backend, calobj, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -3446,7 +3454,8 @@ cal_backend_send_objects_thread (GSimpleAsyncResult *simple,
 
                class->send_objects (
                        backend, data_cal, opid, cancellable,
-                       async_context->calobj);
+                       async_context->calobj,
+                       async_context->opflags);
        }
 
        g_object_unref (data_cal);
@@ -3456,6 +3465,7 @@ cal_backend_send_objects_thread (GSimpleAsyncResult *simple,
  * e_cal_backend_send_objects:
  * @backend: an #ECalBackend
  * @calobj: an iCalendar string
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -3471,6 +3481,7 @@ cal_backend_send_objects_thread (GSimpleAsyncResult *simple,
 void
 e_cal_backend_send_objects (ECalBackend *backend,
                             const gchar *calobj,
+                           guint32 opflags,
                             GCancellable *cancellable,
                             GAsyncReadyCallback callback,
                             gpointer user_data)
@@ -3483,6 +3494,7 @@ e_cal_backend_send_objects (ECalBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->calobj = g_strdup (calobj);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (backend), callback, user_data,
@@ -3759,6 +3771,7 @@ e_cal_backend_get_attachment_uris_finish (ECalBackend *backend,
  * @uid: a unique ID for an iCalendar object
  * @rid: a recurrence ID, or %NULL
  * @alarm_uid: a unique ID for an iCalendar VALARM object
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -3776,6 +3789,7 @@ e_cal_backend_discard_alarm_sync (ECalBackend *backend,
                                   const gchar *uid,
                                   const gchar *rid,
                                   const gchar *alarm_uid,
+                                 guint32 opflags,
                                   GCancellable *cancellable,
                                   GError **error)
 {
@@ -3791,7 +3805,7 @@ e_cal_backend_discard_alarm_sync (ECalBackend *backend,
        closure = e_async_closure_new ();
 
        e_cal_backend_discard_alarm (
-               backend, uid, rid, alarm_uid, cancellable,
+               backend, uid, rid, alarm_uid, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -3850,7 +3864,8 @@ cal_backend_discard_alarm_thread (GSimpleAsyncResult *simple,
                        backend, data_cal, opid, cancellable,
                        async_context->uid,
                        async_context->rid,
-                       async_context->alarm_uid);
+                       async_context->alarm_uid,
+                       async_context->opflags);
        }
 
        g_object_unref (data_cal);
@@ -3862,6 +3877,7 @@ cal_backend_discard_alarm_thread (GSimpleAsyncResult *simple,
  * @uid: a unique ID for an iCalendar object
  * @rid: a recurrence ID, or %NULL
  * @alarm_uid: a unique ID for an iCalendar VALARM object
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -3880,6 +3896,7 @@ e_cal_backend_discard_alarm (ECalBackend *backend,
                              const gchar *uid,
                              const gchar *rid,
                              const gchar *alarm_uid,
+                            guint32 opflags,
                              GCancellable *cancellable,
                              GAsyncReadyCallback callback,
                              gpointer user_data)
@@ -3896,6 +3913,7 @@ e_cal_backend_discard_alarm (ECalBackend *backend,
        async_context->uid = g_strdup (uid);
        async_context->rid = g_strdup (rid);
        async_context->alarm_uid = g_strdup (alarm_uid);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (backend), callback, user_data,
@@ -4225,7 +4243,7 @@ cal_backend_add_timezone_thread (GSimpleAsyncResult *simple,
 }
 
 /**
- * e_cal_backend_add_timezone
+ * e_cal_backend_add_timezone:
  * @backend: an #ECalBackend
  * @tzobject: an iCalendar VTIMEZONE string
  * @cancellable: optional #GCancellable object, or %NULL
@@ -4409,12 +4427,11 @@ match_view_and_notify_component (EDataCalView *view,
        else if (new_match)
                e_data_cal_view_notify_components_added_1 (view, new_component);
        else if (old_match) {
-
                ECalComponentId *id = e_cal_component_get_id (old_component);
 
                e_data_cal_view_notify_objects_removed_1 (view, id);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
        }
 }
 
@@ -4556,56 +4573,6 @@ e_cal_backend_notify_property_changed (ECalBackend *backend,
        }
 }
 
-/**
- * e_cal_backend_empty_cache:
- * @backend: an #ECalBackend
- * @cache: Backend's cache to empty.
- *
- * Empties backend's cache with all notifications and so on, thus all listening
- * will know there is nothing in this backend.
- *
- * Since: 2.28
- **/
-void
-e_cal_backend_empty_cache (ECalBackend *backend,
-                           ECalBackendCache *cache)
-{
-       GList *comps_in_cache;
-
-       g_return_if_fail (backend != NULL);
-       g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
-       if (!cache)
-               return;
-
-       g_return_if_fail (E_IS_CAL_BACKEND_CACHE (cache));
-
-       e_file_cache_freeze_changes (E_FILE_CACHE (cache));
-
-       for (comps_in_cache = e_cal_backend_cache_get_components (cache);
-            comps_in_cache;
-            comps_in_cache = comps_in_cache->next) {
-               ECalComponentId *id;
-               ECalComponent *comp = comps_in_cache->data;
-
-               id = e_cal_component_get_id (comp);
-
-               if (id) {
-                       e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
-
-                       e_cal_backend_notify_component_removed (backend, id, comp, NULL);
-
-                       e_cal_component_free_id (id);
-               }
-
-               g_object_unref (comp);
-       }
-
-       g_list_free (comps_in_cache);
-
-       e_file_cache_thaw_changes (E_FILE_CACHE (cache));
-}
-
 /**
  * e_cal_backend_prepare_for_completion:
  * @backend: an #ECalBackend
diff --git a/src/calendar/libedata-cal/e-cal-backend.h b/src/calendar/libedata-cal/e-cal-backend.h
index 9836d413d..3423b1d10 100644
--- a/src/calendar/libedata-cal/e-cal-backend.h
+++ b/src/calendar/libedata-cal/e-cal-backend.h
@@ -48,8 +48,6 @@
 
 G_BEGIN_DECLS
 
-struct _ECalBackendCache;
-
 typedef struct _ECalBackend ECalBackend;
 typedef struct _ECalBackendClass ECalBackendClass;
 typedef struct _ECalBackendPrivate ECalBackendPrivate;
@@ -137,36 +135,41 @@ struct _ECalBackendClass {
                                                 EDataCal *cal,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *users,
+                                                const GSList *users, /* gchar * */
                                                 time_t start,
                                                 time_t end);
        void            (*create_objects)       (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *calobjs);
+                                                const GSList *calobjs, /* gchar * */
+                                                guint32 opflags); /* bit-or of ECalOperationFlags */
        void            (*modify_objects)       (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *calobjs,
-                                                ECalObjModType mod);
+                                                const GSList *calobjs, /* gchar * */
+                                                ECalObjModType mod,
+                                                guint32 opflags); /* bit-or of ECalOperationFlags */
        void            (*remove_objects)       (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *ids,
-                                                ECalObjModType mod);
+                                                const GSList *ids, /* ECalComponentId * */
+                                                ECalObjModType mod,
+                                                guint32 opflags); /* bit-or of ECalOperationFlags */
        void            (*receive_objects)      (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const gchar *calobj);
+                                                const gchar *calobj,
+                                                guint32 opflags); /* bit-or of ECalOperationFlags */
        void            (*send_objects)         (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const gchar *calobj);
+                                                const gchar *calobj,
+                                                guint32 opflags); /* bit-or of ECalOperationFlags */
        void            (*get_attachment_uris)  (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
@@ -179,7 +182,8 @@ struct _ECalBackendClass {
                                                 GCancellable *cancellable,
                                                 const gchar *uid,
                                                 const gchar *rid,
-                                                const gchar *auid);
+                                                const gchar *auid,
+                                                guint32 opflags); /* bit-or of ECalOperationFlags */
        void            (*get_timezone)         (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
@@ -200,10 +204,13 @@ struct _ECalBackendClass {
        void            (*closed)               (ECalBackend *backend,
                                                 const gchar *sender);
        void            (*shutdown)             (ECalBackend *backend);
+
+       /* Padding for future expansion */
+       gpointer reserved_padding[20];
 };
 
 GType          e_cal_backend_get_type          (void) G_GNUC_CONST;
-icalcomponent_kind
+ICalComponentKind
                e_cal_backend_get_kind          (ECalBackend *backend);
 EDataCal *     e_cal_backend_ref_data_cal      (ECalBackend *backend);
 void           e_cal_backend_set_data_cal      (ECalBackend *backend,
@@ -275,7 +282,7 @@ gchar *             e_cal_backend_get_object_finish (ECalBackend *backend,
 gboolean       e_cal_backend_get_object_list_sync
                                                (ECalBackend *backend,
                                                 const gchar *query,
-                                                GQueue *out_objects,
+                                                GQueue *out_objects, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_get_object_list   (ECalBackend *backend,
@@ -286,14 +293,14 @@ void              e_cal_backend_get_object_list   (ECalBackend *backend,
 gboolean       e_cal_backend_get_object_list_finish
                                                (ECalBackend *backend,
                                                 GAsyncResult *result,
-                                                GQueue *out_objects,
+                                                GQueue *out_objects, /* gchar * */
                                                 GError **error);
 gboolean       e_cal_backend_get_free_busy_sync
                                                (ECalBackend *backend,
                                                 time_t start,
                                                 time_t end,
                                                 const gchar * const *users,
-                                                GSList **out_freebusy,
+                                                GSList **out_freebusy, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_get_free_busy     (ECalBackend *backend,
@@ -306,16 +313,18 @@ void              e_cal_backend_get_free_busy     (ECalBackend *backend,
 gboolean       e_cal_backend_get_free_busy_finish
                                                (ECalBackend *backend,
                                                 GAsyncResult *result,
-                                                GSList **out_freebusy,
+                                                GSList **out_freebusy, /* gchar * */
                                                 GError **error);
 gboolean       e_cal_backend_create_objects_sync
                                                (ECalBackend *backend,
                                                 const gchar * const *calobjs,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GQueue *out_uids,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_create_objects    (ECalBackend *backend,
                                                 const gchar * const *calobjs,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -328,11 +337,13 @@ gboolean  e_cal_backend_modify_objects_sync
                                                (ECalBackend *backend,
                                                 const gchar * const *calobjs,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_modify_objects    (ECalBackend *backend,
                                                 const gchar * const *calobjs,
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -342,13 +353,15 @@ gboolean  e_cal_backend_modify_objects_finish
                                                 GError **error);
 gboolean       e_cal_backend_remove_objects_sync
                                                (ECalBackend *backend,
-                                                GList *component_ids,
+                                                GList *component_ids, /* ECalComponentId * */
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_remove_objects    (ECalBackend *backend,
-                                                GList *component_ids,
+                                                GList *component_ids, /* ECalComponentId * */
                                                 ECalObjModType mod,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -359,10 +372,12 @@ gboolean  e_cal_backend_remove_objects_finish
 gboolean       e_cal_backend_receive_objects_sync
                                                (ECalBackend *backend,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_receive_objects   (ECalBackend *backend,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -372,11 +387,13 @@ gboolean  e_cal_backend_receive_objects_finish
                                                 GError **error);
 gchar *                e_cal_backend_send_objects_sync (ECalBackend *backend,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GQueue *out_users,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_send_objects      (ECalBackend *backend,
                                                 const gchar *calobj,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -409,12 +426,14 @@ gboolean  e_cal_backend_discard_alarm_sync
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 const gchar *alarm_uid,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_cal_backend_discard_alarm     (ECalBackend *backend,
                                                 const gchar *uid,
                                                 const gchar *rid,
                                                 const gchar *alarm_uid,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -473,9 +492,6 @@ void                e_cal_backend_notify_property_changed
                                                 const gchar *prop_name,
                                                 const gchar *prop_value);
 
-void           e_cal_backend_empty_cache       (ECalBackend *backend,
-                                                struct _ECalBackendCache *cache);
-
 GSimpleAsyncResult *
                e_cal_backend_prepare_for_completion
                                                (ECalBackend *backend,
diff --git a/src/calendar/libedata-cal/e-cal-cache.c b/src/calendar/libedata-cal/e-cal-cache.c
index a91fec1d5..7622dca44 100644
--- a/src/calendar/libedata-cal/e-cal-cache.c
+++ b/src/calendar/libedata-cal/e-cal-cache.c
@@ -66,12 +66,13 @@
 #define ECC_COLUMN_HAS_START           "has_start"
 #define ECC_COLUMN_HAS_RECURRENCES     "has_recurrences"
 #define ECC_COLUMN_EXTRA               "bdata"
+#define ECC_COLUMN_CUSTOM_FLAGS                "custom_flags"
 
 struct _ECalCachePrivate {
        gboolean initializing;
 
-       GHashTable *loaded_timezones; /* gchar *tzid ~> icaltimezone * */
-       GHashTable *modified_timezones; /* gchar *tzid ~> icaltimezone * */
+       GHashTable *loaded_timezones; /* gchar *tzid ~> ICalTimezone * */
+       GHashTable *modified_timezones; /* gchar *tzid ~> ICalTimezone * */
        GRecMutex timezones_lock;
 
        GHashTable *sexps; /* gint ~> ECalBackendSExp * */
@@ -397,6 +398,26 @@ e_cal_cache_get_strings (ECache *cache,
        return TRUE;
 }
 
+static gboolean
+e_cal_cache_get_uint64_cb (ECache *cache,
+                          gint ncols,
+                          const gchar **column_names,
+                          const gchar **column_values,
+                          gpointer user_data)
+{
+       guint64 *pui64 = user_data;
+
+       g_return_val_if_fail (pui64 != NULL, FALSE);
+
+       if (ncols == 1) {
+               *pui64 = column_values[0] ? g_ascii_strtoull (column_values[0], NULL, 10) : 0;
+       } else {
+               *pui64 = 0;
+       }
+
+       return TRUE;
+}
+
 static void
 e_cal_cache_populate_other_columns (ECalCache *cal_cache,
                                    GSList **out_other_columns)
@@ -429,6 +450,7 @@ e_cal_cache_populate_other_columns (ECalCache *cal_cache,
        add_column (ECC_COLUMN_HAS_START, "INTEGER", NULL);
        add_column (ECC_COLUMN_HAS_RECURRENCES, "INTEGER", NULL);
        add_column (ECC_COLUMN_EXTRA, "TEXT", NULL);
+       add_column (ECC_COLUMN_CUSTOM_FLAGS, "INTEGER", NULL);
 
        #undef add_column
 
@@ -507,56 +529,62 @@ e_cal_cache_get_ids (ECache *cache,
        return TRUE;
 }
 
-static icaltimezone *
+static ICalTimezone *
 ecc_resolve_tzid_cb (const gchar *tzid,
-                    gpointer user_data)
+                    gpointer user_data,
+                    GCancellable *cancellable,
+                    GError **error)
 {
        ECalCache *cal_cache = user_data;
-       icaltimezone *zone = NULL;
+       ICalTimezone *zone = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), NULL);
 
-       if (e_cal_cache_get_timezone (cal_cache, tzid, &zone, NULL, NULL) && zone)
+       if (e_cal_cache_get_timezone (cal_cache, tzid, &zone, cancellable, NULL) && zone)
                return zone;
 
-       zone = icaltimezone_get_builtin_timezone (tzid);
+       zone = i_cal_timezone_get_builtin_timezone (tzid);
        if (!zone)
-               zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+               zone = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
        if (!zone) {
                tzid = e_cal_match_tzid (tzid);
-               zone = icaltimezone_get_builtin_timezone (tzid);
+               zone = i_cal_timezone_get_builtin_timezone (tzid);
        }
 
        if (!zone)
-               zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+               zone = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
 
        return zone;
 }
 
 static gchar *
-ecc_encode_itt_to_sql (struct icaltimetype itt)
+ecc_encode_itt_to_sql (ICalTime *itt)
 {
+       if (!itt)
+               return g_strdup ("00000000000000");
+
        return g_strdup_printf ("%04d%02d%02d%02d%02d%02d",
-               itt.year, itt.month, itt.day,
-               itt.hour, itt.minute, itt.second);
+               i_cal_time_get_year (itt), i_cal_time_get_month (itt), i_cal_time_get_day (itt),
+               i_cal_time_get_hour (itt), i_cal_time_get_minute (itt), i_cal_time_get_second (itt));
 }
 
 static gchar *
 ecc_encode_time_to_sql (ECalCache *cal_cache,
                        const ECalComponentDateTime *dt)
 {
-       struct icaltimetype itt;
-       icaltimezone *zone = NULL;
+       ICalTime *itt;
+       ICalTimezone *zone = NULL;
 
-       if (!dt || !dt->value)
+       if (!dt || !e_cal_component_datetime_get_value (dt))
                return NULL;
 
-       itt = *dt->value;
+       itt = e_cal_component_datetime_get_value (dt);
 
-       if (!itt.is_date && !icaltime_is_utc (itt) && dt->tzid && *dt->tzid)
-               zone = ecc_resolve_tzid_cb (dt->tzid, cal_cache);
+       if (i_cal_time_is_date (itt) && !i_cal_time_is_utc (itt) &&
+           e_cal_component_datetime_get_tzid (dt))
+               zone = ecc_resolve_tzid_cb (e_cal_component_datetime_get_tzid (dt), cal_cache, NULL, NULL);
 
-       icaltimezone_convert_time (&itt, zone, icaltimezone_get_utc_timezone ());
+       i_cal_timezone_convert_time (itt, zone, i_cal_timezone_get_utc_timezone ());
 
        return ecc_encode_itt_to_sql (itt);
 }
@@ -565,14 +593,19 @@ static gchar *
 ecc_encode_timet_to_sql (ECalCache *cal_cache,
                         time_t tt)
 {
-       struct icaltimetype itt;
+       ICalTime *itt;
+       gchar *res;
 
        if (tt <= 0)
                return NULL;
 
-       itt = icaltime_from_timet_with_zone (tt, FALSE, icaltimezone_get_utc_timezone ());
+       itt = i_cal_time_from_timet_with_zone (tt, FALSE, i_cal_timezone_get_utc_timezone ());
 
-       return ecc_encode_itt_to_sql (itt);
+       res = ecc_encode_itt_to_sql (itt);
+
+       g_clear_object (&itt);
+
+       return res;
 }
 
 static gchar *
@@ -589,10 +622,10 @@ ecc_extract_text_list (const GSList *list)
        for (link = list; link; link = g_slist_next (link)) {
                ECalComponentText *text = link->data;
 
-               if (text && text->value) {
+               if (text && e_cal_component_text_get_value (text)) {
                        gchar *str;
 
-                       str = e_util_utf8_decompose (text->value);
+                       str = e_util_utf8_decompose (e_cal_component_text_get_value (text));
                        if (str)
                                g_string_append (value, str);
                        g_free (str);
@@ -605,14 +638,14 @@ ecc_extract_text_list (const GSList *list)
 static gchar *
 ecc_extract_comment (ECalComponent *comp)
 {
-       GSList *list = NULL;
+       GSList *list;
        gchar *value;
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       e_cal_component_get_comment_list (comp, &list);
+       list = e_cal_component_get_comments (comp);
        value = ecc_extract_text_list (list);
-       e_cal_component_free_text_list (list);
+       g_slist_free_full (list, e_cal_component_text_free);
 
        return value;
 }
@@ -620,14 +653,14 @@ ecc_extract_comment (ECalComponent *comp)
 static gchar *
 ecc_extract_description (ECalComponent *comp)
 {
-       GSList *list = NULL;
+       GSList *list;
        gchar *value;
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       e_cal_component_get_description_list (comp, &list);
+       list = e_cal_component_get_descriptions (comp);
        value = ecc_extract_text_list (list);
-       e_cal_component_free_text_list (list);
+       g_slist_free_full (list, e_cal_component_text_free);
 
        return value;
 }
@@ -674,12 +707,12 @@ ecc_encode_mail (GString *out_value,
 static gchar *
 ecc_extract_attendees (ECalComponent *comp)
 {
-       GSList *attendees = NULL, *link;
+       GSList *attendees, *link;
        GString *value;
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       e_cal_component_get_attendee_list (comp, &attendees);
+       attendees = e_cal_component_get_attendees (comp);
        if (!attendees)
                return NULL;
 
@@ -691,10 +724,10 @@ ecc_extract_attendees (ECalComponent *comp)
                if (!att)
                        continue;
 
-               ecc_encode_mail (value, att->cn, att->value);
+               ecc_encode_mail (value, e_cal_component_attendee_get_cn (att), 
e_cal_component_attendee_get_value (att));
        }
 
-       e_cal_component_free_attendee_list (attendees);
+       g_slist_free_full (attendees, e_cal_component_attendee_free);
 
        if (value->len) {
                /* This way it is encoded as:
@@ -709,19 +742,23 @@ ecc_extract_attendees (ECalComponent *comp)
 static gchar *
 ecc_extract_organizer (ECalComponent *comp)
 {
-       ECalComponentOrganizer org;
+       ECalComponentOrganizer *org;
        GString *value;
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       e_cal_component_get_organizer (comp, &org);
+       org = e_cal_component_get_organizer (comp);
 
-       if (!org.value)
+       if (!org || !e_cal_component_organizer_get_value (org)) {
+               e_cal_component_organizer_free (org);
                return NULL;
+       }
 
        value = g_string_new ("");
 
-       ecc_encode_mail (value, org.cn, org.value);
+       ecc_encode_mail (value, e_cal_component_organizer_get_cn (org), e_cal_component_organizer_get_value 
(org));
+
+       e_cal_component_organizer_free (org);
 
        return g_string_free (value, !value->len);
 }
@@ -734,7 +771,7 @@ ecc_extract_categories (ECalComponent *comp)
 
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       e_cal_component_get_categories_list (comp, &categories);
+       categories = e_cal_component_get_categories_list (comp);
 
        if (!categories)
                return NULL;
@@ -751,7 +788,7 @@ ecc_extract_categories (ECalComponent *comp)
                }
        }
 
-       e_cal_component_free_categories_list (categories);
+       g_slist_free_full (categories, g_free);
 
        if (value->len) {
                /* This way it is encoded as:
@@ -789,38 +826,36 @@ ecc_get_classification_as_string (ECalComponentClassification classification)
 }
 
 static const gchar *
-ecc_get_status_as_string (icalproperty_status status)
+ecc_get_status_as_string (ICalPropertyStatus status)
 {
        switch (status) {
-       case ICAL_STATUS_NONE:
+       case I_CAL_STATUS_NONE:
                return "not started";
-       case ICAL_STATUS_COMPLETED:
+       case I_CAL_STATUS_COMPLETED:
                return "completed";
-       case ICAL_STATUS_CANCELLED:
+       case I_CAL_STATUS_CANCELLED:
                return "cancelled";
-       case ICAL_STATUS_INPROCESS:
+       case I_CAL_STATUS_INPROCESS:
                return "in progress";
-       case ICAL_STATUS_NEEDSACTION:
+       case I_CAL_STATUS_NEEDSACTION:
                return "needs action";
-       case ICAL_STATUS_TENTATIVE:
+       case I_CAL_STATUS_TENTATIVE:
                return "tentative";
-       case ICAL_STATUS_CONFIRMED:
+       case I_CAL_STATUS_CONFIRMED:
                return "confirmed";
-       case ICAL_STATUS_DRAFT:
+       case I_CAL_STATUS_DRAFT:
                return "draft";
-       case ICAL_STATUS_FINAL:
+       case I_CAL_STATUS_FINAL:
                return "final";
-       case ICAL_STATUS_SUBMITTED:
+       case I_CAL_STATUS_SUBMITTED:
                return "submitted";
-       case ICAL_STATUS_PENDING:
+       case I_CAL_STATUS_PENDING:
                return "pending";
-       case ICAL_STATUS_FAILED:
+       case I_CAL_STATUS_FAILED:
                return "failed";
-#ifdef HAVE_ICAL_STATUS_DELETED
-       case ICAL_STATUS_DELETED:
+       case I_CAL_STATUS_DELETED:
                return "deleted";
-#endif
-       case ICAL_STATUS_X:
+       case I_CAL_STATUS_X:
                break;
        }
 
@@ -832,15 +867,15 @@ ecc_fill_other_columns (ECalCache *cal_cache,
                        ECacheColumnValues *other_columns,
                        ECalComponent *comp)
 {
-       time_t occur_start = -1, occur_end = -1;
-       ECalComponentDateTime dt;
-       ECalComponentText text;
+       ECalComponentDateTime *dt;
+       ECalComponentText *text;
        ECalComponentClassification classification = E_CAL_COMPONENT_CLASS_PUBLIC;
-       icalcomponent *icalcomp;
-       icalproperty_status status = ICAL_STATUS_NONE;
-       struct icaltimetype *itt;
-       const gchar *str = NULL;
-       gint *pint = NULL;
+       ICalComponent *icomp;
+       ICalPropertyStatus status = I_CAL_STATUS_NONE;
+       ICalTime *itt;
+       time_t occur_start = -1, occur_end = -1;
+       gchar *str = NULL;
+       gint nint;
        gboolean has;
 
        g_return_if_fail (E_IS_CAL_CACHE (cal_cache));
@@ -849,60 +884,55 @@ ecc_fill_other_columns (ECalCache *cal_cache,
 
        #define add_value(_col, _val) e_cache_column_values_take_value (other_columns, _col, _val)
 
-       icalcomp = e_cal_component_get_icalcomponent (comp);
+       icomp = e_cal_component_get_icalcomponent (comp);
 
        e_cal_util_get_component_occur_times (
                comp, &occur_start, &occur_end,
-               ecc_resolve_tzid_cb, cal_cache, icaltimezone_get_utc_timezone (),
-               icalcomponent_isa (icalcomp));
+               ecc_resolve_tzid_cb, cal_cache, i_cal_timezone_get_utc_timezone (),
+               i_cal_component_isa (icomp));
 
-       e_cal_component_get_dtstart (comp, &dt);
-       add_value (ECC_COLUMN_OCCUR_START, dt.value && ((dt.tzid && *dt.tzid) || icaltime_is_utc (*dt.value)) 
? ecc_encode_timet_to_sql (cal_cache, occur_start) : NULL);
+       dt = e_cal_component_get_dtstart (comp);
+       add_value (ECC_COLUMN_OCCUR_START, dt && e_cal_component_datetime_get_value (dt) &&
+               (e_cal_component_datetime_get_tzid (dt) || i_cal_time_is_utc 
(e_cal_component_datetime_get_value (dt)))
+               ? ecc_encode_timet_to_sql (cal_cache, occur_start) : NULL);
 
-       has = dt.value != NULL;
+       has = dt && e_cal_component_datetime_get_value (dt);
        add_value (ECC_COLUMN_HAS_START, g_strdup (has ? "1" : "0"));
-       e_cal_component_free_datetime (&dt);
+       e_cal_component_datetime_free (dt);
 
-       e_cal_component_get_dtend (comp, &dt);
-       add_value (ECC_COLUMN_OCCUR_END, dt.value && ((dt.tzid && *dt.tzid) || icaltime_is_utc (*dt.value)) ? 
ecc_encode_timet_to_sql (cal_cache, occur_end) : NULL);
-       e_cal_component_free_datetime (&dt);
+       dt = e_cal_component_get_dtend (comp);
+       add_value (ECC_COLUMN_OCCUR_END, dt && e_cal_component_datetime_get_value (dt) &&
+               (e_cal_component_datetime_get_tzid (dt) || i_cal_time_is_utc 
(e_cal_component_datetime_get_value (dt)))
+               ? ecc_encode_timet_to_sql (cal_cache, occur_end) : NULL);
+       e_cal_component_datetime_free (dt);
 
-       e_cal_component_get_due (comp, &dt);
-       add_value (ECC_COLUMN_DUE, ecc_encode_time_to_sql (cal_cache, &dt));
-       e_cal_component_free_datetime (&dt);
+       dt = e_cal_component_get_due (comp);
+       add_value (ECC_COLUMN_DUE, ecc_encode_time_to_sql (cal_cache, dt));
+       e_cal_component_datetime_free (dt);
 
-       itt = NULL;
-       e_cal_component_get_completed (comp, &itt);
-       add_value (ECC_COLUMN_COMPLETED, itt ? ecc_encode_itt_to_sql (*itt) : NULL);
-       if (itt)
-               e_cal_component_free_icaltimetype (itt);
+       itt = e_cal_component_get_completed (comp);
+       add_value (ECC_COLUMN_COMPLETED, itt ? ecc_encode_itt_to_sql (itt) : NULL);
+       g_clear_object (&itt);
 
-       text.value = NULL;
-       e_cal_component_get_summary (comp, &text);
-       add_value (ECC_COLUMN_SUMMARY, text.value ? e_util_utf8_decompose (text.value) : NULL);
+       text = e_cal_component_get_summary (comp);
+       add_value (ECC_COLUMN_SUMMARY, text && e_cal_component_text_get_value (text) ? e_util_utf8_decompose 
(e_cal_component_text_get_value (text)) : NULL);
+       e_cal_component_text_free (text);
 
-       e_cal_component_get_location (comp, &str);
+       str = e_cal_component_get_location (comp);
        add_value (ECC_COLUMN_LOCATION, str ? e_util_utf8_decompose (str) : NULL);
+       g_free (str);
 
-       e_cal_component_get_classification (comp, &classification);
+       classification = e_cal_component_get_classification (comp);
        add_value (ECC_COLUMN_CLASSIFICATION, g_strdup (ecc_get_classification_as_string (classification)));
 
-       e_cal_component_get_status (comp, &status);
+       status = e_cal_component_get_status (comp);
        add_value (ECC_COLUMN_STATUS, g_strdup (ecc_get_status_as_string (status)));
 
-       e_cal_component_get_priority (comp, &pint);
-       add_value (ECC_COLUMN_PRIORITY, pint && *pint ? g_strdup_printf ("%d", *pint) : NULL);
-       if (pint) {
-               e_cal_component_free_priority (pint);
-               pint = NULL;
-       }
+       nint = e_cal_component_get_priority (comp);
+       add_value (ECC_COLUMN_PRIORITY, nint != -1 ? g_strdup_printf ("%d", nint) : NULL);
 
-       e_cal_component_get_percent (comp, &pint);
-       add_value (ECC_COLUMN_PERCENT_COMPLETE, pint && *pint ? g_strdup_printf ("%d", *pint) : NULL);
-       if (pint) {
-               e_cal_component_free_percent (pint);
-               pint = NULL;
-       }
+       nint = e_cal_component_get_percent_complete (comp);
+       add_value (ECC_COLUMN_PERCENT_COMPLETE, nint != -1 ? g_strdup_printf ("%d", nint) : NULL);
 
        has = e_cal_component_has_alarms (comp);
        add_value (ECC_COLUMN_HAS_ALARM, g_strdup (has ? "1" : "0"));
@@ -1115,12 +1145,12 @@ ecc_sexp_func_occur_in_time_range (ESExp *esexp,
        result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
 
        if (!ctx->not_level) {
-               struct icaltimetype itt_start, itt_end;
+               ICalTime *itt_start, *itt_end;
                gchar *start_str, *end_str;
 
                /* The default zone argument, if any, is ignored here */
-               itt_start = icaltime_from_timet_with_zone (argv[0]->value.time, 0, NULL);
-               itt_end = icaltime_from_timet_with_zone (argv[1]->value.time, 0, NULL);
+               itt_start = i_cal_time_from_timet_with_zone (argv[0]->value.time, 0, NULL);
+               itt_end = i_cal_time_from_timet_with_zone (argv[1]->value.time, 0, NULL);
 
                start_str = ecc_encode_itt_to_sql (itt_start);
                end_str = ecc_encode_itt_to_sql (itt_end);
@@ -1130,6 +1160,8 @@ ecc_sexp_func_occur_in_time_range (ESExp *esexp,
                if (!result->value.string)
                        result->value.string = g_strdup ("1=1");
 
+               g_clear_object (&itt_start);
+               g_clear_object (&itt_end);
                g_free (start_str);
                g_free (end_str);
        } else {
@@ -1626,6 +1658,7 @@ ecc_convert_sexp_to_sql (ECalCache *cal_cache,
 
 typedef struct {
        gint extra_idx;
+       gint custom_flags_idx;
        ECalCacheSearchFunc func;
        gpointer func_user_data;
 } SearchContext;
@@ -1643,29 +1676,36 @@ ecc_search_foreach_cb (ECache *cache,
 {
        SearchContext *ctx = user_data;
        gchar *comp_uid = NULL, *comp_rid = NULL;
+       guint32 custom_flags = 0;
        gboolean can_continue;
 
        g_return_val_if_fail (ctx != NULL, FALSE);
        g_return_val_if_fail (ctx->func != NULL, FALSE);
 
-       if (ctx->extra_idx == -1) {
+       if (ctx->extra_idx == -1 || ctx->custom_flags_idx == -1) {
                gint ii;
 
-               for (ii = 0; ii < ncols; ii++) {
-                       if (column_names[ii] && g_ascii_strcasecmp (column_names[ii], ECC_COLUMN_EXTRA) == 0) 
{
-                               ctx->extra_idx = ii;
-                               break;
+               for (ii = 0; ii < ncols && (ctx->extra_idx == -1 || ctx->custom_flags_idx == -1); ii++) {
+                       if (column_names[ii]) {
+                               if (g_ascii_strcasecmp (column_names[ii], ECC_COLUMN_EXTRA) == 0)
+                                       ctx->extra_idx = ii;
+                               else if (g_ascii_strcasecmp (column_names[ii], ECC_COLUMN_CUSTOM_FLAGS) == 0)
+                                       ctx->custom_flags_idx = ii;
                        }
                }
        }
 
        g_return_val_if_fail (ctx->extra_idx != -1, FALSE);
+       g_return_val_if_fail (ctx->custom_flags_idx != -1, FALSE);
 
        g_warn_if_fail (ecc_decode_id_sql (uid, &comp_uid, &comp_rid));
 
+       if (ctx->custom_flags_idx >= 0 && column_values[ctx->custom_flags_idx])
+               custom_flags = g_ascii_strtoull (column_values[ctx->custom_flags_idx], NULL, 10);
+
        /* This type-cast for performance reason */
        can_continue = ctx->func ((ECalCache *) cache, comp_uid, comp_rid, revision, object,
-               column_values[ctx->extra_idx], offline_state, ctx->func_user_data);
+               column_values[ctx->extra_idx], custom_flags, offline_state, ctx->func_user_data);
 
        g_free (comp_uid);
        g_free (comp_rid);
@@ -1691,6 +1731,7 @@ ecc_search_internal (ECalCache *cal_cache,
        }
 
        ctx.extra_idx = -1;
+       ctx.custom_flags_idx = -1;
        ctx.func = func;
        ctx.func_user_data = user_data;
 
@@ -1765,8 +1806,10 @@ ecc_init_sqlite_functions (ECalCache *cal_cache,
 typedef struct _ComponentInfo {
        GSList *online_comps; /* ECalComponent * */
        GSList *online_extras; /* gchar * */
+       GSList *online_custom_flags; /* guint32 */
        GSList *offline_comps; /* ECalComponent * */
        GSList *offline_extras; /* gchar * */
+       GSList *offline_custom_flags; /* guint32 */
 } ComponentInfo;
 
 static void
@@ -1775,8 +1818,10 @@ component_info_clear (ComponentInfo *ci)
        if (ci) {
                g_slist_free_full (ci->online_comps, g_object_unref);
                g_slist_free_full (ci->online_extras, g_free);
+               g_slist_free (ci->online_custom_flags);
                g_slist_free_full (ci->offline_comps, g_object_unref);
                g_slist_free_full (ci->offline_extras, g_free);
+               g_slist_free (ci->offline_custom_flags);
        }
 }
 
@@ -1787,12 +1832,13 @@ cal_cache_gather_v1_affected_cb (ECalCache *cal_cache,
                                 const gchar *revision,
                                 const gchar *object,
                                 const gchar *extra,
+                                guint32 custom_flags,
                                 EOfflineState offline_state,
                                 gpointer user_data)
 {
        ComponentInfo *ci = user_data;
        ECalComponent *comp;
-       ECalComponentDateTime dt;
+       ECalComponentDateTime *dt;
 
        g_return_val_if_fail (object != NULL, FALSE);
        g_return_val_if_fail (ci != NULL, FALSE);
@@ -1804,45 +1850,51 @@ cal_cache_gather_v1_affected_cb (ECalCache *cal_cache,
        if (!comp)
                return TRUE;
 
-       e_cal_component_get_due (comp, &dt);
+       dt = e_cal_component_get_due (comp);
 
-       if (dt.value && !icaltime_is_utc (*dt.value) && (!dt.tzid || !*dt.tzid)) {
-               GSList **pcomps, **pextras;
+       if (dt && e_cal_component_datetime_get_value (dt) &&
+           !i_cal_time_is_utc (e_cal_component_datetime_get_value (dt)) &&
+           !e_cal_component_datetime_get_tzid (dt)) {
+               GSList **pcomps, **pextras, **pcustom_flags;
 
                if (offline_state == E_OFFLINE_STATE_SYNCED) {
                        pcomps = &ci->online_comps;
                        pextras = &ci->online_extras;
+                       pcustom_flags = &ci->online_custom_flags;
                } else {
                        pcomps = &ci->offline_comps;
                        pextras = &ci->offline_extras;
+                       pcustom_flags = &ci->offline_custom_flags;
                }
 
                *pcomps = g_slist_prepend (*pcomps, g_object_ref (comp));
                *pextras = g_slist_prepend (*pextras, g_strdup (extra));
+               *pcustom_flags = g_slist_prepend (*pcustom_flags, GUINT_TO_POINTER (custom_flags));
        }
 
-       e_cal_component_free_datetime (&dt);
+       e_cal_component_datetime_free (dt);
        g_object_unref (comp);
 
        return TRUE;
 }
 
-static icaltimezone *
+static ICalTimezone *
 ecc_timezone_from_string (const gchar *icalstring)
 {
-       icalcomponent *component;
+       ICalComponent *component;
 
        g_return_val_if_fail (icalstring != NULL, NULL);
 
-       component = icalcomponent_new_from_string (icalstring);
+       component = i_cal_component_new_from_string (icalstring);
        if (component) {
-               icaltimezone *zone;
+               ICalTimezone *zone;
 
-               zone = icaltimezone_new ();
-               if (!icaltimezone_set_component (zone, component)) {
-                       icalcomponent_free (component);
-                       icaltimezone_free (zone, 1);
+               zone = i_cal_timezone_new ();
+               if (!i_cal_timezone_set_component (zone, component)) {
+                       g_object_unref (component);
+                       g_object_unref (zone);
                } else {
+                       g_object_unref (component);
                        return zone;
                }
        }
@@ -1855,15 +1907,15 @@ ecc_tzid_is_libical_builtin (const gchar *tzid)
 {
        const gchar *matched_tzid;
 
-       if (!tzid || !*tzid || icaltimezone_get_builtin_timezone (tzid))
+       if (!tzid || !*tzid || i_cal_timezone_get_builtin_timezone (tzid))
                return TRUE;
 
        matched_tzid = e_cal_match_tzid (tzid);
-       return matched_tzid && icaltimezone_get_builtin_timezone_from_tzid (matched_tzid);
+       return matched_tzid && i_cal_timezone_get_builtin_timezone_from_tzid (matched_tzid);
 }
 
 typedef struct _TimezoneMigrationData {
-       icaltimezone *zone;
+       ICalTimezone *zone;
        guint refs;
        gboolean is_deref; /* TRUE when should dereference, instead of reference, the timezone with refs 
references */
 } TimezoneMigrationData;
@@ -1874,8 +1926,7 @@ timezone_migration_data_free (gpointer ptr)
        TimezoneMigrationData *tmd = ptr;
 
        if (tmd) {
-               if (tmd->zone)
-                       icaltimezone_free (tmd->zone, 1);
+               g_clear_object (&tmd->zone);
                g_free (tmd);
        }
 }
@@ -1888,7 +1939,7 @@ typedef struct _CountTimezonesData {
 } CountTimezonesData;
 
 static void
-ecc_count_timezones_in_icalcomp_cb (icalparameter *param,
+ecc_count_timezones_in_icalcomp_cb (ICalParameter *param,
                                    gpointer user_data)
 {
        CountTimezonesData *ctd = user_data;
@@ -1897,7 +1948,7 @@ ecc_count_timezones_in_icalcomp_cb (icalparameter *param,
 
        g_return_if_fail (ctd != NULL);
 
-       tzid = icalparameter_get_tzid (param);
+       tzid = i_cal_parameter_get_tzid (param);
        if (!tzid)
                return;
 
@@ -1927,7 +1978,7 @@ ecc_count_timezones_in_icalcomp_cb (icalparameter *param,
                        }
                }
        } else if (!ecc_tzid_is_libical_builtin (tzid)) {
-               icaltimezone *zone = NULL;
+               ICalTimezone *zone = NULL;
 
                g_signal_emit (ctd->cal_cache, signals[GET_TIMEZONE], 0, tzid, &zone);
 
@@ -1935,25 +1986,8 @@ ecc_count_timezones_in_icalcomp_cb (icalparameter *param,
                        zone = NULL;
 
                /* Make a copy of it, it's not owned by the caller, but by the originator */
-               if (zone) {
-                       icalcomponent *zonecomp;
-
-                       zonecomp = icaltimezone_get_component (zone);
-                       if (zonecomp) {
-                               icalcomponent *clone;
-
-                               clone = icalcomponent_new_clone (zonecomp);
-                               /* icaltimezone_copy() doesn't carry over the component, thus do it this way 
*/
-                               zone = icaltimezone_new ();
-                               if (!icaltimezone_set_component (zone, clone)) {
-                                       icalcomponent_free (clone);
-                                       icaltimezone_free (zone, 1);
-                                       zone = NULL;
-                               }
-                       } else {
-                               zone = NULL;
-                       }
-               }
+               if (zone)
+                       zone = e_cal_util_copy_timezone (zone);
 
                if (zone) {
                        tmd = g_new0 (TimezoneMigrationData, 1);
@@ -1969,14 +2003,14 @@ ecc_count_timezones_in_icalcomp_cb (icalparameter *param,
 static void
 ecc_count_timezones_for_component (ECalCache *cal_cache,
                                   GHashTable *timezones,
-                                  icalcomponent *icalcomp,
+                                  ICalComponent *icomp,
                                   gboolean is_inc,
                                   GCancellable *cancellable)
 {
        g_return_if_fail (E_IS_CAL_CACHE (cal_cache));
        g_return_if_fail (timezones != NULL);
 
-       if (icalcomp) {
+       if (icomp) {
                CountTimezonesData ctd;
 
                ctd.cal_cache = cal_cache;
@@ -1984,7 +2018,7 @@ ecc_count_timezones_for_component (ECalCache *cal_cache,
                ctd.is_inc = is_inc;
                ctd.cancellable = cancellable;
 
-               icalcomponent_foreach_tzid (icalcomp, ecc_count_timezones_in_icalcomp_cb, &ctd);
+               i_cal_component_foreach_tzid (icomp, ecc_count_timezones_in_icalcomp_cb, &ctd);
        }
 }
 
@@ -2002,12 +2036,12 @@ ecc_count_timezones_for_old_component (ECalCache *cal_cache,
 
        objstr = e_cache_get_object_include_deleted (E_CACHE (cal_cache), uid_in_table, NULL, NULL, 
cancellable, NULL);
        if (objstr) {
-               icalcomponent *icalcomp;
+               ICalComponent *icomp;
 
-               icalcomp = icalcomponent_new_from_string (objstr);
-               if (icalcomp) {
-                       ecc_count_timezones_for_component (cal_cache, timezones, icalcomp, FALSE, 
cancellable);
-                       icalcomponent_free (icalcomp);
+               icomp = i_cal_component_new_from_string (objstr);
+               if (icomp) {
+                       ecc_count_timezones_for_component (cal_cache, timezones, icomp, FALSE, cancellable);
+                       g_object_unref (icomp);
                }
 
                g_free (objstr);
@@ -2060,7 +2094,7 @@ e_cal_cache_fill_tmd_cb (ECache *cache,
 
        /* Verify the timezone is not provided twice */
        if (!g_hash_table_lookup (timezones, column_values[0])) {
-               icaltimezone *zone;
+               ICalTimezone *zone;
 
                zone = ecc_timezone_from_string (column_values[1]);
                if (zone) {
@@ -2078,14 +2112,14 @@ e_cal_cache_fill_tmd_cb (ECache *cache,
 }
 
 static void
-ecc_count_tmd_refs_cb (icalparameter *param,
+ecc_count_tmd_refs_cb (ICalParameter *param,
                       gpointer user_data)
 {
        GHashTable *timezones = user_data;
        const gchar *tzid;
        TimezoneMigrationData *tmd;
 
-       tzid = icalparameter_get_tzid (param);
+       tzid = i_cal_parameter_get_tzid (param);
        if (!tzid || !timezones)
                return;
 
@@ -2101,19 +2135,20 @@ cal_cache_count_tmd_refs (ECalCache *cal_cache,
                          const gchar *revision,
                          const gchar *object,
                          const gchar *extra,
+                         guint32 custom_flags,
                          EOfflineState offline_state,
                          gpointer user_data)
 {
        GHashTable *timezones = user_data;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_return_val_if_fail (timezones != NULL, FALSE);
        g_return_val_if_fail (object != NULL, FALSE);
 
-       icalcomp = icalcomponent_new_from_string (object);
-       if (icalcomp) {
-               icalcomponent_foreach_tzid (icalcomp, ecc_count_tmd_refs_cb, timezones);
-               icalcomponent_free (icalcomp);
+       icomp = i_cal_component_new_from_string (object);
+       if (icomp) {
+               i_cal_component_foreach_tzid (icomp, ecc_count_tmd_refs_cb, timezones);
+               g_object_unref (icomp);
        }
 
        return TRUE;
@@ -2195,10 +2230,10 @@ e_cal_cache_migrate (ECache *cache,
                        gboolean success = TRUE;
 
                        if (ci.online_comps)
-                               success = e_cal_cache_put_components (cal_cache, ci.online_comps, 
ci.online_extras, E_CACHE_IS_ONLINE, cancellable, NULL);
+                               success = e_cal_cache_put_components (cal_cache, ci.online_comps, 
ci.online_extras, ci.online_custom_flags, E_CACHE_IS_ONLINE, cancellable, NULL);
 
                        if (success && ci.offline_comps)
-                               e_cal_cache_put_components (cal_cache, ci.offline_comps, ci.offline_extras, 
E_CACHE_IS_OFFLINE, cancellable, NULL);
+                               e_cal_cache_put_components (cal_cache, ci.offline_comps, ci.offline_extras, 
ci.offline_custom_flags, E_CACHE_IS_OFFLINE, cancellable, NULL);
                }
 
                component_info_clear (&ci);
@@ -2319,27 +2354,27 @@ e_cal_cache_new (const gchar *filename,
 /**
  * e_cal_cache_dup_component_revision:
  * @cal_cache: an #ECalCache
- * @icalcomp: an icalcomponent
+ * @icomp: an #ICalComponent
  *
- * Returns the @icalcomp revision, used to detect changes.
+ * Returns the @icomp revision, used to detect changes.
  * The returned string should be freed with g_free(), when
  * no longer needed.
  *
  * Returns: (transfer full): A newly allocated string containing
- *    revision of the @icalcomp.
+ *    revision of the @icomp.
  *
  * Since: 3.26
  **/
 gchar *
 e_cal_cache_dup_component_revision (ECalCache *cal_cache,
-                                   icalcomponent *icalcomp)
+                                   ICalComponent *icomp)
 {
        gchar *revision = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), NULL);
-       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (icomp != NULL, NULL);
 
-       g_signal_emit (cal_cache, signals[DUP_COMPONENT_REVISION], 0, icalcomp, &revision);
+       g_signal_emit (cal_cache, signals[DUP_COMPONENT_REVISION], 0, icomp, &revision);
 
        return revision;
 }
@@ -2386,6 +2421,7 @@ e_cal_cache_contains (ECalCache *cal_cache,
  * @cal_cache: an #ECalCache
  * @component: an #ECalComponent to put into the @cal_cache
  * @extra: (nullable): an extra data to store in association with the @component
+ * @custom_flags: custom flags for the @component, not interpreted by the @cal_cache
  * @offline_flag: one of #ECacheOfflineFlag, whether putting this component in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -2401,12 +2437,14 @@ gboolean
 e_cal_cache_put_component (ECalCache *cal_cache,
                           ECalComponent *component,
                           const gchar *extra,
+                          guint32 custom_flags,
                           ECacheOfflineFlag offline_flag,
                           GCancellable *cancellable,
                           GError **error)
 {
        GSList *components = NULL;
        GSList *extras = NULL;
+       GSList *custom_flags_lst = NULL;
        gboolean success;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
@@ -2414,9 +2452,11 @@ e_cal_cache_put_component (ECalCache *cal_cache,
        components = g_slist_prepend (components, component);
        if (extra)
                extras = g_slist_prepend (extras, (gpointer) extra);
+       custom_flags_lst = g_slist_prepend (custom_flags_lst, GUINT_TO_POINTER (custom_flags));
 
-       success = e_cal_cache_put_components (cal_cache, components, extras, offline_flag, cancellable, 
error);
+       success = e_cal_cache_put_components (cal_cache, components, extras, custom_flags_lst, offline_flag, 
cancellable, error);
 
+       g_slist_free (custom_flags_lst);
        g_slist_free (components);
        g_slist_free (extras);
 
@@ -2427,7 +2467,8 @@ e_cal_cache_put_component (ECalCache *cal_cache,
  * e_cal_cache_put_components:
  * @cal_cache: an #ECalCache
  * @components: (element-type ECalComponent): a #GSList of #ECalComponent to put into the @cal_cache
- * @extras: (nullable) (element-type utf8): an extra data to store in association with the @components
+ * @extras: (nullable) (element-type utf8): optional extra data to store in association with the @components
+ * @custom_flags: (nullable) (element-type guint32): optional custom flags to use for the @components
  * @offline_flag: one of #ECacheOfflineFlag, whether putting these components in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -2435,8 +2476,9 @@ e_cal_cache_put_component (ECalCache *cal_cache,
  * Adds a list of @components into the @cal_cache. Any existing with the same UID
  * and RID are replaced.
  *
- * If @extras is not %NULL, it's length should be the same as the length
- * of the @components.
+ * If @extras is not %NULL, its length should be the same as the length
+ * of the @components. Similarly the non-NULL @custom_flags length
+ * should be the same as the length of the @components.
  *
  * Returns: Whether succeeded.
  *
@@ -2446,17 +2488,19 @@ gboolean
 e_cal_cache_put_components (ECalCache *cal_cache,
                            const GSList *components,
                            const GSList *extras,
+                           const GSList *custom_flags,
                            ECacheOfflineFlag offline_flag,
                            GCancellable *cancellable,
                            GError **error)
 {
-       const GSList *clink, *elink;
+       const GSList *clink, *elink, *flink;
        ECache *cache;
        ECacheColumnValues *other_columns;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
        g_return_val_if_fail (extras == NULL || g_slist_length ((GSList *) components) == g_slist_length 
((GSList *) extras), FALSE);
+       g_return_val_if_fail (custom_flags == NULL || g_slist_length ((GSList *) components) == 
g_slist_length ((GSList *) custom_flags), FALSE);
 
        cache = E_CACHE (cal_cache);
        other_columns = e_cache_column_values_new ();
@@ -2464,9 +2508,12 @@ e_cal_cache_put_components (ECalCache *cal_cache,
        e_cache_lock (cache, E_CACHE_LOCK_WRITE);
        e_cache_freeze_revision_change (cache);
 
-       for (clink = components, elink = extras; clink; clink = g_slist_next (clink), elink = g_slist_next 
(elink)) {
+       for (clink = components, elink = extras, flink = custom_flags;
+            clink;
+            (clink = g_slist_next (clink)), (elink = g_slist_next (elink)), (flink = g_slist_next (flink))) {
                ECalComponent *component = clink->data;
                const gchar *extra = elink ? elink->data : NULL;
+               guint32 custom_flags_val = flink ? GPOINTER_TO_UINT (flink->data) : 0;
                ECalComponentId *id;
                gchar *uid, *rev, *icalstring;
 
@@ -2479,15 +2526,16 @@ e_cal_cache_put_components (ECalCache *cal_cache,
 
                if (extra)
                        e_cache_column_values_take_value (other_columns, ECC_COLUMN_EXTRA, g_strdup (extra));
+               e_cache_column_values_take_value (other_columns, ECC_COLUMN_CUSTOM_FLAGS, g_strdup_printf 
("%u", custom_flags_val));
 
                id = e_cal_component_get_id (component);
                if (id) {
-                       uid = ecc_encode_id_sql (id->uid, id->rid);
+                       uid = ecc_encode_id_sql (e_cal_component_id_get_uid (id), e_cal_component_id_get_rid 
(id));
                } else {
                        g_warn_if_reached ();
                        uid = g_strdup ("");
                }
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
 
                rev = e_cal_cache_dup_component_revision (cal_cache, e_cal_component_get_icalcomponent 
(component));
 
@@ -2514,6 +2562,7 @@ e_cal_cache_put_components (ECalCache *cal_cache,
  * @cal_cache: an #ECalCache
  * @uid: a UID of the component to remove
  * @rid: (nullable): an optional Recurrence-ID to remove
+ * @custom_flags: custom flags for the component, not interpreted by the @cal_cache
  * @offline_flag: one of #ECacheOfflineFlag, whether removing this component in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -2530,24 +2579,27 @@ gboolean
 e_cal_cache_remove_component (ECalCache *cal_cache,
                              const gchar *uid,
                              const gchar *rid,
+                             guint32 custom_flags,
                              ECacheOfflineFlag offline_flag,
                              GCancellable *cancellable,
                              GError **error)
 {
-       ECalComponentId id;
+       ECalComponentId *id;
        GSList *ids = NULL;
+       GSList *custom_flags_lst = NULL;
        gboolean success;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
 
-       id.uid = (gchar *) uid;
-       id.rid = (gchar *) rid;
+       id = e_cal_component_id_new (uid, rid);
 
-       ids = g_slist_prepend (ids, &id);
+       ids = g_slist_prepend (ids, id);
+       custom_flags_lst = g_slist_prepend (custom_flags_lst, GUINT_TO_POINTER (custom_flags));
 
-       success = e_cal_cache_remove_components (cal_cache, ids, offline_flag, cancellable, error);
+       success = e_cal_cache_remove_components (cal_cache, ids, custom_flags_lst, offline_flag, cancellable, 
error);
 
-       g_slist_free (ids);
+       g_slist_free_full (ids, e_cal_component_id_free);
+       g_slist_free (custom_flags_lst);
 
        return success;
 }
@@ -2556,6 +2608,7 @@ e_cal_cache_remove_component (ECalCache *cal_cache,
  * e_cal_cache_remove_components:
  * @cal_cache: an #ECalCache
  * @ids: (element-type ECalComponentId): a #GSList of components to remove
+ * @custom_flags: (element-type guint32) (nullable): an optional #GSList of custom flags for the @ids
  * @offline_flag: one of #ECacheOfflineFlag, whether removing these comonents in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -2563,6 +2616,9 @@ e_cal_cache_remove_component (ECalCache *cal_cache,
  * Removes components identified by @uid and @rid from the @cal_cache
  * in the @ids list. When the @rid is %NULL, or an empty string, then
  * removes the master object only, without any detached instance.
+ * The @custom_flags is used, if not %NULL, only if the @offline_flag
+ * is %E_CACHE_IS_OFFLINE. Otherwise it's ignored. The length of
+ * the @custom_flags should match the length of @ids, when not %NULL.
  *
  * Returns: Whether succeeded.
  *
@@ -2571,23 +2627,26 @@ e_cal_cache_remove_component (ECalCache *cal_cache,
 gboolean
 e_cal_cache_remove_components (ECalCache *cal_cache,
                               const GSList *ids,
+                              const GSList *custom_flags,
                               ECacheOfflineFlag offline_flag,
                               GCancellable *cancellable,
                               GError **error)
 {
        ECache *cache;
-       const GSList *link;
+       const GSList *link, *flink;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
+       g_return_val_if_fail (custom_flags == NULL || g_slist_length ((GSList *) ids) == g_slist_length 
((GSList *) custom_flags), FALSE);
 
        cache = E_CACHE (cal_cache);
 
        e_cache_lock (cache, E_CACHE_LOCK_WRITE);
        e_cache_freeze_revision_change (cache);
 
-       for (link = ids; success && link; link = g_slist_next (link)) {
+       for (link = ids, flink = custom_flags; success && link; (link = g_slist_next (link)), (flink = 
g_slist_next (flink))) {
                const ECalComponentId *id = link->data;
+               guint32 custom_flags_val = flink ? GPOINTER_TO_UINT (flink->data) : 0;
                gchar *uid;
 
                g_warn_if_fail (id != NULL);
@@ -2595,7 +2654,17 @@ e_cal_cache_remove_components (ECalCache *cal_cache,
                if (!id)
                        continue;
 
-               uid = ecc_encode_id_sql (id->uid, id->rid);
+               if (offline_flag == E_CACHE_IS_OFFLINE && flink) {
+                       success = e_cal_cache_set_component_custom_flags (cal_cache,
+                               e_cal_component_id_get_uid (id),
+                               e_cal_component_id_get_rid (id),
+                               custom_flags_val, cancellable, error);
+
+                       if (!success)
+                               break;
+               }
+
+               uid = ecc_encode_id_sql (e_cal_component_id_get_uid (id), e_cal_component_id_get_rid (id));
 
                success = e_cache_remove (cache, uid, offline_flag, cancellable, error);
 
@@ -2689,6 +2758,123 @@ e_cal_cache_get_component_as_string (ECalCache *cal_cache,
        return *out_icalstring != NULL;
 }
 
+/**
+ * e_cal_cache_set_component_custom_flags:
+ * @cal_cache: an #ECalCache
+ * @uid: a UID of the component
+ * @rid: (nullable): an optional Recurrence-ID
+ * @custom_flags: the custom flags to set for the component
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Sets or replaces the custom flags associated with a component
+ * identified by @uid and optionally @rid.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_cache_set_component_custom_flags (ECalCache *cal_cache,
+                                       const gchar *uid,
+                                       const gchar *rid,
+                                       guint32 custom_flags,
+                                       GCancellable *cancellable,
+                                       GError **error)
+{
+       gchar *id, *stmt;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       id = ecc_encode_id_sql (uid, rid);
+
+       if (!e_cache_contains (E_CACHE (cal_cache), id, E_CACHE_INCLUDE_DELETED)) {
+               g_free (id);
+
+               if (rid && *rid)
+                       g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s”, “%s” not 
found"), uid, rid);
+               else
+                       g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s” not 
found"), uid);
+
+               return FALSE;
+       }
+
+       stmt = e_cache_sqlite_stmt_printf (
+               "UPDATE " E_CACHE_TABLE_OBJECTS " SET " ECC_COLUMN_CUSTOM_FLAGS "=%u"
+               " WHERE " E_CACHE_COLUMN_UID "=%Q",
+               custom_flags, id);
+
+       success = e_cache_sqlite_exec (E_CACHE (cal_cache), stmt, cancellable, error);
+
+       e_cache_sqlite_stmt_free (stmt);
+       g_free (id);
+
+       return success;
+}
+
+/**
+ * e_cal_cache_get_component_custom_flags:
+ * @cal_cache: an #ECalCache
+ * @uid: a UID of the component
+ * @rid: (nullable): an optional Recurrence-ID
+ * @out_custom_flags: (out): return location to store the custom flags
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the custom flags previously set for @uid and @rid, either with
+ * e_cal_cache_set_component_custom_flags(), when adding components or
+ * when removing components in offline.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_cache_get_component_custom_flags (ECalCache *cal_cache,
+                                       const gchar *uid,
+                                       const gchar *rid,
+                                       guint32 *out_custom_flags,
+                                       GCancellable *cancellable,
+                                       GError **error)
+{
+       gchar *id, *stmt;
+       guint64 value = 0;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       id = ecc_encode_id_sql (uid, rid);
+
+       if (!e_cache_contains (E_CACHE (cal_cache), id, E_CACHE_INCLUDE_DELETED)) {
+               g_free (id);
+
+               if (rid && *rid)
+                       g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s”, “%s” not 
found"), uid, rid);
+               else
+                       g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s” not 
found"), uid);
+
+               return FALSE;
+       }
+
+       stmt = e_cache_sqlite_stmt_printf (
+               "SELECT " ECC_COLUMN_CUSTOM_FLAGS " FROM " E_CACHE_TABLE_OBJECTS
+               " WHERE " E_CACHE_COLUMN_UID "=%Q",
+               id);
+
+       success = e_cache_sqlite_select (E_CACHE (cal_cache), stmt, e_cal_cache_get_uint64_cb, &value, 
cancellable, error);
+
+       e_cache_sqlite_stmt_free (stmt);
+       g_free (id);
+
+       if (out_custom_flags)
+               *out_custom_flags = (guint32) value;
+
+       return success;
+}
+
 /**
  * e_cal_cache_set_component_extra:
  * @cal_cache: an #ECalCache
@@ -2819,7 +3005,7 @@ e_cal_cache_get_component_extra (ECalCache *cal_cache,
  * Gets all the ID-s the @extra data is set for.
  *
  * The @out_ids should be freed with
- * g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+ * g_slist_free_full (ids, (GDestroyNotify) e_cal_component_id_free);
  * when no longer needed.
  *
  * Returns: Whether succeeded.
@@ -3013,6 +3199,7 @@ ecc_search_icalstrings_cb (ECalCache *cal_cache,
                           const gchar *revision,
                           const gchar *object,
                           const gchar *extra,
+                          guint32 custom_flags,
                           EOfflineState offline_state,
                           gpointer user_data)
 {
@@ -3050,7 +3237,7 @@ e_cal_cache_get_components_in_range_as_strings (ECalCache *cal_cache,
                                                GError **error)
 {
        gchar *sexp;
-       struct icaltimetype itt_start, itt_end;
+       ICalTime *itt_start, *itt_end;
        gboolean success;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
@@ -3058,12 +3245,25 @@ e_cal_cache_get_components_in_range_as_strings (ECalCache *cal_cache,
 
        *out_icalstrings = NULL;
 
-       itt_start = icaltime_from_timet_with_zone (range_start, FALSE, NULL);
-       itt_end = icaltime_from_timet_with_zone (range_end, FALSE, NULL);
+       itt_start = i_cal_time_from_timet_with_zone (range_start, FALSE, NULL);
+       itt_end = i_cal_time_from_timet_with_zone (range_end, FALSE, NULL);
 
        sexp = g_strdup_printf ("(occur-in-time-range? (make-time \"%04d%02d%02dT%02d%02d%02dZ\") (make-time 
\"%04d%02d%02dT%02d%02d%02dZ\"))",
-               itt_start.year, itt_start.month, itt_start.day, itt_start.hour, itt_start.minute, 
itt_start.second,
-               itt_end.year, itt_end.month, itt_end.day, itt_end.hour, itt_end.minute, itt_end.second);
+               i_cal_time_get_year (itt_start),
+               i_cal_time_get_month (itt_start),
+               i_cal_time_get_day (itt_start),
+               i_cal_time_get_hour (itt_start),
+               i_cal_time_get_minute (itt_start),
+               i_cal_time_get_second (itt_start),
+               i_cal_time_get_year (itt_end),
+               i_cal_time_get_month (itt_end),
+               i_cal_time_get_day (itt_end),
+               i_cal_time_get_hour (itt_end),
+               i_cal_time_get_minute (itt_end),
+               i_cal_time_get_second (itt_end));
+
+       g_clear_object (&itt_start);
+       g_clear_object (&itt_end);
 
        success = e_cal_cache_search_with_callback (cal_cache, sexp, ecc_search_icalstrings_cb,
                out_icalstrings, cancellable, error);
@@ -3087,6 +3287,7 @@ ecc_search_data_cb (ECalCache *cal_cache,
                    const gchar *revision,
                    const gchar *object,
                    const gchar *extra,
+                   guint32 custom_flags,
                    EOfflineState offline_state,
                    gpointer user_data)
 {
@@ -3108,6 +3309,7 @@ ecc_search_components_cb (ECalCache *cal_cache,
                          const gchar *revision,
                          const gchar *object,
                          const gchar *extra,
+                         guint32 custom_flags,
                          EOfflineState offline_state,
                          gpointer user_data)
 {
@@ -3129,6 +3331,7 @@ ecc_search_ids_cb (ECalCache *cal_cache,
                   const gchar *revision,
                   const gchar *object,
                   const gchar *extra,
+                  guint32 custom_flags,
                   EOfflineState offline_state,
                   gpointer user_data)
 {
@@ -3242,7 +3445,7 @@ e_cal_cache_search_components (ECalCache *cal_cache,
  * Searches the @cal_cache with the given @sexp and returns ECalComponentId
  * for those components which satisfy the search expression.
  * The @out_ids should be freed with
- * g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+ * g_slist_free_full (ids, (GDestroyNotify) e_cal_component_id_free);
  * when no longer needed.
  *
  * Returns: Whether succeeded.
@@ -3269,7 +3472,7 @@ e_cal_cache_search_ids (ECalCache *cal_cache,
        if (success) {
                *out_ids = g_slist_reverse (*out_ids);
        } else {
-               g_slist_free_full (*out_ids, (GDestroyNotify) e_cal_component_free_id);
+               g_slist_free_full (*out_ids, (GDestroyNotify) e_cal_component_id_free);
                *out_ids = NULL;
        }
 
@@ -3280,8 +3483,8 @@ e_cal_cache_search_ids (ECalCache *cal_cache,
  * e_cal_cache_search_with_callback:
  * @cal_cache: an #ECalCache
  * @sexp: (nullable): search expression; use %NULL or an empty string to list all stored components
- * @func: an #ECalCacheSearchFunc callback to call for each row which satisfies @sexp
- * @user_data: user data for @func
+ * @func: (scope call): an #ECalCacheSearchFunc callback to call for each row which satisfies @sexp
+ * @user_data: (closure func): user data for @func
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -3382,7 +3585,7 @@ e_cal_cache_get_offline_changes   (ECalCache *cal_cache,
 /**
  * e_cal_cache_delete_attachments:
  * @cal_cache: an #ECalCache
- * @component: an icalcomponent
+ * @component: an #ICalComponent
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -3396,33 +3599,29 @@ e_cal_cache_get_offline_changes (ECalCache *cal_cache,
  **/
 gboolean
 e_cal_cache_delete_attachments (ECalCache *cal_cache,
-                               icalcomponent *component,
+                               ICalComponent *component,
                                GCancellable *cancellable,
                                GError **error)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
        gchar *cache_dirname = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
        g_return_val_if_fail (component != NULL, FALSE);
 
-       for (prop = icalcomponent_get_first_property (component, ICAL_ATTACH_PROPERTY);
+       for (prop = i_cal_component_get_first_property (component, I_CAL_ATTACH_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (component, ICAL_ATTACH_PROPERTY)) {
-               icalattach *attach = icalproperty_get_attach (prop);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (component, 
I_CAL_ATTACH_PROPERTY)) {
+               ICalAttach *attach = i_cal_property_get_attach (prop);
 
-               if (attach && icalattach_get_is_url (attach)) {
+               if (attach && i_cal_attach_get_is_url (attach)) {
                        const gchar *url;
 
-                       url = icalattach_get_url (attach);
+                       url = i_cal_attach_get_url (attach);
                        if (url) {
-                               gsize buf_size;
                                gchar *buf;
 
-                               buf_size = strlen (url);
-                               buf = g_malloc0 (buf_size + 1);
-
-                               icalvalue_decode_ical_string (url, buf, buf_size);
+                               buf = i_cal_value_decode_ical_string (url);
 
                                if (g_str_has_prefix (buf, "file://")) {
                                        gchar *filename;
@@ -3444,6 +3643,8 @@ e_cal_cache_delete_attachments (ECalCache *cal_cache,
                                g_free (buf);
                        }
                }
+
+               g_clear_object (&attach);
        }
 
        g_free (cache_dirname);
@@ -3451,26 +3652,6 @@ e_cal_cache_delete_attachments (ECalCache *cal_cache,
        return TRUE;
 }
 
-static gboolean
-e_cal_cache_get_uint64_cb (ECache *cache,
-                          gint ncols,
-                          const gchar **column_names,
-                          const gchar **column_values,
-                          gpointer user_data)
-{
-       guint64 *pui64 = user_data;
-
-       g_return_val_if_fail (pui64 != NULL, FALSE);
-
-       if (ncols == 1) {
-               *pui64 = column_values[0] ? g_ascii_strtoull (column_values[0], NULL, 10) : 0;
-       } else {
-               *pui64 = 0;
-       }
-
-       return TRUE;
-}
-
 static gint
 e_cal_cache_get_current_timezone_refs (ECalCache *cal_cache,
                                       const gchar *tzid,
@@ -3495,7 +3676,7 @@ e_cal_cache_get_current_timezone_refs (ECalCache *cal_cache,
 /**
  * e_cal_cache_put_timezone:
  * @cal_cache: an #ECalCache
- * @zone: an icaltimezone to put
+ * @zone: an #ICalTimezone to put
  * @inc_ref_counts: how many refs to add, or 0 to have it stored forever
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -3512,7 +3693,7 @@ e_cal_cache_get_current_timezone_refs (ECalCache *cal_cache,
  **/
 gboolean
 e_cal_cache_put_timezone (ECalCache *cal_cache,
-                         const icaltimezone *zone,
+                         const ICalTimezone *zone,
                          guint inc_ref_counts,
                          GCancellable *cancellable,
                          GError **error)
@@ -3521,27 +3702,29 @@ e_cal_cache_put_timezone (ECalCache *cal_cache,
        gchar *stmt;
        const gchar *tzid;
        gchar *component_str;
-       icalcomponent *component;
+       ICalComponent *component;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
        g_return_val_if_fail (zone != NULL, FALSE);
 
-       tzid = icaltimezone_get_tzid ((icaltimezone *) zone);
+       tzid = i_cal_timezone_get_tzid ((ICalTimezone *) zone);
        if (!tzid) {
                g_set_error_literal (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Cannot add timezone 
without tzid"));
                return FALSE;
        }
 
-       if (ecc_tzid_is_libical_builtin (icaltimezone_get_tzid ((icaltimezone *) zone)))
+       if (ecc_tzid_is_libical_builtin (tzid))
                return TRUE;
 
-       component = icaltimezone_get_component ((icaltimezone *) zone);
+       component = i_cal_timezone_get_component ((ICalTimezone *) zone);
        if (!component) {
                g_set_error_literal (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Cannot add timezone 
without component"));
                return FALSE;
        }
 
-       component_str = icalcomponent_as_ical_string_r (component);
+       component_str = i_cal_component_as_ical_string_r (component);
+       g_clear_object (&component);
+
        if (!component_str) {
                g_set_error_literal (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Cannot add timezone 
with invalid component"));
                return FALSE;
@@ -3580,13 +3763,13 @@ e_cal_cache_put_timezone (ECalCache *cal_cache,
  * e_cal_cache_get_timezone:
  * @cal_cache: an #ECalCache
  * @tzid: a timezone ID to get
- * @out_zone: (out) (transfer none): return location for the icaltimezone
+ * @out_zone: (out) (transfer none): return location for the #ICalTimezone
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Gets a timezone with given @tzid, which had been previously put
  * into the @cal_cache with e_cal_cache_put_timezone().
- * The returned icaltimezone is owned by the @cal_cache and should
+ * The returned ICalTimezone is owned by the @cal_cache and should
  * not be freed.
  *
  * Returns: Whether succeeded.
@@ -3596,7 +3779,7 @@ e_cal_cache_put_timezone (ECalCache *cal_cache,
 gboolean
 e_cal_cache_get_timezone (ECalCache *cal_cache,
                          const gchar *tzid,
-                         icaltimezone **out_zone,
+                         ICalTimezone **out_zone,
                          GCancellable *cancellable,
                          GError **error)
 
@@ -3625,7 +3808,7 @@ e_cal_cache_get_timezone (ECalCache *cal_cache,
        success = e_cal_cache_dup_timezone_as_string (cal_cache, tzid, &zone_str, cancellable, error);
 
        if (success && zone_str) {
-               icaltimezone *zone;
+               ICalTimezone *zone;
 
                zone = ecc_timezone_from_string (zone_str);
                if (zone) {
@@ -3647,13 +3830,13 @@ e_cal_cache_get_timezone (ECalCache *cal_cache,
  * e_cal_cache_dup_timezone_as_string:
  * @cal_cache: an #ECalCache
  * @tzid: a timezone ID to get
- * @out_zone_string: (out) (transfer full): return location for the icaltimezone as iCal string
+ * @out_zone_string: (out) (transfer full): return location for the #ICalTimezone as iCal string
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Gets a timezone with given @tzid, which had been previously put
  * into the @cal_cache with e_cal_cache_put_timezone().
- * The returned string is an iCal string for that icaltimezone and
+ * The returned string is an iCal string for that ICalTimezone and
  * should be freed with g_free() when no longer needed.
  *
  * Returns: Whether succeeded.
@@ -3706,7 +3889,7 @@ e_cal_cache_load_zones_cb (ECache *cache,
 
        /* Do not overwrite already loaded timezones, they can be used anywhere around */
        if (!g_hash_table_lookup (loaded_zones, column_values[0])) {
-               icaltimezone *zone;
+               ICalTimezone *zone;
 
                zone = ecc_timezone_from_string (column_values[1]);
                if (zone) {
@@ -3720,13 +3903,13 @@ e_cal_cache_load_zones_cb (ECache *cache,
 /**
  * e_cal_cache_list_timezones:
  * @cal_cache: an #ECalCache
- * @out_timezones: (out) (transfer container) (element-type icaltimezone): return location for the list of 
stored timezones
+ * @out_timezones: (out) (transfer container) (element-type ICalTimezone): return location for the list of 
stored timezones
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Gets a list of all stored timezones by the @cal_cache.
  * Only the returned list should be freed with g_list_free()
- * when no longer needed; the icaltimezone-s are owned
+ * when no longer needed; the #ICalTimezone-s are owned
  * by the @cal_cache.
  *
  * Note: The list can contain timezones previously stored
@@ -3914,14 +4097,13 @@ _e_cal_cache_remove_loaded_timezones (ECalCache *cal_cache)
  *
  * An #ECalRecurResolveTimezoneCb callback, which can be used
  * with e_cal_recur_generate_instances_sync(). The @cal_cache
- * is supposed to be an #ECalCache instance. See also
- * e_cal_cache_resolve_timezone_simple_cb().
+ * is supposed to be an #ECalCache instance.
  *
- * Returns: (transfer none) (nullable): the resolved icaltimezone, or %NULL, if not found
+ * Returns: (transfer none) (nullable): the resolved #ICalTimezone, or %NULL, if not found
  *
  * Since: 3.26
  **/
-icaltimezone *
+ICalTimezone *
 e_cal_cache_resolve_timezone_cb (const gchar *tzid,
                                 gpointer cal_cache,
                                 GCancellable *cancellable,
@@ -3929,29 +4111,6 @@ e_cal_cache_resolve_timezone_cb (const gchar *tzid,
 {
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), NULL);
 
-       return e_cal_cache_resolve_timezone_simple_cb (tzid, cal_cache);
-}
-
-/**
- * e_cal_cache_resolve_timezone_simple_cb:
- * @tzid: a timezone ID
- * @cal_cache: an #ECalCache
- *
- * An #ECalRecurResolveTimezoneFn callback, which can be used
- * with e_cal_recur_ensure_end_dates() and simialr functions.
- * The @cal_cache is supposed to be an #ECalCache instance. See
- * also e_cal_cache_resolve_timezone_cb().
- *
- * Returns: (transfer none) (nullable): the resolved icaltimezone, or %NULL, if not found
- *
- * Since: 3.26
- **/
-icaltimezone *
-e_cal_cache_resolve_timezone_simple_cb (const gchar *tzid,
-                                       gpointer cal_cache)
-{
-       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), NULL);
-
        return e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (cal_cache), tzid);
 }
 
@@ -3962,21 +4121,22 @@ ecc_search_delete_attachment_cb (ECalCache *cal_cache,
                                 const gchar *revision,
                                 const gchar *object,
                                 const gchar *extra,
+                                guint32 custom_flags,
                                 EOfflineState offline_state,
                                 gpointer user_data)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        GCancellable *cancellable = user_data;
        GError *local_error = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
        g_return_val_if_fail (object != NULL, FALSE);
 
-       icalcomp = icalcomponent_new_from_string (object);
-       if (!icalcomp)
+       icomp = i_cal_component_new_from_string (object);
+       if (!icomp)
                return TRUE;
 
-       if (!e_cal_cache_delete_attachments (cal_cache, icalcomp, cancellable, &local_error)) {
+       if (!e_cal_cache_delete_attachments (cal_cache, icomp, cancellable, &local_error)) {
                if (rid && !*rid)
                        rid = NULL;
 
@@ -3985,7 +4145,7 @@ ecc_search_delete_attachment_cb (ECalCache *cal_cache,
                g_clear_error (&local_error);
        }
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
 
        return !g_cancellable_is_cancelled (cancellable);
 }
@@ -4011,47 +4171,53 @@ ecc_empty_aux_tables (ECache *cache,
    <DTSTAMP> "-" <LAST-MODIFIED> "-" <SEQUENCE> */
 static gchar *
 ecc_dup_component_revision (ECalCache *cal_cache,
-                           icalcomponent *icalcomp)
+                           ICalComponent *icomp)
 {
-       struct icaltimetype itt;
-       icalproperty *prop;
+       ICalTime *itt;
+       ICalProperty *prop;
        GString *revision;
 
-       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (icomp != NULL, NULL);
 
        revision = g_string_sized_new (48);
 
-       itt = icalcomponent_get_dtstamp (icalcomp);
-       if (icaltime_is_null_time (itt) || !icaltime_is_valid_time (itt)) {
+       itt = i_cal_component_get_dtstamp (icomp);
+       if (!itt || i_cal_time_is_null_time (itt) || !i_cal_time_is_valid_time (itt)) {
                g_string_append_c (revision, 'x');
        } else {
                g_string_append_printf (revision, "%04d%02d%02d%02d%02d%02d",
-                       itt.year, itt.month, itt.day,
-                       itt.hour, itt.minute, itt.second);
+                       i_cal_time_get_year (itt), i_cal_time_get_month (itt), i_cal_time_get_day (itt),
+                       i_cal_time_get_hour (itt), i_cal_time_get_minute (itt), i_cal_time_get_second (itt));
        }
 
+       g_clear_object (&itt);
+
        g_string_append_c (revision, '-');
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_LASTMODIFIED_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_LASTMODIFIED_PROPERTY);
        if (prop)
-               itt = icalproperty_get_lastmodified (prop);
+               itt = i_cal_property_get_lastmodified (prop);
 
-       if (!prop || icaltime_is_null_time (itt) || !icaltime_is_valid_time (itt)) {
+       if (!prop || !itt || i_cal_time_is_null_time (itt) || !i_cal_time_is_valid_time (itt)) {
                g_string_append_c (revision, 'x');
        } else {
                g_string_append_printf (revision, "%04d%02d%02d%02d%02d%02d",
-                       itt.year, itt.month, itt.day,
-                       itt.hour, itt.minute, itt.second);
+                       i_cal_time_get_year (itt), i_cal_time_get_month (itt), i_cal_time_get_day (itt),
+                       i_cal_time_get_hour (itt), i_cal_time_get_minute (itt), i_cal_time_get_second (itt));
        }
 
+       g_clear_object (&prop);
+       g_clear_object (&itt);
+
        g_string_append_c (revision, '-');
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_SEQUENCE_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_SEQUENCE_PROPERTY);
        if (!prop) {
                g_string_append_c (revision, 'x');
        } else {
-               g_string_append_printf (revision, "%d", icalproperty_get_sequence (prop));
+               g_string_append_printf (revision, "%d", i_cal_property_get_sequence (prop));
        }
+       g_clear_object (&prop);
 
        return g_string_free (revision, FALSE);
 }
@@ -4163,41 +4329,41 @@ e_cal_cache_remove_all_locked (ECache *cache,
 static void
 cal_cache_free_zone (gpointer ptr)
 {
-       icaltimezone *zone = ptr;
+       ICalTimezone *zone = ptr;
 
        if (zone)
-               icaltimezone_free (zone, 1);
+               g_object_unref (zone);
 }
 
 static void
 ecc_add_cached_timezone (ETimezoneCache *cache,
-                        icaltimezone *zone)
+                        ICalTimezone *zone)
 {
        ECalCache *cal_cache;
 
        cal_cache = E_CAL_CACHE (cache);
 
-       if (!zone || ecc_tzid_is_libical_builtin (icaltimezone_get_tzid (zone)))
+       if (!zone || ecc_tzid_is_libical_builtin (i_cal_timezone_get_tzid (zone)))
                return;
 
        e_cal_cache_put_timezone (cal_cache, zone, 0, NULL, NULL);
 }
 
-static icaltimezone *
+static ICalTimezone *
 ecc_get_cached_timezone (ETimezoneCache *cache,
                         const gchar *tzid)
 {
        ECalCache *cal_cache;
-       icaltimezone *zone = NULL;
-       icaltimezone *builtin_zone = NULL;
-       icalcomponent *icalcomp;
-       icalproperty *prop;
+       ICalTimezone *zone = NULL;
+       ICalTimezone *builtin_zone = NULL;
+       ICalComponent *icomp, *clone;
+       ICalProperty *prop;
        const gchar *builtin_tzid;
 
        cal_cache = E_CAL_CACHE (cache);
 
        if (g_str_equal (tzid, "UTC"))
-               return icaltimezone_get_utc_timezone ();
+               return i_cal_timezone_get_utc_timezone ();
 
        g_rec_mutex_lock (&cal_cache->priv->timezones_lock);
 
@@ -4211,19 +4377,19 @@ ecc_get_cached_timezone (ETimezoneCache *cache,
                goto exit;
 
        /* Try the location first */
-       /*zone = icaltimezone_get_builtin_timezone (tzid);
+       /*zone = i_cal_timezone_get_builtin_timezone (tzid);
        if (zone)
                goto exit;*/
 
        /* Try to replace the original time zone with a more complete
         * and/or potentially updated built-in time zone.  Note this also
         * applies to TZIDs which match built-in time zones exactly: they
-        * are extracted via icaltimezone_get_builtin_timezone_from_tzid(). */
+        * are extracted via i_cal_timezone_get_builtin_timezone_from_tzid(). */
 
        builtin_tzid = e_cal_match_tzid (tzid);
 
        if (builtin_tzid)
-               builtin_zone = icaltimezone_get_builtin_timezone_from_tzid (builtin_tzid);
+               builtin_zone = i_cal_timezone_get_builtin_timezone_from_tzid (builtin_tzid);
 
        if (!builtin_zone) {
                e_cal_cache_get_timezone (cal_cache, tzid, &zone, NULL, NULL);
@@ -4232,34 +4398,32 @@ ecc_get_cached_timezone (ETimezoneCache *cache,
 
        /* Use the built-in time zone *and* rename it.  Likely the caller
         * is asking for a specific TZID because it has an event with such
-        * a TZID.  Returning an icaltimezone with a different TZID would
+        * a TZID.  Returning an i_cal_timezone with a different TZID would
         * lead to broken VCALENDARs in the caller. */
 
-       icalcomp = icaltimezone_get_component (builtin_zone);
-       icalcomp = icalcomponent_new_clone (icalcomp);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_ANY_PROPERTY);
+       icomp = i_cal_timezone_get_component (builtin_zone);
+       clone = i_cal_component_new_clone (icomp);
+       g_object_unref (icomp);
+       icomp = clone;
 
-       while (prop != NULL) {
-               if (icalproperty_isa (prop) == ICAL_TZID_PROPERTY) {
-                       icalproperty_set_value_from_string (prop, tzid, "NO");
+       for (prop = i_cal_component_get_first_property (icomp, I_CAL_ANY_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icomp, ICAL_ANY_PROPERTY)) {
+               if (i_cal_property_isa (prop) == I_CAL_TZID_PROPERTY) {
+                       i_cal_property_set_value_from_string (prop, tzid, "NO");
+                       g_object_unref (prop);
                        break;
                }
-
-               prop = icalcomponent_get_next_property (icalcomp, ICAL_ANY_PROPERTY);
        }
 
-       if (icalcomp != NULL) {
-               zone = icaltimezone_new ();
-               if (icaltimezone_set_component (zone, icalcomp)) {
-                       tzid = icaltimezone_get_tzid (zone);
-                       g_hash_table_insert (cal_cache->priv->modified_timezones, g_strdup (tzid), zone);
-               } else {
-                       icalcomponent_free (icalcomp);
-                       icaltimezone_free (zone, 1);
-                       zone = NULL;
-               }
+       zone = i_cal_timezone_new ();
+       if (i_cal_timezone_set_component (zone, icomp)) {
+               tzid = i_cal_timezone_get_tzid (zone);
+               g_hash_table_insert (cal_cache->priv->modified_timezones, g_strdup (tzid), zone);
+       } else {
+               g_clear_object (&zone);
        }
+       g_clear_object (&icomp);
 
  exit:
        g_rec_mutex_unlock (&cal_cache->priv->timezones_lock);
@@ -4314,7 +4478,7 @@ e_cal_cache_class_init (ECalCacheClass *klass)
 
        /**
         * ECalCache:dup-component-revision:
-        * A signal being called to get revision of an icalcomponent.
+        * A signal being called to get revision of an ICalComponent.
         * The default implementation uses a concatenation of
         * DTSTAMP '-' LASTMODIFIED '-' SEQUENCE.
         **/
@@ -4337,7 +4501,7 @@ e_cal_cache_class_init (ECalCacheClass *klass)
         * A signal being called to get timezone when putting component
         * into the cache. It's used to make sure the cache contains
         * all timezones which are needed by the component. The returned
-        * icaltimezone will not be freed.
+        * ICalTimezone will not be freed.
         *
         * Since: 3.30
         **/
diff --git a/src/calendar/libedata-cal/e-cal-cache.h b/src/calendar/libedata-cal/e-cal-cache.h
index 3cef7517b..4e3ca2668 100644
--- a/src/calendar/libedata-cal/e-cal-cache.h
+++ b/src/calendar/libedata-cal/e-cal-cache.h
@@ -55,7 +55,7 @@ typedef struct _ECalCachePrivate ECalCachePrivate;
  * @uid: UID of the component
  * @rid: Recurrence-ID of the component
  * @revision: stored revision of the component
- * @object: the component itself, as iCalalendar string
+ * @object: the component itself, as an iCalendar string
  * @state: an #EOfflineState of the component
  *
  * Holds the information about offline change for one component.
@@ -131,7 +131,8 @@ void                e_cal_cache_search_data_free    (/* ECalCacheSearchData * */ gpointer 
ptr);
  * @revision: the object revision
  * @object: the object itself
  * @extra: extra data stored with the object
- * @offline_state: objects offline state, one of #EOfflineState
+ * @custom_flags: object's custom flags
+ * @offline_state: object's offline state, one of #EOfflineState
  * @user_data: user data, as used in e_cal_cache_search_with_callback()
  *
  * A callback called for each object row when using
@@ -147,6 +148,7 @@ typedef gboolean (* ECalCacheSearchFunc)    (ECalCache *cal_cache,
                                                 const gchar *revision,
                                                 const gchar *object,
                                                 const gchar *extra,
+                                                guint32 custom_flags,
                                                 EOfflineState offline_state,
                                                 gpointer user_data);
 
@@ -178,8 +180,8 @@ struct _ECalCacheClass {
        /* Signals */
        gchar *         (* dup_component_revision)
                                                (ECalCache *cal_cache,
-                                                icalcomponent *icalcomp);
-       icaltimezone *  (* get_timezone)        (ECalCache *cal_cache,
+                                                ICalComponent *icomp);
+       ICalTimezone *  (* get_timezone)        (ECalCache *cal_cache,
                                                 const gchar *tzid);
 
        /* Padding for future expansion */
@@ -193,7 +195,7 @@ ECalCache * e_cal_cache_new                 (const gchar *filename,
                                                 GError **error);
 gchar *                e_cal_cache_dup_component_revision
                                                (ECalCache *cal_cache,
-                                                icalcomponent *icalcomp);
+                                                ICalComponent *icomp);
 gboolean       e_cal_cache_contains            (ECalCache *cal_cache,
                                                 const gchar *uid,
                                                 const gchar *rid,
@@ -201,23 +203,27 @@ gboolean  e_cal_cache_contains            (ECalCache *cal_cache,
 gboolean       e_cal_cache_put_component       (ECalCache *cal_cache,
                                                 ECalComponent *component,
                                                 const gchar *extra,
+                                                guint32 custom_flags,
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_cache_put_components      (ECalCache *cal_cache,
                                                 const GSList *components, /* ECalComponent * */
                                                 const GSList *extras, /* gchar * */
+                                                const GSList *custom_flags, /* guint32, through 
GUINT_TO_POINTER() */
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_cache_remove_component    (ECalCache *cal_cache,
                                                 const gchar *uid,
                                                 const gchar *rid,
+                                                guint32 custom_flags,
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_cache_remove_components   (ECalCache *cal_cache,
                                                 const GSList *ids, /* ECalComponentId * */
+                                                const GSList *custom_flags, /* guint32, through 
GUINT_TO_POINTER() */
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -234,6 +240,20 @@ gboolean   e_cal_cache_get_component_as_string
                                                 gchar **out_icalstring,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_cal_cache_set_component_custom_flags
+                                               (ECalCache *cal_cache,
+                                                const gchar *uid,
+                                                const gchar *rid,
+                                                guint32 custom_flags,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_cal_cache_get_component_custom_flags
+                                               (ECalCache *cal_cache,
+                                                const gchar *uid,
+                                                const gchar *rid,
+                                                guint32 *out_custom_flags,
+                                                GCancellable *cancellable,
+                                                GError **error);
 gboolean       e_cal_cache_set_component_extra (ECalCache *cal_cache,
                                                 const gchar *uid,
                                                 const gchar *rid,
@@ -303,18 +323,18 @@ GSList *  e_cal_cache_get_offline_changes (ECalCache *cal_cache,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_cache_delete_attachments  (ECalCache *cal_cache,
-                                                icalcomponent *component,
+                                                ICalComponent *component,
                                                 GCancellable *cancellable,
                                                 GError **error);
 
 gboolean       e_cal_cache_put_timezone        (ECalCache *cal_cache,
-                                                const icaltimezone *zone,
+                                                const ICalTimezone *zone,
                                                 guint inc_ref_counts,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_cache_get_timezone        (ECalCache *cal_cache,
                                                 const gchar *tzid,
-                                                icaltimezone **out_zone,
+                                                ICalTimezone **out_zone,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_cache_dup_timezone_as_string
@@ -335,13 +355,10 @@ gboolean  e_cal_cache_remove_timezone     (ECalCache *cal_cache,
 gboolean       e_cal_cache_remove_timezones    (ECalCache *cal_cache,
                                                 GCancellable *cancellable,
                                                 GError **error);
-icaltimezone * e_cal_cache_resolve_timezone_cb (const gchar *tzid,
+ICalTimezone * e_cal_cache_resolve_timezone_cb (const gchar *tzid,
                                                 gpointer cal_cache,
                                                 GCancellable *cancellable,
                                                 GError **error);
-icaltimezone * e_cal_cache_resolve_timezone_simple_cb
-                                               (const gchar *tzid,
-                                                gpointer cal_cache);
 
 G_END_DECLS
 
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index fbd1e62d5..94b069fea 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -104,7 +104,7 @@ enum {
 static guint signals[LAST_SIGNAL];
 
 /* To be able to call the ECalBackend implementation, which stores zones only in the memory */
-static icaltimezone *  (* ecmb_timezone_cache_parent_get_timezone) (ETimezoneCache *cache,
+static ICalTimezone *  (* ecmb_timezone_cache_parent_get_timezone) (ETimezoneCache *cache,
                                                                     const gchar *tzid);
 static GList *         (* ecmb_timezone_cache_parent_list_timezones) (ETimezoneCache *cache);
 
@@ -132,6 +132,7 @@ static gboolean ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
                                                  EConflictResolution conflict_resolution,
                                                  const GSList *in_instances,
                                                  const gchar *extra,
+                                                 guint32 opflags,
                                                  const gchar *orig_uid,
                                                  gboolean *out_requires_put,
                                                  gchar **out_new_uid,
@@ -309,6 +310,7 @@ ecmb_gather_locally_cached_objects_cb (ECalCache *cal_cache,
                                       const gchar *revision,
                                       const gchar *object,
                                       const gchar *extra,
+                                      guint32 opflags,
                                       EOfflineState offline_state,
                                       gpointer user_data)
 {
@@ -547,6 +549,7 @@ ecmb_upload_local_changes_sync (ECalMetaBackend *meta_backend,
        for (link = offline_changes; link && success; link = g_slist_next (link)) {
                ECalCacheOfflineChange *change = link->data;
                gchar *extra = NULL;
+               guint32 opflags = 0;
 
                success = !g_cancellable_set_error_if_cancelled (cancellable, error);
                if (!success)
@@ -560,6 +563,9 @@ ecmb_upload_local_changes_sync (ECalMetaBackend *meta_backend,
                if (!e_cal_cache_get_component_extra (cal_cache, change->uid, NULL, &extra, cancellable, 
NULL))
                        extra = NULL;
 
+               if (!e_cal_cache_get_component_custom_flags (cal_cache, change->uid, NULL, &opflags, 
cancellable, NULL))
+                       opflags = 0;
+
                if (change->state == E_OFFLINE_STATE_LOCALLY_CREATED ||
                    change->state == E_OFFLINE_STATE_LOCALLY_MODIFIED) {
                        GSList *instances = NULL;
@@ -568,7 +574,7 @@ ecmb_upload_local_changes_sync (ECalMetaBackend *meta_backend,
                        if (success) {
                                success = ecmb_save_component_wrapper_sync (meta_backend, cal_cache,
                                        change->state == E_OFFLINE_STATE_LOCALLY_MODIFIED,
-                                       conflict_resolution, instances, extra, change->uid, NULL, NULL, NULL, 
cancellable, error);
+                                       conflict_resolution, instances, extra, opflags, change->uid, NULL, 
NULL, NULL, cancellable, error);
                        }
 
                        g_slist_free_full (instances, g_object_unref);
@@ -576,10 +582,10 @@ ecmb_upload_local_changes_sync (ECalMetaBackend *meta_backend,
                        GError *local_error = NULL;
 
                        success = e_cal_meta_backend_remove_component_sync (meta_backend, conflict_resolution,
-                               change->uid, extra, change->object, cancellable, &local_error);
+                               change->uid, extra, change->object, opflags, cancellable, &local_error);
 
                        if (!success) {
-                               if (g_error_matches (local_error, E_DATA_CAL_ERROR, ObjectNotFound)) {
+                               if (g_error_matches (local_error, E_CAL_CLIENT_ERROR, 
E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND)) {
                                        g_clear_error (&local_error);
                                        success = TRUE;
                                } else if (local_error) {
@@ -607,6 +613,7 @@ ecmb_maybe_remove_from_cache (ECalMetaBackend *meta_backend,
                              ECalCache *cal_cache,
                              ECacheOfflineFlag offline_flag,
                              const gchar *uid,
+                             guint32 custom_flags,
                              GCancellable *cancellable,
                              GError **error)
 {
@@ -640,15 +647,15 @@ ecmb_maybe_remove_from_cache (ECalMetaBackend *meta_backend,
                id = e_cal_component_get_id (comp);
                if (id) {
                        if (!e_cal_cache_delete_attachments (cal_cache, e_cal_component_get_icalcomponent 
(comp), cancellable, error) ||
-                           !e_cal_cache_remove_component (cal_cache, id->uid, id->rid, offline_flag, 
cancellable, error)) {
-                               e_cal_component_free_id (id);
+                           !e_cal_cache_remove_component (cal_cache, e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id), custom_flags, offline_flag, cancellable, error)) {
+                               e_cal_component_id_free (id);
                                g_slist_free_full (comps, g_object_unref);
 
                                return FALSE;
                        }
 
                        e_cal_backend_notify_component_removed (cal_backend, id, comp, NULL);
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
                }
        }
 
@@ -888,13 +895,13 @@ ecmb_find_in_instances (const GSList *instances, /* ECalComponent * */
                if (!id)
                        continue;
 
-               if (g_strcmp0 (id->uid, uid) == 0 &&
-                   g_strcmp0 (id->rid, rid) == 0) {
-                       e_cal_component_free_id (id);
+               if (g_strcmp0 (e_cal_component_id_get_uid (id), uid) == 0 &&
+                   g_strcmp0 (e_cal_component_id_get_rid (id), rid) == 0) {
+                       e_cal_component_id_free (id);
                        return comp;
                }
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
        }
 
        return NULL;
@@ -906,6 +913,7 @@ ecmb_put_one_component (ECalMetaBackend *meta_backend,
                        ECacheOfflineFlag offline_flag,
                        ECalComponent *comp,
                        const gchar *extra,
+                       guint32 opflags,
                        GSList **inout_cache_instances,
                        GCancellable *cancellable,
                        GError **error)
@@ -918,10 +926,9 @@ ecmb_put_one_component (ECalMetaBackend *meta_backend,
        if (e_cal_component_has_attachments (comp)) {
                success = e_cal_meta_backend_store_inline_attachments_sync (meta_backend,
                        e_cal_component_get_icalcomponent (comp), cancellable, error);
-               e_cal_component_rescan (comp);
        }
 
-       success = success && e_cal_cache_put_component (cal_cache, comp, extra, offline_flag, cancellable, 
error);
+       success = success && e_cal_cache_put_component (cal_cache, comp, extra, opflags, offline_flag, 
cancellable, error);
 
        if (success) {
                ECalComponent *existing = NULL;
@@ -929,9 +936,9 @@ ecmb_put_one_component (ECalMetaBackend *meta_backend,
 
                id = e_cal_component_get_id (comp);
                if (id) {
-                       existing = ecmb_find_in_instances (*inout_cache_instances, id->uid, id->rid);
+                       existing = ecmb_find_in_instances (*inout_cache_instances, e_cal_component_id_get_uid 
(id), e_cal_component_id_get_rid (id));
 
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
                }
 
                if (existing) {
@@ -954,6 +961,7 @@ ecmb_put_instances (ECalMetaBackend *meta_backend,
                    ECacheOfflineFlag offline_flag,
                    const GSList *new_instances, /* ECalComponent * */
                    const gchar *extra,
+                   guint32 opflags,
                    GCancellable *cancellable,
                    GError **error)
 {
@@ -974,7 +982,7 @@ ecmb_put_instances (ECalMetaBackend *meta_backend,
        for (link = (GSList *) new_instances; link && success; link = g_slist_next (link)) {
                ECalComponent *comp = link->data;
 
-               success = ecmb_put_one_component (meta_backend, cal_cache, offline_flag, comp, extra, 
&cache_instances, cancellable, error);
+               success = ecmb_put_one_component (meta_backend, cal_cache, offline_flag, comp, extra, 
opflags, &cache_instances, cancellable, error);
        }
 
        /* What left got removed from the remote side, notify about it */
@@ -994,11 +1002,11 @@ ecmb_put_instances (ECalMetaBackend *meta_backend,
                        if (!success)
                                break;
 
-                       success = e_cal_cache_remove_component (cal_cache, id->uid, id->rid, offline_flag, 
cancellable, error);
+                       success = e_cal_cache_remove_component (cal_cache, e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id), opflags, offline_flag, cancellable, error);
 
                        e_cal_backend_notify_component_removed (cal_backend, id, comp, NULL);
 
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
                }
        }
 
@@ -1010,33 +1018,33 @@ ecmb_put_instances (ECalMetaBackend *meta_backend,
 static void
 ecmb_gather_timezones (ECalMetaBackend *meta_backend,
                       ETimezoneCache *timezone_cache,
-                      icalcomponent *icalcomp)
+                      ICalComponent *icomp)
 {
-       icalcomponent *subcomp;
-       icaltimezone *zone;
+       ICalComponent *subcomp;
+       ICalTimezone *zone;
 
        g_return_if_fail (E_IS_CAL_META_BACKEND (meta_backend));
        g_return_if_fail (E_IS_TIMEZONE_CACHE (timezone_cache));
-       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (icomp != NULL);
 
-       zone = icaltimezone_new ();
+       zone = i_cal_timezone_new ();
 
-       for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+       for (subcomp = i_cal_component_get_first_component (icomp, I_CAL_VTIMEZONE_COMPONENT);
             subcomp;
-            subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT)) {
-               icalcomponent *clone;
+            g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (icomp, 
I_CAL_VTIMEZONE_COMPONENT)) {
+               ICalComponent *clone;
 
-               clone = icalcomponent_new_clone (subcomp);
+               clone = i_cal_component_new_clone (subcomp);
 
-               if (icaltimezone_set_component (zone, clone)) {
-                       if (icaltimezone_get_tzid (zone))
+               if (i_cal_timezone_set_component (zone, clone)) {
+                       if (i_cal_timezone_get_tzid (zone))
                                e_timezone_cache_add_timezone (timezone_cache, zone);
-               } else {
-                       icalcomponent_free (clone);
                }
+
+               g_object_unref (clone);
        }
 
-       icaltimezone_free (zone, TRUE);
+       g_object_unref (zone);
 }
 
 static gboolean
@@ -1050,7 +1058,7 @@ ecmb_load_component_wrapper_sync (ECalMetaBackend *meta_backend,
                                  GError **error)
 {
        ECacheOfflineFlag offline_flag = E_CACHE_IS_ONLINE;
-       icalcomponent *icalcomp = NULL;
+       ICalComponent *icomp = NULL;
        GSList *new_instances = NULL;
        gchar *extra = NULL;
        const gchar *loaded_uid = NULL;
@@ -1058,51 +1066,51 @@ ecmb_load_component_wrapper_sync (ECalMetaBackend *meta_backend,
        GError *local_error = NULL;
 
        if (preloaded_object && *preloaded_object) {
-               icalcomp = icalcomponent_new_from_string (preloaded_object);
-               if (!icalcomp) {
-                       g_propagate_error (error, e_data_cal_create_error_fmt (InvalidObject, _("Preloaded 
object for UID “%s” is invalid"), uid));
+               icomp = i_cal_component_new_from_string (preloaded_object);
+               if (!icomp) {
+                       g_propagate_error (error, e_cal_client_error_create_fmt 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, _("Preloaded object for UID “%s” is invalid"), uid));
                        return FALSE;
                }
        } else if (!e_cal_meta_backend_ensure_connected_sync (meta_backend, cancellable, error) ||
-                  !e_cal_meta_backend_load_component_sync (meta_backend, uid, preloaded_extra, &icalcomp, 
&extra, cancellable, error)) {
+                  !e_cal_meta_backend_load_component_sync (meta_backend, uid, preloaded_extra, &icomp, 
&extra, cancellable, error)) {
                g_free (extra);
                return FALSE;
-       } else if (!icalcomp) {
-               g_propagate_error (error, e_data_cal_create_error_fmt (InvalidObject, _("Received object for 
UID “%s” is invalid"), uid));
+       } else if (!icomp) {
+               g_propagate_error (error, e_cal_client_error_create_fmt (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
_("Received object for UID “%s” is invalid"), uid));
                g_free (extra);
                return FALSE;
        }
 
-       if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT) {
-               icalcomponent_kind kind;
-               icalcomponent *subcomp;
+       if (i_cal_component_isa (icomp) == I_CAL_VCALENDAR_COMPONENT) {
+               ICalComponentKind kind;
+               ICalComponent *subcomp;
 
-               ecmb_gather_timezones (meta_backend, E_TIMEZONE_CACHE (meta_backend), icalcomp);
+               ecmb_gather_timezones (meta_backend, E_TIMEZONE_CACHE (meta_backend), icomp);
 
                kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
 
-               for (subcomp = icalcomponent_get_first_component (icalcomp, kind);
-                    subcomp && success;
-                    subcomp = icalcomponent_get_next_component (icalcomp, kind)) {
-                       ECalComponent *comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone 
(subcomp));
+               for (subcomp = i_cal_component_get_first_component (icomp, kind);
+                    subcomp;
+                    g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (icomp, kind)) {
+                       ECalComponent *comp = e_cal_component_new_from_icalcomponent 
(i_cal_component_new_clone (subcomp));
 
                        if (comp) {
                                new_instances = g_slist_prepend (new_instances, comp);
 
                                if (!loaded_uid)
-                                       loaded_uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent 
(comp));
+                                       loaded_uid = e_cal_component_get_uid (comp);
                        }
                }
        } else {
-               ECalComponent *comp = e_cal_component_new_from_icalcomponent (icalcomp);
+               ECalComponent *comp = e_cal_component_new_from_icalcomponent (icomp);
 
-               icalcomp = NULL;
+               icomp = NULL;
 
                if (comp) {
                        new_instances = g_slist_prepend (new_instances, comp);
 
                        if (!loaded_uid)
-                               loaded_uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (comp));
+                               loaded_uid = e_cal_component_get_uid (comp);
                }
        }
 
@@ -1110,18 +1118,17 @@ ecmb_load_component_wrapper_sync (ECalMetaBackend *meta_backend,
                new_instances = g_slist_reverse (new_instances);
 
                success = ecmb_put_instances (meta_backend, cal_cache, loaded_uid ? loaded_uid : uid, 
offline_flag,
-                       new_instances, extra ? extra : preloaded_extra, cancellable, &local_error);
+                       new_instances, extra ? extra : preloaded_extra, 0, cancellable, &local_error);
 
                if (success && out_new_uid)
                        *out_new_uid = g_strdup (loaded_uid ? loaded_uid : uid);
        } else {
-               g_propagate_error (error, e_data_cal_create_error_fmt (InvalidObject, _("Received object for 
UID “%s” doesn’t contain any expected component"), uid));
+               g_propagate_error (error, e_cal_client_error_create_fmt (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
_("Received object for UID “%s” doesn’t contain any expected component"), uid));
                success = FALSE;
        }
 
        g_slist_free_full (new_instances, g_object_unref);
-       if (icalcomp)
-               icalcomponent_free (icalcomp);
+       g_clear_object (&icomp);
        g_free (extra);
 
        if (local_error) {
@@ -1142,6 +1149,7 @@ ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
                                  EConflictResolution conflict_resolution,
                                  const GSList *in_instances,
                                  const gchar *extra,
+                                 guint32 opflags,
                                  const gchar *orig_uid,
                                  gboolean *out_requires_put,
                                  gchar **out_new_uid,
@@ -1176,7 +1184,6 @@ ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
 
                                success = e_cal_meta_backend_inline_local_attachments_sync (meta_backend,
                                        e_cal_component_get_icalcomponent (comp), cancellable, error);
-                               e_cal_component_rescan (comp);
                        } else {
                                g_object_ref (comp);
                        }
@@ -1184,7 +1191,7 @@ ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
        }
 
        success = success && e_cal_meta_backend_save_component_sync (meta_backend, overwrite_existing, 
conflict_resolution,
-               instances ? instances : in_instances, extra, &new_uid, &new_extra, cancellable, &local_error);
+               instances ? instances : in_instances, extra, opflags, &new_uid, &new_extra, cancellable, 
&local_error);
 
        if (success && new_uid && *new_uid) {
                gchar *loaded_uid = NULL;
@@ -1193,7 +1200,7 @@ ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
                        new_extra ? new_extra : extra, &loaded_uid, cancellable, error);
 
                if (success && g_strcmp0 (loaded_uid, orig_uid) != 0)
-                       success = ecmb_maybe_remove_from_cache (meta_backend, cal_cache, E_CACHE_IS_ONLINE, 
orig_uid, cancellable, error);
+                       success = ecmb_maybe_remove_from_cache (meta_backend, cal_cache, E_CACHE_IS_ONLINE, 
orig_uid, opflags, cancellable, error);
 
                if (success && out_new_uid)
                        *out_new_uid = loaded_uid;
@@ -1331,13 +1338,13 @@ ecmb_get_object_sync (ECalBackendSync *sync_backend,
 
                success = e_cal_cache_get_components_by_uid (cal_cache, uid, &components, cancellable, 
&local_error);
                if (success) {
-                       icalcomponent *icalcomp;
+                       ICalComponent *icomp;
 
-                       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, components, FALSE);
-                       if (icalcomp) {
-                               *calobj = icalcomponent_as_ical_string_r (icalcomp);
+                       icomp = e_cal_meta_backend_merge_instances (meta_backend, components, FALSE);
+                       if (icomp) {
+                               *calobj = i_cal_component_as_ical_string_r (icomp);
 
-                               icalcomponent_free (icalcomp);
+                               g_object_unref (icomp);
                        } else {
                                g_set_error (&local_error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object 
“%s” not found"), uid);
                                success = FALSE;
@@ -1362,11 +1369,11 @@ ecmb_get_object_sync (ECalBackendSync *sync_backend,
                }
 
                if (!found)
-                       g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL));
 
                g_free (loaded_uid);
        } else if (local_error) {
-               g_propagate_error (error, e_data_cal_create_error (OtherError, local_error->message));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, 
local_error->message));
                g_clear_error (&local_error);
        }
 
@@ -1390,49 +1397,52 @@ ecmb_get_object_list_sync (ECalBackendSync *sync_backend,
 }
 
 static gboolean
-ecmb_add_free_busy_instance_cb (icalcomponent *icalcomp,
-                               struct icaltimetype instance_start,
-                               struct icaltimetype instance_end,
+ecmb_add_free_busy_instance_cb (ICalComponent *icomp,
+                               ICalTime *instance_start,
+                               ICalTime *instance_end,
                                gpointer user_data,
                                GCancellable *cancellable,
                                GError **error)
 {
-       icalcomponent *vfreebusy = user_data;
-       icalproperty *prop, *classification;
-       icalparameter *param;
-       struct icalperiodtype ipt;
+       ICalComponent *vfreebusy = user_data;
+       ICalProperty *prop, *classification;
+       ICalParameter *param;
+       ICalPeriod *ipt;
 
-       ipt.start = instance_start;
-       ipt.end = instance_end;
-       ipt.duration = icaldurationtype_null_duration ();
+       ipt = i_cal_period_null_period ();
+       i_cal_period_set_start (ipt, instance_start);
+       i_cal_period_set_end (ipt, instance_end);
 
         /* Add busy information to the VFREEBUSY component */
-       prop = icalproperty_new (ICAL_FREEBUSY_PROPERTY);
-       icalproperty_set_freebusy (prop, ipt);
+       prop = i_cal_property_new (I_CAL_FREEBUSY_PROPERTY);
+       i_cal_property_set_freebusy (prop, ipt);
+       g_object_unref (ipt);
 
-       param = icalparameter_new_fbtype (ICAL_FBTYPE_BUSY);
-       icalproperty_add_parameter (prop, param);
+       param = i_cal_parameter_new_fbtype (I_CAL_FBTYPE_BUSY);
+       i_cal_property_take_parameter (prop, param);
 
-       classification = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
-       if (!classification || icalproperty_get_class (classification) == ICAL_CLASS_PUBLIC) {
+       classification = i_cal_component_get_first_property (icomp, I_CAL_CLASS_PROPERTY);
+       if (!classification || i_cal_property_get_class (classification) == I_CAL_CLASS_PUBLIC) {
                const gchar *str;
 
-               str = icalcomponent_get_summary (icalcomp);
+               str = i_cal_component_get_summary (icomp);
                if (str && *str) {
-                       param = icalparameter_new_x (str);
-                       icalparameter_set_xname (param, "X-SUMMARY");
-                       icalproperty_add_parameter (prop, param);
+                       param = i_cal_parameter_new_x (str);
+                       i_cal_parameter_set_xname (param, "X-SUMMARY");
+                       i_cal_property_take_parameter (prop, param);
                }
 
-               str = icalcomponent_get_location (icalcomp);
+               str = i_cal_component_get_location (icomp);
                if (str && *str) {
-                       param = icalparameter_new_x (str);
-                       icalparameter_set_xname (param, "X-LOCATION");
-                       icalproperty_add_parameter (prop, param);
+                       param = i_cal_parameter_new_x (str);
+                       i_cal_parameter_set_xname (param, "X-LOCATION");
+                       i_cal_property_take_parameter (prop, param);
                }
        }
 
-       icalcomponent_add_property (vfreebusy, prop);
+       g_clear_object (&classification);
+
+       i_cal_component_take_property (vfreebusy, prop);
 
        return TRUE;
 }
@@ -1451,9 +1461,10 @@ ecmb_get_free_busy_sync (ECalBackendSync *sync_backend,
        ECalCache *cal_cache;
        GSList *link, *components = NULL;
        gchar *cal_email_address, *mailto;
-       icalcomponent *vfreebusy, *icalcomp;
-       icalproperty *prop;
-       icaltimezone *utc_zone;
+       ICalComponent *vfreebusy, *icomp;
+       ICalProperty *prop;
+       ICalTimezone *utc_zone;
+       ICalTime *itt;
 
        g_return_if_fail (E_IS_CAL_META_BACKEND (sync_backend));
        g_return_if_fail (out_freebusy != NULL);
@@ -1465,7 +1476,7 @@ ecmb_get_free_busy_sync (ECalBackendSync *sync_backend,
        if (!users)
                return;
 
-       cal_email_address = e_cal_backend_get_backend_property (E_CAL_BACKEND (meta_backend), 
CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
+       cal_email_address = e_cal_backend_get_backend_property (E_CAL_BACKEND (meta_backend), 
E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
        if (!cal_email_address)
                return;
 
@@ -1494,54 +1505,70 @@ ecmb_get_free_busy_sync (ECalBackendSync *sync_backend,
                return;
        }
 
-       vfreebusy = icalcomponent_new_vfreebusy ();
+       vfreebusy = i_cal_component_new_vfreebusy ();
 
        mailto = g_strconcat ("mailto:";, cal_email_address, NULL);
-       prop = icalproperty_new_organizer (mailto);
+       prop = i_cal_property_new_organizer (mailto);
        g_free (mailto);
 
        if (prop)
-               icalcomponent_add_property (vfreebusy, prop);
+               i_cal_component_take_property (vfreebusy, prop);
 
-       utc_zone = icaltimezone_get_utc_timezone ();
-       icalcomponent_set_dtstart (vfreebusy, icaltime_from_timet_with_zone (start, FALSE, utc_zone));
-       icalcomponent_set_dtend (vfreebusy, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
+       utc_zone = i_cal_timezone_get_utc_timezone ();
+
+       itt = i_cal_time_from_timet_with_zone (start, FALSE, utc_zone);
+       i_cal_component_set_dtstart (vfreebusy, itt);
+       g_object_unref (itt);
+
+       itt = i_cal_time_from_timet_with_zone (end, FALSE, utc_zone);
+       i_cal_component_set_dtend (vfreebusy, itt);
+       g_object_unref (itt);
 
        for (link = components; link; link = g_slist_next (link)) {
                ECalComponent *comp = link->data;
+               ICalTime *starttt, *endtt;
+               gboolean success;
 
                if (!E_IS_CAL_COMPONENT (comp)) {
                        g_warn_if_reached ();
                        continue;
                }
 
-               icalcomp = e_cal_component_get_icalcomponent (comp);
-               if (!icalcomp)
+               icomp = e_cal_component_get_icalcomponent (comp);
+               if (!icomp)
                        continue;
 
                /* If the event is TRANSPARENT, skip it. */
-               prop = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
+               prop = i_cal_component_get_first_property (icomp, I_CAL_TRANSP_PROPERTY);
                if (prop) {
-                       icalproperty_transp transp_val = icalproperty_get_transp (prop);
-                       if (transp_val == ICAL_TRANSP_TRANSPARENT ||
-                           transp_val == ICAL_TRANSP_TRANSPARENTNOCONFLICT)
+                       ICalPropertyTransp transp_val = i_cal_property_get_transp (prop);
+
+                       g_object_unref (prop);
+
+                       if (transp_val == I_CAL_TRANSP_TRANSPARENT ||
+                           transp_val == I_CAL_TRANSP_TRANSPARENTNOCONFLICT)
                                continue;
                }
 
-               if (!e_cal_recur_generate_instances_sync (icalcomp,
-                       icaltime_from_timet_with_zone (start, FALSE, NULL),
-                       icaltime_from_timet_with_zone (end, FALSE, NULL),
+               starttt = i_cal_time_from_timet_with_zone (start, FALSE, NULL);
+               endtt = i_cal_time_from_timet_with_zone (end, FALSE, NULL);
+
+               success = e_cal_recur_generate_instances_sync (icomp, starttt, endtt,
                        ecmb_add_free_busy_instance_cb, vfreebusy,
                        e_cal_cache_resolve_timezone_cb, cal_cache,
-                       utc_zone, cancellable, error)) {
+                       utc_zone, cancellable, error);
+
+               g_clear_object (&starttt);
+               g_clear_object (&endtt);
+
+               if (!success)
                        break;
-               }
        }
 
-       *out_freebusy = g_slist_prepend (*out_freebusy, icalcomponent_as_ical_string_r (vfreebusy));
+       *out_freebusy = g_slist_prepend (*out_freebusy, i_cal_component_as_ical_string_r (vfreebusy));
 
        g_slist_free_full (components, g_object_unref);
-       icalcomponent_free (vfreebusy);
+       g_object_unref (vfreebusy);
        g_object_unref (cal_cache);
        g_free (cal_email_address);
 }
@@ -1551,59 +1578,62 @@ ecmb_create_object_sync (ECalMetaBackend *meta_backend,
                         ECalCache *cal_cache,
                         ECacheOfflineFlag *offline_flag,
                         EConflictResolution conflict_resolution,
+                        guint32 opflags,
                         ECalComponent *comp,
                         gchar **out_new_uid,
                         ECalComponent **out_new_comp,
                         GCancellable *cancellable,
                         GError **error)
 {
-       icalcomponent *icalcomp;
-       struct icaltimetype itt;
+       ICalComponent *icomp;
+       ICalTime *itt;
        const gchar *uid;
        gchar *new_uid = NULL, *new_extra = NULL;
        gboolean success, requires_put = TRUE;
 
        g_return_val_if_fail (comp != NULL, FALSE);
 
-       icalcomp = e_cal_component_get_icalcomponent (comp);
-       if (!icalcomp) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+       icomp = e_cal_component_get_icalcomponent (comp);
+       if (!icomp) {
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
                return FALSE;
        }
 
-       uid = icalcomponent_get_uid (icalcomp);
+       uid = i_cal_component_get_uid (icomp);
        if (!uid) {
                gchar *new_uid;
 
                new_uid = e_util_generate_uid ();
                if (!new_uid) {
-                       g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, NULL));
                        return FALSE;
                }
 
-               icalcomponent_set_uid (icalcomp, new_uid);
-               uid = icalcomponent_get_uid (icalcomp);
+               i_cal_component_set_uid (icomp, new_uid);
+               uid = i_cal_component_get_uid (icomp);
 
                g_free (new_uid);
        }
 
        if (e_cal_cache_contains (cal_cache, uid, NULL, E_CACHE_EXCLUDE_DELETED)) {
-               g_propagate_error (error, e_data_cal_create_error (ObjectIdAlreadyExists, NULL));
+               g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS, NULL));
                return FALSE;
        }
 
        /* Set the created and last modified times on the component, if not there already */
-       itt = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+       itt = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
 
-       if (!icalcomponent_get_first_property (icalcomp, ICAL_CREATED_PROPERTY)) {
+       if (!e_cal_util_component_has_property (icomp, I_CAL_CREATED_PROPERTY)) {
                /* Update both when CREATED is missing, to make sure the LAST-MODIFIED
                   is not before CREATED */
-               e_cal_component_set_created (comp, &itt);
-               e_cal_component_set_last_modified (comp, &itt);
-       } else if (!icalcomponent_get_first_property (icalcomp, ICAL_LASTMODIFIED_PROPERTY)) {
-               e_cal_component_set_last_modified (comp, &itt);
+               e_cal_component_set_created (comp, itt);
+               e_cal_component_set_last_modified (comp, itt);
+       } else if (!e_cal_util_component_has_property (icomp, I_CAL_LASTMODIFIED_PROPERTY)) {
+               e_cal_component_set_last_modified (comp, itt);
        }
 
+       g_clear_object (&itt);
+
        if (*offline_flag == E_CACHE_OFFLINE_UNKNOWN) {
                if (e_backend_get_online (E_BACKEND (meta_backend)) &&
                    e_cal_meta_backend_ensure_connected_sync (meta_backend, cancellable, NULL)) {
@@ -1618,7 +1648,7 @@ ecmb_create_object_sync (ECalMetaBackend *meta_backend,
 
                instances = g_slist_prepend (NULL, comp);
 
-               if (!ecmb_save_component_wrapper_sync (meta_backend, cal_cache, FALSE, conflict_resolution, 
instances, NULL, uid,
+               if (!ecmb_save_component_wrapper_sync (meta_backend, cal_cache, FALSE, conflict_resolution, 
instances, NULL, opflags, uid,
                        &requires_put, &new_uid, &new_extra, cancellable, error)) {
                        g_slist_free (instances);
                        return FALSE;
@@ -1628,7 +1658,7 @@ ecmb_create_object_sync (ECalMetaBackend *meta_backend,
        }
 
        if (requires_put) {
-               success = e_cal_cache_put_component (cal_cache, comp, new_extra, *offline_flag, cancellable, 
error);
+               success = e_cal_cache_put_component (cal_cache, comp, new_extra, opflags, *offline_flag, 
cancellable, error);
                if (success && !out_new_comp) {
                        e_cal_backend_notify_component_created (E_CAL_BACKEND (meta_backend), comp);
                }
@@ -1638,7 +1668,7 @@ ecmb_create_object_sync (ECalMetaBackend *meta_backend,
 
        if (success) {
                if (out_new_uid)
-                       *out_new_uid = g_strdup (new_uid ? new_uid : icalcomponent_get_uid 
(e_cal_component_get_icalcomponent (comp)));
+                       *out_new_uid = g_strdup (new_uid ? new_uid : e_cal_component_get_uid (comp));
                if (out_new_comp) {
                        if (new_uid) {
                                if (!e_cal_cache_get_component (cal_cache, new_uid, NULL, out_new_comp, 
cancellable, NULL))
@@ -1660,6 +1690,7 @@ ecmb_create_objects_sync (ECalBackendSync *sync_backend,
                          EDataCal *cal,
                          GCancellable *cancellable,
                          const GSList *calobjs,
+                         guint32 opflags,
                          GSList **out_uids,
                          GSList **out_new_components,
                          GError **error)
@@ -1667,8 +1698,8 @@ ecmb_create_objects_sync (ECalBackendSync *sync_backend,
        ECalMetaBackend *meta_backend;
        ECalCache *cal_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
-       icalcomponent_kind backend_kind;
+       EConflictResolution conflict_resolution = e_cal_util_operation_flags_to_conflict_resolution (opflags);
+       ICalComponentKind backend_kind;
        GSList *link;
        gboolean success = TRUE;
 
@@ -1678,7 +1709,7 @@ ecmb_create_objects_sync (ECalBackendSync *sync_backend,
        g_return_if_fail (out_new_components != NULL);
 
        if (!e_cal_backend_get_writable (E_CAL_BACKEND (sync_backend))) {
-               g_propagate_error (error, e_data_cal_create_error (PermissionDenied, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, NULL));
                return;
        }
 
@@ -1698,15 +1729,15 @@ ecmb_create_objects_sync (ECalBackendSync *sync_backend,
                comp = e_cal_component_new_from_string (link->data);
                if (!comp ||
                    !e_cal_component_get_icalcomponent (comp) ||
-                   backend_kind != icalcomponent_isa (e_cal_component_get_icalcomponent (comp))) {
+                   backend_kind != i_cal_component_isa (e_cal_component_get_icalcomponent (comp))) {
                        g_clear_object (&comp);
 
-                       g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, NULL));
                        break;
                }
 
                success = ecmb_create_object_sync (meta_backend, cal_cache, &offline_flag, 
conflict_resolution,
-                       comp, &new_uid, &new_comp, cancellable, error);
+                       opflags, comp, &new_uid, &new_comp, cancellable, error);
 
                if (success) {
                        *out_uids = g_slist_prepend (*out_uids, new_uid);
@@ -1728,13 +1759,14 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
                         ECacheOfflineFlag *offline_flag,
                         EConflictResolution conflict_resolution,
                         ECalObjModType mod,
+                        guint32 opflags,
                         ECalComponent *comp,
                         ECalComponent **out_old_comp,
                         ECalComponent **out_new_comp,
                         GCancellable *cancellable,
                         GError **error)
 {
-       struct icaltimetype itt;
+       ICalTime *itt;
        ECalComponentId *id;
        ECalComponent *old_comp = NULL, *new_comp = NULL, *master_comp, *existing_comp = NULL;
        GSList *instances = NULL;
@@ -1746,32 +1778,32 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
 
        id = e_cal_component_get_id (comp);
        if (!id) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
                return FALSE;
        }
 
-       if (!e_cal_cache_get_components_by_uid (cal_cache, id->uid, &instances, cancellable, &local_error)) {
+       if (!e_cal_cache_get_components_by_uid (cal_cache, e_cal_component_id_get_uid (id), &instances, 
cancellable, &local_error)) {
                if (g_error_matches (local_error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND)) {
                        g_clear_error (&local_error);
-                       local_error = e_data_cal_create_error (ObjectNotFound, NULL);
+                       local_error = e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL);
                }
 
                g_propagate_error (error, local_error);
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
 
                return FALSE;
        }
 
-       master_comp = ecmb_find_in_instances (instances, id->uid, NULL);
+       master_comp = ecmb_find_in_instances (instances, e_cal_component_id_get_uid (id), NULL);
        if (e_cal_component_is_instance (comp)) {
                /* Set detached instance as the old object */
-               existing_comp = ecmb_find_in_instances (instances, id->uid, id->rid);
+               existing_comp = ecmb_find_in_instances (instances, e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id));
 
                if (!existing_comp && mod == E_CAL_OBJ_MOD_ONLY_THIS) {
-                       g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL));
 
                        g_slist_free_full (instances, g_object_unref);
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
 
                        return FALSE;
                }
@@ -1780,14 +1812,16 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
        if (!existing_comp)
                existing_comp = master_comp;
 
-       if (!e_cal_cache_get_component_extra (cal_cache, id->uid, id->rid, &extra, cancellable, NULL) && 
id->rid) {
-               if (!e_cal_cache_get_component_extra (cal_cache, id->uid, NULL, &extra, cancellable, NULL))
+       if (!e_cal_cache_get_component_extra (cal_cache, e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id), &extra, cancellable, NULL) &&
+           e_cal_component_id_get_rid (id)) {
+               if (!e_cal_cache_get_component_extra (cal_cache, e_cal_component_id_get_uid (id), NULL, 
&extra, cancellable, NULL))
                        extra = NULL;
        }
 
        /* Set the last modified time on the component */
-       itt = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       e_cal_component_set_last_modified (comp, &itt);
+       itt = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       e_cal_component_set_last_modified (comp, itt);
+       g_clear_object (&itt);
 
        /* Remember old and new components */
        if (out_old_comp && existing_comp)
@@ -1813,7 +1847,7 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
                instances = g_slist_append (instances, e_cal_component_clone (comp));
                break;
        case E_CAL_OBJ_MOD_ALL:
-               e_cal_recur_ensure_end_dates (comp, TRUE, e_cal_cache_resolve_timezone_simple_cb, cal_cache);
+               e_cal_recur_ensure_end_dates (comp, TRUE, e_cal_cache_resolve_timezone_cb, cal_cache, 
cancellable, NULL);
 
                /* Replace master object */
                instances = g_slist_remove (instances, master_comp);
@@ -1825,25 +1859,24 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
        case E_CAL_OBJ_MOD_THIS_AND_PRIOR:
        case E_CAL_OBJ_MOD_THIS_AND_FUTURE:
                if (e_cal_component_is_instance (comp) && master_comp) {
-                       struct icaltimetype rid, master_dtstart;
-                       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
-                       icalcomponent *split_icalcomp;
-                       icalproperty *prop;
+                       ICalTime *rid, *master_dtstart;
+                       ICalComponent *icomp = e_cal_component_get_icalcomponent (comp);
+                       ICalComponent *split_icomp;
+                       ICalProperty *prop;
 
-                       rid = icalcomponent_get_recurrenceid (icalcomp);
+                       rid = i_cal_component_get_recurrenceid (icomp);
 
                        if (mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE &&
-                           e_cal_util_is_first_instance (master_comp, icalcomponent_get_recurrenceid 
(icalcomp),
-                               e_cal_cache_resolve_timezone_simple_cb, cal_cache)) {
-                               icalproperty *prop = icalcomponent_get_first_property (icalcomp, 
ICAL_RECURRENCEID_PROPERTY);
+                           e_cal_util_is_first_instance (master_comp, rid, e_cal_cache_resolve_timezone_cb, 
cal_cache)) {
+                               prop = i_cal_component_get_first_property (icomp, 
I_CAL_RECURRENCEID_PROPERTY);
 
-                               if (prop)
-                                       icalcomponent_remove_property (icalcomp, prop);
-
-                               e_cal_component_rescan (comp);
+                               if (prop) {
+                                       i_cal_component_remove_property (icomp, prop);
+                                       g_object_unref (prop);
+                               }
 
                                /* Then do it like for "mod_all" */
-                               e_cal_recur_ensure_end_dates (comp, TRUE, 
e_cal_cache_resolve_timezone_simple_cb, cal_cache);
+                               e_cal_recur_ensure_end_dates (comp, TRUE, e_cal_cache_resolve_timezone_cb, 
cal_cache, cancellable, NULL);
 
                                /* Replace master */
                                instances = g_slist_remove (instances, master_comp);
@@ -1856,42 +1889,51 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
                                        g_clear_object (&new_comp);
                                        new_comp = e_cal_component_clone (comp);
                                }
+
+                               g_clear_object (&rid);
                                break;
                        }
 
-                       prop = icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY);
-                       if (prop)
-                               icalcomponent_remove_property (icalcomp, prop);
-                       e_cal_component_rescan (comp);
+                       prop = i_cal_component_get_first_property (icomp, I_CAL_RECURRENCEID_PROPERTY);
+                       if (prop) {
+                               i_cal_component_remove_property (icomp, prop);
+                               g_object_unref (prop);
+                       }
+
+                       master_dtstart = i_cal_component_get_dtstart (e_cal_component_get_icalcomponent 
(master_comp));
+                       split_icomp = e_cal_util_split_at_instance (icomp, rid, master_dtstart);
+                       if (split_icomp) {
+                               ICalTime *rid_utc;
 
-                       master_dtstart = icalcomponent_get_dtstart (e_cal_component_get_icalcomponent 
(master_comp));
-                       split_icalcomp = e_cal_util_split_at_instance (icalcomp, rid, master_dtstart);
-                       if (split_icalcomp) {
-                               rid = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ());
-                               e_cal_util_remove_instances (e_cal_component_get_icalcomponent (master_comp), 
rid, mod);
-                               e_cal_component_rescan (master_comp);
-                               e_cal_recur_ensure_end_dates (master_comp, TRUE, 
e_cal_cache_resolve_timezone_simple_cb, cal_cache);
+                               rid_utc = i_cal_time_convert_to_zone (rid, i_cal_timezone_get_utc_timezone 
());
+                               e_cal_util_remove_instances (e_cal_component_get_icalcomponent (master_comp), 
rid_utc, mod);
+                               e_cal_recur_ensure_end_dates (master_comp, TRUE, 
e_cal_cache_resolve_timezone_cb, cal_cache, cancellable, NULL);
 
                                if (out_new_comp) {
                                        g_clear_object (&new_comp);
                                        new_comp = e_cal_component_clone (master_comp);
                                }
+
+                               g_object_unref (rid_utc);
                        }
 
-                       if (split_icalcomp) {
+                       if (split_icomp) {
                                gchar *new_uid;
 
                                new_uid = e_util_generate_uid ();
-                               icalcomponent_set_uid (split_icalcomp, new_uid);
+                               i_cal_component_set_uid (split_icomp, new_uid);
                                g_free (new_uid);
 
-                               g_warn_if_fail (e_cal_component_set_icalcomponent (comp, split_icalcomp));
+                               g_warn_if_fail (e_cal_component_set_icalcomponent (comp, split_icomp));
 
-                               e_cal_recur_ensure_end_dates (comp, TRUE, 
e_cal_cache_resolve_timezone_simple_cb, cal_cache);
+                               e_cal_recur_ensure_end_dates (comp, TRUE, e_cal_cache_resolve_timezone_cb, 
cal_cache, cancellable, NULL);
 
-                               success = ecmb_create_object_sync (meta_backend, cal_cache, offline_flag, 
E_CONFLICT_RESOLUTION_FAIL,
-                                       comp, NULL, NULL, cancellable, error);
+                               success = ecmb_create_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution,
+                                       opflags, comp, NULL, NULL, cancellable, error);
                        }
+
+                       g_clear_object (&master_dtstart);
+                       g_clear_object (&rid);
                } else {
                        /* Replace master */
                        instances = g_slist_remove (instances, master_comp);
@@ -1914,11 +1956,12 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
 
        if (success && *offline_flag == E_CACHE_IS_ONLINE) {
                success = ecmb_save_component_wrapper_sync (meta_backend, cal_cache, TRUE, 
conflict_resolution,
-                       instances, extra, id->uid, &requires_put, &new_uid, &new_extra, cancellable, error);
+                       instances, extra, opflags, e_cal_component_id_get_uid (id), &requires_put, &new_uid, 
&new_extra, cancellable, error);
        }
 
        if (success && requires_put)
-               success = ecmb_put_instances (meta_backend, cal_cache, id->uid, *offline_flag, instances, 
new_extra ? new_extra : extra, cancellable, error);
+               success = ecmb_put_instances (meta_backend, cal_cache, e_cal_component_id_get_uid (id), 
*offline_flag, instances,
+                       new_extra ? new_extra : extra, opflags, cancellable, error);
 
        if (!success) {
                g_clear_object (&old_comp);
@@ -1929,7 +1972,7 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
                *out_old_comp = old_comp;
        if (out_new_comp) {
                if (new_uid) {
-                       if (!e_cal_cache_get_component (cal_cache, new_uid, id->rid, out_new_comp, 
cancellable, NULL))
+                       if (!e_cal_cache_get_component (cal_cache, new_uid, e_cal_component_id_get_rid (id), 
out_new_comp, cancellable, NULL))
                                *out_new_comp = NULL;
                } else {
                        *out_new_comp = new_comp ? g_object_ref (new_comp) : NULL;
@@ -1937,7 +1980,7 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
        }
 
        g_slist_free_full (instances, g_object_unref);
-       e_cal_component_free_id (id);
+       e_cal_component_id_free (id);
        g_clear_object (&new_comp);
        g_free (new_extra);
        g_free (new_uid);
@@ -1952,6 +1995,7 @@ ecmb_modify_objects_sync (ECalBackendSync *sync_backend,
                          GCancellable *cancellable,
                          const GSList *calobjs,
                          ECalObjModType mod,
+                         guint32 opflags,
                          GSList **out_old_components,
                          GSList **out_new_components,
                          GError **error)
@@ -1959,8 +2003,8 @@ ecmb_modify_objects_sync (ECalBackendSync *sync_backend,
        ECalMetaBackend *meta_backend;
        ECalCache *cal_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
-       icalcomponent_kind backend_kind;
+       EConflictResolution conflict_resolution = e_cal_util_operation_flags_to_conflict_resolution (opflags);
+       ICalComponentKind backend_kind;
        GSList *link;
        gboolean success = TRUE;
 
@@ -1970,7 +2014,7 @@ ecmb_modify_objects_sync (ECalBackendSync *sync_backend,
        g_return_if_fail (out_new_components != NULL);
 
        if (!e_cal_backend_get_writable (E_CAL_BACKEND (sync_backend))) {
-               g_propagate_error (error, e_data_cal_create_error (PermissionDenied, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, NULL));
                return;
        }
 
@@ -1989,13 +2033,13 @@ ecmb_modify_objects_sync (ECalBackendSync *sync_backend,
                comp = e_cal_component_new_from_string (link->data);
                if (!comp ||
                    !e_cal_component_get_icalcomponent (comp) ||
-                   backend_kind != icalcomponent_isa (e_cal_component_get_icalcomponent (comp))) {
-                       g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+                   backend_kind != i_cal_component_isa (e_cal_component_get_icalcomponent (comp))) {
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, NULL));
                        break;
                }
 
                success = ecmb_modify_object_sync (meta_backend, cal_cache, &offline_flag, 
conflict_resolution,
-                       mod, comp, &old_comp, &new_comp, cancellable, error);
+                       mod, opflags, comp, &old_comp, &new_comp, cancellable, error);
 
                if (success) {
                        *out_old_components = g_slist_prepend (*out_old_components, old_comp);
@@ -2017,6 +2061,7 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                         ECacheOfflineFlag *offline_flag,
                         EConflictResolution conflict_resolution,
                         ECalObjModType mod,
+                        guint32 opflags,
                         const gchar *uid,
                         const gchar *rid,
                         ECalComponent **out_old_comp,
@@ -2024,7 +2069,7 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                         GCancellable *cancellable,
                         GError **error)
 {
-       struct icaltimetype itt;
+       ICalTime *itt;
        ECalComponent *old_comp = NULL, *new_comp = NULL, *master_comp, *existing_comp = NULL;
        GSList *instances = NULL;
        gboolean success = TRUE;
@@ -2038,14 +2083,14 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
        if ((mod == E_CAL_OBJ_MOD_THIS_AND_PRIOR ||
            mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE) && !rid) {
                /* Require Recurrence-ID for these types */
-               g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, 
NULL));
                return FALSE;
        }
 
        if (!e_cal_cache_get_components_by_uid (cal_cache, uid, &instances, cancellable, &local_error)) {
                if (g_error_matches (local_error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND)) {
                        g_clear_error (&local_error);
-                       local_error = e_data_cal_create_error (ObjectNotFound, NULL);
+                       local_error = e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL);
                }
 
                g_propagate_error (error, local_error);
@@ -2099,26 +2144,28 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
 
                        if (existing_comp == master_comp && master_comp && mod == E_CAL_OBJ_MOD_ONLY_THIS) {
                                success = FALSE;
-                               g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+                               g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL));
                        } else {
-                               itt = icaltime_from_string (rid);
-                               if (!itt.zone) {
-                                       ECalComponentDateTime dt;
+                               itt = i_cal_time_from_string (rid);
+                               if (itt && !i_cal_time_get_timezone (itt)) {
+                                       ECalComponentDateTime *dt;
 
-                                       e_cal_component_get_dtstart (master_comp, &dt);
-                                       if (dt.value && dt.tzid) {
-                                               icaltimezone *zone = e_cal_cache_resolve_timezone_simple_cb 
(dt.tzid, cal_cache);
+                                       dt = e_cal_component_get_dtstart (master_comp);
+                                       if (dt && e_cal_component_datetime_get_value (dt) && 
e_cal_component_datetime_get_tzid (dt)) {
+                                               ICalTimezone *zone = e_cal_cache_resolve_timezone_cb 
(e_cal_component_datetime_get_tzid (dt), cal_cache, NULL, NULL);
 
                                                if (zone)
-                                                       itt = icaltime_convert_to_zone (itt, zone);
+                                                       i_cal_time_convert_to_zone_inplace (itt, zone);
                                        }
-                                       e_cal_component_free_datetime (&dt);
+                                       e_cal_component_datetime_free (dt);
 
-                                       itt = icaltime_convert_to_zone (itt, icaltimezone_get_utc_timezone 
());
+                                       i_cal_time_convert_to_zone_inplace (itt, 
i_cal_timezone_get_utc_timezone ());
                                }
 
                                if (master_comp)
                                        e_cal_util_remove_instances (e_cal_component_get_icalcomponent 
(master_comp), itt, mod);
+
+                               g_clear_object (&itt);
                        }
 
                        if (success && out_new_comp && (master_comp || existing_comp))
@@ -2133,30 +2180,31 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                        time_t fromtt, instancett;
                        GSList *link, *previous = instances;
 
-                       itt = icaltime_from_string (rid);
-                       if (!itt.zone) {
-                               ECalComponentDateTime dt;
+                       itt = i_cal_time_from_string (rid);
+                       if (itt && !i_cal_time_get_timezone (itt)) {
+                               ECalComponentDateTime *dt;
 
-                               e_cal_component_get_dtstart (master_comp, &dt);
-                               if (dt.value && dt.tzid) {
-                                       icaltimezone *zone = e_cal_cache_resolve_timezone_simple_cb (dt.tzid, 
cal_cache);
+                               dt = e_cal_component_get_dtstart (master_comp);
+                               if (dt && e_cal_component_datetime_get_value (dt) && 
e_cal_component_datetime_get_tzid (dt)) {
+                                       ICalTimezone *zone = e_cal_cache_resolve_timezone_cb 
(e_cal_component_datetime_get_tzid (dt), cal_cache, NULL, NULL);
 
                                        if (zone)
-                                               itt = icaltime_convert_to_zone (itt, zone);
+                                               i_cal_time_convert_to_zone_inplace (itt, zone);
                                }
-                               e_cal_component_free_datetime (&dt);
+                               e_cal_component_datetime_free (dt);
 
-                               itt = icaltime_convert_to_zone (itt, icaltimezone_get_utc_timezone ());
+                               i_cal_time_convert_to_zone_inplace (itt, i_cal_timezone_get_utc_timezone ());
                        }
 
                        e_cal_util_remove_instances (e_cal_component_get_icalcomponent (master_comp), itt, 
mod);
 
-                       fromtt = icaltime_as_timet (itt);
+                       fromtt = i_cal_time_as_timet (itt);
 
                        /* Remove detached instances */
                        for (link = instances; link && fromtt > 0;) {
                                ECalComponent *comp = link->data;
-                               ECalComponentRange range;
+                               ECalComponentRange *range;
+                               ECalComponentDateTime *rangedt;
 
                                if (!e_cal_component_is_instance (comp)) {
                                        previous = link;
@@ -2164,12 +2212,13 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                                        continue;
                                }
 
-                               e_cal_component_get_recurid (comp, &range);
-                               if (range.datetime.value)
-                                       instancett = icaltime_as_timet (*range.datetime.value);
+                               range = e_cal_component_get_recurid (comp);
+                               rangedt = range ? e_cal_component_range_get_datetime (range) : NULL;
+                               if (rangedt && e_cal_component_datetime_get_value (rangedt))
+                                       instancett = i_cal_time_as_timet (e_cal_component_datetime_get_value 
(rangedt));
                                else
                                        instancett = 0;
-                               e_cal_component_free_range (&range);
+                               e_cal_component_range_free (range);
 
                                if (instancett > 0 && (
                                    (mod == E_CAL_OBJ_MOD_THIS_AND_PRIOR && instancett <= fromtt) ||
@@ -2189,6 +2238,8 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                                        link = g_slist_next (link);
                                }
                        }
+
+                       g_clear_object (&itt);
                } else {
                        mod = E_CAL_OBJ_MOD_ALL;
                }
@@ -2207,7 +2258,7 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
 
                                /* Use the master object, if exists */
                                if (e_cal_cache_get_component_as_string (cal_cache, uid, NULL, &ical_string, 
cancellable, NULL)) {
-                                       success = e_cal_meta_backend_remove_component_sync (meta_backend, 
conflict_resolution, uid, extra, ical_string, cancellable, &local_error);
+                                       success = e_cal_meta_backend_remove_component_sync (meta_backend, 
conflict_resolution, uid, extra, ical_string, opflags, cancellable, &local_error);
 
                                        g_free (ical_string);
                                } else {
@@ -2226,11 +2277,11 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                                                if (!id)
                                                        continue;
 
-                                               if (!e_cal_cache_get_component_extra (cal_cache, id->uid, 
id->rid, &comp_extra, cancellable, NULL)) {
+                                               if (!e_cal_cache_get_component_extra (cal_cache, 
e_cal_component_id_get_uid (id), e_cal_component_id_get_rid (id), &comp_extra, cancellable, NULL)) {
                                                        comp_extra = NULL;
                                                        if (g_cancellable_set_error_if_cancelled 
(cancellable, &local_error)) {
                                                                success = FALSE;
-                                                               e_cal_component_free_id (id);
+                                                               e_cal_component_id_free (id);
                                                                break;
                                                        }
 
@@ -2240,9 +2291,10 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                                                ical_string = e_cal_component_get_as_string (comp);
 
                                                /* This pretends the first instance is the master object and 
the implementations should count with it */
-                                               success = e_cal_meta_backend_remove_component_sync 
(meta_backend, conflict_resolution, id->uid, comp_extra, ical_string, cancellable, &local_error);
+                                               success = e_cal_meta_backend_remove_component_sync 
(meta_backend, conflict_resolution,
+                                                       e_cal_component_id_get_uid (id), comp_extra, 
ical_string, opflags, cancellable, &local_error);
 
-                                               e_cal_component_free_id (id);
+                                               e_cal_component_id_free (id);
                                                g_clear_pointer (&ical_string, g_free);
                                                g_free (comp_extra);
 
@@ -2260,30 +2312,34 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                                }
                        }
 
-                       success = success && ecmb_maybe_remove_from_cache (meta_backend, cal_cache, 
*offline_flag, uid, cancellable, error);
+                       success = success && ecmb_maybe_remove_from_cache (meta_backend, cal_cache, 
*offline_flag, uid, opflags, cancellable, error);
                } else {
                        gboolean requires_put = TRUE;
                        gchar *new_uid = NULL, *new_extra = NULL;
 
                        if (master_comp) {
-                               icalcomponent *icalcomp = e_cal_component_get_icalcomponent (master_comp);
+                               gint sequence = e_cal_component_get_sequence (master_comp);
 
-                               icalcomponent_set_sequence (icalcomp, icalcomponent_get_sequence (icalcomp) + 
1);
+                               if (sequence < 0)
+                                       sequence = 0;
 
-                               e_cal_component_rescan (master_comp);
+                               e_cal_component_set_sequence (master_comp, sequence + 1);
 
                                /* Set the last modified time on the component */
-                               itt = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-                               e_cal_component_set_last_modified (master_comp, &itt);
+                               itt = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+                               e_cal_component_set_last_modified (master_comp, itt);
+                               g_clear_object (&itt);
                        }
 
                        if (*offline_flag == E_CACHE_IS_ONLINE) {
                                success = ecmb_save_component_wrapper_sync (meta_backend, cal_cache, TRUE, 
conflict_resolution,
-                                       instances, extra, uid, &requires_put, &new_uid, &new_extra, 
cancellable, error);
+                                       instances, extra, opflags, uid, &requires_put, &new_uid, &new_extra, 
cancellable, error);
                        }
 
-                       if (success && requires_put)
-                               success = ecmb_put_instances (meta_backend, cal_cache, uid, *offline_flag, 
instances, new_extra ? new_extra : extra, cancellable, error);
+                       if (success && requires_put) {
+                               success = ecmb_put_instances (meta_backend, cal_cache, uid, *offline_flag, 
instances,
+                                       new_extra ? new_extra : extra, opflags, cancellable, error);
+                       }
 
                        if (success && new_uid && !requires_put) {
                                g_clear_object (&new_comp);
@@ -2320,6 +2376,7 @@ ecmb_remove_objects_sync (ECalBackendSync *sync_backend,
                          GCancellable *cancellable,
                          const GSList *ids,
                          ECalObjModType mod,
+                         guint32 opflags,
                          GSList **out_old_components,
                          GSList **out_new_components,
                          GError **error)
@@ -2327,7 +2384,7 @@ ecmb_remove_objects_sync (ECalBackendSync *sync_backend,
        ECalMetaBackend *meta_backend;
        ECalCache *cal_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_cal_util_operation_flags_to_conflict_resolution (opflags);
        GSList *link;
        gboolean success = TRUE;
 
@@ -2337,7 +2394,7 @@ ecmb_remove_objects_sync (ECalBackendSync *sync_backend,
        g_return_if_fail (out_new_components != NULL);
 
        if (!e_cal_backend_get_writable (E_CAL_BACKEND (sync_backend))) {
-               g_propagate_error (error, e_data_cal_create_error (PermissionDenied, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, NULL));
                return;
        }
 
@@ -2353,12 +2410,12 @@ ecmb_remove_objects_sync (ECalBackendSync *sync_backend,
                        break;
 
                if (!id) {
-                       g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_INVALID_OBJECT, NULL));
                        break;
                }
 
-               success = ecmb_remove_object_sync (meta_backend, cal_cache, &offline_flag, 
conflict_resolution,
-                       mod, id->uid, id->rid, &old_comp, &new_comp, cancellable, error);
+               success = ecmb_remove_object_sync (meta_backend, cal_cache, &offline_flag, 
conflict_resolution, mod, opflags,
+                       e_cal_component_id_get_uid (id), e_cal_component_id_get_rid (id), &old_comp, 
&new_comp, cancellable, error);
 
                if (success) {
                        *out_old_components = g_slist_prepend (*out_old_components, old_comp);
@@ -2378,7 +2435,8 @@ ecmb_receive_object_sync (ECalMetaBackend *meta_backend,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
                          ECalComponent *comp,
-                         icalproperty_method method,
+                         ICalPropertyMethod method,
+                         guint32 opflags,
                          GCancellable *cancellable,
                          GError **error)
 {
@@ -2393,7 +2451,7 @@ ecmb_receive_object_sync (ECalMetaBackend *meta_backend,
 
        id = e_cal_component_get_id (comp);
 
-       if (!id && method == ICAL_METHOD_PUBLISH) {
+       if (!id && method == I_CAL_METHOD_PUBLISH) {
                gchar *new_uid;
 
                new_uid = e_util_generate_uid ();
@@ -2404,7 +2462,7 @@ ecmb_receive_object_sync (ECalMetaBackend *meta_backend,
        }
 
        if (!id) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
                return FALSE;
        }
 
@@ -2412,14 +2470,14 @@ ecmb_receive_object_sync (ECalMetaBackend *meta_backend,
        registry = e_cal_backend_get_registry (cal_backend);
 
        /* Just to check whether component exists in the cache */
-       is_in_cache = e_cal_cache_contains (cal_cache, id->uid, NULL, E_CACHE_EXCLUDE_DELETED) ||
-               (id->rid && *id->rid && e_cal_cache_contains (cal_cache, id->uid, id->rid, 
E_CACHE_EXCLUDE_DELETED));
+       is_in_cache = e_cal_cache_contains (cal_cache, e_cal_component_id_get_uid (id), NULL, 
E_CACHE_EXCLUDE_DELETED) ||
+               (e_cal_component_id_get_rid (id) && e_cal_cache_contains (cal_cache, 
e_cal_component_id_get_uid (id), e_cal_component_id_get_rid (id), E_CACHE_EXCLUDE_DELETED));
 
        /* For cases when there's no master object in the cache */
        if (!is_in_cache) {
                GSList *icalstrings = NULL;
 
-               if (e_cal_cache_get_components_by_uid_as_string (cal_cache, id->uid, &icalstrings, 
cancellable, NULL)) {
+               if (e_cal_cache_get_components_by_uid_as_string (cal_cache, e_cal_component_id_get_uid (id), 
&icalstrings, cancellable, NULL)) {
                        is_in_cache = icalstrings && icalstrings->data;
                        g_slist_free_full (icalstrings, g_free);
                }
@@ -2428,38 +2486,38 @@ ecmb_receive_object_sync (ECalMetaBackend *meta_backend,
        mod = e_cal_component_is_instance (comp) ? E_CAL_OBJ_MOD_THIS : E_CAL_OBJ_MOD_ALL;
 
        switch (method) {
-       case ICAL_METHOD_PUBLISH:
-       case ICAL_METHOD_REQUEST:
-       case ICAL_METHOD_REPLY:
+       case I_CAL_METHOD_PUBLISH:
+       case I_CAL_METHOD_REQUEST:
+       case I_CAL_METHOD_REPLY:
                is_declined = e_cal_backend_user_declined (registry, e_cal_component_get_icalcomponent 
(comp));
                if (is_in_cache) {
                        if (!is_declined) {
                                success = ecmb_modify_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution,
-                                       mod, comp, NULL, NULL, cancellable, error);
+                                       mod, opflags, comp, NULL, NULL, cancellable, error);
                        } else {
-                               success = ecmb_remove_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution,
-                                       mod, id->uid, id->rid, NULL, NULL, cancellable, error);
+                               success = ecmb_remove_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution, mod, opflags,
+                                       e_cal_component_id_get_uid (id), e_cal_component_id_get_rid (id), 
NULL, NULL, cancellable, error);
                        }
                } else if (!is_declined) {
                        success = ecmb_create_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution,
-                               comp, NULL, NULL, cancellable, error);
+                               opflags, comp, NULL, NULL, cancellable, error);
                }
                break;
-       case ICAL_METHOD_CANCEL:
+       case I_CAL_METHOD_CANCEL:
                if (is_in_cache) {
-                       success = ecmb_remove_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution,
-                               E_CAL_OBJ_MOD_THIS, id->uid, id->rid, NULL, NULL, cancellable, error);
+                       success = ecmb_remove_object_sync (meta_backend, cal_cache, offline_flag, 
conflict_resolution, E_CAL_OBJ_MOD_THIS, opflags,
+                               e_cal_component_id_get_uid (id), e_cal_component_id_get_rid (id), NULL, NULL, 
cancellable, error);
                } else {
-                       g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+                       g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL));
                }
                break;
 
        default:
-               g_propagate_error (error, e_data_cal_create_error (UnsupportedMethod, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Unsupported 
method")));
                break;
        }
 
-       e_cal_component_free_id (id);
+       e_cal_component_id_free (id);
 
        return success;
 }
@@ -2469,16 +2527,17 @@ ecmb_receive_objects_sync (ECalBackendSync *sync_backend,
                           EDataCal *cal,
                           GCancellable *cancellable,
                           const gchar *calobj,
+                          guint32 opflags,
                           GError **error)
 {
        ECalMetaBackend *meta_backend;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_cal_util_operation_flags_to_conflict_resolution (opflags);
        ECalCache *cal_cache;
        ECalComponent *comp;
-       icalcomponent *icalcomp, *subcomp;
-       icalcomponent_kind kind;
-       icalproperty_method top_method;
+       ICalComponent *icomp, *subcomp;
+       ICalComponentKind kind;
+       ICalPropertyMethod top_method;
        GSList *comps = NULL, *link;
        gboolean success = TRUE;
 
@@ -2486,7 +2545,7 @@ ecmb_receive_objects_sync (ECalBackendSync *sync_backend,
        g_return_if_fail (calobj != NULL);
 
        if (!e_cal_backend_get_writable (E_CAL_BACKEND (sync_backend))) {
-               g_propagate_error (error, e_data_cal_create_error (PermissionDenied, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, NULL));
                return;
        }
 
@@ -2494,66 +2553,66 @@ ecmb_receive_objects_sync (ECalBackendSync *sync_backend,
        cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
        g_return_if_fail (cal_cache != NULL);
 
-       icalcomp = icalparser_parse_string (calobj);
-       if (!icalcomp) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+       icomp = i_cal_parser_parse_string (calobj);
+       if (!icomp) {
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
                g_object_unref (cal_cache);
                return;
        }
 
        kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
 
-       if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT) {
-               for (subcomp = icalcomponent_get_first_component (icalcomp, kind);
-                    subcomp && success;
-                    subcomp = icalcomponent_get_next_component (icalcomp, kind)) {
-                       comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (subcomp));
+       if (i_cal_component_isa (icomp) == I_CAL_VCALENDAR_COMPONENT) {
+               for (subcomp = i_cal_component_get_first_component (icomp, kind);
+                    subcomp;
+                    g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (icomp, kind)) {
+                       comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (subcomp));
 
                        if (comp)
                                comps = g_slist_prepend (comps, comp);
                }
-       } else if (icalcomponent_isa (icalcomp) == kind) {
-               comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (icalcomp));
+       } else if (i_cal_component_isa (icomp) == kind) {
+               comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icomp));
 
                if (comp)
                        comps = g_slist_prepend (comps, comp);
        }
 
        if (!comps) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
-               icalcomponent_free (icalcomp);
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
+               g_object_unref (icomp);
                g_object_unref (cal_cache);
                return;
        }
 
        comps = g_slist_reverse (comps);
 
-       if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT)
-               ecmb_gather_timezones (meta_backend, E_TIMEZONE_CACHE (meta_backend), icalcomp);
+       if (i_cal_component_isa (icomp) == I_CAL_VCALENDAR_COMPONENT)
+               ecmb_gather_timezones (meta_backend, E_TIMEZONE_CACHE (meta_backend), icomp);
 
-       if (icalcomponent_get_first_property (icalcomp, ICAL_METHOD_PROPERTY))
-               top_method = icalcomponent_get_method (icalcomp);
+       if (e_cal_util_component_has_property (icomp, I_CAL_METHOD_PROPERTY))
+               top_method = i_cal_component_get_method (icomp);
        else
-               top_method = ICAL_METHOD_PUBLISH;
+               top_method = I_CAL_METHOD_PUBLISH;
 
        for (link = comps; link && success; link = g_slist_next (link)) {
                ECalComponent *comp = link->data;
-               icalproperty_method method;
+               ICalPropertyMethod method;
 
                subcomp = e_cal_component_get_icalcomponent (comp);
 
-               if (icalcomponent_get_first_property (subcomp, ICAL_METHOD_PROPERTY)) {
-                       method = icalcomponent_get_method (subcomp);
+               if (e_cal_util_component_has_property (subcomp, I_CAL_METHOD_PROPERTY)) {
+                       method = i_cal_component_get_method (subcomp);
                } else {
                        method = top_method;
                }
 
                success = ecmb_receive_object_sync (meta_backend, cal_cache, &offline_flag, 
conflict_resolution,
-                       comp, method, cancellable, error);
+                       comp, method, opflags, cancellable, error);
        }
 
        g_slist_free_full (comps, g_object_unref);
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_object_unref (cal_cache);
 }
 
@@ -2562,6 +2621,7 @@ ecmb_send_objects_sync (ECalBackendSync *sync_backend,
                        EDataCal *cal,
                        GCancellable *cancellable,
                        const gchar *calobj,
+                       guint32 opflags,
                        GSList **out_users,
                        gchar **out_modified_calobj,
                        GError **error)
@@ -2579,38 +2639,36 @@ static void
 ecmb_add_attachment_uris (ECalComponent *comp,
                          GSList **out_uris)
 {
-       icalcomponent *icalcomp;
-       icalproperty *prop;
+       ICalComponent *icomp;
+       ICalProperty *prop;
 
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
        g_return_if_fail (out_uris != NULL);
 
-       icalcomp = e_cal_component_get_icalcomponent (comp);
-       g_return_if_fail (icalcomp != NULL);
+       icomp = e_cal_component_get_icalcomponent (comp);
+       g_return_if_fail (icomp != NULL);
 
-       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTACH_PROPERTY)) {
-               icalattach *attach = icalproperty_get_attach (prop);
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icomp, I_CAL_ATTACH_PROPERTY)) {
+               ICalAttach *attach = i_cal_property_get_attach (prop);
 
-               if (attach && icalattach_get_is_url (attach)) {
+               if (attach && i_cal_attach_get_is_url (attach)) {
                        const gchar *url;
 
-                       url = icalattach_get_url (attach);
+                       url = i_cal_attach_get_url (attach);
                        if (url) {
-                               gsize buf_size;
                                gchar *buf;
 
-                               buf_size = strlen (url);
-                               buf = g_malloc0 (buf_size + 1);
-
-                               icalvalue_decode_ical_string (url, buf, buf_size);
+                               buf = i_cal_value_decode_ical_string (url);
 
                                *out_uris = g_slist_prepend (*out_uris, g_strdup (buf));
 
                                g_free (buf);
                        }
                }
+
+               g_clear_object (&attach);
        }
 }
 
@@ -2664,7 +2722,7 @@ ecmb_get_attachment_uris_sync (ECalBackendSync *sync_backend,
        if (local_error) {
                if (g_error_matches (local_error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND)) {
                        g_clear_error (&local_error);
-                       local_error = e_data_cal_create_error (ObjectNotFound, NULL);
+                       local_error = e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL);
                }
 
                g_propagate_error (error, local_error);
@@ -2678,6 +2736,7 @@ ecmb_discard_alarm_sync (ECalBackendSync *sync_backend,
                         const gchar *uid,
                         const gchar *rid,
                         const gchar *auid,
+                        guint32 opflags,
                         GError **error)
 {
        g_return_if_fail (E_IS_CAL_META_BACKEND (sync_backend));
@@ -2698,7 +2757,7 @@ ecmb_get_timezone_sync (ECalBackendSync *sync_backend,
                        gchar **tzobject,
                        GError **error)
 {
-       icaltimezone *zone;
+       ICalTimezone *zone;
        gchar *timezone_str = NULL;
        GError *local_error = NULL;
 
@@ -2711,19 +2770,20 @@ ecmb_get_timezone_sync (ECalBackendSync *sync_backend,
 
        zone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (sync_backend), tzid);
        if (zone) {
-               icalcomponent *icalcomp;
+               ICalComponent *icomp;
 
-               icalcomp = icaltimezone_get_component (zone);
+               icomp = i_cal_timezone_get_component (zone);
 
-               if (!icalcomp) {
-                       local_error = e_data_cal_create_error (InvalidObject, NULL);
+               if (!icomp) {
+                       local_error = e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, NULL);
                } else {
-                       timezone_str = icalcomponent_as_ical_string_r (icalcomp);
+                       timezone_str = i_cal_component_as_ical_string_r (icomp);
+                       g_object_unref (icomp);
                }
        }
 
        if (!local_error && !timezone_str)
-               local_error = e_data_cal_create_error (ObjectNotFound, NULL);
+               local_error = e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, NULL);
 
        *tzobject = timezone_str;
 
@@ -2738,7 +2798,7 @@ ecmb_add_timezone_sync (ECalBackendSync *sync_backend,
                        const gchar *tzobject,
                        GError **error)
 {
-       icalcomponent *tz_comp;
+       ICalComponent *tz_comp;
 
        g_return_if_fail (E_IS_CAL_META_BACKEND (sync_backend));
 
@@ -2746,29 +2806,26 @@ ecmb_add_timezone_sync (ECalBackendSync *sync_backend,
                return;
 
        if (!tzobject || !*tzobject) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
                return;
        }
 
-       tz_comp = icalparser_parse_string (tzobject);
+       tz_comp = i_cal_parser_parse_string (tzobject);
        if (!tz_comp ||
-           icalcomponent_isa (tz_comp) != ICAL_VTIMEZONE_COMPONENT) {
-               g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
+           i_cal_component_isa (tz_comp) != I_CAL_VTIMEZONE_COMPONENT) {
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT, 
NULL));
        } else {
-               icaltimezone *zone;
-
-               zone = icaltimezone_new ();
-               icaltimezone_set_component (zone, tz_comp);
+               ICalTimezone *zone;
 
-               tz_comp = NULL;
+               zone = i_cal_timezone_new ();
+               i_cal_timezone_set_component (zone, tz_comp);
 
                /* Add it only to memory, do not store it persistently into the ECalCache */
                e_timezone_cache_add_timezone (E_TIMEZONE_CACHE (sync_backend), zone);
-               icaltimezone_free (zone, 1);
+               g_object_unref (zone);
        }
 
-       if (tz_comp)
-               icalcomponent_free (tz_comp);
+       g_clear_object (&tz_comp);
 }
 
 static gchar *
@@ -2778,7 +2835,7 @@ ecmb_get_backend_property (ECalBackend *cal_backend,
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (cal_backend), NULL);
        g_return_val_if_fail (prop_name != NULL, NULL);
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_REVISION)) {
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_REVISION)) {
                ECalCache *cal_cache;
                gchar *revision = NULL;
 
@@ -2791,7 +2848,7 @@ ecmb_get_backend_property (ECalBackend *cal_backend,
                }
 
                return revision;
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
                ECalComponent *comp;
                gchar *prop_value;
 
@@ -3063,12 +3120,12 @@ ecmb_maybe_wait_for_credentials (ECalMetaBackend *meta_backend,
        if (!op_error || g_cancellable_is_cancelled (cancellable))
                return FALSE;
 
-       if (g_error_matches (op_error, E_DATA_CAL_ERROR, TLSNotAvailable) &&
+       if (g_error_matches (op_error, E_CLIENT_ERROR, E_CLIENT_ERROR_TLS_NOT_AVAILABLE) &&
            e_cal_meta_backend_get_ssl_error_details (meta_backend, &certificate_pem, &certificate_errors)) {
                reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
-       } else if (g_error_matches (op_error, E_DATA_CAL_ERROR, AuthenticationRequired)) {
+       } else if (g_error_matches (op_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED)) {
                reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
-       } else if (g_error_matches (op_error, E_DATA_CAL_ERROR, AuthenticationFailed)) {
+       } else if (g_error_matches (op_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
                reason = E_SOURCE_CREDENTIALS_REASON_REJECTED;
        }
 
@@ -3113,12 +3170,12 @@ ecmb_maybe_wait_for_credentials (ECalMetaBackend *meta_backend,
        return got_credentials;
 }
 
-static icaltimezone *
+static ICalTimezone *
 ecmb_get_cached_timezone (ETimezoneCache *cache,
                          const gchar *tzid)
 {
        ECalCache *cal_cache;
-       icaltimezone *zone;
+       ICalTimezone *zone;
 
        if (ecmb_timezone_cache_parent_get_timezone) {
                zone = ecmb_timezone_cache_parent_get_timezone (cache, tzid);
@@ -3454,10 +3511,10 @@ e_cal_meta_backend_get_capabilities (ECalMetaBackend *meta_backend)
 {
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), NULL);
 
-       return CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED ","
-               CAL_STATIC_CAPABILITY_BULK_ADDS ","
-               CAL_STATIC_CAPABILITY_BULK_MODIFIES ","
-               CAL_STATIC_CAPABILITY_BULK_REMOVES;
+       return E_CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED ","
+               E_CAL_STATIC_CAPABILITY_BULK_ADDS ","
+               E_CAL_STATIC_CAPABILITY_BULK_MODIFIES ","
+               E_CAL_STATIC_CAPABILITY_BULK_REMOVES;
 }
 
 /**
@@ -3636,12 +3693,12 @@ ecmb_cache_revision_changed_cb (ECache *cache,
        revision = e_cache_dup_revision (cache);
        if (revision) {
                e_cal_backend_notify_property_changed (E_CAL_BACKEND (meta_backend),
-                       CAL_BACKEND_PROPERTY_REVISION, revision);
+                       E_CAL_BACKEND_PROPERTY_REVISION, revision);
                g_free (revision);
        }
 }
 
-static icaltimezone *
+static ICalTimezone *
 ecmb_cache_get_timezone_cb (ECalCache *cal_cache,
                            const gchar *tzid,
                            gpointer user_data)
@@ -3738,7 +3795,9 @@ static gint
 sort_master_first_cb (gconstpointer a,
                      gconstpointer b)
 {
-       icalcomponent *ca, *cb;
+       ICalComponent *ca, *cb;
+       ICalTime *rida, *ridb;
+       gint res;
 
        ca = e_cal_component_get_icalcomponent ((ECalComponent *) a);
        cb = e_cal_component_get_icalcomponent ((ECalComponent *) b);
@@ -3752,70 +3811,106 @@ sort_master_first_cb (gconstpointer a,
                return 1;
        }
 
-       return icaltime_compare (icalcomponent_get_recurrenceid (ca), icalcomponent_get_recurrenceid (cb));
+       rida = i_cal_component_get_recurrenceid (ca);
+       ridb = i_cal_component_get_recurrenceid (cb);
+
+       if (!rida || !ridb) {
+               if (rida == ridb)
+                       res = 0;
+               else
+                       res = rida ? -1 : 1;
+       } else {
+               res = i_cal_time_compare (rida, ridb);
+       }
+
+       g_clear_object (&rida);
+       g_clear_object (&ridb);
+
+       return res;
 }
 
 typedef struct {
        ETimezoneCache *timezone_cache;
        gboolean replace_tzid_with_location;
-       icalcomponent *vcalendar;
-       icalcomponent *icalcomp;
+       ICalComponent *vcalendar;
+       ICalComponent *icomp;
 } ForeachTzidData;
 
 static void
-add_timezone_cb (icalparameter *param,
+add_timezone_cb (ICalParameter *param,
                  gpointer user_data)
 {
-       icaltimezone *tz;
+       ICalTimezone *tz;
        const gchar *tzid;
-       icalcomponent *vtz_comp;
+       ICalComponent *vtz_comp;
        ForeachTzidData *f_data = user_data;
 
-       tzid = icalparameter_get_tzid (param);
+       tzid = i_cal_parameter_get_tzid (param);
        if (!tzid)
                return;
 
-       tz = icalcomponent_get_timezone (f_data->vcalendar, tzid);
-       if (tz)
+       tz = i_cal_component_get_timezone (f_data->vcalendar, tzid);
+       if (tz) {
+               g_object_unref (tz);
                return;
+       }
 
-       tz = icalcomponent_get_timezone (f_data->icalcomp, tzid);
-       if (!tz)
-               tz = icaltimezone_get_builtin_timezone_from_tzid (tzid);
-       if (!tz && f_data->timezone_cache)
+       tz = i_cal_component_get_timezone (f_data->icomp, tzid);
+       if (!tz) {
+               tz = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
+               if (tz)
+                       g_object_ref (tz);
+       }
+
+       if (!tz && f_data->timezone_cache) {
                tz = e_timezone_cache_get_timezone (f_data->timezone_cache, tzid);
+               if (tz)
+                       g_object_ref (tz);
+       }
+
        if (!tz)
                return;
 
        if (f_data->replace_tzid_with_location) {
                const gchar *location;
 
-               location = icaltimezone_get_location (tz);
+               location = i_cal_timezone_get_location (tz);
                if (location && *location) {
-                       icalparameter_set_tzid (param, location);
+                       ICalTimezone *existing_tz;
+
+                       i_cal_parameter_set_tzid (param, location);
                        tzid = location;
 
-                       if (icalcomponent_get_timezone (f_data->vcalendar, tzid))
+                       existing_tz = i_cal_component_get_timezone (f_data->vcalendar, tzid);
+                       if (existing_tz) {
+                               g_object_unref (existing_tz);
+                               g_object_unref (tz);
                                return;
+                       }
                }
        }
 
-       vtz_comp = icaltimezone_get_component (tz);
+       vtz_comp = i_cal_timezone_get_component (tz);
 
        if (vtz_comp) {
-               icalcomponent *clone = icalcomponent_new_clone (vtz_comp);
+               ICalComponent *clone = i_cal_component_new_clone (vtz_comp);
 
                if (f_data->replace_tzid_with_location) {
-                       icalproperty *prop;
+                       ICalProperty *prop;
 
-                       prop = icalcomponent_get_first_property (clone, ICAL_TZID_PROPERTY);
+                       prop = i_cal_component_get_first_property (clone, I_CAL_TZID_PROPERTY);
                        if (prop) {
-                               icalproperty_set_tzid (prop, tzid);
+                               i_cal_property_set_tzid (prop, tzid);
+                               g_object_unref (prop);
                        }
                }
 
-               icalcomponent_add_component (f_data->vcalendar, clone);
+               i_cal_component_take_component (f_data->vcalendar, clone);
+
+               g_object_unref (vtz_comp);
        }
+
+       g_object_unref (tz);
 }
 
 /**
@@ -3832,21 +3927,21 @@ add_timezone_cb (icalparameter *param,
  * Any TZID property parameters can be replaced with corresponding timezone
  * location, which will not influence the timezone itself.
  *
- * Returns: (transfer full): an #icalcomponent containing a VCALENDAR
+ * Returns: (transfer full): an #ICalComponent containing a VCALENDAR
  *    component which consists of all the given instances. Free
- *    the returned pointer with icalcomponent_free() when no longer needed.
+ *    the returned pointer with g_object_unref(), when no longer needed.
  *
  * See: e_cal_meta_backend_save_component_sync()
  *
  * Since: 3.26
  **/
-icalcomponent *
+ICalComponent *
 e_cal_meta_backend_merge_instances (ECalMetaBackend *meta_backend,
                                    const GSList *instances,
                                    gboolean replace_tzid_with_location)
 {
        ForeachTzidData f_data;
-       icalcomponent *vcalendar;
+       ICalComponent *vcalendar;
        GSList *link, *sorted;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), NULL);
@@ -3862,19 +3957,16 @@ e_cal_meta_backend_merge_instances (ECalMetaBackend *meta_backend,
 
        for (link = sorted; link; link = g_slist_next (link)) {
                ECalComponent *comp = link->data;
-               icalcomponent *icalcomp;
 
                if (!E_IS_CAL_COMPONENT (comp)) {
                        g_warn_if_reached ();
                        continue;
                }
 
-               icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
-               icalcomponent_add_component (vcalendar, icalcomp);
+               f_data.icomp = i_cal_component_new_clone (e_cal_component_get_icalcomponent (comp));
 
-               f_data.icalcomp = icalcomp;
-
-               icalcomponent_foreach_tzid (icalcomp, add_timezone_cb, &f_data);
+               i_cal_component_foreach_tzid (f_data.icomp, add_timezone_cb, &f_data);
+               i_cal_component_take_component (vcalendar, f_data.icomp);
        }
 
        g_slist_free (sorted);
@@ -3883,27 +3975,29 @@ e_cal_meta_backend_merge_instances (ECalMetaBackend *meta_backend,
 }
 
 static void
-ecmb_remove_all_but_filename_parameter (icalproperty *prop)
+ecmb_remove_all_but_filename_parameter (ICalProperty *prop)
 {
-       icalparameter *param;
+       ICalParameter *param;
 
        g_return_if_fail (prop != NULL);
 
-       while (param = icalproperty_get_first_parameter (prop, ICAL_ANY_PARAMETER), param) {
-               if (icalparameter_isa (param) == ICAL_FILENAME_PARAMETER) {
-                       param = icalproperty_get_next_parameter (prop, ICAL_ANY_PARAMETER);
+       while (param = i_cal_property_get_first_parameter (prop, I_CAL_ANY_PARAMETER), param) {
+               if (i_cal_parameter_isa (param) == I_CAL_FILENAME_PARAMETER) {
+                       g_object_unref (param);
+                       param = i_cal_property_get_next_parameter (prop, I_CAL_ANY_PARAMETER);
                        if (!param)
                                break;
                }
 
-               icalproperty_remove_parameter_by_ref (prop, param);
+               i_cal_property_remove_parameter_by_ref (prop, param);
+               g_object_unref (param);
        }
 }
 
 /**
  * e_cal_meta_backend_inline_local_attachments_sync:
  * @meta_backend: an #ECalMetaBackend
- * @component: an icalcomponent to work with
+ * @component: an #ICalComponent to work with
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -3920,29 +4014,29 @@ ecmb_remove_all_but_filename_parameter (icalproperty *prop)
  **/
 gboolean
 e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
-                                                 icalcomponent *component,
+                                                 ICalComponent *component,
                                                  GCancellable *cancellable,
                                                  GError **error)
 {
-       icalproperty *prop;
+       ICalProperty *prop;
        const gchar *uid;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
        g_return_val_if_fail (component != NULL, FALSE);
 
-       uid = icalcomponent_get_uid (component);
+       uid = i_cal_component_get_uid (component);
 
-       for (prop = icalcomponent_get_first_property (component, ICAL_ATTACH_PROPERTY);
+       for (prop = i_cal_component_get_first_property (component, I_CAL_ATTACH_PROPERTY);
             prop && success;
-            prop = icalcomponent_get_next_property (component, ICAL_ATTACH_PROPERTY)) {
-               icalattach *attach;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (component, 
I_CAL_ATTACH_PROPERTY)) {
+               ICalAttach *attach;
 
-               attach = icalproperty_get_attach (prop);
-               if (icalattach_get_is_url (attach)) {
+               attach = i_cal_property_get_attach (prop);
+               if (attach && i_cal_attach_get_is_url (attach)) {
                        const gchar *url;
 
-                       url = icalattach_get_url (attach);
+                       url = i_cal_attach_get_url (attach);
                        if (g_str_has_prefix (url, LOCAL_PREFIX)) {
                                GFile *file;
                                gchar *basename;
@@ -3952,28 +4046,28 @@ e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
                                file = g_file_new_for_uri (url);
                                basename = g_file_get_basename (file);
                                if (g_file_load_contents (file, cancellable, &content, &len, NULL, error)) {
-                                       icalattach *new_attach;
-                                       icalparameter *param;
+                                       ICalAttach *new_attach;
+                                       ICalParameter *param;
                                        gchar *base64;
 
                                        base64 = g_base64_encode ((const guchar *) content, len);
-                                       new_attach = icalattach_new_from_data (base64, NULL, NULL);
+                                       new_attach = i_cal_attach_new_from_data (base64, NULL, NULL);
                                        g_free (content);
                                        g_free (base64);
 
                                        ecmb_remove_all_but_filename_parameter (prop);
 
-                                       icalproperty_set_attach (prop, new_attach);
-                                       icalattach_unref (new_attach);
+                                       i_cal_property_set_attach (prop, new_attach);
+                                       g_object_unref (new_attach);
 
-                                       param = icalparameter_new_value (ICAL_VALUE_BINARY);
-                                       icalproperty_add_parameter (prop, param);
+                                       param = i_cal_parameter_new_value (I_CAL_VALUE_BINARY);
+                                       i_cal_property_take_parameter (prop, param);
 
-                                       param = icalparameter_new_encoding (ICAL_ENCODING_BASE64);
-                                       icalproperty_add_parameter (prop, param);
+                                       param = i_cal_parameter_new_encoding (I_CAL_ENCODING_BASE64);
+                                       i_cal_property_take_parameter (prop, param);
 
                                        /* Preserve existing FILENAME parameter */
-                                       if (!icalproperty_get_first_parameter (prop, 
ICAL_FILENAME_PARAMETER)) {
+                                       if (!e_cal_util_property_has_parameter (prop, 
I_CAL_FILENAME_PARAMETER)) {
                                                const gchar *use_filename = basename;
 
                                                /* generated filename by Evolution */
@@ -3982,8 +4076,8 @@ e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
                                                        use_filename += strlen (uid) + 1;
                                                }
 
-                                               param = icalparameter_new_filename (use_filename);
-                                               icalproperty_add_parameter (prop, param);
+                                               param = i_cal_parameter_new_filename (use_filename);
+                                               i_cal_property_take_parameter (prop, param);
                                        }
                                } else {
                                        success = FALSE;
@@ -3993,15 +4087,19 @@ e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
                                g_free (basename);
                        }
                }
+
+               g_clear_object (&attach);
        }
 
+       g_clear_object (&prop);
+
        return success;
 }
 
 /**
  * e_cal_meta_backend_store_inline_attachments_sync:
  * @meta_backend: an #ECalMetaBackend
- * @component: an icalcomponent to work with
+ * @component: an #ICalComponent to work with
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -4018,55 +4116,58 @@ e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
  **/
 gboolean
 e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
-                                                 icalcomponent *component,
+                                                 ICalComponent *component,
                                                  GCancellable *cancellable,
                                                  GError **error)
 {
        gint fileindex;
-       icalproperty *prop;
+       ICalProperty *prop;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
        g_return_val_if_fail (component != NULL, FALSE);
 
-       for (prop = icalcomponent_get_first_property (component, ICAL_ATTACH_PROPERTY), fileindex = 0;
+       for (prop = i_cal_component_get_first_property (component, I_CAL_ATTACH_PROPERTY), fileindex = 0;
             prop && success;
-            prop = icalcomponent_get_next_property (component, ICAL_ATTACH_PROPERTY), fileindex++) {
-               icalattach *attach;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (component, 
I_CAL_ATTACH_PROPERTY), fileindex++) {
+               ICalAttach *attach;
+
+               attach = i_cal_property_get_attach (prop);
 
-               attach = icalproperty_get_attach (prop);
-               if (!icalattach_get_is_url (attach)) {
-                       icalparameter *param;
+               if (attach && !i_cal_attach_get_is_url (attach)) {
+                       ICalParameter *param;
                        const gchar *basename;
                        gsize len = -1;
                        gchar *decoded = NULL;
                        gchar *local_filename;
 
-                       param = icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER);
-                       basename = param ? icalparameter_get_filename (param) : NULL;
+                       param = i_cal_property_get_first_parameter (prop, I_CAL_FILENAME_PARAMETER);
+                       basename = param ? i_cal_parameter_get_filename (param) : NULL;
                        if (!basename || !*basename)
                                basename = _("attachment.dat");
 
-                       local_filename = e_cal_backend_create_cache_filename (E_CAL_BACKEND (meta_backend), 
icalcomponent_get_uid (component), basename, fileindex);
+                       local_filename = e_cal_backend_create_cache_filename (E_CAL_BACKEND (meta_backend), 
i_cal_component_get_uid (component), basename, fileindex);
+
+                       g_clear_object (&param);
 
                        if (local_filename) {
                                const gchar *content;
 
-                               content = (const gchar *) icalattach_get_data (attach);
+                               content = (const gchar *) i_cal_attach_get_data (attach);
                                decoded = (gchar *) g_base64_decode (content, &len);
 
                                if (g_file_set_contents (local_filename, decoded, len, error)) {
-                                       icalattach *new_attach;
+                                       ICalAttach *new_attach;
                                        gchar *url;
 
                                        ecmb_remove_all_but_filename_parameter (prop);
 
                                        url = g_filename_to_uri (local_filename, NULL, NULL);
-                                       new_attach = icalattach_new_from_url (url);
+                                       new_attach = i_cal_attach_new_from_url (url);
 
-                                       icalproperty_set_attach (prop, new_attach);
+                                       i_cal_property_set_attach (prop, new_attach);
 
-                                       icalattach_unref (new_attach);
+                                       g_object_unref (new_attach);
                                        g_free (url);
                                } else {
                                        success = FALSE;
@@ -4077,15 +4178,19 @@ e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
 
                        g_free (local_filename);
                }
+
+               g_clear_object (&attach);
        }
 
+       g_clear_object (&prop);
+
        return success;
 }
 
 /**
  * e_cal_meta_backend_gather_timezones_sync:
  * @meta_backend: an #ECalMetaBackend
- * @vcalendar: a VCALENDAR icalcomponent
+ * @vcalendar: a VCALENDAR #ICalComponent
  * @remove_existing: whether to remove any existing first
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -4104,7 +4209,7 @@ e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
  **/
 gboolean
 e_cal_meta_backend_gather_timezones_sync (ECalMetaBackend *meta_backend,
-                                         icalcomponent *vcalendar,
+                                         ICalComponent *vcalendar,
                                          gboolean remove_existing,
                                          GCancellable *cancellable,
                                          GError **error)
@@ -4115,7 +4220,7 @@ e_cal_meta_backend_gather_timezones_sync (ECalMetaBackend *meta_backend,
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
        g_return_val_if_fail (vcalendar != NULL, FALSE);
 
-       if (icalcomponent_isa (vcalendar) != ICAL_VCALENDAR_COMPONENT)
+       if (i_cal_component_isa (vcalendar) != I_CAL_VCALENDAR_COMPONENT)
                return TRUE;
 
        cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
@@ -4188,7 +4293,7 @@ e_cal_meta_backend_empty_cache_sync (ECalMetaBackend *meta_backend,
                }
        }
 
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_id_free);
 
        return success;
 }
@@ -4360,7 +4465,7 @@ e_cal_meta_backend_ensure_connected_sync (ECalMetaBackend *meta_backend,
 /**
  * e_cal_meta_backend_split_changes_sync:
  * @meta_backend: an #ECalMetaBackend
- * @objects: (inout caller-allocates) (element-type ECalMetaBackendInfo):
+ * @objects: (inout) (element-type ECalMetaBackendInfo):
  *    a #GSList of #ECalMetaBackendInfo object infos to split
  * @out_created_objects: (out) (element-type ECalMetaBackendInfo) (transfer full):
  *    a #GSList of #ECalMetaBackendInfo object infos which had been created
@@ -4418,7 +4523,7 @@ e_cal_meta_backend_split_changes_sync (ECalMetaBackend *meta_backend,
        locally_cached = g_hash_table_new_full (
                (GHashFunc) e_cal_component_id_hash,
                (GEqualFunc) e_cal_component_id_equal,
-               (GDestroyNotify) e_cal_component_free_id,
+               (GDestroyNotify) e_cal_component_id_free,
                g_free);
 
        if (!e_cal_cache_search_with_callback (cal_cache, NULL,
@@ -4430,20 +4535,19 @@ e_cal_meta_backend_split_changes_sync (ECalMetaBackend *meta_backend,
 
        for (link = objects; link; link = g_slist_next (link)) {
                ECalMetaBackendInfo *nfo = link->data;
-               ECalComponentId id;
+               ECalComponentId *id;
 
                if (!nfo)
                        continue;
 
-               id.uid = nfo->uid;
-               id.rid = NULL;
+               id = e_cal_component_id_new (nfo->uid, NULL);
 
-               if (!g_hash_table_contains (locally_cached, &id)) {
+               if (!g_hash_table_contains (locally_cached, id)) {
                        link->data = NULL;
 
                        *out_created_objects = g_slist_prepend (*out_created_objects, nfo);
                } else {
-                       const gchar *local_revision = g_hash_table_lookup (locally_cached, &id);
+                       const gchar *local_revision = g_hash_table_lookup (locally_cached, id);
 
                        if (g_strcmp0 (local_revision, nfo->revision) != 0) {
                                link->data = NULL;
@@ -4451,8 +4555,10 @@ e_cal_meta_backend_split_changes_sync (ECalMetaBackend *meta_backend,
                                *out_modified_objects = g_slist_prepend (*out_modified_objects, nfo);
                        }
 
-                       g_hash_table_remove (locally_cached, &id);
+                       g_hash_table_remove (locally_cached, id);
                }
+
+               e_cal_component_id_free (id);
        }
 
        if (out_removed_objects) {
@@ -4469,17 +4575,20 @@ e_cal_meta_backend_split_changes_sync (ECalMetaBackend *meta_backend,
                        }
 
                        /* Skit detached instances, if the master object is still in the cache */
-                       if (id->rid && *id->rid) {
-                               ECalComponentId master_id;
+                       if (e_cal_component_id_get_rid (id)) {
+                               ECalComponentId *master_id;
 
-                               master_id.uid = id->uid;
-                               master_id.rid = NULL;
+                               master_id = e_cal_component_id_new (e_cal_component_id_get_uid (id), NULL);
 
-                               if (!g_hash_table_contains (locally_cached, &master_id))
+                               if (!g_hash_table_contains (locally_cached, master_id)) {
+                                       e_cal_component_id_free (master_id);
                                        continue;
+                               }
+
+                               e_cal_component_id_free (master_id);
                        }
 
-                       nfo = e_cal_meta_backend_info_new (id->uid, revision, NULL, NULL);
+                       nfo = e_cal_meta_backend_info_new (e_cal_component_id_get_uid (id), revision, NULL, 
NULL);
                        *out_removed_objects = g_slist_prepend (*out_removed_objects, nfo);
                }
 
@@ -4545,7 +4654,7 @@ e_cal_meta_backend_process_changes_sync (ECalMetaBackend *meta_backend,
                        continue;
                }
 
-               success = ecmb_maybe_remove_from_cache (meta_backend, cal_cache, E_CACHE_IS_ONLINE, nfo->uid, 
cancellable, error);
+               success = ecmb_maybe_remove_from_cache (meta_backend, cal_cache, E_CACHE_IS_ONLINE, nfo->uid, 
0, cancellable, error);
        }
 
        /* Then modified objects */
@@ -4567,7 +4676,7 @@ e_cal_meta_backend_process_changes_sync (ECalMetaBackend *meta_backend,
                success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, nfo->uid, nfo->object, 
nfo->extra, NULL, cancellable, &local_error);
 
                /* Do not stop on invalid objects, just notify about them later, and load as many as possible 
*/
-               if (!success && g_error_matches (local_error, E_DATA_CAL_ERROR, InvalidObject)) {
+               if (!success && g_error_matches (local_error, E_CAL_CLIENT_ERROR, 
E_CAL_CLIENT_ERROR_INVALID_OBJECT)) {
                        if (!invalid_objects) {
                                invalid_objects = g_string_new (local_error->message);
                        } else {
@@ -4599,7 +4708,7 @@ e_cal_meta_backend_process_changes_sync (ECalMetaBackend *meta_backend,
                success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, nfo->uid, nfo->object, 
nfo->extra, NULL, cancellable, &local_error);
 
                /* Do not stop on invalid objects, just notify about them later, and load as many as possible 
*/
-               if (!success && g_error_matches (local_error, E_DATA_CAL_ERROR, InvalidObject)) {
+               if (!success && g_error_matches (local_error, E_CAL_CLIENT_ERROR, 
E_CAL_CLIENT_ERROR_INVALID_OBJECT)) {
                        if (!invalid_objects) {
                                invalid_objects = g_string_new (local_error->message);
                        } else {
@@ -4904,7 +5013,7 @@ e_cal_meta_backend_list_existing_sync (ECalMetaBackend *meta_backend,
  * @meta_backend: an #ECalMetaBackend
  * @uid: a component UID
  * @extra: (nullable): optional extra data stored with the component, or %NULL
- * @out_component: (out) (transfer full): a loaded component, as icalcomponent
+ * @out_component: (out) (transfer full): a loaded component, as #ICalComponent
  * @out_extra: (out) (transfer full): an extra data to store to #ECalCache with this component
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -4917,7 +5026,7 @@ e_cal_meta_backend_list_existing_sync (ECalMetaBackend *meta_backend,
  *
  * It is mandatory to implement this virtual method by the descendant.
  *
- * The returned @out_component should be freed with icalcomponent_free(),
+ * The returned @out_component should be freed with g_object_unref(),
  * when no longer needed.
  *
  * The returned @out_extra should be freed with g_free(), when no longer
@@ -4931,7 +5040,7 @@ gboolean
 e_cal_meta_backend_load_component_sync (ECalMetaBackend *meta_backend,
                                        const gchar *uid,
                                        const gchar *extra,
-                                       icalcomponent **out_component,
+                                       ICalComponent **out_component,
                                        gchar **out_extra,
                                        GCancellable *cancellable,
                                        GError **error)
@@ -4980,6 +5089,7 @@ e_cal_meta_backend_load_component_sync (ECalMetaBackend *meta_backend,
  * @conflict_resolution: one of #EConflictResolution, what to do on conflicts
  * @instances: (element-type ECalComponent): instances of the component to save
  * @extra: (nullable): extra data saved with the components in an #ECalCache
+ * @opflags: bit-or of #ECalOperationFlags
  * @out_new_uid: (out) (transfer full): return location for the UID of the saved component
  * @out_new_extra: (out) (transfer full): return location for the extra data to store with the component
  * @cancellable: optional #GCancellable object, or %NULL
@@ -5025,6 +5135,7 @@ e_cal_meta_backend_save_component_sync (ECalMetaBackend *meta_backend,
                                        EConflictResolution conflict_resolution,
                                        const GSList *instances,
                                        const gchar *extra,
+                                       guint32 opflags,
                                        gchar **out_new_uid,
                                        gchar **out_new_extra,
                                        GCancellable *cancellable,
@@ -5044,7 +5155,7 @@ e_cal_meta_backend_save_component_sync (ECalMetaBackend *meta_backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (!klass->save_component_sync) {
-               g_propagate_error (error, e_data_cal_create_error (NotSupported, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                return FALSE;
        }
 
@@ -5064,6 +5175,7 @@ e_cal_meta_backend_save_component_sync (ECalMetaBackend *meta_backend,
                        conflict_resolution,
                        instances,
                        extra,
+                       opflags,
                        out_new_uid,
                        out_new_extra,
                        cancellable,
@@ -5086,6 +5198,7 @@ e_cal_meta_backend_save_component_sync (ECalMetaBackend *meta_backend,
  * @uid: a component UID
  * @extra: (nullable): extra data being saved with the component in the local cache, or %NULL
  * @object: (nullable): corresponding iCalendar object, as stored in the local cache, or %NULL
+ * @opflags: bit-or of #ECalOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -5106,6 +5219,7 @@ e_cal_meta_backend_remove_component_sync (ECalMetaBackend *meta_backend,
                                          const gchar *uid,
                                          const gchar *extra,
                                          const gchar *object,
+                                         guint32 opflags,
                                          GCancellable *cancellable,
                                          GError **error)
 {
@@ -5121,7 +5235,7 @@ e_cal_meta_backend_remove_component_sync (ECalMetaBackend *meta_backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (!klass->remove_component_sync) {
-               g_propagate_error (error, e_data_cal_create_error (NotSupported, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                return FALSE;
        }
 
@@ -5135,7 +5249,7 @@ e_cal_meta_backend_remove_component_sync (ECalMetaBackend *meta_backend,
                g_clear_error (&local_error);
                repeat_count++;
 
-               success = klass->remove_component_sync (meta_backend, conflict_resolution, uid, extra, 
object, cancellable, &local_error);
+               success = klass->remove_component_sync (meta_backend, conflict_resolution, uid, extra, 
object, opflags, cancellable, &local_error);
 
                if (!success && repeat_count <= MAX_REPEAT_COUNT && !ecmb_maybe_wait_for_credentials 
(meta_backend, wait_credentials_stamp, local_error, cancellable))
                        break;
@@ -5272,7 +5386,7 @@ e_cal_meta_backend_requires_reconnect (ECalMetaBackend *meta_backend)
  *
  * It is optional to implement this virtual method by the descendants.
  * It is used to receive SSL error details when any online operation
- * returns E_DATA_CAL_ERROR, TLSNotAvailable error.
+ * returns E_CLIENT_ERROR, E_CLIENT_ERROR_TLS_NOT_AVAILABLE error.
  *
  * Returns: %TRUE, when the SSL error details had been available and
  *    the out parameters populated, %FALSE otherwise.
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.h b/src/calendar/libedata-cal/e-cal-meta-backend.h
index 4318e151d..3057bf27b 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.h
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.h
@@ -127,7 +127,7 @@ struct _ECalMetaBackendClass {
        gboolean        (* load_component_sync) (ECalMetaBackend *meta_backend,
                                                 const gchar *uid,
                                                 const gchar *extra,
-                                                icalcomponent **out_component,
+                                                ICalComponent **out_component,
                                                 gchar **out_extra,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -136,6 +136,7 @@ struct _ECalMetaBackendClass {
                                                 EConflictResolution conflict_resolution,
                                                 const GSList *instances, /* ECalComponent * */
                                                 const gchar *extra,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 gchar **out_new_uid,
                                                 gchar **out_new_extra,
                                                 GCancellable *cancellable,
@@ -146,6 +147,7 @@ struct _ECalMetaBackendClass {
                                                 const gchar *uid,
                                                 const gchar *extra,
                                                 const gchar *object,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (* search_sync)         (ECalMetaBackend *meta_backend,
@@ -190,23 +192,23 @@ gchar *           e_cal_meta_backend_dup_sync_tag (ECalMetaBackend *meta_backend);
 void           e_cal_meta_backend_set_cache    (ECalMetaBackend *meta_backend,
                                                 ECalCache *cache);
 ECalCache *    e_cal_meta_backend_ref_cache    (ECalMetaBackend *meta_backend);
-icalcomponent *        e_cal_meta_backend_merge_instances
+ICalComponent *        e_cal_meta_backend_merge_instances
                                                (ECalMetaBackend *meta_backend,
                                                 const GSList *instances, /* ECalComponent * */
                                                 gboolean replace_tzid_with_location);
 gboolean       e_cal_meta_backend_inline_local_attachments_sync
                                                (ECalMetaBackend *meta_backend,
-                                                icalcomponent *component,
+                                                ICalComponent *component,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_meta_backend_store_inline_attachments_sync
                                                (ECalMetaBackend *meta_backend,
-                                                icalcomponent *component,
+                                                ICalComponent *component,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_meta_backend_gather_timezones_sync
                                                (ECalMetaBackend *meta_backend,
-                                                icalcomponent *vcalendar,
+                                                ICalComponent *vcalendar,
                                                 gboolean remove_existing,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -270,7 +272,7 @@ gboolean    e_cal_meta_backend_load_component_sync
                                                (ECalMetaBackend *meta_backend,
                                                 const gchar *uid,
                                                 const gchar *extra,
-                                                icalcomponent **out_component,
+                                                ICalComponent **out_component,
                                                 gchar **out_extra,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -280,6 +282,7 @@ gboolean    e_cal_meta_backend_save_component_sync
                                                 EConflictResolution conflict_resolution,
                                                 const GSList *instances, /* ECalComponent * */
                                                 const gchar *extra,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 gchar **out_new_uid,
                                                 gchar **out_new_extra,
                                                 GCancellable *cancellable,
@@ -290,6 +293,7 @@ gboolean    e_cal_meta_backend_remove_component_sync
                                                 const gchar *uid,
                                                 const gchar *extra,
                                                 const gchar *object,
+                                                guint32 opflags, /* bit-or of ECalOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_cal_meta_backend_search_sync  (ECalMetaBackend *meta_backend,
diff --git a/src/calendar/libedata-cal/e-data-cal-factory.c b/src/calendar/libedata-cal/e-data-cal-factory.c
index dcb05be23..5a4de310a 100644
--- a/src/calendar/libedata-cal/e-data-cal-factory.c
+++ b/src/calendar/libedata-cal/e-data-cal-factory.c
@@ -47,27 +47,7 @@
 #include "e-data-cal.h"
 #include "e-data-cal-factory.h"
 
-#include <libical/ical.h>
-
-/*
- * FIXME: Remove this when there's a build time dependency on libical
- * 3.0.4 (where this is fixed). See
- * https://github.com/libical/libical/pull/335 and the implementation in
- * https://github.com/libical/libical/blob/master/src/libical/icalversion.h.cmake.
- */
-#if defined(ICAL_CHECK_VERSION) && defined(ICAL_MAJOR_VERSION) && defined(ICAL_MINOR_VERSION) && 
defined(ICAL_MICRO_VERSION)
-#undef ICAL_CHECK_VERSION
-#define ICAL_CHECK_VERSION(major,minor,micro)                          \
-    (ICAL_MAJOR_VERSION > (major) ||                                   \
-    (ICAL_MAJOR_VERSION == (major) && ICAL_MINOR_VERSION > (minor)) || \
-    (ICAL_MAJOR_VERSION == (major) && ICAL_MINOR_VERSION == (minor) && \
-    ICAL_MICRO_VERSION >= (micro)))
-#else
-#if defined(ICAL_CHECK_VERSION)
-#undef ICAL_CHECK_VERSION
-#endif
-#define ICAL_CHECK_VERSION(major,minor,micro) (0)
-#endif
+#include <libical-glib/libical-glib.h>
 
 #define d(x)
 
@@ -384,48 +364,7 @@ e_data_cal_factory_new (gint backend_per_process,
                        GCancellable *cancellable,
                         GError **error)
 {
-#if !ICAL_CHECK_VERSION(3, 0, 2)
-       icalarray *builtin_timezones;
-       gint ii;
-#endif
-
-#ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING
-       ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN);
-#endif
-
-#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT
-       icaltzutil_set_exact_vtimezones_support (0);
-#endif
-
-#if !ICAL_CHECK_VERSION(3, 0, 2)
-       /* XXX Pre-load all built-in timezones in libical.
-        *
-        *     Built-in time zones in libical 0.43 are loaded on demand,
-        *     but not in a thread-safe manner, resulting in a race when
-        *     multiple threads call icaltimezone_load_builtin_timezone()
-        *     on the same time zone.  Until built-in time zone loading
-        *     in libical is made thread-safe, work around the issue by
-        *     loading all built-in time zones now, so libical's internal
-        *     time zone array will be fully populated before any threads
-        *     are spawned.
-        *
-        *     This is apparently fixed with additional locking in
-        *     libical 3.0.1 and 3.0.2:
-        *     https://github.com/libical/libical/releases/tag/v3.0.1
-        *     https://github.com/libical/libical/releases/tag/v3.0.2
-        */
-       builtin_timezones = icaltimezone_get_builtin_timezones ();
-       for (ii = 0; ii < builtin_timezones->num_elements; ii++) {
-               icaltimezone *zone;
-
-               zone = icalarray_element_at (builtin_timezones, ii);
-
-               /* We don't care about the component right now,
-                * we just need some function that will trigger
-                * icaltimezone_load_builtin_timezone(). */
-               icaltimezone_get_component (zone);
-       }
-#endif
+       i_cal_set_unknown_token_handling_setting (I_CAL_DISCARD_TOKEN);
 
        return g_initable_new (E_TYPE_DATA_CAL_FACTORY, cancellable, error,
                "reload-supported", TRUE,
diff --git a/src/calendar/libedata-cal/e-data-cal-view.c b/src/calendar/libedata-cal/e-data-cal-view.c
index f60d0da4d..8ece57fcf 100644
--- a/src/calendar/libedata-cal/e-data-cal-view.c
+++ b/src/calendar/libedata-cal/e-data-cal-view.c
@@ -139,25 +139,6 @@ str_ic_equal (gconstpointer a,
        return stra[ii] == strb[ii];
 }
 
-static guint
-id_hash (gconstpointer key)
-{
-       const ECalComponentId *id = key;
-
-       return g_str_hash (id->uid) ^ (id->rid ? g_str_hash (id->rid) : 0);
-}
-
-static gboolean
-id_equal (gconstpointer a,
-          gconstpointer b)
-{
-       const ECalComponentId *id_a = a;
-       const ECalComponentId *id_b = b;
-
-       return (g_strcmp0 (id_a->uid, id_b->uid) == 0) &&
-               (g_strcmp0 (id_a->rid, id_b->rid) == 0);
-}
-
 static void
 reset_array (GArray *array)
 {
@@ -598,9 +579,9 @@ e_data_cal_view_init (EDataCalView *view)
                TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS);
 
        view->priv->ids = g_hash_table_new_full (
-               (GHashFunc) id_hash,
-               (GEqualFunc) id_equal,
-               (GDestroyNotify) e_cal_component_free_id,
+               (GHashFunc) e_cal_component_id_hash,
+               (GEqualFunc) e_cal_component_id_equal,
+               (GDestroyNotify) e_cal_component_id_free,
                (GDestroyNotify) NULL);
 
        g_mutex_init (&view->priv->pending_mutex);
@@ -619,7 +600,7 @@ e_data_cal_view_init (EDataCalView *view)
  * @connection at @object_path.  If an error occurs while exporting,
  * the function sets @error and returns %NULL.
  *
- * Returns: an #EDataCalView
+ * Returns: (transfer full) (nullable): a new #EDataCalView, or %NULL on error
  **/
 EDataCalView *
 e_data_cal_view_new (ECalBackend *backend,
@@ -784,15 +765,15 @@ notify_remove (EDataCalView *view,
                send_pending_removes (view);
 
        /* store ECalComponentId as <uid>[\n<rid>] (matches D-Bus API) */
-       if (id->uid) {
-               uid = e_util_utf8_make_valid (id->uid);
+       if (e_cal_component_id_get_uid (id)) {
+               uid = e_util_utf8_make_valid (e_cal_component_id_get_uid (id));
                uid_len = strlen (uid);
        } else {
                uid = NULL;
                uid_len = 0;
        }
-       if (id->rid) {
-               rid = e_util_utf8_make_valid (id->rid);
+       if (e_cal_component_id_get_rid (id)) {
+               rid = e_util_utf8_make_valid (e_cal_component_id_get_rid (id));
                rid_len = strlen (rid);
        } else {
                rid = NULL;
@@ -828,7 +809,7 @@ notify_remove (EDataCalView *view,
  *
  * Gets the backend that @view is querying.
  *
- * Returns: The associated #ECalBackend.
+ * Returns: (transfer none): The associated #ECalBackend.
  *
  * Since: 3.8
  **/
@@ -847,7 +828,7 @@ e_data_cal_view_get_backend (EDataCalView *view)
  * Returns the #GDBusConnection on which the CalendarView D-Bus
  * interface is exported.
  *
- * Returns: the #GDBusConnection
+ * Returns: (transfer none): the #GDBusConnection
  *
  * Since: 3.8
  **/
@@ -884,7 +865,7 @@ e_data_cal_view_get_object_path (EDataCalView *view)
  *
  * Get the #ECalBackendSExp object used for the given view.
  *
- * Returns: The expression object used to search.
+ * Returns: (transfer none): The expression object used to search.
  *
  * Since: 3.8
  */
@@ -1011,7 +992,7 @@ e_data_cal_view_is_completed (EDataCalView *view)
  * e_data_cal_view_get_fields_of_interest:
  * @view: an #EDataCalView
  *
- * Returns: Hash table of field names which the listener is interested in.
+ * Returns: (transfer none): Hash table of field names which the listener is interested in.
  * Backends can return fully populated objects, but the listener advertised
  * that it will use only these. Returns %NULL for all available fields.
  *
@@ -1048,7 +1029,7 @@ e_data_cal_view_get_flags (EDataCalView *view)
 }
 
 static gboolean
-filter_component (icalcomponent *icomponent,
+filter_component (ICalComponent *icomponent,
                   GHashTable *fields_of_interest,
                   GString *string)
 {
@@ -1057,10 +1038,10 @@ filter_component (icalcomponent *icomponent,
        /* RFC 2445 explicitly says that the newline is *ALWAYS* a \r\n (CRLF)!!!! */
        const gchar        newline[] = "\r\n";
 
-       icalcomponent_kind kind;
+       ICalComponentKind  kind;
        const gchar       *kind_string;
-       icalproperty      *prop;
-       icalcomponent     *icomp;
+       ICalProperty      *prop;
+       ICalComponent     *icomp;
        gboolean           fail = FALSE;
 
        g_return_val_if_fail (icomponent != NULL, FALSE);
@@ -1068,29 +1049,29 @@ filter_component (icalcomponent *icomponent,
        /* Open iCalendar string */
        g_string_append (string, "BEGIN:");
 
-       kind = icalcomponent_isa (icomponent);
+       kind = i_cal_component_isa (icomponent);
 
-       /* if (kind != ICAL_X_COMPONENT) { */
-       /*      kind_string  = icalcomponent_kind_to_string (kind); */
+       /* if (kind != I_CAL_X_COMPONENT) { */
+       /*      kind_string  = i_cal_component_kind_to_string (kind); */
        /* } else { */
        /*      kind_string = icomponent->x_name; */
        /* } */
 
-       kind_string = icalcomponent_kind_to_string (kind);
+       kind_string = i_cal_component_kind_to_string (kind);
 
        g_string_append (string, kind_string);
        g_string_append (string, newline);
 
-       for (prop = icalcomponent_get_first_property (icomponent, ICAL_ANY_PROPERTY);
+       for (prop = i_cal_component_get_first_property (icomponent, I_CAL_ANY_PROPERTY);
             prop;
-            prop = icalcomponent_get_next_property (icomponent, ICAL_ANY_PROPERTY)) {
-               const gchar *name;
-               gboolean     is_field_of_interest;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icomponent, 
I_CAL_ANY_PROPERTY)) {
+               gchar *name;
+               gboolean is_field_of_interest;
 
-               name = icalproperty_get_property_name (prop);
+               name = i_cal_property_get_property_name_r (prop);
 
                if (!name) {
-                       g_warning ("NULL ical property name encountered while serializing component");
+                       g_warning ("NULL iCal property name encountered while serializing component");
                        fail = TRUE;
                        break;
                }
@@ -1099,15 +1080,17 @@ filter_component (icalcomponent *icomponent,
 
                /* Append any name that is mentioned in the fields-of-interest */
                if (is_field_of_interest) {
-                       str = icalproperty_as_ical_string_r (prop);
+                       str = i_cal_property_as_ical_string_r (prop);
                        g_string_append (string, str);
                        g_free (str);
                }
+
+               g_free (name);
        }
 
-       for (icomp = icalcomponent_get_first_component (icomponent, ICAL_ANY_COMPONENT);
+       for (icomp = i_cal_component_get_first_component (icomponent, I_CAL_ANY_COMPONENT);
             fail == FALSE && icomp;
-            icomp = icalcomponent_get_next_component (icomponent, ICAL_ANY_COMPONENT)) {
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (icomponent, 
I_CAL_ANY_COMPONENT)) {
 
                if (!filter_component (icomp, fields_of_interest, string)) {
                        fail = TRUE;
@@ -1115,8 +1098,10 @@ filter_component (icalcomponent *icomponent,
                }
        }
 
+       g_clear_object (&icomp);
+
        g_string_append (string, "END:");
-       g_string_append (string, icalcomponent_kind_to_string (kind));
+       g_string_append (string, i_cal_component_kind_to_string (kind));
        g_string_append (string, newline);
 
        return fail == FALSE;
@@ -1147,9 +1132,9 @@ e_data_cal_view_get_component_string (EDataCalView *view,
 
        if (view->priv->fields_of_interest) {
                GString *string = g_string_new ("");
-               icalcomponent *icalcomp = e_cal_component_get_icalcomponent (component);
+               ICalComponent *icomp = e_cal_component_get_icalcomponent (component);
 
-               if (filter_component (icalcomp, view->priv->fields_of_interest, string))
+               if (filter_component (icomp, view->priv->fields_of_interest, string))
                        str = g_string_free (string, FALSE);
                else
                        g_string_free (string, TRUE);
@@ -1169,12 +1154,12 @@ e_data_cal_view_get_component_string (EDataCalView *view,
 /**
  * e_data_cal_view_notify_components_added:
  * @view: an #EDataCalView
- * @ecalcomponents: List of #ECalComponent-s that have been added.
+ * @ecalcomponents: (element-type ECalComponent): List of #ECalComponent-s that have been added.
  *
  * Notifies all view listeners of the addition of a list of components.
  *
  * Uses the #EDataCalView's fields-of-interest to filter out unwanted
- * information from ical strings sent over the bus.
+ * information from iCalendar strings sent over the bus.
  *
  * Since: 3.4
  */
@@ -1210,7 +1195,7 @@ e_data_cal_view_notify_components_added (EDataCalView *view,
  * Notifies all the view listeners of the addition of a single object.
  *
  * Uses the #EDataCalView's fields-of-interest to filter out unwanted
- * information from ical strings sent over the bus.
+ * information from iCalendar strings sent over the bus.
  *
  * Since: 3.4
  */
@@ -1230,12 +1215,12 @@ e_data_cal_view_notify_components_added_1 (EDataCalView *view,
 /**
  * e_data_cal_view_notify_components_modified:
  * @view: an #EDataCalView
- * @ecalcomponents: List of modified #ECalComponent-s.
+ * @ecalcomponents: (element-type ECalComponent): List of modified #ECalComponent-s.
  *
  * Notifies all view listeners of the modification of a list of components.
  *
  * Uses the #EDataCalView's fields-of-interest to filter out unwanted
- * information from ical strings sent over the bus.
+ * information from iCalendar strings sent over the bus.
  *
  * Since: 3.4
  */
@@ -1271,7 +1256,7 @@ e_data_cal_view_notify_components_modified (EDataCalView *view,
  * Notifies all view listeners of the modification of @component.
  * 
  * Uses the #EDataCalView's fields-of-interest to filter out unwanted
- * information from ical strings sent over the bus.
+ * information from iCalendar strings sent over the bus.
  *
  * Since: 3.4
  */
@@ -1291,7 +1276,7 @@ e_data_cal_view_notify_components_modified_1 (EDataCalView *view,
 /**
  * e_data_cal_view_notify_objects_removed:
  * @view: an #EDataCalView
- * @ids: List of IDs for the objects that have been removed.
+ * @ids: (element-type ECalComponentId): List of IDs for the objects that have been removed.
  *
  * Notifies all view listener of the removal of a list of objects.
  */
diff --git a/src/calendar/libedata-cal/e-data-cal.c b/src/calendar/libedata-cal/e-data-cal.c
index a1c052bf7..baccdfa2a 100644
--- a/src/calendar/libedata-cal/e-data-cal.c
+++ b/src/calendar/libedata-cal/e-data-cal.c
@@ -26,7 +26,6 @@
 
 #include "evolution-data-server-config.h"
 
-#include <libical/ical.h>
 #include <glib/gi18n-lib.h>
 #include <unistd.h>
 
@@ -43,9 +42,6 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_DATA_CAL, EDataCalPrivate))
 
-#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
-#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
-
 typedef struct _AsyncContext AsyncContext;
 
 struct _EDataCalPrivate {
@@ -220,292 +216,9 @@ data_cal_convert_to_client_error (GError *error)
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
                error->domain = E_CAL_CLIENT_ERROR;
                error->code = E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR;
-
-               return;
-       }
-
-       if (error->domain != E_DATA_CAL_ERROR)
-               return;
-
-       switch (error->code) {
-               case RepositoryOffline:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_REPOSITORY_OFFLINE;
-                       break;
-
-               case PermissionDenied:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_PERMISSION_DENIED;
-                       break;
-
-               case InvalidRange:
-                       error->domain = E_CAL_CLIENT_ERROR;
-                       error->code = E_CAL_CLIENT_ERROR_INVALID_RANGE;
-                       break;
-
-               case ObjectNotFound:
-                       error->domain = E_CAL_CLIENT_ERROR;
-                       error->code = E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND;
-                       break;
-
-               case InvalidObject:
-                       error->domain = E_CAL_CLIENT_ERROR;
-                       error->code = E_CAL_CLIENT_ERROR_INVALID_OBJECT;
-                       break;
-
-               case ObjectIdAlreadyExists:
-                       error->domain = E_CAL_CLIENT_ERROR;
-                       error->code = E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS;
-                       break;
-
-               case AuthenticationFailed:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
-                       break;
-
-               case AuthenticationRequired:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_AUTHENTICATION_REQUIRED;
-                       break;
-
-               case UnsupportedAuthenticationMethod:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD;
-                       break;
-
-               case TLSNotAvailable:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
-                       break;
-
-               case NoSuchCal:
-                       error->domain = E_CAL_CLIENT_ERROR;
-                       error->code = E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR;
-                       break;
-
-               case UnknownUser:
-                       error->domain = E_CAL_CLIENT_ERROR;
-                       error->code = E_CAL_CLIENT_ERROR_UNKNOWN_USER;
-                       break;
-
-               case OfflineUnavailable:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_OFFLINE_UNAVAILABLE;
-                       break;
-
-               case SearchSizeLimitExceeded:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED;
-                       break;
-
-               case SearchTimeLimitExceeded:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED;
-                       break;
-
-               case InvalidQuery:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_INVALID_QUERY;
-                       break;
-
-               case QueryRefused:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_QUERY_REFUSED;
-                       break;
-
-               case CouldNotCancel:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_COULD_NOT_CANCEL;
-                       break;
-
-               case InvalidArg:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_INVALID_ARG;
-                       break;
-
-               case NotSupported:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_NOT_SUPPORTED;
-                       break;
-
-               case NotOpened:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_NOT_OPENED;
-                       break;
-
-               case UnsupportedField:
-               case UnsupportedMethod:
-               case OtherError:
-               case InvalidServerVersion:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_OTHER_ERROR;
-                       break;
-
-               default:
-                       g_warn_if_reached ();
        }
 }
 
-/* Create the EDataCal error quark */
-GQuark
-e_data_cal_error_quark (void)
-{
-       #define ERR_PREFIX "org.gnome.evolution.dataserver.Calendar."
-
-       static const GDBusErrorEntry entries[] = {
-               { Success,                              ERR_PREFIX "Success" },
-               { Busy,                                 ERR_PREFIX "Busy" },
-               { RepositoryOffline,                    ERR_PREFIX "RepositoryOffline" },
-               { PermissionDenied,                     ERR_PREFIX "PermissionDenied" },
-               { InvalidRange,                         ERR_PREFIX "InvalidRange" },
-               { ObjectNotFound,                       ERR_PREFIX "ObjectNotFound" },
-               { InvalidObject,                        ERR_PREFIX "InvalidObject" },
-               { ObjectIdAlreadyExists,                ERR_PREFIX "ObjectIdAlreadyExists" },
-               { AuthenticationFailed,                 ERR_PREFIX "AuthenticationFailed" },
-               { AuthenticationRequired,               ERR_PREFIX "AuthenticationRequired" },
-               { UnsupportedField,                     ERR_PREFIX "UnsupportedField" },
-               { UnsupportedMethod,                    ERR_PREFIX "UnsupportedMethod" },
-               { UnsupportedAuthenticationMethod,      ERR_PREFIX "UnsupportedAuthenticationMethod" },
-               { TLSNotAvailable,                      ERR_PREFIX "TLSNotAvailable" },
-               { NoSuchCal,                            ERR_PREFIX "NoSuchCal" },
-               { UnknownUser,                          ERR_PREFIX "UnknownUser" },
-               { OfflineUnavailable,                   ERR_PREFIX "OfflineUnavailable" },
-               { SearchSizeLimitExceeded,              ERR_PREFIX "SearchSizeLimitExceeded" },
-               { SearchTimeLimitExceeded,              ERR_PREFIX "SearchTimeLimitExceeded" },
-               { InvalidQuery,                         ERR_PREFIX "InvalidQuery" },
-               { QueryRefused,                         ERR_PREFIX "QueryRefused" },
-               { CouldNotCancel,                       ERR_PREFIX "CouldNotCancel" },
-               { OtherError,                           ERR_PREFIX "OtherError" },
-               { InvalidServerVersion,                 ERR_PREFIX "InvalidServerVersion" },
-               { InvalidArg,                           ERR_PREFIX "InvalidArg" },
-               { NotSupported,                         ERR_PREFIX "NotSupported" },
-               { NotOpened,                            ERR_PREFIX "NotOpened" }
-       };
-
-       #undef ERR_PREFIX
-
-       static volatile gsize quark_volatile = 0;
-
-       g_dbus_error_register_error_domain ("e-data-cal-error", &quark_volatile, entries, G_N_ELEMENTS 
(entries));
-
-       return (GQuark) quark_volatile;
-}
-
-/**
- * e_data_cal_status_to_string:
- * @status: an #EDataCalCallStatus
- *
- * Returns: A localized text representation of the @status.
- *
- * Since: 2.32
- **/
-const gchar *
-e_data_cal_status_to_string (EDataCalCallStatus status)
-{
-       gint i;
-       static struct _statuses {
-               EDataCalCallStatus status;
-               const gchar *msg;
-       } statuses[] = {
-               { Success,                              N_("Success") },
-               { Busy,                                 N_("Backend is busy") },
-               { RepositoryOffline,                    N_("Repository offline") },
-               { PermissionDenied,                     N_("Permission denied") },
-               { InvalidRange,                         N_("Invalid range") },
-               { ObjectNotFound,                       N_("Object not found") },
-               { InvalidObject,                        N_("Invalid object") },
-               { ObjectIdAlreadyExists,                N_("Object ID already exists") },
-               { AuthenticationFailed,                 N_("Authentication Failed") },
-               { AuthenticationRequired,               N_("Authentication Required") },
-               { UnsupportedField,                     N_("Unsupported field") },
-               { UnsupportedMethod,                    N_("Unsupported method") },
-               { UnsupportedAuthenticationMethod,      N_("Unsupported authentication method") },
-               { TLSNotAvailable,                      N_("TLS not available") },
-               { NoSuchCal,                            N_("Calendar does not exist") },
-               { UnknownUser,                          N_("Unknown user") },
-               { OfflineUnavailable,                   N_("Not available in offline mode") },
-               { SearchSizeLimitExceeded,              N_("Search size limit exceeded") },
-               { SearchTimeLimitExceeded,              N_("Search time limit exceeded") },
-               { InvalidQuery,                         N_("Invalid query") },
-               { QueryRefused,                         N_("Query refused") },
-               { CouldNotCancel,                       N_("Could not cancel") },
-               /* { OtherError,                        N_("Other error") }, */
-               { InvalidServerVersion,                 N_("Invalid server version") },
-               { InvalidArg,                           N_("Invalid argument") },
-               /* Translators: The string for NOT_SUPPORTED error */
-               { NotSupported,                         N_("Not supported") },
-               { NotOpened,                            N_("Backend is not opened yet") }
-       };
-
-       for (i = 0; i < G_N_ELEMENTS (statuses); i++) {
-               if (statuses[i].status == status)
-                       return _(statuses[i].msg);
-       }
-
-       return _("Other error");
-}
-
-/**
- * e_data_cal_create_error:
- * @status: #EDataCalCallStatus code
- * @custom_msg: Custom message to use for the error. When NULL,
- *              then uses a default message based on the @status code.
- *
- * Returns: (nullable) (transfer full): %NULL, when the @status is Success,
- *          or a newly allocated GError, which should be freed
- *          with g_error_free() call.
- *
- * Since: 2.32
- **/
-GError *
-e_data_cal_create_error (EDataCalCallStatus status,
-                         const gchar *custom_msg)
-{
-       if (status == Success)
-               return NULL;
-
-       return g_error_new_literal (E_DATA_CAL_ERROR, status, custom_msg ? custom_msg : 
e_data_cal_status_to_string (status));
-}
-
-/**
- * e_data_cal_create_error_fmt:
- * @status: an #EDataCalCallStatus
- * @custom_msg_fmt: (nullable): message format, or %NULL to use the default message for the @status
- * @...: arguments for the format
- *
- * Similar as e_data_cal_create_error(), only here, instead of custom_msg,
- * is used a printf() format to create a custom message for the error.
- *
- * Returns: (nullable) (transfer full): %NULL, when the @status is Success,
- *   or a newly allocated #GError, which should be freed with g_error_free() call.
- *   The #GError has set the custom message, or the default message for
- *   @status, when @custom_msg_fmt is %NULL.
- *
- * Since: 2.32
- **/
-GError *
-e_data_cal_create_error_fmt (EDataCalCallStatus status,
-                             const gchar *custom_msg_fmt,
-                             ...)
-{
-       GError *error;
-       gchar *custom_msg;
-       va_list ap;
-
-       if (!custom_msg_fmt)
-               return e_data_cal_create_error (status, NULL);
-
-       va_start (ap, custom_msg_fmt);
-       custom_msg = g_strdup_vprintf (custom_msg_fmt, ap);
-       va_end (ap);
-
-       error = e_data_cal_create_error (status, custom_msg);
-
-       g_free (custom_msg);
-
-       return error;
-}
-
 static GPtrArray *
 data_cal_encode_properties (EDBusCalendar *dbus_interface)
 {
@@ -952,6 +665,7 @@ static gboolean
 data_cal_handle_create_objects_cb (EDBusCalendar *dbus_interface,
                                    GDBusMethodInvocation *invocation,
                                    const gchar * const *in_calobjs,
+                                  guint32 in_opflags,
                                    EDataCal *data_cal)
 {
        ECalBackend *backend;
@@ -965,6 +679,7 @@ data_cal_handle_create_objects_cb (EDBusCalendar *dbus_interface,
        e_cal_backend_create_objects (
                backend,
                in_calobjs,
+               in_opflags,
                async_context->cancellable,
                data_cal_complete_create_objects_cb,
                async_context);
@@ -1003,6 +718,7 @@ data_cal_handle_modify_objects_cb (EDBusCalendar *dbus_interface,
                                    GDBusMethodInvocation *invocation,
                                    const gchar * const *in_ics_objects,
                                    const gchar *in_mod_type,
+                                  guint32 in_opflags,
                                    EDataCal *data_cal)
 {
        ECalBackend *backend;
@@ -1037,7 +753,7 @@ data_cal_handle_modify_objects_cb (EDBusCalendar *dbus_interface,
 
        e_cal_backend_modify_objects (
                backend,
-               in_ics_objects, mod,
+               in_ics_objects, mod, in_opflags,
                async_context->cancellable,
                data_cal_complete_modify_objects_cb,
                async_context);
@@ -1076,6 +792,7 @@ data_cal_handle_remove_objects_cb (EDBusCalendar *dbus_interface,
                                    GDBusMethodInvocation *invocation,
                                    GVariant *in_uid_rid_array,
                                    const gchar *in_mod_type,
+                                  guint32 in_opflags,
                                    EDataCal *data_cal)
 {
        ECalBackend *backend;
@@ -1109,42 +826,30 @@ data_cal_handle_remove_objects_cb (EDBusCalendar *dbus_interface,
 
        n_children = g_variant_n_children (in_uid_rid_array);
        for (ii = 0; ii < n_children; ii++) {
-               ECalComponentId *id;
-
-               /* e_cal_component_free_id() uses g_free(),
-                * not g_slice_free().  Therefore allocate
-                * with g_malloc(), not g_slice_new(). */
-               id = g_malloc0 (sizeof (ECalComponentId));
+               gchar *uid = NULL, *rid = NULL;
 
-               g_variant_get_child (
-                       in_uid_rid_array, ii, "(ss)", &id->uid, &id->rid);
+               g_variant_get_child (in_uid_rid_array, ii, "(ss)", &uid, &rid);
 
-               if (id->uid != NULL && *id->uid == '\0') {
-                       e_cal_component_free_id (id);
+               if (!uid || !*uid) {
+                       g_free (uid);
+                       g_free (rid);
                        continue;
                }
 
-               /* Recurrence ID is optional.  Its omission is denoted
-                * via D-Bus by an empty string.  Convert it to NULL. */
-               if (id->rid != NULL && *id->rid == '\0') {
-                       g_free (id->rid);
-                       id->rid = NULL;
-               }
-
-               g_queue_push_tail (&component_ids, id);
+               g_queue_push_tail (&component_ids, e_cal_component_id_new_take (uid, rid));
        }
 
        async_context = async_context_new (data_cal, invocation);
 
        e_cal_backend_remove_objects (
                backend,
-               component_ids.head, mod,
+               component_ids.head, mod, in_opflags,
                async_context->cancellable,
                data_cal_complete_remove_objects_cb,
                async_context);
 
        while (!g_queue_is_empty (&component_ids))
-               e_cal_component_free_id (g_queue_pop_head (&component_ids));
+               e_cal_component_id_free (g_queue_pop_head (&component_ids));
 
        g_object_unref (backend);
 
@@ -1179,6 +884,7 @@ static gboolean
 data_cal_handle_receive_objects_cb (EDBusCalendar *dbus_interface,
                                     GDBusMethodInvocation *invocation,
                                     const gchar *in_calobj,
+                                   guint32 in_opflags,
                                     EDataCal *data_cal)
 {
        ECalBackend *backend;
@@ -1192,6 +898,7 @@ data_cal_handle_receive_objects_cb (EDBusCalendar *dbus_interface,
        e_cal_backend_receive_objects (
                backend,
                in_calobj,
+               in_opflags,
                async_context->cancellable,
                data_cal_complete_receive_objects_cb,
                async_context);
@@ -1259,6 +966,7 @@ static gboolean
 data_cal_handle_send_objects_cb (EDBusCalendar *dbus_interface,
                                  GDBusMethodInvocation *invocation,
                                  const gchar *in_calobj,
+                                guint32 in_opflags,
                                  EDataCal *data_cal)
 {
        ECalBackend *backend;
@@ -1272,6 +980,7 @@ data_cal_handle_send_objects_cb (EDBusCalendar *dbus_interface,
        e_cal_backend_send_objects (
                backend,
                in_calobj,
+               in_opflags,
                async_context->cancellable,
                data_cal_complete_send_objects_cb,
                async_context);
@@ -1384,6 +1093,7 @@ data_cal_handle_discard_alarm_cb (EDBusCalendar *dbus_interface,
                                   const gchar *in_uid,
                                   const gchar *in_rid,
                                   const gchar *in_alarm_uid,
+                                 guint32 in_opflags,
                                   EDataCal *data_cal)
 {
        ECalBackend *backend;
@@ -1401,7 +1111,7 @@ data_cal_handle_discard_alarm_cb (EDBusCalendar *dbus_interface,
 
        e_cal_backend_discard_alarm (
                backend,
-               in_uid, in_rid, in_alarm_uid,
+               in_uid, in_rid, in_alarm_uid, in_opflags,
                async_context->cancellable,
                data_cal_complete_discard_alarm_cb,
                async_context);
@@ -1759,7 +1469,7 @@ e_data_cal_respond_get_object (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @objects: List of retrieved objects.
+ * @objects: (element-type utf8): List of retrieved objects.
  *
  * Notifies listeners of the completion of the get_object_list method call.
  *
@@ -1814,7 +1524,7 @@ e_data_cal_respond_get_object_list (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @freebusy: a #GSList of iCalendar strings with all gathered free/busy components.
+ * @freebusy: (element-type utf8): a #GSList of iCalendar strings with all gathered free/busy components.
  *
  * Notifies listeners of the completion of the get_free_busy method call.
  * To pass actual free/busy objects to the client asynchronously
@@ -1866,8 +1576,8 @@ e_data_cal_respond_get_free_busy (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @uids: UIDs of the objects created.
- * @new_components: The newly created #ECalComponent objects.
+ * @uids: (element-type utf8): UIDs of the objects created.
+ * @new_components: (element-type ECalComponent): The newly created #ECalComponent objects.
  *
  * Notifies listeners of the completion of the create_objects method call.
  *
@@ -1935,8 +1645,8 @@ e_data_cal_respond_create_objects (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @old_components: The old #ECalComponent(s).
- * @new_components: The new #ECalComponent(s).
+ * @old_components: (element-type ECalComponent): The old #ECalComponent(s).
+ * @new_components: (element-type ECalComponent): The new #ECalComponent(s).
  *
  * Notifies listeners of the completion of the modify_objects method call.
  *
@@ -2011,7 +1721,7 @@ e_data_cal_respond_modify_objects (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @ids: (element-type: utf8) IDs of the removed objects.
+ * @ids: (element-type ECalComponentId): IDs of the removed objects.
  * @old_components: (element-type ECalComponent): The old #ECalComponent(s).
  * @new_components: (element-type ECalComponent): The new #ECalComponent(s).
  *    They will not be NULL only when removing instances of recurring appointments.
@@ -2145,7 +1855,7 @@ e_data_cal_respond_receive_objects (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @users: List of users.
+ * @users: (element-type utf8): List of users.
  * @calobj: An iCalendar string representing the object sent.
  *
  * Notifies listeners of the completion of the send_objects method call.
@@ -2200,7 +1910,7 @@ e_data_cal_respond_send_objects (EDataCal *cal,
  * @cal: A calendar client interface.
  * @opid: associated operation id
  * @error: Operation error, if any, automatically freed if passed it.
- * @attachment_uris: List of retrieved attachment uri's.
+ * @attachment_uris: (element-type utf8): List of retrieved attachment uri's.
  *
  * Notifies listeners of the completion of the get_attachment_uris method call.
  *
@@ -2461,13 +2171,13 @@ e_data_cal_report_backend_property_changed (EDataCal *cal,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_REVISION))
                e_dbus_calendar_set_revision (dbus_interface, prop_value);
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS))
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS))
                e_dbus_calendar_set_cal_email_address (dbus_interface, prop_value);
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS))
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS))
                e_dbus_calendar_set_alarm_email_address (dbus_interface, prop_value);
 
-       if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT))
+       if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT))
                e_dbus_calendar_set_default_object (dbus_interface, prop_value);
 
        /* Disregard anything else. */
@@ -2651,19 +2361,19 @@ data_cal_constructed (GObject *object)
                cal, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
+       prop_name = E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
        prop_value = e_cal_backend_get_backend_property (backend, prop_name);
        e_data_cal_report_backend_property_changed (
                cal, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
+       prop_name = E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
        prop_value = e_cal_backend_get_backend_property (backend, prop_name);
        e_data_cal_report_backend_property_changed (
                cal, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
+       prop_name = E_CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
        prop_value = e_cal_backend_get_backend_property (backend, prop_name);
        e_data_cal_report_backend_property_changed (
                cal, prop_name, prop_value);
@@ -2821,7 +2531,7 @@ e_data_cal_init (EDataCal *data_cal)
 
 /**
  * e_data_cal_new:
- * @backend: an #ECalBackend
+ * @backend: (type ECalBackend): an #ECalBackend
  * @connection: a #GDBusConnection
  * @object_path: object path for the D-Bus interface
  * @error: return location for a #GError, or %NULL
@@ -2861,7 +2571,7 @@ e_data_cal_new (ECalBackend *backend,
  * The returned #ECalBackend is referenced for thread-safety and should
  * be unreferenced with g_object_unref() when finished with it.
  *
- * Returns: an #ECalBackend
+ * Returns: (type ECalBackend) (transfer full) (nullable): an #ECalBackend
  *
  * Since: 3.10
  **/
@@ -2880,7 +2590,7 @@ e_data_cal_ref_backend (EDataCal *cal)
  * Returns the #GDBusConnection on which the Calendar D-Bus interface
  * is exported.
  *
- * Returns: the #GDBusConnection
+ * Returns: (transfer none): the #GDBusConnection
  *
  * Since: 3.8
  **/
diff --git a/src/calendar/libedata-cal/e-data-cal.h b/src/calendar/libedata-cal/e-data-cal.h
index 4ec1b9573..a2ad31780 100644
--- a/src/calendar/libedata-cal/e-data-cal.h
+++ b/src/calendar/libedata-cal/e-data-cal.h
@@ -44,13 +44,6 @@
        (G_TYPE_INSTANCE_GET_CLASS \
        ((obj), E_TYPE_DATA_CAL, EDataCalClass))
 
-/**
- * E_DATA_CAL_ERROR:
- *
- * Since: 2.30
- **/
-#define E_DATA_CAL_ERROR e_data_cal_error_quark ()
-
 G_BEGIN_DECLS
 
 struct _ECalBackend;
@@ -68,84 +61,6 @@ struct _EDataCalClass {
        GObjectClass parent_class;
 };
 
-/**
- * EDataCalCallStatus:
- * @Success: call finished successfully
- * @Busy: the backend is busy
- * @RepositoryOffline: the backend is offline
- * @PermissionDenied: the call failed due to permission restrictions
- * @InvalidRange: the provided range for the call is invalid
- * @ObjectNotFound: the requested object could not be found
- * @InvalidObject: the provided object is invalid
- * @ObjectIdAlreadyExists: the provided object has an ID which already exists
- * @AuthenticationFailed: failed to authenticate with given credentials
- * @AuthenticationRequired: authentication credentials are required to connect to the calendar
- * @UnsupportedField: requested field is not supported
- * @UnsupportedMethod: requested method is not supported
- * @UnsupportedAuthenticationMethod: requested authentication method is not supported
- * @TLSNotAvailable: TLS for connection is not available for the calendar
- * @NoSuchCal: requested calendar does not exist
- * @UnknownUser: provided user is unknown
- * @OfflineUnavailable: requested data are not available in offline
- * @SearchSizeLimitExceeded: a successful search doesn't contain all responses due to size limit
- * @SearchTimeLimitExceeded: a successful search doesn't contain all responses due to time limit
- * @InvalidQuery: a requested search query is invalid
- * @QueryRefused: a requested search query had been refused, possibly by the server
- * @CouldNotCancel: an ongoing operation cannot be cancelled
- * @OtherError: a generic error happened
- * @InvalidServerVersion: server version is invalid
- * @InvalidArg: one of the arguments of the call was invalid
- * @NotSupported: the operation is not supported
- * @NotOpened: the calendar is not opened
- *
- * Response statuses of the calls.
- *
- * Since: 3.6
- **/
-typedef enum {
-       Success,
-       Busy,
-       RepositoryOffline,
-       PermissionDenied,
-       InvalidRange,
-       ObjectNotFound,
-       InvalidObject,
-       ObjectIdAlreadyExists,
-       AuthenticationFailed,
-       AuthenticationRequired,
-       UnsupportedField,
-       UnsupportedMethod,
-       UnsupportedAuthenticationMethod,
-       TLSNotAvailable,
-       NoSuchCal,
-       UnknownUser,
-       OfflineUnavailable,
-
-       /* These can be returned for successful searches, but
-               indicate the result set was truncated */
-       SearchSizeLimitExceeded,
-       SearchTimeLimitExceeded,
-
-       InvalidQuery,
-       QueryRefused,
-
-       CouldNotCancel,
-
-       OtherError,
-       InvalidServerVersion,
-       InvalidArg,
-       NotSupported,
-       NotOpened
-} EDataCalCallStatus;
-
-GQuark         e_data_cal_error_quark          (void);
-GError *       e_data_cal_create_error         (EDataCalCallStatus status,
-                                                const gchar *custom_msg);
-GError *       e_data_cal_create_error_fmt     (EDataCalCallStatus status,
-                                                const gchar *custom_msg_fmt,
-                                                ...) G_GNUC_PRINTF (2, 3);
-const gchar *  e_data_cal_status_to_string     (EDataCalCallStatus status);
-
 GType          e_data_cal_get_type             (void) G_GNUC_CONST;
 EDataCal *     e_data_cal_new                  (struct _ECalBackend *backend,
                                                 GDBusConnection *connection,
diff --git a/src/calendar/libedata-cal/e-subprocess-cal-factory.c 
b/src/calendar/libedata-cal/e-subprocess-cal-factory.c
index 7547a30fb..22fb66059 100644
--- a/src/calendar/libedata-cal/e-subprocess-cal-factory.c
+++ b/src/calendar/libedata-cal/e-subprocess-cal-factory.c
@@ -38,26 +38,6 @@
 
 #include <e-dbus-subprocess-backend.h>
 
-/*
- * FIXME: Remove this when there's a build time dependency on libical
- * 3.0.4 (where this is fixed). See
- * https://github.com/libical/libical/pull/335 and the implementation in
- * https://github.com/libical/libical/blob/master/src/libical/icalversion.h.cmake.
- */
-#if defined(ICAL_CHECK_VERSION) && defined(ICAL_MAJOR_VERSION) && defined(ICAL_MINOR_VERSION) && 
defined(ICAL_MICRO_VERSION)
-#undef ICAL_CHECK_VERSION
-#define ICAL_CHECK_VERSION(major,minor,micro)                          \
-    (ICAL_MAJOR_VERSION > (major) ||                                   \
-    (ICAL_MAJOR_VERSION == (major) && ICAL_MINOR_VERSION > (minor)) || \
-    (ICAL_MAJOR_VERSION == (major) && ICAL_MINOR_VERSION == (minor) && \
-    ICAL_MICRO_VERSION >= (micro)))
-#else
-#if defined(ICAL_CHECK_VERSION)
-#undef ICAL_CHECK_VERSION
-#endif
-#define ICAL_CHECK_VERSION(major,minor,micro) (0)
-#endif
-
 /* Forward Declarations */
 static void    e_subprocess_cal_factory_initable_init
                                                (GInitableIface *iface);
@@ -157,48 +137,7 @@ ESubprocessCalFactory *
 e_subprocess_cal_factory_new (GCancellable *cancellable,
                               GError **error)
 {
-#if !ICAL_CHECK_VERSION(3, 0, 2)
-       icalarray *builtin_timezones;
-       gint ii;
-#endif
-
-#ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING
-       ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN);
-#endif
-
-#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT
-       icaltzutil_set_exact_vtimezones_support (0);
-#endif
-
-#if !ICAL_CHECK_VERSION(3, 0, 2)
-       /* XXX Pre-load all built-in timezones in libical.
-        *
-        *     Built-in time zones in libical 0.43 are loaded on demand,
-        *     but not in a thread-safe manner, resulting in a race when
-        *     multiple threads call icaltimezone_load_builtin_timezone()
-        *     on the same time zone.  Until built-in time zone loading
-        *     in libical is made thread-safe, work around the issue by
-        *     loading all built-in time zones now, so libical's internal
-        *     time zone array will be fully populated before any threads
-        *     are spawned.
-        *
-        *     This is apparently fixed with additional locking in
-        *     libical 3.0.1 and 3.0.2:
-        *     https://github.com/libical/libical/releases/tag/v3.0.1
-        *     https://github.com/libical/libical/releases/tag/v3.0.2
-        */
-       builtin_timezones = icaltimezone_get_builtin_timezones ();
-       for (ii = 0; ii < builtin_timezones->num_elements; ii++) {
-               icaltimezone *zone;
-
-               zone = icalarray_element_at (builtin_timezones, ii);
-
-               /* We don't care about the component right now,
-                * we just need some function that will trigger
-                * icaltimezone_load_builtin_timezone(). */
-               icaltimezone_get_component (zone);
-       }
-#endif
+       i_cal_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN);
 
        return g_initable_new (
                E_TYPE_SUBPROCESS_CAL_FACTORY,
diff --git a/src/calendar/libedata-cal/libedata-cal.h b/src/calendar/libedata-cal/libedata-cal.h
index a754d7019..4fd49a2f2 100644
--- a/src/calendar/libedata-cal/libedata-cal.h
+++ b/src/calendar/libedata-cal/libedata-cal.h
@@ -23,12 +23,12 @@
 #include <libecal/libecal.h>
 #include <libebackend/libebackend.h>
 
-#include <libedata-cal/e-cal-backend-cache.h>
+#define LIBICAL_GLIB_UNSTABLE_API 1
+
 #include <libedata-cal/e-cal-backend-factory.h>
 #include <libedata-cal/e-cal-backend.h>
 #include <libedata-cal/e-cal-backend-intervaltree.h>
 #include <libedata-cal/e-cal-backend-sexp.h>
-#include <libedata-cal/e-cal-backend-store.h>
 #include <libedata-cal/e-cal-backend-sync.h>
 #include <libedata-cal/e-cal-backend-util.h>
 #include <libedata-cal/e-cal-cache.h>
@@ -38,7 +38,8 @@
 #include <libedata-cal/e-data-cal-view.h>
 #include <libedata-cal/e-subprocess-cal-factory.h>
 
+#undef LIBICAL_GLIB_UNSTABLE_API
+
 #undef __LIBEDATA_CAL_H_INSIDE__
 
 #endif /* LIBEDATA_CAL_H */
-
diff --git a/src/calendar/libedata-cal/libedata-cal.pc.in b/src/calendar/libedata-cal/libedata-cal.pc.in
index da2670892..3b6cda36e 100644
--- a/src/calendar/libedata-cal/libedata-cal.pc.in
+++ b/src/calendar/libedata-cal/libedata-cal.pc.in
@@ -13,6 +13,6 @@ backenddir=@ecal_backenddir@
 Name: libedata-cal
 Description: Backend library for evolution calendars
 Version: @PROJECT_VERSION@
-Requires: libical libebackend-@API_VERSION@ libecal-@API_VERSION@
-Libs: -L${libdir} -ledata-cal-@API_VERSION@
+Requires: libical-glib libebackend-@API_VERSION@ libecal-@CAL_API_VERSION@
+Libs: -L${libdir} -ledata-cal-@CAL_API_VERSION@
 Cflags: -I${privincludedir}
diff --git a/src/camel/providers/imapx/camel-imapx-server.c b/src/camel/providers/imapx/camel-imapx-server.c
index d5178ea88..9dda8a37d 100644
--- a/src/camel/providers/imapx/camel-imapx-server.c
+++ b/src/camel/providers/imapx/camel-imapx-server.c
@@ -27,7 +27,7 @@
 #include <glib/gi18n-lib.h>
 #include <gio/gnetworking.h>
 
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 
 #ifndef G_OS_WIN32
 #include <glib-unix.h>
diff --git a/src/libebackend/e-backend-enums.h b/src/libebackend/e-backend-enums.h
index 5c3656960..6fefc40a1 100644
--- a/src/libebackend/e-backend-enums.h
+++ b/src/libebackend/e-backend-enums.h
@@ -103,26 +103,4 @@ typedef enum {
        E_OFFLINE_STATE_LOCALLY_DELETED
 } EOfflineState;
 
-/**
- * EConflictResolution:
- * @E_CONFLICT_RESOLUTION_FAIL: Fail when a write-conflict occurs.
- * @E_CONFLICT_RESOLUTION_USE_NEWER: Use newer version of the object,
- *    which can be either the server version or the local version of it.
- * @E_CONFLICT_RESOLUTION_KEEP_SERVER: Keep server object on conflict.
- * @E_CONFLICT_RESOLUTION_KEEP_LOCAL: Write local version of the object on conflict.
- * @E_CONFLICT_RESOLUTION_WRITE_COPY: Create a new copy of the object on conflict.
- *
- * Defines what to do when a conflict between the locally stored and
- * remotely stored object versions happen during object modify or remove.
- *
- * Since: 3.26
- **/
-typedef enum {
-       E_CONFLICT_RESOLUTION_FAIL = 0,
-       E_CONFLICT_RESOLUTION_USE_NEWER,
-       E_CONFLICT_RESOLUTION_KEEP_SERVER,
-       E_CONFLICT_RESOLUTION_KEEP_LOCAL,
-       E_CONFLICT_RESOLUTION_WRITE_COPY
-} EConflictResolution;
-
 #endif /* E_BACKEND_ENUMS_H */
diff --git a/src/libebackend/e-server-side-source.c b/src/libebackend/e-server-side-source.c
index 961660e3f..2c92d9fbf 100644
--- a/src/libebackend/e-server-side-source.c
+++ b/src/libebackend/e-server-side-source.c
@@ -2019,6 +2019,7 @@ e_server_side_source_load (EServerSideSource *source,
                return FALSE;
 
        } else {
+               g_free (source->priv->file_contents);
                source->priv->file_contents = g_strdup (data);
        }
 
diff --git a/src/libedataserver/e-client.c b/src/libedataserver/e-client.c
index 23ae880b1..b85f99845 100644
--- a/src/libedataserver/e-client.c
+++ b/src/libedataserver/e-client.c
@@ -191,29 +191,64 @@ e_client_error_to_string (EClientError code)
 /**
  * e_client_error_create:
  * @code: an #EClientError code to create
- * @custom_msg: custom message to use for the error; can be %NULL
+ * @custom_msg: (nullable): custom message to use for the error; can be %NULL
  *
- * Returns: a new #GError containing an E_CLIENT_ERROR of the given
- * @code. If the @custom_msg is NULL, then the error message is
- * the one returned from e_client_error_to_string() for the @code,
- * otherwise the given message is used.
- *
- * Returned pointer should be freed with g_error_free().
+ * Returns: (transfer full): a new #GError containing an #E_CLIENT_ERROR of the given
+ *    @code. If the @custom_msg is NULL, then the error message is the one returned
+ *    from e_client_error_to_string() for the @code, otherwise the given message is used.
+ *    Returned pointer should be freed with g_error_free().
  *
  * Since: 3.2
- *
- * Deprecated: 3.8: Just use the #GError API directly.
  **/
 GError *
 e_client_error_create (EClientError code,
                        const gchar *custom_msg)
 {
-       if (custom_msg == NULL)
+       if (!custom_msg)
                custom_msg = e_client_error_to_string (code);
 
        return g_error_new_literal (E_CLIENT_ERROR, code, custom_msg);
 }
 
+/**
+ * e_client_error_create_fmt:
+ * @code: an #EClientError
+ * @format: (nullable): message format, or %NULL to use the default message for the @code
+ * @...: arguments for the format
+ *
+ * Similar as e_client_error_create(), only here, instead of custom_msg,
+ * is used a printf() format to create a custom message for the error.
+ *
+ * Returns: (transfer full): a newly allocated #GError, which should be
+ *   freed with g_error_free(), when no longer needed.
+ *   The #GError has set the custom message, or the default message for
+ *   @code, when @format is %NULL.
+ *
+ * Since: 3.36
+ **/
+GError *
+e_client_error_create_fmt (EClientError code,
+                          const gchar *format,
+                          ...)
+{
+       GError *error;
+       gchar *custom_msg;
+       va_list ap;
+
+       if (!format)
+               return e_client_error_create (code, NULL);
+
+       va_start (ap, format);
+       custom_msg = g_strdup_vprintf (format, ap);
+       va_end (ap);
+
+       error = e_client_error_create (code, custom_msg);
+
+       g_free (custom_msg);
+
+       return error;
+}
+
 static void
 client_set_source (EClient *client,
                    ESource *source)
diff --git a/src/libedataserver/e-client.h b/src/libedataserver/e-client.h
index 33fe2ebe6..8c8cba07a 100644
--- a/src/libedataserver/e-client.h
+++ b/src/libedataserver/e-client.h
@@ -114,8 +114,6 @@
 
 G_BEGIN_DECLS
 
-GQuark e_client_error_quark (void) G_GNUC_CONST;
-
 /**
  * EClientError:
  * @E_CLIENT_ERROR_INVALID_ARG: Invalid argument was used
@@ -139,7 +137,7 @@ GQuark e_client_error_quark (void) G_GNUC_CONST;
  * @E_CLIENT_ERROR_DBUS_ERROR: A D-Bus error occurred
  * @E_CLIENT_ERROR_OTHER_ERROR: Other error
  * @E_CLIENT_ERROR_NOT_OPENED: The client is not opened
- * @E_CLIENT_ERROR_OUT_OF_SYNC: The clien tis out of sync
+ * @E_CLIENT_ERROR_OUT_OF_SYNC: The client is out of sync with the server
  *
  * Error codes for #EClient operations.
  *
@@ -170,7 +168,13 @@ typedef enum {
        E_CLIENT_ERROR_OUT_OF_SYNC
 } EClientError;
 
+GQuark         e_client_error_quark            (void) G_GNUC_CONST;
 const gchar *  e_client_error_to_string        (EClientError code);
+GError *       e_client_error_create           (EClientError code,
+                                                const gchar *custom_msg);
+GError *       e_client_error_create_fmt       (EClientError code,
+                                                const gchar *format,
+                                                ...) G_GNUC_PRINTF (2, 3);
 
 /**
  * EClient:
@@ -388,8 +392,6 @@ GSList *    e_client_util_parse_comma_strings
  **/
 #define CLIENT_BACKEND_PROPERTY_OPENING                        "opening"
 
-GError *       e_client_error_create           (EClientError code,
-                                                const gchar *custom_msg);
 gboolean       e_client_is_opened              (EClient *client);
 void           e_client_cancel_all             (EClient *client);
 void           e_client_unwrap_dbus_error      (EClient *client,
diff --git a/src/libedataserver/e-source-enums.h b/src/libedataserver/e-source-enums.h
index ec56c2b9e..19adc28b7 100644
--- a/src/libedataserver/e-source-enums.h
+++ b/src/libedataserver/e-source-enums.h
@@ -289,4 +289,26 @@ typedef enum {
        E_THREE_STATE_INCONSISTENT
 } EThreeState;
 
+/**
+ * EConflictResolution:
+ * @E_CONFLICT_RESOLUTION_FAIL: Fail when a write-conflict occurs.
+ * @E_CONFLICT_RESOLUTION_USE_NEWER: Use newer version of the object,
+ *    which can be either the server version or the local version of it.
+ * @E_CONFLICT_RESOLUTION_KEEP_SERVER: Keep server object on conflict.
+ * @E_CONFLICT_RESOLUTION_KEEP_LOCAL: Write local version of the object on conflict.
+ * @E_CONFLICT_RESOLUTION_WRITE_COPY: Create a new copy of the object on conflict.
+ *
+ * Defines what to do when a conflict between the locally stored and
+ * remotely stored object versions happen during object modify or remove.
+ *
+ * Since: 3.26
+ **/
+typedef enum {
+       E_CONFLICT_RESOLUTION_FAIL = 0,
+       E_CONFLICT_RESOLUTION_USE_NEWER,
+       E_CONFLICT_RESOLUTION_KEEP_SERVER,
+       E_CONFLICT_RESOLUTION_KEEP_LOCAL,
+       E_CONFLICT_RESOLUTION_WRITE_COPY
+} EConflictResolution;
+
 #endif /* E_SOURCE_ENUMS_H */
diff --git a/src/libedataserverui/CMakeLists.txt b/src/libedataserverui/CMakeLists.txt
index eebb7ec11..d7a026e38 100644
--- a/src/libedataserverui/CMakeLists.txt
+++ b/src/libedataserverui/CMakeLists.txt
@@ -128,6 +128,7 @@ set(gir_libs
 set(gir_deps
        ${CMAKE_BINARY_DIR}/src/camel/Camel-${API_VERSION}.gir
        ${CMAKE_BINARY_DIR}/src/libedataserver/EDataServer-${API_VERSION}.gir
+       ${CMAKE_BINARY_DIR}/src/calendar/libecal/ECal-${CAL_API_VERSION}.gir
 )
 
 gir_add_introspection_simple(
diff --git a/src/libedataserverui/e-reminders-widget.c b/src/libedataserverui/e-reminders-widget.c
index f89cd4a5c..1bba511cc 100644
--- a/src/libedataserverui/e-reminders-widget.c
+++ b/src/libedataserverui/e-reminders-widget.c
@@ -262,7 +262,7 @@ reminders_get_reminder_markups (ERemindersWidget *reminders,
                gboolean in_future;
                gchar *time_str;
 
-               diff = (g_get_real_time () / G_USEC_PER_SEC) - ((gint64) rd->instance.occur_start);
+               diff = (g_get_real_time () / G_USEC_PER_SEC) - ((gint64) 
e_cal_component_alarm_instance_get_occur_start (e_reminder_data_get_instance (rd)));
                in_future = diff < 0;
                if (in_future)
                        diff = (-1) * diff;
@@ -479,20 +479,27 @@ reminders_sort_by_occur (gconstpointer ptr1,
                         gconstpointer ptr2)
 {
        const EReminderData *rd1 = ptr1, *rd2 = ptr2;
+       const ECalComponentAlarmInstance *inst1, *inst2;
        gint cmp;
 
        if (!rd1 || !rd2)
                return rd1 == rd2 ? 0 : rd1 ? 1 : -1;
 
-       if (rd1->instance.occur_start != rd2->instance.occur_start)
-               return rd1->instance.occur_start < rd2->instance.occur_start ? -1 : 1;
+       inst1 = e_reminder_data_get_instance (rd1);
+       inst2 = e_reminder_data_get_instance (rd2);
 
-       if (rd1->instance.trigger != rd2->instance.trigger)
-               return rd1->instance.trigger < rd2->instance.trigger ? -1 : 1;
+       if (!inst1 || !inst2)
+               return inst1 == inst2 ? 0 : inst1 ? 1 : -1;
 
-       cmp = g_strcmp0 (rd1->source_uid, rd2->source_uid);
+       if (e_cal_component_alarm_instance_get_occur_start (inst1) != 
e_cal_component_alarm_instance_get_occur_start (inst2))
+               return e_cal_component_alarm_instance_get_occur_start (inst1) < 
e_cal_component_alarm_instance_get_occur_start (inst2) ? -1 : 1;
+
+       if (e_cal_component_alarm_instance_get_time (inst1) != e_cal_component_alarm_instance_get_time 
(inst2))
+               return e_cal_component_alarm_instance_get_time (inst1) < 
e_cal_component_alarm_instance_get_time (inst2) ? -1 : 1;
+
+       cmp = g_strcmp0 (e_reminder_data_get_source_uid (rd1), e_reminder_data_get_source_uid (rd2));
        if (!cmp)
-               cmp = g_strcmp0 (rd1->instance.auid, rd2->instance.auid);
+               cmp = g_strcmp0 (e_cal_component_alarm_instance_get_uid (inst1), 
e_cal_component_alarm_instance_get_uid (inst2));
 
        return cmp;
 }
@@ -612,7 +619,7 @@ reminders_widget_refresh_content_cb (gpointer user_data)
                        const EReminderData *rd = link->data;
                        gchar *overdue = NULL, *description = NULL;
 
-                       if (!rd || !rd->component)
+                       if (!rd || !e_reminder_data_get_component (rd))
                                continue;
 
                        reminders_get_reminder_markups (reminders, rd, &overdue, &description);
@@ -870,9 +877,9 @@ reminders_widget_row_activated_cb (GtkTreeView *tree_view,
                                const gchar *scheme = NULL;
                                const gchar *comp_uid = NULL;
 
-                               e_cal_component_get_uid (rd->component, &comp_uid);
+                               comp_uid = e_cal_component_get_uid (e_reminder_data_get_component (rd));
 
-                               switch (e_cal_component_get_vtype (rd->component)) {
+                               switch (e_cal_component_get_vtype (e_reminder_data_get_component (rd))) {
                                        case E_CAL_COMPONENT_EVENT:
                                                scheme = "calendar:";
                                                break;
@@ -886,7 +893,7 @@ reminders_widget_row_activated_cb (GtkTreeView *tree_view,
                                                break;
                                }
 
-                               if (scheme && comp_uid && rd->source_uid) {
+                               if (scheme && comp_uid && e_reminder_data_get_source_uid (rd)) {
                                        GString *uri;
                                        gchar *tmp;
                                        GError *error = NULL;
@@ -895,7 +902,7 @@ reminders_widget_row_activated_cb (GtkTreeView *tree_view,
                                        g_string_append (uri, scheme);
                                        g_string_append (uri, "///?");
 
-                                       tmp = g_uri_escape_string (rd->source_uid, NULL, TRUE);
+                                       tmp = g_uri_escape_string (e_reminder_data_get_source_uid (rd), NULL, 
TRUE);
                                        g_string_append (uri, "source-uid=");
                                        g_string_append (uri, tmp);
                                        g_free (tmp);
diff --git a/src/libedataserverui/libedataserverui.pc.in b/src/libedataserverui/libedataserverui.pc.in
index 1b9747f54..f631fe1ec 100644
--- a/src/libedataserverui/libedataserverui.pc.in
+++ b/src/libedataserverui/libedataserverui.pc.in
@@ -14,7 +14,7 @@ uimoduledir=@uimoduledir@
 Name: libedataserverui
 Description: UI utility library for Evolution Data Server
 Version: @PROJECT_VERSION@
-Requires: gio-2.0 gmodule-2.0 libsecret-1 libxml-2.0 libsoup-2.4 gtk+-3.0 libedataserver-@API_VERSION@ 
libecal-@API_VERSION@
+Requires: gio-2.0 gmodule-2.0 libsecret-1 libxml-2.0 libsoup-2.4 gtk+-3.0 libedataserver-@API_VERSION@ 
libecal-@CAL_API_VERSION@
 Requires.private: camel-@API_VERSION@
 Libs: -L${libdir} -ledataserver-@API_VERSION@ -ledataserverui-@API_VERSION@
 Cflags: -I${privincludedir}
diff --git a/src/private/org.gnome.evolution.dataserver.Calendar.xml 
b/src/private/org.gnome.evolution.dataserver.Calendar.xml
index 2d8949e18..4caa6f9dc 100644
--- a/src/private/org.gnome.evolution.dataserver.Calendar.xml
+++ b/src/private/org.gnome.evolution.dataserver.Calendar.xml
@@ -46,25 +46,30 @@
 
   <method name="CreateObjects">
     <arg name="ics_objects" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
     <arg name="uids" direction="out" type="as"/>
   </method>
 
   <method name="ModifyObjects">
     <arg name="ics_objects" direction="in" type="as"/>
     <arg name="mod_type" direction="in" type="s"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="RemoveObjects">
     <arg name="uid_rid_array" direction="in" type="a(ss)"/>
     <arg name="mod_type" direction="in" type="s"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="ReceiveObjects">
     <arg name="ics_object" direction="in" type="s"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="SendObjects">
     <arg name="ics_object" direction="in" type="s"/>
+    <arg name="opflags" direction="in" type="u"/>
     <arg name="users" direction="out" type="as"/>
     <arg name="out_ics_object" direction="out" type="s"/>
   </method>
@@ -97,6 +102,7 @@
     <arg name="uid" direction="in" type="s"/>
     <arg name="rid" direction="in" type="s"/>
     <arg name="alarm_uid" direction="in" type="s"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="GetTimezone">
diff --git a/src/services/evolution-alarm-notify/e-alarm-notify.c 
b/src/services/evolution-alarm-notify/e-alarm-notify.c
index 4f89fef45..57ea7b66c 100644
--- a/src/services/evolution-alarm-notify/e-alarm-notify.c
+++ b/src/services/evolution-alarm-notify/e-alarm-notify.c
@@ -99,19 +99,22 @@ e_alarm_notify_audio (EAlarmNotify *an,
                      const EReminderData *rd,
                      ECalComponentAlarm *alarm)
 {
-       icalattach *attach = NULL;
+       ICalAttach *attach = NULL;
+       GSList *attachments;
        gboolean did_play = FALSE;
 
        g_return_val_if_fail (an != NULL, FALSE);
        g_return_val_if_fail (rd != NULL, FALSE);
        g_return_val_if_fail (alarm != NULL, FALSE);
 
-       e_cal_component_alarm_get_attach (alarm, &attach);
+       attachments = e_cal_component_alarm_get_attachments (alarm);
+       if (attachments && !attachments->next)
+               attach = attachments->data;
 
-       if (attach && icalattach_get_is_url (attach)) {
+       if (attach && i_cal_attach_get_is_url (attach)) {
                const gchar *url;
 
-               url = icalattach_get_url (attach);
+               url = i_cal_attach_get_url (attach);
                if (url && *url) {
                        gchar *filename;
                        GError *error = NULL;
@@ -136,8 +139,7 @@ e_alarm_notify_audio (EAlarmNotify *an,
        if (!did_play)
                gdk_beep ();
 
-       if (attach)
-               icalattach_unref (attach);
+       g_slist_free_full (attachments, g_object_unref);
 
        return FALSE;
 }
@@ -174,32 +176,35 @@ e_alarm_notify_build_notif_id (const EReminderData *rd)
 {
        GString *string;
        ECalComponentId *id;
+       ECalComponentAlarmInstance *instance;
 
        g_return_val_if_fail (rd != NULL, NULL);
 
        string = g_string_sized_new (32);
 
-       if (rd->source_uid) {
-               g_string_append (string, rd->source_uid);
+       if (e_reminder_data_get_source_uid (rd)) {
+               g_string_append (string, e_reminder_data_get_source_uid (rd));
                g_string_append (string, "\n");
        }
 
-       id = e_cal_component_get_id (rd->component);
+       id = e_cal_component_get_id (e_reminder_data_get_component (rd));
        if (id) {
-               if (id->uid) {
-                       g_string_append (string, id->uid);
+               if (e_cal_component_id_get_uid (id)) {
+                       g_string_append (string, e_cal_component_id_get_uid (id));
                        g_string_append (string, "\n");
                }
 
-               if (id->rid) {
-                       g_string_append (string, id->rid);
+               if (e_cal_component_id_get_rid (id)) {
+                       g_string_append (string, e_cal_component_id_get_rid (id));
                        g_string_append (string, "\n");
                }
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
        }
 
-       g_string_append_printf (string, "%" G_GINT64_FORMAT, (gint64) rd->instance.trigger);
+       instance = e_reminder_data_get_instance (rd);
+
+       g_string_append_printf (string, "%" G_GINT64_FORMAT, (gint64) (instance ? 
e_cal_component_alarm_instance_get_time (instance) : -1));
 
        return g_string_free (string, FALSE);
 }
@@ -282,8 +287,8 @@ e_alarm_notify_email (EAlarmNotify *an,
        g_return_val_if_fail (rd != NULL, FALSE);
        g_return_val_if_fail (alarm != NULL, FALSE);
 
-       client = e_reminder_watcher_ref_opened_client (an->priv->watcher, rd->source_uid);
-       if (client && !e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS)) {
+       client = e_reminder_watcher_ref_opened_client (an->priv->watcher, e_reminder_data_get_source_uid 
(rd));
+       if (client && !e_client_check_capability (E_CLIENT (client), 
E_CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS)) {
                g_object_unref (client);
                return FALSE;
        }
@@ -405,8 +410,9 @@ e_alarm_notify_procedure (EAlarmNotify *an,
                          const EReminderData *rd,
                          ECalComponentAlarm *alarm)
 {
-       ECalComponentText description;
-       icalattach *attach;
+       ECalComponentText *description;
+       ICalAttach *attach = NULL;
+       GSList *attachments;
        const gchar *url;
        gchar *cmd;
        gboolean result = FALSE;
@@ -415,24 +421,27 @@ e_alarm_notify_procedure (EAlarmNotify *an,
        g_return_val_if_fail (rd != NULL, FALSE);
        g_return_val_if_fail (alarm != NULL, FALSE);
 
-       e_cal_component_alarm_get_attach (alarm, &attach);
-       e_cal_component_alarm_get_description (alarm, &description);
+       attachments = e_cal_component_alarm_get_attachments (alarm);
+
+       if (attachments && !attachments->next)
+               attach = attachments->data;
+
+       description = e_cal_component_alarm_get_description (alarm);
 
        /* If the alarm has no attachment, simply display a notification dialog. */
        if (!attach)
                goto fallback;
 
-       if (!icalattach_get_is_url (attach)) {
-               icalattach_unref (attach);
+       if (!i_cal_attach_get_is_url (attach)) {
                goto fallback;
        }
 
-       url = icalattach_get_url (attach);
+       url = i_cal_attach_get_url (attach);
        g_return_val_if_fail (url != NULL, FALSE);
 
        /* Ask for confirmation before executing the stuff */
-       if (description.value)
-               cmd = g_strconcat (url, " ", description.value, NULL);
+       if (description && e_cal_component_text_get_value (description))
+               cmd = g_strconcat (url, " ", e_cal_component_text_get_value (description), NULL);
        else
                cmd = (gchar *) url;
 
@@ -442,15 +451,17 @@ e_alarm_notify_procedure (EAlarmNotify *an,
        if (cmd != (gchar *) url)
                g_free (cmd);
 
-       icalattach_unref (attach);
-
        /* Fall back to display notification if we got an error */
        if (!result)
                goto fallback;
 
+       g_slist_free_full (attachments, g_object_unref);
+
        return FALSE;
 
  fallback:
+       g_slist_free_full (attachments, g_object_unref);
+
        return e_alarm_notify_display (an, rd, alarm);
 }
 
@@ -461,43 +472,44 @@ e_alarm_notify_process (EAlarmNotify *an,
                        gboolean snoozed)
 {
        ECalComponentAlarm *alarm;
+       ECalComponentAlarmInstance *instance;
        ECalComponentAlarmAction action;
        gboolean keep_in_reminders = FALSE;
 
        g_return_val_if_fail (an != NULL, FALSE);
        g_return_val_if_fail (rd != NULL, FALSE);
 
-       if (e_cal_component_get_vtype (rd->component) == E_CAL_COMPONENT_TODO) {
-               icalproperty_status status = ICAL_STATUS_NONE;
+       if (e_cal_component_get_vtype (e_reminder_data_get_component (rd)) == E_CAL_COMPONENT_TODO) {
+               ICalPropertyStatus status;
 
-               e_cal_component_get_status (rd->component, &status);
+               status = e_cal_component_get_status (e_reminder_data_get_component (rd));
 
-               if (status == ICAL_STATUS_COMPLETED &&
+               if (status == I_CAL_STATUS_COMPLETED &&
                    !g_settings_get_boolean (an->priv->settings, "notify-completed-tasks")) {
                        return FALSE;
                }
        }
 
-       alarm = e_cal_component_get_alarm (rd->component, rd->instance.auid);
+       instance = e_reminder_data_get_instance (rd);
+
+       alarm = instance ? e_cal_component_get_alarm (e_reminder_data_get_component (rd), 
e_cal_component_alarm_instance_get_uid (instance)) : NULL;
        if (!alarm)
                return FALSE;
 
        if (!snoozed && !g_settings_get_boolean (an->priv->settings, "notify-past-events")) {
-               ECalComponentAlarmTrigger trigger;
-               ECalComponentAlarmRepeat repeat;
+               ECalComponentAlarmTrigger *trigger;
                time_t offset = 0, event_relative, orig_trigger_day, today;
 
-               e_cal_component_alarm_get_trigger (alarm, &trigger);
-               e_cal_component_alarm_get_repeat (alarm, &repeat);
+               trigger = e_cal_component_alarm_get_trigger (alarm);
 
-               switch (trigger.type) {
+               switch (trigger ? e_cal_component_alarm_trigger_get_kind (trigger) : 
E_CAL_COMPONENT_ALARM_TRIGGER_NONE) {
                case E_CAL_COMPONENT_ALARM_TRIGGER_NONE:
                case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
                        break;
 
                case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
                case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
-                       offset = icaldurationtype_as_int (trigger.u.rel_duration);
+                       offset = i_cal_duration_as_int (e_cal_component_alarm_trigger_get_duration (trigger));
                        break;
 
                default:
@@ -505,12 +517,12 @@ e_alarm_notify_process (EAlarmNotify *an,
                }
 
                today = time (NULL);
-               event_relative = rd->instance.occur_start - offset;
+               event_relative = e_cal_component_alarm_instance_get_occur_start (instance) - offset;
 
                #define CLAMP_TO_DAY(x) ((x) - ((x) % (60 * 60 * 24)))
 
                event_relative = CLAMP_TO_DAY (event_relative);
-               orig_trigger_day = CLAMP_TO_DAY (rd->instance.trigger);
+               orig_trigger_day = CLAMP_TO_DAY (e_cal_component_alarm_instance_get_time (instance));
                today = CLAMP_TO_DAY (today);
 
                #undef CLAMP_TO_DAY
@@ -521,7 +533,7 @@ e_alarm_notify_process (EAlarmNotify *an,
                }
        }
 
-       e_cal_component_alarm_get_action (alarm, &action);
+       action = e_cal_component_alarm_get_action (alarm);
 
        switch (action) {
        case E_CAL_COMPONENT_ALARM_AUDIO:
diff --git a/src/services/evolution-calendar-factory/evolution-calendar-factory.c 
b/src/services/evolution-calendar-factory/evolution-calendar-factory.c
index 4217305bd..08a07a64b 100644
--- a/src/services/evolution-calendar-factory/evolution-calendar-factory.c
+++ b/src/services/evolution-calendar-factory/evolution-calendar-factory.c
@@ -25,7 +25,7 @@
 #include <gtk/gtk.h>
 #endif
 
-#include <libical/ical.h>
+#include <libical-glib/libical-glib.h>
 
 #include <libedataserver/libedataserver.h>
 #include <libedata-cal/libedata-cal.h>
@@ -84,13 +84,7 @@ main (gint argc,
                exit (EXIT_FAILURE);
        }
 
-#ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING
        ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN);
-#endif
-
-#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT
-       icaltzutil_set_exact_vtimezones_support (0);
-#endif
 
        e_xml_initialize_in_main ();
 
diff --git a/src/vala/CMakeLists.txt b/src/vala/CMakeLists.txt
index 1815ad78b..1266d1ed2 100644
--- a/src/vala/CMakeLists.txt
+++ b/src/vala/CMakeLists.txt
@@ -1,3 +1,7 @@
+# disabled until some issues are fixed;
+# when fixed, then remove the conditions below and build the vala bindings unconditionally
+set(ENABLE_DATACAL 0)
+
 set(valafiles
        ${CMAKE_CURRENT_SOURCE_DIR}/camel-${API_VERSION}.deps
        ${CMAKE_CURRENT_BINARY_DIR}/camel-${API_VERSION}.vapi
@@ -7,8 +11,17 @@ set(valafiles
        ${CMAKE_CURRENT_BINARY_DIR}/libebook-${API_VERSION}.vapi
        ${CMAKE_CURRENT_SOURCE_DIR}/libebook-contacts-${API_VERSION}.deps
        ${CMAKE_CURRENT_BINARY_DIR}/libebook-contacts-${API_VERSION}.vapi
+       ${CMAKE_CURRENT_SOURCE_DIR}/libecal-${CAL_API_VERSION}.deps
+       ${CMAKE_CURRENT_BINARY_DIR}/libecal-${CAL_API_VERSION}.vapi
 )
 
+if(ENABLE_DATACAL)
+       list(APPEND valafiles
+               ${CMAKE_CURRENT_SOURCE_DIR}/libedata-cal-${CAL_API_VERSION}.deps
+               ${CMAKE_CURRENT_BINARY_DIR}/libedata-cal-${CAL_API_VERSION}.vapi
+       )
+endif(ENABLE_DATACAL)
+
 if(HAVE_GTK)
        list(APPEND valafiles
                ${CMAKE_CURRENT_SOURCE_DIR}/libedataserverui-${API_VERSION}.deps
@@ -32,6 +45,7 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/camel-${API_VERSION}.vapi
                --vapidir=${CMAKE_CURRENT_SOURCE_DIR}
                --vapidir=${CMAKE_CURRENT_BINARY_DIR}
                --girdir=${CMAKE_BINARY_DIR}/src/camel
+               --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
                --pkg gio-2.0
                --pkg libxml-2.0
                --pkg posix
@@ -58,6 +72,7 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libedataserver-${API_VERSI
                --vapidir=${CMAKE_CURRENT_BINARY_DIR}
                --girdir=${CMAKE_BINARY_DIR}/src/camel
                --girdir=${CMAKE_BINARY_DIR}/src/libedataserver
+               --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
                --pkg gio-2.0
                --pkg libxml-2.0
                --pkg libsoup-2.4
@@ -87,7 +102,10 @@ if(HAVE_GTK)
                        --vapidir=${CMAKE_CURRENT_BINARY_DIR}
                        --girdir=${CMAKE_BINARY_DIR}/src/camel
                        --girdir=${CMAKE_BINARY_DIR}/src/libedataserver
+                       --girdir=${CMAKE_BINARY_DIR}/src/calendar/libecal
+                       --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
                        --pkg libedataserver-${API_VERSION}
+                       --pkg libecal-${CAL_API_VERSION}
                        --pkg gio-2.0
                        --pkg gtk+-3.0
                        --pkg libxml-2.0
@@ -98,6 +116,7 @@ if(HAVE_GTK)
                        ${gir_fullname}
                DEPENDS libedataserverui-${API_VERSION}.deps
                        ${CMAKE_CURRENT_BINARY_DIR}/libedataserver-${API_VERSION}.vapi
+                       ${CMAKE_CURRENT_BINARY_DIR}/libecal-${CAL_API_VERSION}.vapi
                        ${gir_fullname}
                        ${gir_deps}
        )
@@ -118,6 +137,7 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libebook-contacts-${API_VE
                --vapidir=${CMAKE_CURRENT_BINARY_DIR}
                --girdir=${CMAKE_BINARY_DIR}/src/camel
                --girdir=${CMAKE_BINARY_DIR}/src/libedataserver
+               --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
                --pkg libedataserver-${API_VERSION}
                --pkg gio-2.0
                --pkg libxml-2.0
@@ -150,6 +170,7 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libebook-${API_VERSION}.va
                --girdir=${CMAKE_BINARY_DIR}/src/camel
                --girdir=${CMAKE_BINARY_DIR}/src/libedataserver
                --girdir=${CMAKE_BINARY_DIR}/src/addressbook/libebook-contacts
+               --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
                --pkg libedataserver-${API_VERSION}
                --pkg libebook-contacts-${API_VERSION}
                --pkg gio-2.0
@@ -166,6 +187,76 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libebook-${API_VERSION}.va
                ${gir_deps}
 )
 
+# ***********************************
+# libecal
+# ***********************************
+
+set(gir_fullname ${CMAKE_BINARY_DIR}/src/calendar/libecal/ECal-${CAL_API_VERSION}.gir)
+gir_girfilename_to_target(gir_deps ECal-${CAL_API_VERSION}.gir)
+
+add_dependencies(vala ${gir_deps})
+
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libecal-${CAL_API_VERSION}.vapi
+       COMMAND ${VAPIGEN}
+               --vapidir=${CMAKE_CURRENT_SOURCE_DIR}
+               --vapidir=${CMAKE_CURRENT_BINARY_DIR}
+               --girdir=${CMAKE_BINARY_DIR}/src/camel
+               --girdir=${CMAKE_BINARY_DIR}/src/libedataserver
+               --girdir=${CMAKE_BINARY_DIR}/src/calendar/libecal
+               --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
+               --pkg libedataserver-${API_VERSION}
+               --pkg gio-2.0
+               --pkg libxml-2.0
+               --pkg libsoup-2.4
+               --pkg posix
+               --library libecal-${CAL_API_VERSION}
+               --metadatadir=${CMAKE_CURRENT_SOURCE_DIR}
+               ${gir_fullname}
+       DEPENDS libecal-${CAL_API_VERSION}.deps
+               ${CMAKE_CURRENT_BINARY_DIR}/libedataserver-${API_VERSION}.vapi
+               ${gir_fullname}
+               ${gir_deps}
+)
+
+# ***********************************
+# libedata-cal
+# ***********************************
+
+if(ENABLE_DATACAL)
+set(gir_fullname ${CMAKE_BINARY_DIR}/src/calendar/libedata-cal/EDataCal-${CAL_API_VERSION}.gir)
+gir_girfilename_to_target(gir_deps EDataCal-${CAL_API_VERSION}.gir)
+
+add_dependencies(vala ${gir_deps})
+
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libedata-cal-${CAL_API_VERSION}.vapi
+       COMMAND ${VAPIGEN}
+               --vapidir=${CMAKE_CURRENT_SOURCE_DIR}
+               --vapidir=${CMAKE_CURRENT_BINARY_DIR}
+               --girdir=${CMAKE_BINARY_DIR}/src/camel
+               --girdir=${CMAKE_BINARY_DIR}/src/libebackend
+               --girdir=${CMAKE_BINARY_DIR}/src/libedataserver
+               --girdir=${CMAKE_BINARY_DIR}/src/calendar/libecal
+               --girdir=${CMAKE_BINARY_DIR}/src/calendar/libedata-cal
+               --girdir=${SHARE_INSTALL_PREFIX}/gir-1.0
+               --pkg libedataserver-${API_VERSION}
+               --pkg libebackend-${API_VERSION}
+               --pkg libecal-${CAL_API_VERSION}
+               --pkg gio-2.0
+               --pkg libxml-2.0
+               --pkg libsoup-2.4
+               --pkg posix
+               --library libedata-cal-${CAL_API_VERSION}
+               --metadatadir=${CMAKE_CURRENT_SOURCE_DIR}
+               ${gir_fullname}
+       DEPENDS libedata-cal-${CAL_API_VERSION}.deps
+               ${CMAKE_CURRENT_BINARY_DIR}/libedataserver-${API_VERSION}.vapi
+               ${CMAKE_CURRENT_BINARY_DIR}/libebackend-${API_VERSION}.vapi
+               ${CMAKE_CURRENT_BINARY_DIR}/libecal-${CAL_API_VERSION}.vapi
+               ${gir_fullname}
+               ${gir_deps}
+)
+endif(ENABLE_DATACAL)
+
 # ***********************************
 # Install all VAPI files
 # ***********************************
diff --git a/src/vala/ECal-2.0.metadata b/src/vala/ECal-2.0.metadata
new file mode 100644
index 000000000..014b2fcc6
--- /dev/null
+++ b/src/vala/ECal-2.0.metadata
@@ -0,0 +1,2 @@
+TimezoneCache.add_timezone name="add_tz"
+TimezoneCache.get_timezone name="get_tz"
diff --git a/src/vala/EDataCal-2.0.metadata b/src/vala/EDataCal-2.0.metadata
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/vala/libecal-2.0.deps b/src/vala/libecal-2.0.deps
new file mode 100644
index 000000000..8a75d97ec
--- /dev/null
+++ b/src/vala/libecal-2.0.deps
@@ -0,0 +1,3 @@
+libxml-2.0
+gio-2.0
+ICalGLib-3.0
diff --git a/src/vala/libedata-cal-2.0.deps b/src/vala/libedata-cal-2.0.deps
new file mode 100644
index 000000000..1c0917349
--- /dev/null
+++ b/src/vala/libedata-cal-2.0.deps
@@ -0,0 +1,3 @@
+libecal-2.0
+libxml-2.0
+gio-2.0
diff --git a/src/vala/libedataserverui-1.2.deps b/src/vala/libedataserverui-1.2.deps
index bc54ec344..bc2ec38b0 100644
--- a/src/vala/libedataserverui-1.2.deps
+++ b/src/vala/libedataserverui-1.2.deps
@@ -1,2 +1,3 @@
 libedataserver-1.2
+libecal-2.0
 gtk+-3.0
diff --git a/tests/libecal/CMakeLists.txt b/tests/libecal/CMakeLists.txt
index fbf037180..5575e53cc 100644
--- a/tests/libecal/CMakeLists.txt
+++ b/tests/libecal/CMakeLists.txt
@@ -1,19 +1,14 @@
 set(extra_deps
        ecal
-       etestserverutils
 )
 
-set(extra_defines
-       -DLOCALEDIR=\"${LOCALE_INSTALL_DIR}\"
-)
+set(extra_defines)
 
 set(extra_cflags
        ${CALENDAR_CFLAGS}
 )
 
 set(extra_incdirs
-       ${CMAKE_BINARY_DIR}/src/calendar
-       ${CMAKE_SOURCE_DIR}/src/calendar
        ${CALENDAR_INCLUDE_DIRS}
 )
 
@@ -21,73 +16,24 @@ set(extra_ldflags
        ${CALENDAR_LDFLAGS}
 )
 
-set(SOURCES
-       ecal-test-utils.c
-       ecal-test-utils.h
-)
-
-add_library(ecal-test-utils STATIC
-       ${SOURCES}
-)
-
-add_dependencies(ecal-test-utils
-       edataserver
-       ${extra_deps}
-)
-
-target_compile_definitions(ecal-test-utils PRIVATE
-       -DG_LOG_DOMAIN=\"ecal-test-utils\"
-       ${extra_defines}
-)
-
-target_compile_options(ecal-test-utils PUBLIC
-       ${BACKEND_CFLAGS}
-       ${DATA_SERVER_CFLAGS}
-       ${extra_cflags}
-)
-
-target_include_directories(ecal-test-utils PUBLIC
-       ${CMAKE_BINARY_DIR}
-       ${CMAKE_BINARY_DIR}/src
-       ${CMAKE_SOURCE_DIR}/src
-       ${BACKEND_INCLUDE_DIRS}
-       ${DATA_SERVER_INCLUDE_DIRS}
-       ${extra_incdirs}
-)
-
-target_link_libraries(ecal-test-utils
-       edataserver
-       ${extra_deps}
-       ${BACKEND_LDFLAGS}
-       ${DATA_SERVER_LDFLAGS}
-       ${extra_ldflags}
-)
-
-set(extra_deps
-       ecal
-       ecal-test-utils
-)
-
 # Should be kept ordered approximately from least to most difficult/complex
 set(TESTS
-       test-ecal-get-timezone
-       test-ecal-add-timezone
-       test-ecal-set-default-timezone
-       test-ecal-recur-description
-       test-ecal-get-alarm-email-address
-       test-ecal-get-cal-address
-       test-ecal-get-ldap-attribute
-       test-ecal-get-capabilities
-       test-ecal-get-default-object
-       test-ecal-create-object
-       test-ecal-create-object--2
-       test-ecal-get-objects-for-uid
-       test-ecal-remove-object
-       test-ecal-get-object-list
-       test-ecal-modify-object
-       test-ecal-send-objects
-       test-ecal-receive-objects
-       test-ecal-get-query
+       test-cal-client-refresh
+       test-cal-client-add-timezone
+       test-cal-client-create-object
+       test-cal-client-remove-object
+       test-cal-client-get-object-list
+       test-cal-client-modify-object
+       test-cal-client-send-objects
+       test-cal-client-receive-objects
+        test-cal-client-bulk-methods
+       test-cal-client-get-attachment-uris
+       test-cal-client-get-view
+       test-cal-client-revision-view
+       test-cal-client-get-revision
+       test-cal-client-get-free-busy
+       test-cal-component
+       test-cal-recur
 )
 
 foreach(_test ${TESTS})
@@ -104,24 +50,3 @@ foreach(_test ${TESTS})
                "TEST_INSTALLED_SERVICES=1"
        )
 endforeach(_test)
-
-# test-ecal-get-free-busy:
-#   broken by design, the API needs to be fixed.
-set(TESTS_SKIP
-       test-ecal-get-free-busy
-)
-
-foreach(_test ${TESTS_SKIP})
-       set(SOURCES ${_test}.c)
-
-       build_only_installable_test(${_test}
-               SOURCES
-               extra_deps
-               extra_defines
-               extra_cflags
-               extra_incdirs
-               extra_ldflags
-       )
-endforeach(_test)
-
-add_subdirectory(client)
diff --git a/tests/libecal/client/test-cal-client-add-timezone.c 
b/tests/libecal/test-cal-client-add-timezone.c
similarity index 72%
rename from tests/libecal/client/test-cal-client-add-timezone.c
rename to tests/libecal/test-cal-client-add-timezone.c
index 85f4e58ee..7b7ecb69e 100644
--- a/tests/libecal/client/test-cal-client-add-timezone.c
+++ b/tests/libecal/test-cal-client-add-timezone.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -33,20 +32,21 @@ test_add_timezone_sync (ETestServerFixture *fixture,
                         gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icalproperty *property;
-       icalcomponent *component;
-       icaltimezone *zone;
-       icaltimezone *zone2 = NULL;
+       ICalProperty *property;
+       ICalComponent *component;
+       ICalTimezone *zone;
+       ICalTimezone *zone2 = NULL;
        GError *error = NULL;
 
        /* Build up new timezone */
-       component = icalcomponent_new_vtimezone ();
-       property = icalproperty_new_tzid (TZID_NEW);
-       icalcomponent_add_property (component, property);
-       property = icalproperty_new_tzname (TZNAME_NEW);
-       icalcomponent_add_property (component, property);
-       zone = icaltimezone_new ();
-       icaltimezone_set_component (zone, component);
+       component = i_cal_component_new_vtimezone ();
+       property = i_cal_property_new_tzid (TZID_NEW);
+       i_cal_component_take_property (component, property);
+       property = i_cal_property_new_tzname (TZNAME_NEW);
+       i_cal_component_take_property (component, property);
+       zone = i_cal_timezone_new ();
+       g_assert (i_cal_timezone_set_component (zone, component));
+       g_object_unref (component);
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
@@ -59,14 +59,14 @@ test_add_timezone_sync (ETestServerFixture *fixture,
        if (!zone2)
                g_error ("Failure: get timezone returned NULL");
 
-       g_assert_cmpstr (icaltimezone_get_tzid (zone), ==, icaltimezone_get_tzid (zone2));
-       g_assert_cmpstr (icaltimezone_get_tznames (zone), ==, icaltimezone_get_tznames (zone2));
+       g_assert_cmpstr (i_cal_timezone_get_tzid (zone), ==, i_cal_timezone_get_tzid (zone2));
+       g_assert_cmpstr (i_cal_timezone_get_tznames (zone), ==, i_cal_timezone_get_tznames (zone2));
 
-       icaltimezone_free (zone, TRUE);
+       g_object_unref (zone);
 }
 
 typedef struct {
-       icaltimezone *zone;
+       ICalTimezone *zone;
        GMainLoop *loop;
 } AsyncData;
 
@@ -78,7 +78,7 @@ async_read_result_ready (GObject *source_object,
        ECalClient *cal_client;
        GError *error = NULL;
        AsyncData *data = (AsyncData *) user_data;
-       icaltimezone *zone1 = data->zone, *zone2 = NULL;
+       ICalTimezone *zone1 = data->zone, *zone2 = NULL;
 
        cal_client = E_CAL_CLIENT (source_object);
 
@@ -88,8 +88,8 @@ async_read_result_ready (GObject *source_object,
        if (!zone2)
                g_error ("Failure: get timezone returned NULL");
 
-       g_assert_cmpstr (icaltimezone_get_tzid (zone1), ==, icaltimezone_get_tzid (zone2));
-       g_assert_cmpstr (icaltimezone_get_tznames (zone1), ==, icaltimezone_get_tznames (zone2));
+       g_assert_cmpstr (i_cal_timezone_get_tzid (zone1), ==, i_cal_timezone_get_tzid (zone2));
+       g_assert_cmpstr (i_cal_timezone_get_tznames (zone1), ==, i_cal_timezone_get_tznames (zone2));
 
        g_main_loop_quit (data->loop);
 }
@@ -116,19 +116,20 @@ test_add_timezone_async (ETestServerFixture *fixture,
                          gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icalproperty *property;
-       icalcomponent *component;
-       icaltimezone *zone;
+       ICalProperty *property;
+       ICalComponent *component;
+       ICalTimezone *zone;
        AsyncData data;
 
        /* Build up new timezone */
-       component = icalcomponent_new_vtimezone ();
-       property = icalproperty_new_tzid (TZID_NEW);
-       icalcomponent_add_property (component, property);
-       property = icalproperty_new_tzname (TZNAME_NEW);
-       icalcomponent_add_property (component, property);
-       zone = icaltimezone_new ();
-       icaltimezone_set_component (zone, component);
+       component = i_cal_component_new_vtimezone ();
+       property = i_cal_property_new_tzid (TZID_NEW);
+       i_cal_component_take_property (component, property);
+       property = i_cal_property_new_tzname (TZNAME_NEW);
+       i_cal_component_take_property (component, property);
+       zone = i_cal_timezone_new ();
+       g_assert (i_cal_timezone_set_component (zone, component));
+       g_object_unref (component);
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
@@ -137,7 +138,7 @@ test_add_timezone_async (ETestServerFixture *fixture,
        e_cal_client_add_timezone (cal_client, zone, NULL, async_write_result_ready, &data);
        g_main_loop_run (fixture->loop);
 
-       icaltimezone_free (zone, TRUE);
+       g_object_unref (zone);
 }
 
 gint
diff --git a/tests/libecal/test-cal-client-bulk-methods.c b/tests/libecal/test-cal-client-bulk-methods.c
new file mode 100644
index 000000000..da9f7b0dd
--- /dev/null
+++ b/tests/libecal/test-cal-client-bulk-methods.c
@@ -0,0 +1,407 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <libecal/libecal.h>
+
+#include "e-test-server-utils.h"
+
+static ETestServerClosure cal_closure =
+       { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS };
+
+#define NB_COMPONENTS 5
+
+static void
+test_icomps (ICalComponent *icomp1,
+            ICalComponent *icomp2)
+{
+       ICalTime *t1, *t2;
+
+       if (!icomp2)
+               g_error ("Failure: get object returned NULL");
+
+       g_assert_cmpstr (i_cal_component_get_uid (icomp1), ==, i_cal_component_get_uid (icomp2));
+       g_assert_cmpstr (i_cal_component_get_summary (icomp1), ==, i_cal_component_get_summary (icomp2));
+
+       t1 = i_cal_component_get_dtstart (icomp1);
+       t2 = i_cal_component_get_dtstart (icomp2);
+
+       if (i_cal_time_compare (t1, t2) != 0) {
+               gchar *str1, *str2;
+
+               str1 = i_cal_time_as_ical_string_r (t1);
+               str2 = i_cal_time_as_ical_string_r (t2);
+
+               g_error ("Failure: dtend doesn't match, expected '%s', got '%s'\n", str1, str2);
+
+               g_free (str1);
+               g_free (str2);
+       }
+
+       g_clear_object (&t1);
+       g_clear_object (&t2);
+
+       t1 = i_cal_component_get_dtend (icomp1);
+       t2 = i_cal_component_get_dtend (icomp2);
+
+       if (i_cal_time_compare (t1, t2) != 0) {
+               gchar *str1, *str2;
+
+               str1 = i_cal_time_as_ical_string_r (t1);
+               str2 = i_cal_time_as_ical_string_r (t2);
+
+               g_error ("Failure: dtend doesn't match, expected '%s', got '%s'\n", str1, str2);
+
+               g_free (str1);
+               g_free (str2);
+       }
+
+       g_clear_object (&t1);
+       g_clear_object (&t2);
+}
+
+static void
+check_removed (ECalClient *cal_client,
+               const GSList *uids)
+{
+       g_assert (cal_client != NULL);
+       g_assert (uids != NULL);
+
+       while (uids) {
+               GError *error = NULL;
+               ICalComponent *icomp = NULL;
+
+               if (!e_cal_client_get_object_sync (cal_client, uids->data, NULL, &icomp, NULL, &error) &&
+                   g_error_matches (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND)) {
+                       g_clear_error (&error);
+               } else if (error) {
+                       g_error ("check objects removed sync: %s", error->message);
+                       g_clear_error (&error);
+               } else {
+                       g_clear_object (&icomp);
+
+                       g_error ("check objects removed sync: object found in the backend");
+               }
+
+               uids = uids->next;
+       }
+}
+
+static GSList *
+uid_slist_to_ecalcomponentid_slist (GSList *uids)
+{
+       GSList *ids = NULL;
+       const GSList *l;
+
+       for (l = uids; l; l = l->next) {
+               ids = g_slist_append (ids, e_cal_component_id_new (l->data, NULL));
+       }
+
+       return ids;
+}
+
+static void
+check_icomps_exist (ECalClient *cal_client,
+                   GSList *icomps)
+{
+       GSList *link;
+
+       for (link = icomps; link; link = g_slist_next (link)) {
+               GError *error = NULL;
+               ICalComponent *icomp = link->data;
+               ICalComponent *icomp2 = NULL;
+               const gchar *uid = i_cal_component_get_uid (icomp);
+
+               if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icomp2, NULL, &error))
+                       g_error ("get object sync: %s", error->message);
+
+               g_assert_nonnull (icomp2);
+
+               test_icomps (icomp, icomp2);
+
+               g_object_unref (icomp2);
+       }
+}
+
+static void
+test_bulk_methods_sync (ECalClient *cal_client,
+                       GSList *icomps)
+{
+       GError *error = NULL;
+       GSList *uids = NULL, *ids = NULL;
+       const GSList *lcomp, *luid;
+       gint i = 0;
+
+       g_assert_nonnull (icomps);
+
+       /* Create all the objects in bulk */
+       if (!e_cal_client_create_objects_sync (cal_client, icomps, E_CAL_OPERATION_FLAG_NONE, &uids, NULL, 
&error))
+               g_error ("create objects sync: %s", error->message);
+
+       g_assert (uids != NULL);
+       g_assert_cmpint (g_slist_length (uids), ==, NB_COMPONENTS);
+
+       /* Update ICalComponents uids */
+       luid = uids;
+       lcomp = icomps;
+       while (luid && lcomp) {
+               i_cal_component_set_uid (lcomp->data, luid->data);
+               luid = luid->next;
+               lcomp = lcomp->next;
+       }
+
+       /* Retrieve all the objects and check that they are the same */
+       check_icomps_exist (cal_client, icomps);
+
+       /* Modify the objects */
+       for (lcomp = icomps; lcomp; lcomp = lcomp->next) {
+               gchar *summary;
+               ICalComponent *icomp = lcomp->data;
+
+               summary = g_strdup_printf ("Edited test summary %d", i);
+               i_cal_component_set_summary (icomp, summary);
+
+               g_free (summary);
+               ++i;
+       }
+
+       /* Save the modified objects in bulk */
+       if (!e_cal_client_modify_objects_sync (cal_client, icomps, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
+               g_error ("modify objects sync: %s", error->message);
+
+       /* Retrieve all the objects and check that they have been modified */
+       check_icomps_exist (cal_client, icomps);
+
+       /* Remove all the objects in bulk */
+       ids = uid_slist_to_ecalcomponentid_slist (uids);
+
+       if (!e_cal_client_remove_objects_sync (cal_client, ids, E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE, 
NULL, &error))
+               g_error ("remove objects sync: %s", error->message);
+
+       g_slist_free_full (ids, e_cal_component_id_free);
+
+       /* Check that the objects don't exist anymore */
+       check_removed (cal_client, uids);
+
+       g_slist_free_full (uids, g_free);
+}
+
+typedef struct _AsyncContext {
+       ECalClient *cal_client;
+       GSList *icomps; /* ICalComponent * */
+       GSList *ids; /* ECalComponentId * */
+       GSList *uids; /* gchar * */
+       GMainLoop *main_loop;
+} AsyncContext;
+
+static void
+bulk_async_remove_objects_cb (GObject *source_object,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+       AsyncContext *async_context = user_data;
+       gboolean success;
+       GError *error = NULL;
+
+       g_assert_nonnull (async_context);
+       g_assert (E_IS_CAL_CLIENT (source_object));
+       g_assert (async_context->cal_client == E_CAL_CLIENT (source_object));
+
+       success = e_cal_client_remove_objects_finish (async_context->cal_client, result, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       /* Check that the objects don't exist anymore */
+       check_removed (async_context->cal_client, async_context->uids);
+
+       g_main_loop_quit (async_context->main_loop);
+}
+
+static void
+bulk_async_modify_objects_cb (GObject *source_object,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+       AsyncContext *async_context = user_data;
+       gboolean success;
+       GError *error = NULL;
+
+       g_assert_nonnull (async_context);
+       g_assert (E_IS_CAL_CLIENT (source_object));
+       g_assert (async_context->cal_client == E_CAL_CLIENT (source_object));
+
+       success = e_cal_client_modify_objects_finish (async_context->cal_client, result, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       /* Retrieve all the objects and check that they have been modified */
+       check_icomps_exist (async_context->cal_client, async_context->icomps);
+
+       /* Remove all the objects in bulk */
+       async_context->ids = uid_slist_to_ecalcomponentid_slist (async_context->uids);
+
+       e_cal_client_remove_objects (async_context->cal_client, async_context->ids, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE,
+               NULL, bulk_async_remove_objects_cb, async_context);
+}
+
+static void
+bulk_async_create_objects_cb (GObject *source_object,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+       AsyncContext *async_context = user_data;
+       GSList *luid, *lcomp;
+       gboolean success;
+       gint ii;
+       GError *error = NULL;
+
+       g_assert_nonnull (async_context);
+       g_assert (E_IS_CAL_CLIENT (source_object));
+       g_assert (async_context->cal_client == E_CAL_CLIENT (source_object));
+
+       success = e_cal_client_create_objects_finish (async_context->cal_client, result, 
&async_context->uids, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_nonnull (async_context->uids);
+       g_assert_cmpint (g_slist_length (async_context->uids), ==, NB_COMPONENTS);
+
+       /* Update ICalComponents uids */
+       for (luid = async_context->uids, lcomp = async_context->icomps;
+            luid && lcomp;
+            luid = g_slist_next (luid), lcomp = g_slist_next (lcomp)) {
+               i_cal_component_set_uid (lcomp->data, luid->data);
+       }
+
+       /* Retrieve all the objects and check that they are the same */
+       check_icomps_exist (async_context->cal_client, async_context->icomps);
+
+       /* Modify the objects */
+       for (ii = 0, lcomp = async_context->icomps; lcomp; ii++, lcomp = g_slist_next (lcomp)) {
+               gchar *summary;
+               ICalComponent *icomp = lcomp->data;
+
+               summary = g_strdup_printf ("Edited test summary %d", ii);
+               i_cal_component_set_summary (icomp, summary);
+
+               g_free (summary);
+       }
+
+       e_cal_client_modify_objects (async_context->cal_client, async_context->icomps, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE,
+               NULL, bulk_async_modify_objects_cb, async_context);
+}
+
+static void
+test_bulk_methods_async (ECalClient *cal_client,
+                        GSList *icomps)
+{
+       AsyncContext async_context;
+
+       g_assert_nonnull (icomps);
+
+       async_context.cal_client = cal_client;
+       async_context.icomps = icomps;
+       async_context.ids = NULL;
+       async_context.uids = NULL;
+       async_context.main_loop = g_main_loop_new (NULL, FALSE);
+
+       e_cal_client_create_objects (async_context.cal_client, async_context.icomps, 
E_CAL_OPERATION_FLAG_NONE, NULL,
+               bulk_async_create_objects_cb, &async_context);
+
+       g_main_loop_run (async_context.main_loop);
+
+       g_slist_free_full (async_context.ids, e_cal_component_id_free);
+       g_slist_free_full (async_context.uids, g_free);
+       g_main_loop_unref (async_context.main_loop);
+}
+
+static void
+run_test_bulk_methods_wrapper (ETestServerFixture *fixture,
+                              void (* func)(ECalClient *cal_client,
+                                            GSList *icomps))
+{
+       ECalClient *cal_client;
+       GSList *icomps = NULL;
+       ICalTime *dtstart, *dtend;
+       gint ii;
+
+       cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
+
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
+
+       /* Build up new components */
+       for (ii = 0; ii < NB_COMPONENTS; ++ii) {
+               ICalComponent *icomp;
+               gchar *summary;
+
+               icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+               summary = g_strdup_printf ("Test summary %d", ii);
+               i_cal_component_set_summary (icomp, summary);
+               i_cal_component_set_dtstart (icomp, dtstart);
+               i_cal_component_set_dtend (icomp, dtend);
+
+               icomps = g_slist_append (icomps, icomp);
+               g_free (summary);
+       }
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       /* Test synchronous bulk methods */
+       func (cal_client, icomps);
+
+       g_slist_free_full (icomps, g_object_unref);
+}
+
+static void
+run_test_bulk_methods_sync (ETestServerFixture *fixture,
+                           gconstpointer user_data)
+{
+       run_test_bulk_methods_wrapper (fixture, test_bulk_methods_sync);
+}
+
+static void
+run_test_bulk_methods_async (ETestServerFixture *fixture,
+                            gconstpointer user_data)
+{
+       run_test_bulk_methods_wrapper (fixture, test_bulk_methods_async);
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       g_test_init (&argc, &argv, NULL);
+       g_test_bug_base ("http://bugzilla.gnome.org/";);
+
+       g_test_add (
+               "/ECalClient/BulkMethods/Sync",
+               ETestServerFixture,
+               &cal_closure,
+               e_test_server_utils_setup,
+               run_test_bulk_methods_sync,
+               e_test_server_utils_teardown);
+       g_test_add (
+               "/ECalClient/BulkMethods/Async",
+               ETestServerFixture,
+               &cal_closure,
+               e_test_server_utils_setup,
+               run_test_bulk_methods_async,
+               e_test_server_utils_teardown);
+
+       return e_test_server_utils_run ();
+}
diff --git a/tests/libecal/client/test-cal-client-create-object.c 
b/tests/libecal/test-cal-client-create-object.c
similarity index 56%
rename from tests/libecal/client/test-cal-client-create-object.c
rename to tests/libecal/test-cal-client-create-object.c
index 29e04b856..f76432feb 100644
--- a/tests/libecal/client/test-cal-client-create-object.c
+++ b/tests/libecal/test-cal-client-create-object.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -26,32 +25,52 @@ static ETestServerClosure cal_closure_async =
        { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, FALSE, NULL, TRUE };
 
 static void
-test_icalcomps (icalcomponent *icalcomp1,
-                icalcomponent *icalcomp2)
+test_icomps (ICalComponent *icomp1,
+            ICalComponent *icomp2)
 {
-       struct icaltimetype t1, t2;
+       ICalTime *t1, *t2;
 
-       if (!icalcomp2)
+       if (!icomp2)
                g_error ("Failure: get object returned NULL");
 
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp1), ==, icalcomponent_get_uid (icalcomp2));
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp1), ==, icalcomponent_get_summary (icalcomp2));
+       g_assert_cmpstr (i_cal_component_get_uid (icomp1), ==, i_cal_component_get_uid (icomp2));
+       g_assert_cmpstr (i_cal_component_get_summary (icomp1), ==, i_cal_component_get_summary (icomp2));
 
-       t1 = icalcomponent_get_dtstart (icalcomp1);
-       t2 = icalcomponent_get_dtstart (icalcomp2);
+       t1 = i_cal_component_get_dtstart (icomp1);
+       t2 = i_cal_component_get_dtstart (icomp2);
 
-       if (icaltime_compare (t1, t2) != 0)
-               g_error (
-                       "Failure: dtend doesn't match, expected '%s', got '%s'\n",
-                       icaltime_as_ical_string (t1), icaltime_as_ical_string (t2));
+       if (i_cal_time_compare (t1, t2) != 0) {
+               gchar *str1, *str2;
 
-       t1 = icalcomponent_get_dtend (icalcomp1);
-       t2 = icalcomponent_get_dtend (icalcomp2);
+               str1 = i_cal_time_as_ical_string_r (t1);
+               str2 = i_cal_time_as_ical_string_r (t2);
 
-       if (icaltime_compare (t1, t2) != 0)
-               g_error (
-                       "Failure: dtend doesn't match, expected '%s', got '%s'\n",
-                       icaltime_as_ical_string (t1), icaltime_as_ical_string (t2));
+               g_error ("Failure: dtend doesn't match, expected '%s', got '%s'\n", str1, str2);
+
+               g_free (str1);
+               g_free (str2);
+       }
+
+       g_clear_object (&t1);
+       g_clear_object (&t2);
+
+       t1 = i_cal_component_get_dtend (icomp1);
+       t2 = i_cal_component_get_dtend (icomp2);
+
+       if (i_cal_time_compare (t1, t2) != 0) {
+               gchar *str1, *str2;
+
+               str1 = i_cal_time_as_ical_string_r (t1);
+               str2 = i_cal_time_as_ical_string_r (t2);
+
+               g_error ("Failure: dtend doesn't match, expected '%s', got '%s'\n", str1, str2);
+
+               g_free (str1);
+               g_free (str2);
+       }
+
+       g_clear_object (&t1);
+       g_clear_object (&t2);
 }
 
 static void
@@ -59,9 +78,9 @@ test_create_object_sync (ETestServerFixture *fixture,
                          gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icalcomponent *icalcomp;
-       icalcomponent *icalcomp2 = NULL, *clone;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalComponent *icomp2 = NULL, *clone;
+       ICalTime *dtstart, *dtend;
        GError *error = NULL;
        GSList *ecalcomps = NULL;
        gchar *uid = NULL;
@@ -69,24 +88,30 @@ test_create_object_sync (ETestServerFixture *fixture,
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
        /* Build up new component */
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Test event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
+
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Test event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp2, NULL, &error))
+       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icomp2, NULL, &error))
                g_error ("get object sync: %s", error->message);
 
-       clone = icalcomponent_new_clone (icalcomp);
-       icalcomponent_set_uid (clone, uid);
+       clone = i_cal_component_new_clone (icomp);
+       i_cal_component_set_uid (clone, uid);
 
-       test_icalcomps (clone, icalcomp2);
+       test_icomps (clone, icomp2);
 
-       icalcomponent_free (icalcomp2);
+       g_object_unref (icomp2);
 
        if (!e_cal_client_get_objects_for_uid_sync (cal_client, uid, &ecalcomps, NULL, &error))
                g_error ("get objects for uid sync: %s", error->message);
@@ -96,18 +121,18 @@ test_create_object_sync (ETestServerFixture *fixture,
        else {
                ECalComponent *ecalcomp = ecalcomps->data;
 
-               test_icalcomps (clone, e_cal_component_get_icalcomponent (ecalcomp));
+               test_icomps (clone, e_cal_component_get_icalcomponent (ecalcomp));
        }
-       e_cal_client_free_ecalcomp_slist (ecalcomps);
+       e_util_free_nullable_object_slist (ecalcomps);
 
-       icalcomponent_free (clone);
+       g_object_unref (clone);
+       g_object_unref (icomp);
        g_free (uid);
-       icalcomponent_free (icalcomp);
 }
 
 typedef struct {
-       icalcomponent *icalcomp;
-       icalcomponent *clone;
+       ICalComponent *icomp;
+       ICalComponent *clone;
        GMainLoop *loop;
 } AsyncData;
 
@@ -119,10 +144,10 @@ async_read2_result_ready (GObject *source_object,
        ECalClient *cal_client;
        GError *error = NULL;
        AsyncData *data = (AsyncData *) user_data;
-       icalcomponent *icalcomp1 = data->clone;
+       ICalComponent *icomp1 = data->clone;
        GSList *ecalcomps = NULL;
 
-       g_return_if_fail (icalcomp1 != NULL);
+       g_return_if_fail (icomp1 != NULL);
 
        cal_client = E_CAL_CLIENT (source_object);
 
@@ -134,11 +159,11 @@ async_read2_result_ready (GObject *source_object,
        else {
                ECalComponent *ecalcomp = ecalcomps->data;
 
-               test_icalcomps (icalcomp1, e_cal_component_get_icalcomponent (ecalcomp));
+               test_icomps (icomp1, e_cal_component_get_icalcomponent (ecalcomp));
        }
-       e_cal_client_free_ecalcomp_slist (ecalcomps);
+       e_util_free_nullable_object_slist (ecalcomps);
 
-       icalcomponent_free (icalcomp1);
+       g_object_unref (icomp1);
        g_main_loop_quit (data->loop);
 }
 
@@ -150,19 +175,19 @@ async_read_result_ready (GObject *source_object,
        ECalClient *cal_client;
        GError *error = NULL;
        AsyncData *data = (AsyncData *) user_data;
-       icalcomponent *icalcomp1 = data->clone, *icalcomp2 = NULL;
+       ICalComponent *icomp1 = data->clone, *icomp2 = NULL;
 
-       g_return_if_fail (icalcomp1 != NULL);
+       g_return_if_fail (icomp1 != NULL);
 
        cal_client = E_CAL_CLIENT (source_object);
-       if (!e_cal_client_get_object_finish (cal_client, result, &icalcomp2, &error))
+       if (!e_cal_client_get_object_finish (cal_client, result, &icomp2, &error))
                g_error ("get object finish: %s", error->message);
 
-       test_icalcomps (icalcomp1, icalcomp2);
-       icalcomponent_free (icalcomp2);
+       test_icomps (icomp1, icomp2);
+       g_object_unref (icomp2);
 
        e_cal_client_get_objects_for_uid (cal_client,
-                                         icalcomponent_get_uid (icalcomp1), NULL,
+                                         i_cal_component_get_uid (icomp1), NULL,
                                          async_read2_result_ready, data);
 }
 
@@ -175,17 +200,17 @@ async_write_result_ready (GObject *source_object,
        GError *error = NULL;
        gchar *uid = NULL;
        AsyncData *data = (AsyncData *) user_data;
-       icalcomponent *clone, *icalcomp = data->icalcomp;
+       ICalComponent *clone, *icomp = data->icomp;
 
-       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (icomp != NULL);
 
        cal_client = E_CAL_CLIENT (source_object);
 
        if (!e_cal_client_create_object_finish (cal_client, result, &uid, &error))
                g_error ("create object finish: %s", error->message);
 
-       clone = icalcomponent_new_clone (icalcomp);
-       icalcomponent_set_uid (clone, uid);
+       clone = i_cal_component_new_clone (icomp);
+       i_cal_component_set_uid (clone, uid);
 
        data->clone = clone;
        e_cal_client_get_object (cal_client, uid, NULL, NULL, async_read_result_ready, data);
@@ -197,25 +222,31 @@ test_create_object_async (ETestServerFixture *fixture,
                           gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
        AsyncData data = { 0, };
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
        /* Build up new component */
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Test event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
+
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Test event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
 
-       data.icalcomp = icalcomp;
+       data.icomp = icomp;
        data.loop = fixture->loop;
-       e_cal_client_create_object (cal_client, icalcomp, NULL, async_write_result_ready, &data);
+       e_cal_client_create_object (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, NULL, 
async_write_result_ready, &data);
        g_main_loop_run (fixture->loop);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
 }
 
 gint
diff --git a/tests/libecal/client/test-cal-client-get-attachment-uris.c 
b/tests/libecal/test-cal-client-get-attachment-uris.c
similarity index 80%
rename from tests/libecal/client/test-cal-client-get-attachment-uris.c
rename to tests/libecal/test-cal-client-get-attachment-uris.c
index 49cad5a47..19e1765e4 100644
--- a/tests/libecal/client/test-cal-client-get-attachment-uris.c
+++ b/tests/libecal/test-cal-client-get-attachment-uris.c
@@ -17,7 +17,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -31,48 +30,53 @@ static ETestServerClosure cal_closure_async =
        { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, FALSE, NULL, TRUE };
 
 static void
-add_attach (icalcomponent *icalcomp,
+add_attach (ICalComponent *icomp,
             const gchar *uri)
 {
-       gsize buf_size;
        gchar *buf;
-       icalproperty *prop;
-       icalattach *attach;
+       ICalProperty *prop;
+       ICalAttach *attach;
 
-       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (icomp != NULL);
        g_return_if_fail (uri != NULL);
 
-       buf_size = 2 * strlen (uri);
-       buf = g_malloc0 (buf_size);
-       icalvalue_encode_ical_string (uri, buf, buf_size);
-       attach = icalattach_new_from_url (uri);
-       prop = icalproperty_new_attach (attach);
-       icalcomponent_add_property (icalcomp, prop);
-       icalattach_unref (attach);
+       buf = i_cal_value_encode_ical_string (uri);
+       attach = i_cal_attach_new_from_url (buf);
+       prop = i_cal_property_new_attach (attach);
+       i_cal_component_take_property (icomp, prop);
+       g_object_unref (attach);
        g_free (buf);
 }
 
 static const gchar *
 setup_cal (ECalClient *cal_client)
 {
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
        gchar *uid = NULL;
        GError *error = NULL;
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Test event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
-       add_attach (icalcomp, ATTACH1);
-       add_attach (icalcomp, ATTACH2);
-       add_attach (icalcomp, ATTACH3);
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Test event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       add_attach (icomp, ATTACH1);
+       add_attach (icomp, ATTACH2);
+       add_attach (icomp, ATTACH3);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
+
        g_object_set_data_full (G_OBJECT (cal_client), "use-uid", uid, g_free);
 
        return uid;
diff --git a/tests/libecal/client/test-cal-client-get-free-busy.c 
b/tests/libecal/test-cal-client-get-free-busy.c
similarity index 95%
rename from tests/libecal/client/test-cal-client-get-free-busy.c
rename to tests/libecal/test-cal-client-get-free-busy.c
index d3949ea83..0fbfce37f 100644
--- a/tests/libecal/client/test-cal-client-get-free-busy.c
+++ b/tests/libecal/test-cal-client-get-free-busy.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -108,16 +107,16 @@ add_component_sync (ECalClient *cal_client)
                "CREATED:20040211T080000Z\r\n"
                "LAST-MODIFIED:20040211T080000Z\r\n"
                "END:VEVENT\r\n";
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        GError *error = NULL;
 
-       icalcomp = icalcomponent_new_from_string (comp_str);
-       g_assert_nonnull (icalcomp);
+       icomp = i_cal_component_new_from_string (comp_str);
+       g_assert_nonnull (icomp);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, NULL, NULL, &error))
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, NULL, NULL, 
&error))
                g_error ("Failed to add component: %s", error ? error->message : "Unknown error");
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_clear_error (&error);
 }
 
@@ -151,7 +150,7 @@ test_get_free_busy_sync (ETestServerFixture *fixture,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       icaltimezone *utc;
+       ICalTimezone *utc;
        GSList *users = NULL, *freebusy_data = NULL;
        time_t start, end;
 
@@ -164,7 +163,7 @@ test_get_free_busy_sync (ETestServerFixture *fixture,
 
        g_signal_connect (cal_client, "free-busy-data", G_CALLBACK (free_busy_data_cb), (gpointer) G_STRFUNC);
 
-       utc = icaltimezone_get_utc_timezone ();
+       utc = i_cal_timezone_get_utc_timezone ();
        start = time_from_isodate ("20040212T000000Z");
        end = time_add_day_with_zone (start, 2, utc);
        users = g_slist_append (users, (gpointer) USER_EMAIL);
@@ -212,7 +211,7 @@ test_get_free_busy_async (ETestServerFixture *fixture,
                           gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icaltimezone *utc;
+       ICalTimezone *utc;
        GSList *users = NULL;
        time_t start, end;
 
@@ -223,7 +222,7 @@ test_get_free_busy_async (ETestServerFixture *fixture,
        /* This is set by the free-busy-data callback */
        received_free_busy_data = FALSE;
 
-       utc = icaltimezone_get_utc_timezone ();
+       utc = i_cal_timezone_get_utc_timezone ();
        start = time_from_isodate ("20040212T000000Z");
        end = time_add_day_with_zone (start, 2, utc);
        users = g_slist_append (users, (gpointer) USER_EMAIL);
diff --git a/tests/libecal/client/test-cal-client-get-object-list.c 
b/tests/libecal/test-cal-client-get-object-list.c
similarity index 77%
rename from tests/libecal/client/test-cal-client-get-object-list.c
rename to tests/libecal/test-cal-client-get-object-list.c
index 3143dcdf4..6bd62efea 100644
--- a/tests/libecal/client/test-cal-client-get-object-list.c
+++ b/tests/libecal/test-cal-client-get-object-list.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -31,29 +30,35 @@ static ETestServerClosure cal_closure_async =
 static void
 setup_cal (ECalClient *cal_client)
 {
-       struct icaltimetype now;
-       icalcomponent *icalcomp;
+       ICalTime *dtstart, *dtend;
+       ICalComponent *icomp;
        gchar *uid = NULL;
        GError *error = NULL;
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, EVENT_SUMMARY);
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, EVENT_SUMMARY);
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_free (uid);
 }
 
 static void
-test_result (icalcomponent *icalcomp)
+test_result (ICalComponent *icomp)
 {
-       g_assert (icalcomp != NULL);
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), ==, EVENT_SUMMARY);
+       g_assert_nonnull (icomp);
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), ==, EVENT_SUMMARY);
 }
 
 static void
@@ -61,19 +66,19 @@ test_get_object_list_sync (ETestServerFixture *fixture,
                            gconstpointer user_data)
 {
        ECalClient *cal_client;
-       GSList *icalcomps = NULL, *ecalcomps = NULL;
+       GSList *icomps = NULL, *ecalcomps = NULL;
        GError *error = NULL;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
        setup_cal (cal_client);
 
-       if (!e_cal_client_get_object_list_sync (cal_client, EVENT_QUERY, &icalcomps, NULL, &error))
+       if (!e_cal_client_get_object_list_sync (cal_client, EVENT_QUERY, &icomps, NULL, &error))
                g_error ("get object list sync: %s", error->message);
 
-       g_assert_cmpint (g_slist_length (icalcomps), ==, 1);
-       test_result (icalcomps->data);
+       g_assert_cmpint (g_slist_length (icomps), ==, 1);
+       test_result (icomps->data);
 
-       e_cal_client_free_icalcomp_slist (icalcomps);
+       e_util_free_nullable_object_slist (icomps);
 
        if (!e_cal_client_get_object_list_as_comps_sync (cal_client, EVENT_QUERY, &ecalcomps, NULL, &error))
                g_error ("get object list as comps sync: %s", error->message);
@@ -81,7 +86,7 @@ test_get_object_list_sync (ETestServerFixture *fixture,
        g_assert_cmpint (g_slist_length (ecalcomps), ==, 1);
        test_result (e_cal_component_get_icalcomponent (ecalcomps->data));
 
-       e_cal_client_free_ecalcomp_slist (ecalcomps);
+       e_util_free_nullable_object_slist (ecalcomps);
 }
 
 static void
@@ -102,7 +107,7 @@ async_get_object_list_as_comps_result_ready (GObject *source_object,
        g_assert_cmpint (g_slist_length (ecalcomps), ==, 1);
        test_result (e_cal_component_get_icalcomponent (ecalcomps->data));
 
-       e_cal_client_free_ecalcomp_slist (ecalcomps);
+       e_util_free_nullable_object_slist (ecalcomps);
        g_main_loop_quit (loop);
 }
 
@@ -113,16 +118,16 @@ async_get_object_list_result_ready (GObject *source_object,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       GSList *icalcomps = NULL;
+       GSList *icomps = NULL;
 
        cal_client = E_CAL_CLIENT (source_object);
 
-       if (!e_cal_client_get_object_list_finish (cal_client, result, &icalcomps, &error))
+       if (!e_cal_client_get_object_list_finish (cal_client, result, &icomps, &error))
                g_error ("get object list finish: %s", error->message);
 
-       g_assert_cmpint (g_slist_length (icalcomps), ==, 1);
-       test_result (icalcomps->data);
-       e_cal_client_free_icalcomp_slist (icalcomps);
+       g_assert_cmpint (g_slist_length (icomps), ==, 1);
+       test_result (icomps->data);
+       e_util_free_nullable_object_slist (icomps);
 
        e_cal_client_get_object_list_as_comps (
                cal_client, EVENT_QUERY, NULL,
diff --git a/tests/libecal/client/test-cal-client-get-revision.c 
b/tests/libecal/test-cal-client-get-revision.c
similarity index 78%
rename from tests/libecal/client/test-cal-client-get-revision.c
rename to tests/libecal/test-cal-client-get-revision.c
index 96887a360..8f3279957 100644
--- a/tests/libecal/client/test-cal-client-get-revision.c
+++ b/tests/libecal/test-cal-client-get-revision.c
@@ -28,26 +28,32 @@ static ETestServerClosure cal_closure =
 static void
 get_revision_compare_cycle (ECalClient *client)
 {
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
-       gchar    *revision_before = NULL, *revision_after = NULL, *uid = NULL;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
+       gchar *revision_before = NULL, *revision_after = NULL, *uid = NULL;
        GError   *error = NULL;
 
        /* Build up new component */
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Test event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
+
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Test event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
 
        if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION,
                                                &revision_before, NULL, &error))
                g_error ("Error getting calendar revision: %s", error->message);
 
-       if (!e_cal_client_create_object_sync (client, icalcomp, &uid, NULL, &error))
+       if (!e_cal_client_create_object_sync (client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, &error))
                g_error ("Error creating object: %s", error->message);
 
-       if (!e_cal_client_remove_object_sync (client, uid, NULL, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_remove_object_sync (client, uid, NULL, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Error removing created object: %s", error->message);
 
        if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION,
@@ -66,7 +72,7 @@ get_revision_compare_cycle (ECalClient *client)
        g_free (revision_after);
        g_free (uid);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
 }
 
 static void
diff --git a/tests/libecal/client/test-cal-client-get-view.c b/tests/libecal/test-cal-client-get-view.c
similarity index 83%
rename from tests/libecal/client/test-cal-client-get-view.c
rename to tests/libecal/test-cal-client-get-view.c
index 228064613..52e13019b 100644
--- a/tests/libecal/client/test-cal-client-get-view.c
+++ b/tests/libecal/test-cal-client-get-view.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -60,7 +59,7 @@ objects_added_cb (GObject *object,
        const GSList *l;
 
        for (l = objects; l; l = l->next)
-               g_print ("Object added %s (%s)\n", icalcomponent_get_uid (l->data), icalcomponent_get_summary 
(l->data));
+               g_print ("Object added %s (%s)\n", i_cal_component_get_uid (l->data), 
i_cal_component_get_summary (l->data));
 
        subtest_passed (SUBTEST_OBJECTS_ADDED, loop);
 }
@@ -74,7 +73,7 @@ objects_modified_cb (GObject *object,
        const GSList *l;
 
        for (l = objects; l; l = l->next)
-               g_print ("Object modified %s (%s)\n", icalcomponent_get_uid (l->data), 
icalcomponent_get_summary (l->data));
+               g_print ("Object modified %s (%s)\n", i_cal_component_get_uid (l->data), 
i_cal_component_get_summary (l->data));
 
        subtest_passed (SUBTEST_OBJECTS_MODIFIED, loop);
 }
@@ -90,7 +89,7 @@ objects_removed_cb (GObject *object,
        for (l = objects; l; l = l->next) {
                ECalComponentId *id = l->data;
 
-               g_print ("Object removed: uid: %s, rid: %s\n", id->uid, id->rid);
+               g_print ("Object removed: uid: %s, rid: %s\n", e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id));
        }
 
        subtest_passed (SUBTEST_OBJECTS_REMOVED, loop);
@@ -113,32 +112,38 @@ alter_cal_client (gpointer user_data)
 {
        ECalClient *cal_client = user_data;
        GError *error = NULL;
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
        gchar *uid = NULL;
 
        g_return_val_if_fail (cal_client != NULL, NULL);
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Initial event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Initial event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_set_uid (icalcomp, uid);
-       icalcomponent_set_summary (icalcomp, "Modified event summary");
+       i_cal_component_set_uid (icomp, uid);
+       i_cal_component_set_summary (icomp, "Modified event summary");
 
-       if (!e_cal_client_modify_object_sync (cal_client, icalcomp, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_modify_object_sync (cal_client, icomp, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("modify object sync: %s", error->message);
 
-       if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("remove object sync: %s", error->message);
 
+       g_object_unref (icomp);
        g_free (uid);
-       icalcomponent_free (icalcomp);
 
        return FALSE;
 }
diff --git a/tests/libecal/client/test-cal-client-modify-object.c 
b/tests/libecal/test-cal-client-modify-object.c
similarity index 67%
rename from tests/libecal/client/test-cal-client-modify-object.c
rename to tests/libecal/test-cal-client-modify-object.c
index 62afb49dd..c28c5f119 100644
--- a/tests/libecal/client/test-cal-client-modify-object.c
+++ b/tests/libecal/test-cal-client-modify-object.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -30,29 +29,35 @@ static ETestServerClosure cal_closure_async =
 static void
 setup_cal (ECalClient *cal_client)
 {
-       struct icaltimetype now;
-       icalcomponent *icalcomp;
+       ICalTime *dtstart, *dtend;
+       ICalComponent *icomp;
        gchar *uid = NULL;
        GError *error = NULL;
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Initial" EVENT_SUMMARY);
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Initial" EVENT_SUMMARY);
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_object_set_data_full (G_OBJECT (cal_client), "use-uid", uid, g_free);
 }
 
 static void
-test_result (icalcomponent *icalcomp)
+test_result (ICalComponent *icomp)
 {
-       g_assert (icalcomp != NULL);
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), ==, EVENT_SUMMARY);
+       g_assert_nonnull (icomp);
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), ==, EVENT_SUMMARY);
 }
 
 static void
@@ -61,7 +66,7 @@ test_modify_object_sync (ETestServerFixture *fixture,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       icalcomponent *icalcomp = NULL;
+       ICalComponent *icomp = NULL;
        const gchar *uid;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
@@ -70,21 +75,21 @@ test_modify_object_sync (ETestServerFixture *fixture,
        uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
        g_assert (uid != NULL);
 
-       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error))
+       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icomp, NULL, &error))
                g_error ("get object sync: %s", error->message);
 
-       icalcomponent_set_summary (icalcomp, EVENT_SUMMARY);
+       i_cal_component_set_summary (icomp, EVENT_SUMMARY);
 
-       if (!e_cal_client_modify_object_sync (cal_client, icalcomp, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_modify_object_sync (cal_client, icomp, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("modify object sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
 
-       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error))
+       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icomp, NULL, &error))
                g_error ("get object sync after modification: %s", error->message);
 
-       test_result (icalcomp);
-       icalcomponent_free (icalcomp);
+       test_result (icomp);
+       g_object_unref (icomp);
 }
 
 static void
@@ -94,7 +99,7 @@ async_modify_result_ready (GObject *source_object,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       icalcomponent *icalcomp = NULL;
+       ICalComponent *icomp = NULL;
        const gchar *uid;
        GMainLoop *loop = (GMainLoop *) user_data;
 
@@ -104,11 +109,11 @@ async_modify_result_ready (GObject *source_object,
        if (!e_cal_client_modify_object_finish (cal_client, result, &error))
                g_error ("modify object finish: %s", error->message);
 
-       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error))
+       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icomp, NULL, &error))
                g_error ("get object sync after async modification: %s", error->message);
 
-       test_result (icalcomp);
-       icalcomponent_free (icalcomp);
+       test_result (icomp);
+       g_object_unref (icomp);
 
        g_main_loop_quit (loop);
 }
@@ -119,7 +124,7 @@ test_modify_object_async (ETestServerFixture *fixture,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       icalcomponent *icalcomp = NULL;
+       ICalComponent *icomp = NULL;
        const gchar *uid;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
@@ -128,13 +133,13 @@ test_modify_object_async (ETestServerFixture *fixture,
        uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
        g_assert (uid != NULL);
 
-       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error))
+       if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icomp, NULL, &error))
                g_error ("get object sync: %s", error->message);
 
-       icalcomponent_set_summary (icalcomp, EVENT_SUMMARY);
+       i_cal_component_set_summary (icomp, EVENT_SUMMARY);
 
-       e_cal_client_modify_object (cal_client, icalcomp, E_CAL_OBJ_MOD_ALL, NULL, async_modify_result_ready, 
fixture->loop);
-       icalcomponent_free (icalcomp);
+       e_cal_client_modify_object (cal_client, icomp, E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE, NULL, 
async_modify_result_ready, fixture->loop);
+       g_object_unref (icomp);
 
        g_main_loop_run (fixture->loop);
 }
diff --git a/tests/libecal/client/test-cal-client-receive-objects.c 
b/tests/libecal/test-cal-client-receive-objects.c
similarity index 73%
rename from tests/libecal/client/test-cal-client-receive-objects.c
rename to tests/libecal/test-cal-client-receive-objects.c
index edc59257b..44b4192d8 100644
--- a/tests/libecal/client/test-cal-client-receive-objects.c
+++ b/tests/libecal/test-cal-client-receive-objects.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -25,19 +24,25 @@ static ETestServerClosure cal_closure_sync =
 static ETestServerClosure cal_closure_async =
        { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, FALSE, NULL, TRUE };
 
-static icalcomponent *
+static ICalComponent *
 create_object (void)
 {
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalTime *dtstart, *dtend;
+       ICalComponent *icomp;
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "To-be-received event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       return icalcomp;
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "To-be-received event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       return icomp;
 }
 
 static void
@@ -46,17 +51,17 @@ test_receive_objects_sync (ETestServerFixture *fixture,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
-       icalcomp = create_object ();
-       g_assert (icalcomp != NULL);
+       icomp = create_object ();
+       g_assert_nonnull (icomp);
 
-       if (!e_cal_client_receive_objects_sync (cal_client, icalcomp, NULL, &error))
+       if (!e_cal_client_receive_objects_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("receive objects sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
 }
 
 static void
@@ -81,15 +86,15 @@ test_receive_objects_async (ETestServerFixture *fixture,
                             gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
-       icalcomp = create_object ();
-       g_assert (icalcomp != NULL);
+       icomp = create_object ();
+       g_assert_nonnull (icomp);
 
-       e_cal_client_receive_objects (cal_client, icalcomp, NULL, async_receive_result_ready, fixture->loop);
-       icalcomponent_free (icalcomp);
+       e_cal_client_receive_objects (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, NULL, 
async_receive_result_ready, fixture->loop);
+       g_object_unref (icomp);
 
        g_main_loop_run (fixture->loop);
 }
diff --git a/tests/libecal/client/test-cal-client-refresh.c b/tests/libecal/test-cal-client-refresh.c
similarity index 83%
rename from tests/libecal/client/test-cal-client-refresh.c
rename to tests/libecal/test-cal-client-refresh.c
index 4eaf84130..fd53ec590 100644
--- a/tests/libecal/client/test-cal-client-refresh.c
+++ b/tests/libecal/test-cal-client-refresh.c
@@ -17,7 +17,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -30,20 +29,26 @@ static void
 setup_cal (ECalClient *cal_client)
 {
        GError *error = NULL;
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
        gchar *uid = NULL;
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Test event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Test event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_free (uid);
 }
 
@@ -127,4 +132,3 @@ main (gint argc,
 
        return e_test_server_utils_run ();
 }
-
diff --git a/tests/libecal/client/test-cal-client-remove-object.c 
b/tests/libecal/test-cal-client-remove-object.c
similarity index 80%
rename from tests/libecal/client/test-cal-client-remove-object.c
rename to tests/libecal/test-cal-client-remove-object.c
index be5dcbef4..a9cd44ca9 100644
--- a/tests/libecal/client/test-cal-client-remove-object.c
+++ b/tests/libecal/test-cal-client-remove-object.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -28,23 +27,29 @@ static ETestServerClosure cal_closure_async =
 static gchar *
 create_object (ECalClient *cal_client)
 {
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
        gchar *uid = NULL;
        GError *error = NULL;
 
        g_return_val_if_fail (cal_client != NULL, NULL);
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "To-be-removed event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "To-be-removed event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
+
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
+
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
 
        return uid;
 }
@@ -62,7 +67,7 @@ test_remove_object_sync (ETestServerFixture *fixture,
        uid = create_object (cal_client);
        g_assert (uid != NULL);
 
-       if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("remove object sync: %s", error->message);
 
        g_free (uid);
@@ -97,7 +102,7 @@ test_remove_object_async (ETestServerFixture *fixture,
        uid = create_object (cal_client);
        g_assert (uid != NULL);
 
-       e_cal_client_remove_object (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, NULL, 
async_remove_result_ready, fixture->loop);
+       e_cal_client_remove_object (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE, 
NULL, async_remove_result_ready, fixture->loop);
        g_free (uid);
        g_main_loop_run (fixture->loop);
 }
@@ -114,10 +119,11 @@ test_remove_object_empty_uid (ETestServerFixture *fixture,
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
        e_cal_client_remove_object_sync (
-               cal_client, "", NULL, E_CAL_OBJ_MOD_ALL, NULL, &error);
+               cal_client, "", NULL, E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE, NULL, &error);
        g_assert_error (
                error, E_CAL_CLIENT_ERROR,
                E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
+       g_clear_error (&error);
 }
 
 gint
diff --git a/tests/libecal/client/test-cal-client-revision-view.c 
b/tests/libecal/test-cal-client-revision-view.c
similarity index 72%
rename from tests/libecal/client/test-cal-client-revision-view.c
rename to tests/libecal/test-cal-client-revision-view.c
index fdb386ca7..9eb063124 100644
--- a/tests/libecal/client/test-cal-client-revision-view.c
+++ b/tests/libecal/test-cal-client-revision-view.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -51,19 +50,28 @@ subtest_passed (SubTestId id,
                g_main_loop_quit (loop);
 }
 
-static struct icaltimetype
-get_last_modified (icalcomponent *component)
+static ICalTime *
+get_last_modified (ICalComponent *component)
 {
-       icalcomponent *inner = icalcomponent_get_inner (component);
-       icalproperty  *prop;
+       ICalComponent *inner = i_cal_component_get_inner (component);
+       ICalProperty *prop;
+       ICalTime *res;
 
-       prop = icalcomponent_get_first_property (inner, ICAL_LASTMODIFIED_PROPERTY);
+       if (!inner)
+               return i_cal_time_null_time ();
 
-       if (prop == 0) {
-               return icaltime_null_time ();
+       prop = i_cal_component_get_first_property (inner, I_CAL_LASTMODIFIED_PROPERTY);
+
+       if (prop) {
+               res = i_cal_property_get_lastmodified (prop);
+               g_object_unref (prop);
+       } else {
+               res = i_cal_time_null_time ();
        }
 
-       return icalproperty_get_lastmodified (prop);
+       g_clear_object (&inner);
+
+       return res;
 }
 
 static void
@@ -75,17 +83,26 @@ objects_added_cb (GObject *object,
        GMainLoop *loop = (GMainLoop *) data;
 
        for (l = objects; l; l = l->next) {
-               icalcomponent      *component = l->data;
-               struct icaltimetype recurrence = icalcomponent_get_recurrenceid (component);
-               struct icaltimetype last_modified = get_last_modified (component);
+               ICalComponent *component = l->data;
+               ICalTime *recurrence = i_cal_component_get_recurrenceid (component);
+               ICalTime *last_modified = get_last_modified (component);
+               gchar *str_recurrence, *str_last_modified;
+
+               str_recurrence = i_cal_time_as_ical_string_r (recurrence);
+               str_last_modified = i_cal_time_as_ical_string_r (last_modified);
 
                g_print (
                        "Object added %s (recurrence id:%s, last-modified:%s)\n",
-                       icalcomponent_get_uid (component),
-                       icaltime_as_ical_string (recurrence),
-                       icaltime_as_ical_string (last_modified));
+                       i_cal_component_get_uid (component),
+                       str_recurrence,
+                       str_last_modified);
+
+               g_clear_object (&recurrence);
+               g_clear_object (&last_modified);
+               g_free (str_recurrence);
+               g_free (str_last_modified);
 
-               g_assert (icalcomponent_get_summary (component) == NULL);
+               g_assert (i_cal_component_get_summary (component) == NULL);
        }
 
        subtest_passed (SUBTEST_OBJECTS_ADDED, loop);
@@ -100,17 +117,26 @@ objects_modified_cb (GObject *object,
        GMainLoop *loop = (GMainLoop *) data;
 
        for (l = objects; l; l = l->next) {
-               icalcomponent      *component = l->data;
-               struct icaltimetype recurrence = icalcomponent_get_recurrenceid (component);
-               struct icaltimetype last_modified = get_last_modified (component);
+               ICalComponent *component = l->data;
+               ICalTime *recurrence = i_cal_component_get_recurrenceid (component);
+               ICalTime *last_modified = get_last_modified (component);
+               gchar *str_recurrence, *str_last_modified;
+
+               str_recurrence = i_cal_time_as_ical_string_r (recurrence);
+               str_last_modified = i_cal_time_as_ical_string_r (last_modified);
 
                g_print (
                        "Object modified %s (recurrence id:%s, last-modified:%s)\n",
-                       icalcomponent_get_uid (component),
-                       icaltime_as_ical_string (recurrence),
-                       icaltime_as_ical_string (last_modified));
+                       i_cal_component_get_uid (component),
+                       str_recurrence,
+                       str_last_modified);
+
+               g_clear_object (&recurrence);
+               g_clear_object (&last_modified);
+               g_free (str_recurrence);
+               g_free (str_last_modified);
 
-               g_assert (icalcomponent_get_summary (component) == NULL);
+               g_assert (i_cal_component_get_summary (component) == NULL);
        }
 
        subtest_passed (SUBTEST_OBJECTS_MODIFIED, loop);
@@ -127,7 +153,7 @@ objects_removed_cb (GObject *object,
        for (l = objects; l; l = l->next) {
                ECalComponentId *id = l->data;
 
-               g_print ("Object removed: uid: %s, rid: %s\n", id->uid, id->rid);
+               g_print ("Object removed: uid: %s, rid: %s\n", e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id));
        }
 
        subtest_passed (SUBTEST_OBJECTS_REMOVED, loop);
@@ -150,32 +176,36 @@ alter_cal_client (gpointer user_data)
 {
        ECalClient *cal_client = user_data;
        GError *error = NULL;
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *now, *itt;
        gchar *uid = NULL;
 
        g_return_val_if_fail (cal_client != NULL, NULL);
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "Initial event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       now = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (now) + 60 * 60 * 60, 0, NULL);
+
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "Initial event summary");
+       i_cal_component_set_dtstart (icomp, now);
+       i_cal_component_set_dtend   (icomp, itt);
 
-       if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error))
+       if (!e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("create object sync: %s", error->message);
 
-       icalcomponent_set_uid (icalcomp, uid);
-       icalcomponent_set_summary (icalcomp, "Modified event summary");
+       i_cal_component_set_uid (icomp, uid);
+       i_cal_component_set_summary (icomp, "Modified event summary");
 
-       if (!e_cal_client_modify_object_sync (cal_client, icalcomp, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_modify_object_sync (cal_client, icomp, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("modify object sync: %s", error->message);
 
-       if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, NULL, &error))
+       if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, E_CAL_OBJ_MOD_ALL, 
E_CAL_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("remove object sync: %s", error->message);
 
+       g_object_unref (icomp);
+       g_object_unref (now);
+       g_object_unref (itt);
        g_free (uid);
-       icalcomponent_free (icalcomp);
 
        return FALSE;
 }
diff --git a/tests/libecal/client/test-cal-client-send-objects.c 
b/tests/libecal/test-cal-client-send-objects.c
similarity index 62%
rename from tests/libecal/client/test-cal-client-send-objects.c
rename to tests/libecal/test-cal-client-send-objects.c
index 609f24037..34232e29f 100644
--- a/tests/libecal/client/test-cal-client-send-objects.c
+++ b/tests/libecal/test-cal-client-send-objects.c
@@ -16,7 +16,6 @@
 
 #include <stdlib.h>
 #include <libecal/libecal.h>
-#include <libical/ical.h>
 
 #include "e-test-server-utils.h"
 
@@ -28,60 +27,60 @@ static ETestServerClosure cal_closure_async =
 static void
 print_ecomp (ECalComponent *ecalcomp)
 {
-       const gchar *uid = NULL;
-       ECalComponentText summary = { 0 };
+       const gchar *uid;
+       ECalComponentText *summary;
 
        g_return_if_fail (ecalcomp != NULL);
 
-       e_cal_component_get_uid (ecalcomp, &uid);
-       e_cal_component_get_summary (ecalcomp, &summary);
+       uid = e_cal_component_get_uid (ecalcomp);
+       summary = e_cal_component_get_summary (ecalcomp);
 
        g_print ("   Component: %s\n", uid ? uid : "no-uid");
-       g_print ("   Summary: %s\n", summary.value ? summary.value : "NULL");
+       g_print ("   Summary: %s\n", summary && e_cal_component_text_get_value (summary) ? 
e_cal_component_text_get_value (summary) : "NULL");
        g_print ("\n");
+
+       e_cal_component_text_free (summary);
 }
 
 static void
-print_icomp (icalcomponent *icalcomp)
+print_icomp (ICalComponent *icomp)
 {
        ECalComponent *ecomp;
 
-       g_return_if_fail (icalcomp != NULL);
-
-       ecomp = e_cal_component_new ();
-       icalcomp = icalcomponent_new_clone (icalcomp);
+       g_assert_nonnull (icomp);
 
-       if (!e_cal_component_set_icalcomponent (ecomp, icalcomp)) {
-               icalcomponent_free (icalcomp);
-               g_object_unref (ecomp);
-               g_printerr ("%s: Failed to assing icalcomp to ECalComponent\n", G_STRFUNC);
-               g_print ("\n");
-               return;
-       }
+       ecomp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icomp));
+       g_assert_nonnull (ecomp);
 
        print_ecomp (ecomp);
 
        g_object_unref (ecomp);
 }
 
-static icalcomponent *
+static ICalComponent *
 create_object (void)
 {
-       icalcomponent *icalcomp;
-       struct icaltimetype now;
+       ICalComponent *icomp;
+       ICalTime *dtstart, *dtend;
+
+       dtstart = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
+       dtend = i_cal_time_new_clone (dtstart);
+       i_cal_time_adjust (dtend, 0, 1, 0, 0);
+
+       icomp = i_cal_component_new (I_CAL_VEVENT_COMPONENT);
+       i_cal_component_set_summary (icomp, "To-be-sent event summary");
+       i_cal_component_set_dtstart (icomp, dtstart);
+       i_cal_component_set_dtend (icomp, dtend);
 
-       now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-       icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
-       icalcomponent_set_summary (icalcomp, "To-be-sent event summary");
-       icalcomponent_set_dtstart (icalcomp, now);
-       icalcomponent_set_dtend   (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 
* 60, 0, NULL));
+       g_clear_object (&dtstart);
+       g_clear_object (&dtend);
 
-       return icalcomp;
+       return icomp;
 }
 
 static void
 manage_result (GSList *users,
-               icalcomponent *modified_icalcomp)
+              ICalComponent *modified_icomp)
 {
        g_print ("Wishes to send to %d users", g_slist_length (users));
        if (users) {
@@ -94,14 +93,13 @@ manage_result (GSList *users,
        }
        g_print ("\n");
 
-       if (!modified_icalcomp)
-               g_print ("No modified icalcomp, would send the same\n");
+       if (!modified_icomp)
+               g_print ("No modified iCalendar component, would send the same\n");
        else
-               print_icomp (modified_icalcomp);
+               print_icomp (modified_icomp);
 
        e_client_util_free_string_slist (users);
-       if (modified_icalcomp)
-               icalcomponent_free (modified_icalcomp);
+       g_clear_object (&modified_icomp);
 }
 
 static void
@@ -110,17 +108,17 @@ test_send_objects_sync (ETestServerFixture *fixture,
 {
        ECalClient *cal_client;
        GError *error = NULL;
-       icalcomponent *icalcomp, *modified_icalcomp = NULL;
+       ICalComponent *icomp, *modified_icomp = NULL;
        GSList *users = NULL;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
-       icalcomp = create_object ();
-       if (!e_cal_client_send_objects_sync (cal_client, icalcomp, &users, &modified_icalcomp, NULL, &error))
+       icomp = create_object ();
+       if (!e_cal_client_send_objects_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &users, 
&modified_icomp, NULL, &error))
                g_error ("send objects sync: %s", error->message);
 
-       icalcomponent_free (icalcomp);
-       manage_result (users, modified_icalcomp);
+       g_object_unref (icomp);
+       manage_result (users, modified_icomp);
 }
 
 static void
@@ -131,15 +129,15 @@ async_send_result_ready (GObject *source_object,
        ECalClient *cal_client;
        GError *error = NULL;
        GSList *users = NULL;
-       icalcomponent *modified_icalcomp = NULL;
+       ICalComponent *modified_icomp = NULL;
        GMainLoop *loop = (GMainLoop *) user_data;
 
        cal_client = E_CAL_CLIENT (source_object);
 
-       if (!e_cal_client_send_objects_finish (cal_client, result, &users, &modified_icalcomp, &error))
+       if (!e_cal_client_send_objects_finish (cal_client, result, &users, &modified_icomp, &error))
                g_error ("send objects finish: %s", error->message);
 
-       manage_result (users, modified_icalcomp);
+       manage_result (users, modified_icomp);
        g_main_loop_quit (loop);
 }
 
@@ -148,15 +146,15 @@ test_send_objects_async (ETestServerFixture *fixture,
                         gconstpointer user_data)
 {
        ECalClient *cal_client;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
 
-       icalcomp = create_object ();
-       g_assert (icalcomp);
+       icomp = create_object ();
+       g_assert_nonnull (icomp);
 
-       e_cal_client_send_objects (cal_client, icalcomp, NULL, async_send_result_ready, fixture->loop);
-       icalcomponent_free (icalcomp);
+       e_cal_client_send_objects (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, NULL, 
async_send_result_ready, fixture->loop);
+       g_object_unref (icomp);
 
        g_main_loop_run (fixture->loop);
 }
diff --git a/tests/libecal/test-cal-component.c b/tests/libecal/test-cal-component.c
new file mode 100644
index 000000000..6f58f83c5
--- /dev/null
+++ b/tests/libecal/test-cal-component.c
@@ -0,0 +1,4022 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib.h>
+#include <libecal/libecal.h>
+
+static void
+verify_ical_attach_equal (ICalAttach *expected,
+                         ICalAttach *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+       g_assert_cmpint (i_cal_attach_get_is_url (expected) ? 1 : 0, ==, i_cal_attach_get_is_url (received) ? 
1 : 0);
+
+       if (i_cal_attach_get_is_url (expected)) {
+               g_assert_cmpstr (i_cal_attach_get_url (expected), ==, i_cal_attach_get_url (received));
+       } else {
+               const gchar *data_expected, *data_received;
+
+               data_expected = i_cal_attach_get_data (expected);
+               data_received = i_cal_attach_get_data (received);
+
+               g_assert_nonnull (data_expected);
+               g_assert_nonnull (data_received);
+               g_assert_cmpmem (data_expected, strlen (data_expected), data_received, strlen 
(data_received));
+       }
+}
+
+static void
+verify_ical_attach_list_equal (GSList *expected, /* ICalAttach * */
+                              GSList *received) /* ICalAttach * */
+{
+       GSList *link1, *link2;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 = 
g_slist_next (link2)) {
+               verify_ical_attach_equal (link1->data, link2->data);
+       }
+
+       g_assert (link1 == link2);
+}
+
+static void
+verify_ical_durationtype_equal (ICalDuration *expected,
+                               ICalDuration *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (i_cal_duration_as_int (expected), ==, i_cal_duration_as_int (received));
+}
+
+static void
+verify_ical_timetype_equal (ICalTime *expected,
+                           ICalTime *received)
+{
+       ICalTimezone *zone_expected, *zone_received;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (i_cal_time_get_year (expected), ==, i_cal_time_get_year (received));
+       g_assert_cmpint (i_cal_time_get_month (expected), ==, i_cal_time_get_month (received));
+       g_assert_cmpint (i_cal_time_get_day (expected), ==, i_cal_time_get_day (received));
+       g_assert_cmpint (i_cal_time_get_hour (expected), ==, i_cal_time_get_hour (received));
+       g_assert_cmpint (i_cal_time_get_minute (expected), ==, i_cal_time_get_minute (received));
+       g_assert_cmpint (i_cal_time_get_second (expected), ==, i_cal_time_get_second (received));
+       g_assert_cmpint (i_cal_time_is_date (expected) ? 1 : 0, ==, i_cal_time_is_date (received) ? 1 : 0);
+       g_assert_cmpint (i_cal_time_is_daylight (expected) ? 1 : 0, ==, i_cal_time_is_daylight (received) ? 1 
: 0);
+
+       zone_expected = i_cal_time_get_timezone (expected);
+       zone_received = i_cal_time_get_timezone (received);
+
+       if (!zone_expected) {
+               g_assert_null (zone_received);
+       } else if (zone_received) {
+               g_assert_cmpstr (i_cal_timezone_get_location (zone_expected), ==, i_cal_timezone_get_location 
(zone_received));
+       }
+}
+
+static void
+verify_struct_parameter_bag_equal (const ECalComponentParameterBag *expected,
+                                  const ECalComponentParameterBag *received)
+{
+       gint ii, count;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (expected), ==, 
e_cal_component_parameter_bag_get_count (received));
+
+       count = e_cal_component_parameter_bag_get_count (expected);
+       for (ii = 0; ii < count; ii++) {
+               ICalParameter *param_expected, *param_received;
+               gchar *value_expected, *value_received;
+
+               param_expected = e_cal_component_parameter_bag_get (expected, ii);
+               param_received = e_cal_component_parameter_bag_get (received, ii);
+
+               g_assert_nonnull (param_expected);
+               g_assert_nonnull (param_received);
+               g_assert_cmpint (i_cal_parameter_isa (param_expected), ==, i_cal_parameter_isa 
(param_received));
+
+               value_expected = i_cal_parameter_as_ical_string_r (param_expected);
+               value_received = i_cal_parameter_as_ical_string_r (param_received);
+
+               g_assert_cmpstr (value_expected, ==, value_received);
+
+               g_free (value_expected);
+               g_free (value_received);
+       }
+}
+
+static void
+verify_struct_property_bag_equal (const ECalComponentPropertyBag *expected,
+                                 const ECalComponentPropertyBag *received)
+{
+       gint ii, count;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_property_bag_get_count (expected), ==, 
e_cal_component_property_bag_get_count (received));
+
+       count = e_cal_component_property_bag_get_count (expected);
+       for (ii = 0; ii < count; ii++) {
+               ICalProperty *prop_expected, *prop_received;
+               gchar *value_expected, *value_received;
+
+               prop_expected = e_cal_component_property_bag_get (expected, ii);
+               prop_received = e_cal_component_property_bag_get (received, ii);
+
+               g_assert_nonnull (prop_expected);
+               g_assert_nonnull (prop_received);
+               g_assert_cmpint (i_cal_property_isa (prop_expected), ==, i_cal_property_isa (prop_received));
+
+               value_expected = i_cal_property_as_ical_string_r (prop_expected);
+               value_received = i_cal_property_as_ical_string_r (prop_received);
+
+               g_assert_cmpstr (value_expected, ==, value_received);
+
+               g_free (value_expected);
+               g_free (value_received);
+       }
+}
+
+static void
+verify_struct_attendee_equal (const ECalComponentAttendee *expected,
+                             const ECalComponentAttendee *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_attendee_get_value (expected), ==, 
e_cal_component_attendee_get_value (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_member (expected), ==, 
e_cal_component_attendee_get_member (received));
+       g_assert_cmpint (e_cal_component_attendee_get_cutype (expected), ==, 
e_cal_component_attendee_get_cutype (received));
+       g_assert_cmpint (e_cal_component_attendee_get_role (expected), ==, e_cal_component_attendee_get_role 
(received));
+       g_assert_cmpint (e_cal_component_attendee_get_partstat (expected), ==, 
e_cal_component_attendee_get_partstat (received));
+       g_assert_cmpint (e_cal_component_attendee_get_rsvp (expected) ? 1 : 0, ==, 
e_cal_component_attendee_get_rsvp (received) ? 1 : 0);
+       g_assert_cmpstr (e_cal_component_attendee_get_delegatedfrom (expected), ==, 
e_cal_component_attendee_get_delegatedfrom (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_delegatedto (expected), ==, 
e_cal_component_attendee_get_delegatedto (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_sentby (expected), ==, 
e_cal_component_attendee_get_sentby (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_cn (expected), ==, e_cal_component_attendee_get_cn 
(received));
+       g_assert_cmpstr (e_cal_component_attendee_get_language (expected), ==, 
e_cal_component_attendee_get_language (received));
+
+       verify_struct_parameter_bag_equal (e_cal_component_attendee_get_parameter_bag (expected),
+                                          e_cal_component_attendee_get_parameter_bag (received));
+}
+
+static void
+verify_struct_attendee_list_equal (GSList *expected, /* ECalComponentAttendee * */
+                                  GSList *received) /* ECalComponentAttendee * */
+{
+       GSList *link1, *link2;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 = 
g_slist_next (link2)) {
+               verify_struct_attendee_equal (link1->data, link2->data);
+       }
+
+       g_assert (link1 == link2);
+}
+
+static void
+verify_struct_datetime_equal (const ECalComponentDateTime *expected,
+                             const ECalComponentDateTime *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       verify_ical_timetype_equal (e_cal_component_datetime_get_value (expected),
+                                   e_cal_component_datetime_get_value (received));
+
+       g_assert_cmpstr (e_cal_component_datetime_get_tzid (expected), ==, e_cal_component_datetime_get_tzid 
(received));
+}
+
+static void
+verify_struct_id_equal (const ECalComponentId *expected,
+                       const ECalComponentId *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_id_get_uid (expected), ==, e_cal_component_id_get_uid (received));
+       g_assert_cmpstr (e_cal_component_id_get_rid (expected), ==, e_cal_component_id_get_rid (received));
+       g_assert_cmpint (e_cal_component_id_hash (expected), ==, e_cal_component_id_hash (received));
+       g_assert (e_cal_component_id_equal (expected, received));
+}
+
+static void
+verify_struct_organizer_equal (const ECalComponentOrganizer *expected,
+                              const ECalComponentOrganizer *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_organizer_get_value (expected), ==, 
e_cal_component_organizer_get_value (received));
+       g_assert_cmpstr (e_cal_component_organizer_get_sentby (expected), ==, 
e_cal_component_organizer_get_sentby (received));
+       g_assert_cmpstr (e_cal_component_organizer_get_cn (expected), ==, e_cal_component_organizer_get_cn 
(received));
+       g_assert_cmpstr (e_cal_component_organizer_get_language (expected), ==, 
e_cal_component_organizer_get_language (received));
+
+       verify_struct_parameter_bag_equal (e_cal_component_organizer_get_parameter_bag (expected),
+                                          e_cal_component_organizer_get_parameter_bag (received));
+}
+
+static void
+verify_struct_period_equal (const ECalComponentPeriod *expected,
+                           const ECalComponentPeriod *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_period_get_kind (expected), ==, e_cal_component_period_get_kind 
(received));
+
+       verify_ical_timetype_equal (e_cal_component_period_get_start (expected),
+                                   e_cal_component_period_get_start (received));
+
+       switch (e_cal_component_period_get_kind (expected)) {
+       case E_CAL_COMPONENT_PERIOD_DATETIME:
+               verify_ical_timetype_equal (e_cal_component_period_get_end (expected),
+                                           e_cal_component_period_get_end (received));
+               break;
+       case E_CAL_COMPONENT_PERIOD_DURATION:
+               verify_ical_durationtype_equal (e_cal_component_period_get_duration (expected),
+                                               e_cal_component_period_get_duration (received));
+               break;
+       }
+}
+
+static void
+verify_struct_range_equal (const ECalComponentRange *expected,
+                          const ECalComponentRange *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_range_get_kind (expected), ==, e_cal_component_range_get_kind 
(received));
+
+       verify_struct_datetime_equal (e_cal_component_range_get_datetime (expected),
+                                     e_cal_component_range_get_datetime (received));
+}
+
+static void
+verify_struct_text_equal (const ECalComponentText *expected,
+                         const ECalComponentText *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_text_get_value (expected), ==, e_cal_component_text_get_value 
(received));
+       g_assert_cmpstr (e_cal_component_text_get_altrep (expected), ==, e_cal_component_text_get_altrep 
(received));
+}
+
+static void
+verify_struct_alarm_repeat_equal (const ECalComponentAlarmRepeat *expected,
+                                 const ECalComponentAlarmRepeat *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_repetitions (expected), ==, 
e_cal_component_alarm_repeat_get_repetitions (received));
+       verify_ical_durationtype_equal (e_cal_component_alarm_repeat_get_interval (expected),
+                                       e_cal_component_alarm_repeat_get_interval (received));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==, 
e_cal_component_alarm_repeat_get_interval_seconds (received));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==,
+                        i_cal_duration_as_int (e_cal_component_alarm_repeat_get_interval (expected)));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (received), ==,
+                        i_cal_duration_as_int (e_cal_component_alarm_repeat_get_interval (received)));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==,
+                        i_cal_duration_as_int (e_cal_component_alarm_repeat_get_interval (received)));
+}
+
+static void
+verify_struct_alarm_trigger_equal (const ECalComponentAlarmTrigger *expected,
+                                  const ECalComponentAlarmTrigger *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_alarm_trigger_get_kind (expected), ==, 
e_cal_component_alarm_trigger_get_kind (received));
+
+       switch (e_cal_component_alarm_trigger_get_kind (expected)) {
+       case E_CAL_COMPONENT_ALARM_TRIGGER_NONE:
+               break;
+       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
+       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
+               verify_ical_durationtype_equal (e_cal_component_alarm_trigger_get_duration (expected),
+                                               e_cal_component_alarm_trigger_get_duration (received));
+               break;
+       case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
+               verify_ical_timetype_equal (e_cal_component_alarm_trigger_get_absolute_time (expected),
+                                           e_cal_component_alarm_trigger_get_absolute_time (received));
+               break;
+       }
+
+       verify_struct_parameter_bag_equal (e_cal_component_alarm_trigger_get_parameter_bag (expected),
+                                          e_cal_component_alarm_trigger_get_parameter_bag (received));
+}
+
+static void
+verify_struct_alarm_equal (const ECalComponentAlarm *expected,
+                          const ECalComponentAlarm *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_alarm_get_uid (expected), ==, e_cal_component_alarm_get_uid 
(received));
+       g_assert_cmpint (e_cal_component_alarm_get_action (expected), ==, e_cal_component_alarm_get_action 
(received));
+
+       verify_struct_text_equal (e_cal_component_alarm_get_summary (expected),
+                                 e_cal_component_alarm_get_summary (received));
+
+       verify_struct_text_equal (e_cal_component_alarm_get_description (expected),
+                                 e_cal_component_alarm_get_description (received));
+
+       verify_struct_alarm_repeat_equal (e_cal_component_alarm_get_repeat (expected),
+                                         e_cal_component_alarm_get_repeat (received));
+
+       verify_struct_alarm_trigger_equal (e_cal_component_alarm_get_trigger (expected),
+                                          e_cal_component_alarm_get_trigger (received));
+
+       g_assert_cmpint (e_cal_component_alarm_has_attendees (expected) ? 1 : 0, ==, 
e_cal_component_alarm_has_attendees (received) ? 1 : 0);
+
+       verify_struct_attendee_list_equal (e_cal_component_alarm_get_attendees (expected),
+                                          e_cal_component_alarm_get_attendees (received));
+
+       g_assert_cmpint (e_cal_component_alarm_has_attachments (expected) ? 1 : 0, ==, 
e_cal_component_alarm_has_attachments (received) ? 1 : 0);
+
+       verify_ical_attach_list_equal (e_cal_component_alarm_get_attachments (expected),
+                                      e_cal_component_alarm_get_attachments (received));
+
+       verify_struct_property_bag_equal (e_cal_component_alarm_get_property_bag (expected),
+                                         e_cal_component_alarm_get_property_bag (received));
+}
+
+static void
+verify_struct_alarm_instance_equal (const ECalComponentAlarmInstance *expected,
+                                   const ECalComponentAlarmInstance *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_alarm_instance_get_uid (expected), ==, 
e_cal_component_alarm_instance_get_uid (received));
+       g_assert_cmpint (e_cal_component_alarm_instance_get_time (expected), ==, 
e_cal_component_alarm_instance_get_time (received));
+       g_assert_cmpint (e_cal_component_alarm_instance_get_occur_start (expected), ==, 
e_cal_component_alarm_instance_get_occur_start (received));
+       g_assert_cmpint (e_cal_component_alarm_instance_get_occur_end (expected), ==, 
e_cal_component_alarm_instance_get_occur_end (received));
+}
+
+static void
+verify_struct_alarms_equal (const ECalComponentAlarms *expected,
+                           const ECalComponentAlarms *received)
+{
+       GSList *inst_expected, *inst_received, *link1, *link2;
+       const gchar *uid_expected, *uid_received;
+       gchar *rid_expected, *rid_received;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       uid_expected = e_cal_component_get_uid (e_cal_component_alarms_get_component (expected));
+       uid_received = e_cal_component_get_uid (e_cal_component_alarms_get_component (received));
+       g_assert_cmpstr (uid_expected, ==, uid_received);
+
+       rid_expected = e_cal_component_get_recurid_as_string (e_cal_component_alarms_get_component 
(expected));
+       rid_received = e_cal_component_get_recurid_as_string (e_cal_component_alarms_get_component 
(received));
+       g_assert_cmpstr (rid_expected, ==, rid_received);
+       g_free (rid_expected);
+       g_free (rid_received);
+
+       inst_expected = e_cal_component_alarms_get_instances (expected);
+       inst_received = e_cal_component_alarms_get_instances (received);
+
+       g_assert_cmpint (g_slist_length (inst_expected), ==, g_slist_length (inst_received));
+
+       for (link1 = inst_expected, link2 = inst_received; link1 && link2; link1 = g_slist_next (link1), 
link2 = g_slist_next (link2)) {
+               verify_struct_alarm_instance_equal (link1->data, link2->data);
+       }
+
+       g_assert (link1 == link2);
+}
+
+static void
+test_component_struct_alarm (void)
+{
+       struct _values {
+               const gchar *uid;
+               ECalComponentAlarmAction action;
+               const gchar *summary;
+               const gchar *description;
+               gboolean with_repeat;
+               gboolean with_trigger;
+               gboolean with_attendees;
+               gboolean with_attachments;
+               gboolean with_properties;
+       } values[] = {
+               { "1", E_CAL_COMPONENT_ALARM_AUDIO, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE },
+               { "2", E_CAL_COMPONENT_ALARM_DISPLAY, NULL, "display text", FALSE, FALSE, FALSE, FALSE, FALSE 
},
+               { "3", E_CAL_COMPONENT_ALARM_EMAIL, "summary text", NULL, TRUE, FALSE, FALSE, FALSE, FALSE },
+               { "4", E_CAL_COMPONENT_ALARM_PROCEDURE, NULL, "procedure", FALSE, TRUE, FALSE, FALSE, TRUE },
+               { "5", E_CAL_COMPONENT_ALARM_AUDIO, NULL, NULL, FALSE, FALSE, TRUE, FALSE, TRUE },
+               { "6", E_CAL_COMPONENT_ALARM_DISPLAY, NULL, "display text", FALSE, FALSE, FALSE, TRUE, TRUE },
+               { "7", E_CAL_COMPONENT_ALARM_EMAIL, "summary", "description", TRUE, FALSE, TRUE, FALSE, TRUE 
},
+               { "8", E_CAL_COMPONENT_ALARM_PROCEDURE, NULL, "procedure", TRUE, TRUE, TRUE, TRUE, TRUE }
+       };
+       gint ii, nth_summary = 0, nth_description = 0, nth_repeat = 0, nth_trigger = 0, nth_attendees = 0, 
nth_attachments = 0, nth_properties = 0;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentAlarm *expected, *received;
+               ICalComponent *icalcomp;
+
+               expected = e_cal_component_alarm_new ();
+               e_cal_component_alarm_set_uid (expected, values[ii].uid);
+               e_cal_component_alarm_set_action (expected, values[ii].action);
+
+               if (values[ii].summary) {
+                       nth_summary++;
+
+                       if ((nth_summary & 1) != 0) {
+                               ECalComponentText *txt;
+
+                               txt = e_cal_component_text_new (values[ii].summary, "alt-representation");
+                               e_cal_component_alarm_set_summary (expected, txt);
+                               e_cal_component_text_free (txt);
+                       } else {
+                               e_cal_component_alarm_take_summary (expected, e_cal_component_text_new 
(values[ii].summary, NULL));
+                       }
+               }
+
+               if (values[ii].description) {
+                       nth_description++;
+
+                       if ((nth_description & 1) != 0) {
+                               ECalComponentText *txt;
+
+                               txt = e_cal_component_text_new (values[ii].description, "alt-representation");
+                               e_cal_component_alarm_set_description (expected, txt);
+                               e_cal_component_text_free (txt);
+                       } else {
+                               e_cal_component_alarm_take_description (expected, e_cal_component_text_new 
(values[ii].description, NULL));
+                       }
+               }
+
+               if (values[ii].with_repeat) {
+                       nth_repeat++;
+
+                       if ((nth_repeat & 1) != 0) {
+                               ECalComponentAlarmRepeat *rpt;
+
+                               rpt = e_cal_component_alarm_repeat_new_seconds (3, 6);
+                               e_cal_component_alarm_set_repeat (expected, rpt);
+                               e_cal_component_alarm_repeat_free (rpt);
+                       } else {
+                               e_cal_component_alarm_take_repeat (expected, 
e_cal_component_alarm_repeat_new_seconds (9, 12));
+                       }
+               }
+
+               if (values[ii].with_trigger) {
+                       nth_trigger++;
+
+                       if ((nth_trigger & 1) != 0) {
+                               ECalComponentAlarmTrigger *trg;
+                               ICalTime *tt;
+
+                               tt = i_cal_time_from_string ("20201030T102030");
+                               g_assert_nonnull (tt);
+
+                               trg = e_cal_component_alarm_trigger_new_absolute (tt);
+                               e_cal_component_alarm_set_trigger (expected, trg);
+                               e_cal_component_alarm_trigger_free (trg);
+                               g_object_unref (tt);
+                       } else {
+                               ICalTime *tt;
+
+                               tt = i_cal_time_from_string ("21211129T122233");
+                               g_assert_nonnull (tt);
+
+                               e_cal_component_alarm_take_trigger (expected, 
e_cal_component_alarm_trigger_new_absolute (tt));
+
+                               g_object_unref (tt);
+                       }
+               }
+
+               if (values[ii].with_attendees) {
+                       GSList *attendees = NULL;
+                       gint jj;
+
+                       nth_attendees++;
+
+                       for (jj = 0; jj < nth_attendees; jj++) {
+                               ECalComponentAttendee *att;
+                               gchar *value;
+
+                               value = g_strdup_printf ("mailto:attendee-%d";, jj);
+
+                               att = e_cal_component_attendee_new ();
+                               e_cal_component_attendee_set_value (att, value);
+                               g_free (value);
+
+                               attendees = g_slist_prepend (attendees, att);
+                       }
+
+                       if ((nth_attendees & 1) != 0) {
+                               e_cal_component_alarm_set_attendees (expected, attendees);
+                               g_slist_free_full (attendees, e_cal_component_attendee_free);
+                       } else {
+                               e_cal_component_alarm_take_attendees (expected, attendees);
+                       }
+               }
+
+               if (values[ii].with_attachments) {
+                       GSList *attachments = NULL;
+                       gint jj;
+
+                       nth_attachments++;
+
+                       for (jj = 0; jj < nth_attachments; jj++) {
+                               ICalAttach *attach;
+                               gchar *value;
+
+                               if ((jj & 1) != 0) {
+                                       value = g_strdup_printf ("https://www.no.where/link%d";, jj);
+                                       attach = i_cal_attach_new_from_url (value);
+                               } else {
+                                       value = g_strdup_printf ("Content*%d", jj);
+                                       attach = i_cal_attach_new_from_data (value, NULL, NULL);
+                               }
+
+                               g_free (value);
+
+                               g_assert_nonnull (attach);
+
+                               attachments = g_slist_prepend (attachments, attach);
+                       }
+
+                       if ((nth_attachments & 1) != 0) {
+                               e_cal_component_alarm_set_attachments (expected, attachments);
+                               g_slist_free_full (attachments, g_object_unref);
+                       } else {
+                               e_cal_component_alarm_take_attachments (expected, attachments);
+                       }
+               }
+
+               if (values[ii].with_properties) {
+                       ECalComponentPropertyBag *bag;
+                       gint ii;
+
+                       nth_properties++;
+
+                       bag = e_cal_component_alarm_get_property_bag (expected);
+
+                       g_assert_nonnull (bag);
+
+                       for (ii = nth_properties; ii > 0; ii--) {
+                               ICalProperty *prop;
+
+                               if (ii == 0) {
+                                       prop = i_cal_property_new_url ("https://www.gnome.org";);
+                               } else if (ii == 1) {
+                                       prop = i_cal_property_new_voter ("mailto:user@no.where";);
+                               } else {
+                                       gchar *x_name;
+
+                                       x_name = g_strdup_printf ("X-CUSTOM-PROP-%d", ii);
+                                       prop = i_cal_property_new_x (x_name + 2);
+                                       i_cal_property_set_x_name (prop, x_name);
+                                       g_free (x_name);
+                               }
+
+                               g_assert_nonnull (prop);
+
+                               e_cal_component_property_bag_take (bag, prop);
+                       }
+
+                       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, nth_properties);
+               }
+
+               received = e_cal_component_alarm_copy (expected);
+               verify_struct_alarm_equal (expected, received);
+               e_cal_component_alarm_free (received);
+
+               icalcomp = e_cal_component_alarm_get_as_component (expected);
+               g_assert_nonnull (icalcomp);
+               received = e_cal_component_alarm_new_from_component (icalcomp);
+               verify_struct_alarm_equal (expected, received);
+               e_cal_component_alarm_free (received);
+               g_object_unref (icalcomp);
+
+               icalcomp = i_cal_component_new_valarm ();
+               g_assert_nonnull (icalcomp);
+               e_cal_component_alarm_fill_component (expected, icalcomp);
+               received = e_cal_component_alarm_new ();
+               e_cal_component_alarm_set_from_component (received, icalcomp);
+               g_object_unref (icalcomp);
+               verify_struct_alarm_equal (expected, received);
+               e_cal_component_alarm_free (received);
+
+               e_cal_component_alarm_free (expected);
+       }
+
+       g_assert_cmpint (nth_summary, >, 1);
+       g_assert_cmpint (nth_description, >, 1);
+       g_assert_cmpint (nth_repeat, >, 1);
+       g_assert_cmpint (nth_trigger, >, 1);
+       g_assert_cmpint (nth_attendees, >, 1);
+       g_assert_cmpint (nth_attachments, >, 1);
+       g_assert_cmpint (nth_properties, >, 1);
+}
+
+static void
+test_component_struct_alarms (void)
+{
+       ECalComponent *comp;
+       ECalComponentAlarms *expected, *received;
+       ECalComponentAlarmInstance *instance;
+       GSList *instances = NULL;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       e_cal_component_set_uid (comp, "123");
+
+       expected = e_cal_component_alarms_new (comp);
+       g_assert_nonnull (e_cal_component_alarms_get_component (expected));
+       g_assert_cmpstr ("123", ==, e_cal_component_get_uid (e_cal_component_alarms_get_component 
(expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instance = e_cal_component_alarm_instance_new ("1", (time_t) 1, (time_t) 2, (time_t) 3);
+       e_cal_component_alarms_add_instance (expected, instance);
+
+       g_assert_cmpint (1, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+       verify_struct_alarm_instance_equal (instance, e_cal_component_alarms_get_instances (expected)->data);
+       e_cal_component_alarm_instance_free (instance);
+
+       g_object_unref (comp);
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instance = e_cal_component_alarm_instance_new ("2", (time_t) 2, (time_t) 3, (time_t) 4);
+       e_cal_component_alarms_take_instance (expected, instance);
+       g_assert_cmpint (2, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       g_assert (!e_cal_component_alarms_remove_instance (expected, GINT_TO_POINTER (123)));
+       g_assert (e_cal_component_alarms_remove_instance (expected, instance));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       e_cal_component_alarms_set_instances (expected, NULL);
+       g_assert_cmpint (0, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instances = NULL;
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("3", (time_t) 3, (time_t) 
4, (time_t) 5));
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("4", (time_t) 4, (time_t) 
5, (time_t) 6));
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("5", (time_t) 5, (time_t) 
6, (time_t) 7));
+
+       e_cal_component_alarms_set_instances (expected, instances);
+       g_assert_cmpint (3, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+       g_slist_free_full (instances, e_cal_component_alarm_instance_free);
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instances = NULL;
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("6", (time_t) 6, (time_t) 
7, (time_t) 8));
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("7", (time_t) 7, (time_t) 
8, (time_t) 9));
+
+       e_cal_component_alarms_take_instances (expected, instances);
+       g_assert_cmpint (2, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       e_cal_component_alarms_free (expected);
+}
+
+static void
+test_component_struct_alarm_instance (void)
+{
+       struct _values {
+               const gchar *uid;
+               gint instance_time;
+               gint occur_start;
+               gint occur_end;
+       } values[] = {
+               { "1", 1, 2, 3 },
+               { "2", 2, 3, 4 },
+               { "3", 3, 4, 6 },
+               { "4", 4, 5, 6 },
+               { "5", 5, 6, 7 }
+       };
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentAlarmInstance *expected, *received;
+
+               if ((ii & 1) != 0) {
+                       expected = e_cal_component_alarm_instance_new (values[ii].uid,
+                                                                      (time_t) values[ii].instance_time,
+                                                                      (time_t) values[ii].occur_start,
+                                                                      (time_t) values[ii].occur_end);
+               } else {
+                       expected = e_cal_component_alarm_instance_new ("X", (time_t) 100, (time_t) 200, 
(time_t) 300);
+                       e_cal_component_alarm_instance_set_uid (expected, values[ii].uid);
+                       e_cal_component_alarm_instance_set_time (expected, (time_t) values[ii].instance_time);
+                       e_cal_component_alarm_instance_set_occur_start (expected, (time_t) 
values[ii].occur_start);
+                       e_cal_component_alarm_instance_set_occur_end (expected, (time_t) 
values[ii].occur_end);
+               }
+
+               g_assert_nonnull (expected);
+
+               g_assert_cmpstr (e_cal_component_alarm_instance_get_uid (expected), ==, values[ii].uid);
+               g_assert_cmpint (e_cal_component_alarm_instance_get_time (expected), ==, (time_t) 
values[ii].instance_time);
+               g_assert_cmpint (e_cal_component_alarm_instance_get_occur_start (expected), ==, (time_t) 
values[ii].occur_start);
+               g_assert_cmpint (e_cal_component_alarm_instance_get_occur_end (expected), ==, (time_t) 
values[ii].occur_end);
+
+               received = e_cal_component_alarm_instance_copy (expected);
+               verify_struct_alarm_instance_equal (expected, received);
+               e_cal_component_alarm_instance_free (received);
+
+               e_cal_component_alarm_instance_free (expected);
+       }
+
+       g_assert_cmpint (ii, >, 1);
+}
+
+static void
+test_component_add_params_to_bag (ECalComponentParameterBag *bag,
+                                 gint n_params)
+{
+       gint ii;
+
+       g_assert_nonnull (bag);
+
+       for (ii = 0; ii < n_params; ii++) {
+               ICalParameter *param;
+
+               if (ii == 0) {
+                       param = i_cal_parameter_new_local (I_CAL_LOCAL_TRUE);
+               } else if (ii == 1) {
+                       param = i_cal_parameter_new_localize ("en_US");
+               } else {
+                       gchar *x_name;
+
+                       x_name = g_strdup_printf ("X-CUSTOM-PARAM-%d", ii);
+                       param = i_cal_parameter_new_x (x_name + 2);
+                       i_cal_parameter_set_xname (param, x_name);
+                       g_free (x_name);
+               }
+
+               g_assert_nonnull (param);
+
+               e_cal_component_parameter_bag_take (bag, param);
+       }
+
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, n_params);
+}
+
+static void
+test_component_struct_alarm_repeat (void)
+{
+       struct _values {
+               gint repetitions;
+               gint interval;
+       } values[] = {
+               { 10, 20 },
+               { 30, 40 },
+               { 50, 60 },
+               { 70, 80 },
+               { 90, 55 }
+       };
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentAlarmRepeat *expected, *received;
+               ICalDuration *dur;
+
+               if ((ii % 4) == 0) {
+                       dur = i_cal_duration_from_int (values[ii].interval);
+                       expected = e_cal_component_alarm_repeat_new (values[ii].repetitions, dur);
+                       g_object_unref (dur);
+               } else if ((ii % 4) == 1) {
+                       expected = e_cal_component_alarm_repeat_new_seconds (values[ii].repetitions, 
values[ii].interval);
+               } else if ((ii % 4) == 2) {
+                       expected = e_cal_component_alarm_repeat_new_seconds (1000, 2000);
+                       e_cal_component_alarm_repeat_set_repetitions (expected, values[ii].repetitions);
+                       e_cal_component_alarm_repeat_set_interval_seconds (expected, values[ii].interval);
+               } else {
+                       dur = i_cal_duration_from_int (values[ii].interval);
+
+                       expected = e_cal_component_alarm_repeat_new_seconds (1000, 2000);
+                       e_cal_component_alarm_repeat_set_repetitions (expected, values[ii].repetitions);
+                       e_cal_component_alarm_repeat_set_interval (expected, dur);
+
+                       g_object_unref (dur);
+               }
+
+               g_assert_nonnull (expected);
+
+               dur = i_cal_duration_from_int (values[ii].interval);
+               g_assert_nonnull (dur);
+               g_assert_cmpint (e_cal_component_alarm_repeat_get_repetitions (expected), ==, 
values[ii].repetitions);
+               g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==, 
values[ii].interval);
+               verify_ical_durationtype_equal (dur, e_cal_component_alarm_repeat_get_interval (expected));
+               g_object_unref (dur);
+
+               received = e_cal_component_alarm_repeat_copy (expected);
+               verify_struct_alarm_repeat_equal (expected, received);
+               e_cal_component_alarm_repeat_free (received);
+
+               e_cal_component_alarm_repeat_free (expected);
+       }
+
+       g_assert_cmpint (ii, >, 4);
+}
+
+static void
+test_component_struct_alarm_trigger (void)
+{
+       struct _values {
+               ECalComponentAlarmTriggerKind kind;
+               gint duration;
+               const gchar *abs_time;
+       } values[] = {
+               { E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START, -100, NULL },
+               { E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE, 0, "21090807T001122Z" },
+               { E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, 200, NULL },
+               { E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE, 0, "21090807T213243Z" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 3; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentAlarmTrigger *expected = NULL, *received;
+                       ICalDuration *dur;
+                       ICalTime *tt;
+                       ICalProperty *prop;
+
+                       if (set_kind == 0) {
+                               /* nothing, create it as it should be */
+                       } else if (set_kind == 1) {
+                               dur = i_cal_duration_from_int (33);
+                               expected = e_cal_component_alarm_trigger_new_relative 
(E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, dur);
+                               g_object_unref (dur);
+
+                               g_assert_nonnull (expected);
+                       } else if (set_kind == 2) {
+                               tt = i_cal_time_today ();
+                               expected = e_cal_component_alarm_trigger_new_absolute (tt);
+                               g_object_unref (tt);
+
+                               g_assert_nonnull (expected);
+                       } else {
+                               g_assert_not_reached ();
+                       }
+
+                       if (expected) {
+                               if (values[ii].kind == e_cal_component_alarm_trigger_get_kind (expected)) {
+                                       if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                                               tt = i_cal_time_from_string (values[ii].abs_time);
+                                               e_cal_component_alarm_trigger_set_absolute_time (expected, 
tt);
+                                               g_object_unref (tt);
+                                       } else {
+                                               dur = i_cal_duration_from_int (values[ii].duration);
+                                               e_cal_component_alarm_trigger_set_kind (expected, 
values[ii].kind);
+                                               e_cal_component_alarm_trigger_set_duration (expected, dur);
+                                               g_object_unref (dur);
+                                       }
+                               } else if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                                       tt = i_cal_time_from_string (values[ii].abs_time);
+                                       e_cal_component_alarm_trigger_set_absolute (expected, tt);
+                                       g_object_unref (tt);
+                               } else {
+                                       dur = i_cal_duration_from_int (values[ii].duration);
+                                       e_cal_component_alarm_trigger_set_relative (expected, 
values[ii].kind, dur);
+                                       g_object_unref (dur);
+                               }
+                       } else {
+                               if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                                       tt = i_cal_time_from_string (values[ii].abs_time);
+                                       expected = e_cal_component_alarm_trigger_new_absolute (tt);
+                                       g_assert_nonnull (expected);
+                                       g_assert_nonnull (e_cal_component_alarm_trigger_get_absolute_time 
(expected));
+                                       verify_ical_timetype_equal (tt, 
e_cal_component_alarm_trigger_get_absolute_time (expected));
+                                       g_object_unref (tt);
+                               } else {
+                                       dur = i_cal_duration_from_int (values[ii].duration);
+                                       expected = e_cal_component_alarm_trigger_new_relative 
(values[ii].kind, dur);
+                                       g_assert_nonnull (expected);
+                                       g_object_unref (dur);
+                               }
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       if (set_kind == 1)
+                               test_component_add_params_to_bag 
(e_cal_component_alarm_trigger_get_parameter_bag (expected), ii + 1);
+
+                       g_assert_cmpint (values[ii].kind, ==, e_cal_component_alarm_trigger_get_kind 
(expected));
+                       if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                               tt = i_cal_time_from_string (values[ii].abs_time);
+                               g_assert_nonnull (tt);
+                               verify_ical_timetype_equal (tt, 
e_cal_component_alarm_trigger_get_absolute_time (expected));
+                               g_object_unref (tt);
+                       } else {
+                               dur = i_cal_duration_from_int (values[ii].duration);
+                               g_assert_nonnull (dur);
+                               verify_ical_durationtype_equal (dur, 
e_cal_component_alarm_trigger_get_duration (expected));
+                               g_object_unref (dur);
+                       }
+
+                       received = e_cal_component_alarm_trigger_copy (expected);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       prop = e_cal_component_alarm_trigger_get_as_property (expected);
+                       g_assert_nonnull (prop);
+
+                       received = e_cal_component_alarm_trigger_new_from_property (prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       dur = i_cal_duration_from_int (33);
+                       received = e_cal_component_alarm_trigger_new_relative 
(E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, dur);
+                       g_object_unref (dur);
+                       e_cal_component_alarm_trigger_set_from_property (received, prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       tt = i_cal_time_today ();
+                       received = e_cal_component_alarm_trigger_new_absolute (tt);
+                       g_object_unref (tt);
+                       e_cal_component_alarm_trigger_set_from_property (received, prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       g_object_unref (prop);
+
+                       prop = i_cal_property_new (I_CAL_TRIGGER_PROPERTY);
+                       e_cal_component_alarm_trigger_fill_property (expected, prop);
+                       received = e_cal_component_alarm_trigger_new_from_property (prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+                       g_object_unref (prop);
+
+                       e_cal_component_alarm_trigger_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_attendee (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *member;
+               ICalParameterCutype cutype;
+               ICalParameterRole role;
+               ICalParameterPartstat partstat;
+               gboolean rsvp;
+               const gchar *delegatedfrom;
+               const gchar *delegatedto;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "mailto:att1";,
+                  "member",
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_CHAIR,
+                  I_CAL_PARTSTAT_NEEDSACTION,
+                  FALSE,
+                  "mailto:delgfrom";,
+                  "mailto:delgto";,
+                  "mailto:sentby";,
+                  "First attendee",
+                  "en_US" },
+               { "mailto:room";,
+                  NULL,
+                  I_CAL_CUTYPE_ROOM,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_ACCEPTED,
+                  FALSE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "Meeting room",
+                  NULL },
+               { "mailto:att2";,
+                  NULL,
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_TENTATIVE,
+                  TRUE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "en_US" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentAttendee *expected = NULL, *received;
+                       ICalProperty *prop;
+
+                       if (set_kind == 1) {
+                               expected = e_cal_component_attendee_new ();
+                       } else if (set_kind == 2) {
+                               expected = e_cal_component_attendee_new_full ("value", "member",
+                                       I_CAL_CUTYPE_INDIVIDUAL,
+                                       I_CAL_ROLE_CHAIR,
+                                       I_CAL_PARTSTAT_DECLINED,
+                                       TRUE,
+                                       "delegatedfrom", "delegatedto",
+                                       "sentby", "cn", "language");
+                       }
+
+                       if (expected) {
+                               e_cal_component_attendee_set_value (expected, values[ii].value);
+                               e_cal_component_attendee_set_member (expected, values[ii].member);
+                               e_cal_component_attendee_set_cutype (expected, values[ii].cutype);
+                               e_cal_component_attendee_set_role (expected, values[ii].role);
+                               e_cal_component_attendee_set_partstat (expected, values[ii].partstat);
+                               e_cal_component_attendee_set_rsvp (expected, values[ii].rsvp);
+                               e_cal_component_attendee_set_delegatedfrom (expected, 
values[ii].delegatedfrom);
+                               e_cal_component_attendee_set_delegatedto (expected, values[ii].delegatedto);
+                               e_cal_component_attendee_set_sentby (expected, values[ii].sentby);
+                               e_cal_component_attendee_set_cn (expected, values[ii].cn);
+                               e_cal_component_attendee_set_language (expected, values[ii].language);
+                       } else {
+                               expected = e_cal_component_attendee_new_full (values[ii].value,
+                                       values[ii].member,
+                                       values[ii].cutype,
+                                       values[ii].role,
+                                       values[ii].partstat,
+                                       values[ii].rsvp,
+                                       values[ii].delegatedfrom,
+                                       values[ii].delegatedto,
+                                       values[ii].sentby,
+                                       values[ii].cn,
+                                       values[ii].language);
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       if (set_kind == 1)
+                               test_component_add_params_to_bag (e_cal_component_attendee_get_parameter_bag 
(expected), ii + 1);
+
+                       g_assert_cmpstr (e_cal_component_attendee_get_value (expected), ==, values[ii].value);
+                       g_assert_cmpstr (e_cal_component_attendee_get_member (expected), ==, 
values[ii].member);
+                       g_assert_cmpint (e_cal_component_attendee_get_cutype (expected), ==, 
values[ii].cutype);
+                       g_assert_cmpint (e_cal_component_attendee_get_role (expected), ==, values[ii].role);
+                       g_assert_cmpint (e_cal_component_attendee_get_partstat (expected), ==, 
values[ii].partstat);
+                       g_assert_cmpint (e_cal_component_attendee_get_rsvp (expected) ? 1 : 0, ==, 
values[ii].rsvp ? 1 : 0);
+                       g_assert_cmpstr (e_cal_component_attendee_get_delegatedfrom (expected), ==, 
values[ii].delegatedfrom);
+                       g_assert_cmpstr (e_cal_component_attendee_get_delegatedto (expected), ==, 
values[ii].delegatedto);
+                       g_assert_cmpstr (e_cal_component_attendee_get_sentby (expected), ==, 
values[ii].sentby);
+                       g_assert_cmpstr (e_cal_component_attendee_get_cn (expected), ==, values[ii].cn);
+                       g_assert_cmpstr (e_cal_component_attendee_get_language (expected), ==, 
values[ii].language);
+
+                       received = e_cal_component_attendee_copy (expected);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+
+                       prop = e_cal_component_attendee_get_as_property (expected);
+                       g_assert_nonnull (prop);
+
+                       received = e_cal_component_attendee_new_from_property (prop);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+
+                       received = e_cal_component_attendee_new_full ("value", "member",
+                               I_CAL_CUTYPE_INDIVIDUAL,
+                               I_CAL_ROLE_CHAIR,
+                               I_CAL_PARTSTAT_DECLINED,
+                               TRUE,
+                               "delegatedfrom", "delegatedto",
+                               "sentby", "cn", "language");
+                       e_cal_component_attendee_set_from_property (received, prop);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+
+                       g_object_unref (prop);
+
+                       prop = i_cal_property_new (I_CAL_ATTENDEE_PROPERTY);
+                       e_cal_component_attendee_fill_property (expected, prop);
+                       received = e_cal_component_attendee_new_from_property (prop);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+                       g_object_unref (prop);
+
+                       e_cal_component_attendee_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_datetime (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314", "Europe/Berlin" },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentDateTime *expected = NULL, *received;
+                       ICalTime *tt;
+
+                       if (set_kind == 2) {
+                               tt = i_cal_time_from_string ("19981019");
+                               expected = e_cal_component_datetime_new (tt, NULL);
+                               g_object_unref (tt);
+                       } else if (set_kind == 3) {
+                               tt = i_cal_time_from_string ("19981019");
+                               expected = e_cal_component_datetime_new_take (tt, g_strdup ("Unknown"));
+                       }
+
+                       tt = i_cal_time_from_string (values[ii].time);
+                       g_assert_nonnull (tt);
+
+                       if (expected) {
+                               if (((set_kind + ii) % 3) == 0) {
+                                       e_cal_component_datetime_set (expected, tt, values[ii].tzid);
+                               } else if (((set_kind + ii) % 3) == 1) {
+                                       ICalTime *ttcopy;
+
+                                       ttcopy = i_cal_time_new_clone (tt);
+                                       g_assert_nonnull (ttcopy);
+
+                                       e_cal_component_datetime_take_value (expected, ttcopy);
+                                       e_cal_component_datetime_take_tzid (expected, g_strdup 
(values[ii].tzid));
+                               } else {
+                                       e_cal_component_datetime_set_value (expected, tt);
+                                       e_cal_component_datetime_set_tzid (expected, values[ii].tzid);
+                               }
+                       } else {
+                               if (set_kind == 0) {
+                                       expected = e_cal_component_datetime_new (tt, values[ii].tzid);
+                               } else {
+                                       ICalTime *ttcopy;
+
+                                       ttcopy = i_cal_time_new_clone (tt);
+                                       g_assert_nonnull (ttcopy);
+
+                                       expected = e_cal_component_datetime_new_take (ttcopy, g_strdup 
(values[ii].tzid));
+                               }
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       verify_ical_timetype_equal (e_cal_component_datetime_get_value (expected), tt);
+                       g_assert_cmpstr (e_cal_component_datetime_get_tzid (expected), ==, values[ii].tzid);
+
+                       g_object_unref (tt);
+
+                       received = e_cal_component_datetime_copy (expected);
+                       verify_struct_datetime_equal (expected, received);
+                       e_cal_component_datetime_free (received);
+
+                       e_cal_component_datetime_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_id (void)
+{
+       struct _values {
+               const gchar *uid;
+               const gchar *rid;
+       } values[] = {
+               { "123", "20181215T111213Z" },
+               { "222", NULL },
+               { "333", NULL },
+               { "44", "20211215T101112" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentId *expected = NULL, *received;
+
+                       if (set_kind == 2) {
+                               expected = e_cal_component_id_new ("4567", "123");
+                       } else if (set_kind == 3) {
+                               expected = e_cal_component_id_new_take (g_strdup ("5678"), g_strdup 
("Unknown"));
+                       }
+
+                       if (expected) {
+                               e_cal_component_id_set_uid (expected, values[ii].uid);
+                               e_cal_component_id_set_rid (expected, values[ii].rid);
+                       } else {
+                               if (set_kind == 0) {
+                                       expected = e_cal_component_id_new (values[ii].uid, values[ii].rid);
+                               } else {
+                                       expected = e_cal_component_id_new_take (g_strdup (values[ii].uid), 
g_strdup (values[ii].rid));
+                               }
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       g_assert_cmpstr (e_cal_component_id_get_uid (expected), ==, values[ii].uid);
+                       g_assert_cmpstr (e_cal_component_id_get_rid (expected), ==, values[ii].rid);
+
+                       received = e_cal_component_id_copy (expected);
+                       verify_struct_id_equal (expected, received);
+                       g_assert_cmpint (e_cal_component_id_hash (expected), ==, e_cal_component_id_hash 
(received));
+                       g_assert (e_cal_component_id_equal (expected, received));
+                       e_cal_component_id_free (received);
+
+                       e_cal_component_id_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_organizer (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "mailto:org1";,
+                  "mailto:sentby";,
+                  "First organizer",
+                  "en_US" },
+               { "mailto:room";,
+                  NULL,
+                  "Meeting room",
+                  NULL },
+               { "mailto:org2";,
+                  NULL,
+                  NULL,
+                  "en_US" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentOrganizer *expected = NULL, *received;
+                       ICalProperty *prop;
+
+                       if (set_kind == 1) {
+                               expected = e_cal_component_organizer_new ();
+                       } else if (set_kind == 2) {
+                               expected = e_cal_component_organizer_new_full ("value", "sentby", "cn", 
"language");
+                       }
+
+                       if (expected) {
+                               e_cal_component_organizer_set_value (expected, values[ii].value);
+                               e_cal_component_organizer_set_sentby (expected, values[ii].sentby);
+                               e_cal_component_organizer_set_cn (expected, values[ii].cn);
+                               e_cal_component_organizer_set_language (expected, values[ii].language);
+                       } else {
+                               expected = e_cal_component_organizer_new_full (values[ii].value,
+                                       values[ii].sentby,
+                                       values[ii].cn,
+                                       values[ii].language);
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       if (set_kind == 1)
+                               test_component_add_params_to_bag (e_cal_component_organizer_get_parameter_bag 
(expected), ii + 1);
+
+                       g_assert_cmpstr (e_cal_component_organizer_get_value (expected), ==, 
values[ii].value);
+                       g_assert_cmpstr (e_cal_component_organizer_get_sentby (expected), ==, 
values[ii].sentby);
+                       g_assert_cmpstr (e_cal_component_organizer_get_cn (expected), ==, values[ii].cn);
+                       g_assert_cmpstr (e_cal_component_organizer_get_language (expected), ==, 
values[ii].language);
+
+                       received = e_cal_component_organizer_copy (expected);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+
+                       prop = e_cal_component_organizer_get_as_property (expected);
+                       g_assert_nonnull (prop);
+
+                       received = e_cal_component_organizer_new_from_property (prop);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+
+                       received = e_cal_component_organizer_new_full ("value", "sentby", "cn", "language");
+                       e_cal_component_organizer_set_from_property (received, prop);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+
+                       g_object_unref (prop);
+
+                       prop = i_cal_property_new (I_CAL_ORGANIZER_PROPERTY);
+                       e_cal_component_organizer_fill_property (expected, prop);
+                       received = e_cal_component_organizer_new_from_property (prop);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+                       g_object_unref (prop);
+
+                       e_cal_component_organizer_free (expected);
+               }
+       }
+}
+
+#define X_PARAM_NAME "X-PARAM"
+#define X_PARAM_VALUE "xVaLuE"
+
+static gboolean
+test_parameter_bag_filter_cb (ICalParameter *param,
+                             gpointer user_data)
+{
+       ICalParameterKind *expected = user_data, kind;
+       gint ii;
+
+       g_return_val_if_fail (expected != NULL, FALSE);
+
+       kind = i_cal_parameter_isa (param);
+
+       for (ii = 0; expected[ii] != I_CAL_ANY_PARAMETER; ii++) {
+               if (kind == expected[ii])
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void
+test_check_parameter_bag (const ECalComponentParameterBag *bag,
+                         const ICalParameterKind *expected)
+{
+       ICalParameter *param;
+       gint ii;
+
+       g_assert_nonnull (bag);
+       g_assert_nonnull (expected);
+
+       for (ii = 0; expected[ii] != I_CAL_ANY_PARAMETER; ii++) {
+               param = e_cal_component_parameter_bag_get (bag, ii);
+
+               g_assert_nonnull (param);
+               g_assert_cmpint (i_cal_parameter_isa (param), ==, expected[ii]);
+               if (i_cal_parameter_isa (param) == I_CAL_X_PARAMETER) {
+                       g_assert_cmpstr (i_cal_parameter_get_xname (param), ==, X_PARAM_NAME);
+                       g_assert_cmpstr (i_cal_parameter_get_xvalue (param), ==, X_PARAM_VALUE);
+               }
+       }
+
+       /* Out of bounds */
+       param = e_cal_component_parameter_bag_get (bag, ii);
+       g_assert_null (param);
+}
+
+static void
+test_component_struct_parameter_bag (void)
+{
+       const gchar *prop_str =
+               "ATTENDEE;CHARSET=utf-8;CN=User;CUTYPE=INDIVIDUAL;" X_PARAM_NAME "=" X_PARAM_VALUE 
";LANGUAGE=en_US:mailto:user@no.where";;
+       ICalParameterKind expected_unfiltered[] = {
+               I_CAL_CHARSET_PARAMETER,
+               I_CAL_CN_PARAMETER,
+               I_CAL_CUTYPE_PARAMETER,
+               I_CAL_X_PARAMETER,
+               I_CAL_LANGUAGE_PARAMETER,
+               I_CAL_ANY_PARAMETER /* sentinel */
+       },
+       expected_filtered[] = {
+               I_CAL_CN_PARAMETER,
+               I_CAL_CUTYPE_PARAMETER,
+               I_CAL_X_PARAMETER,
+               I_CAL_ANY_PARAMETER /* sentinel */
+       };
+       ICalProperty *prop;
+       ICalParameter *param;
+       ECalComponentParameterBag *bag, *bag2;
+       gint ii;
+
+       prop = i_cal_property_new_from_string (prop_str);
+       g_assert_nonnull (prop);
+       g_assert_cmpint (i_cal_property_count_parameters (prop), ==, 5);
+
+       bag = e_cal_component_parameter_bag_new ();
+       g_assert_nonnull (bag);
+       e_cal_component_parameter_bag_set_from_property (bag, prop, NULL, NULL);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, G_N_ELEMENTS 
(expected_unfiltered) - 1);
+       test_check_parameter_bag (bag, expected_unfiltered);
+
+       bag2 = e_cal_component_parameter_bag_copy (bag);
+       g_assert_nonnull (bag2);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag2), ==, G_N_ELEMENTS 
(expected_unfiltered) - 1);
+       test_check_parameter_bag (bag2, expected_unfiltered);
+       e_cal_component_parameter_bag_free (bag2);
+       e_cal_component_parameter_bag_free (bag);
+
+       bag = e_cal_component_parameter_bag_new_from_property (prop, NULL, NULL);
+       g_assert_nonnull (bag);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, G_N_ELEMENTS 
(expected_unfiltered) - 1);
+       test_check_parameter_bag (bag, expected_unfiltered);
+       e_cal_component_parameter_bag_free (bag);
+
+       bag = e_cal_component_parameter_bag_new ();
+       g_assert_nonnull (bag);
+       e_cal_component_parameter_bag_set_from_property (bag, prop, test_parameter_bag_filter_cb, 
expected_filtered);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, G_N_ELEMENTS (expected_filtered) 
- 1);
+       test_check_parameter_bag (bag, expected_filtered);
+       e_cal_component_parameter_bag_free (bag);
+
+       bag = e_cal_component_parameter_bag_new_from_property (prop, test_parameter_bag_filter_cb, 
expected_filtered);
+       g_assert_nonnull (bag);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, G_N_ELEMENTS (expected_filtered) 
- 1);
+       test_check_parameter_bag (bag, expected_filtered);
+
+       g_object_unref (prop);
+
+       prop = i_cal_property_new (I_CAL_COMMENT_PROPERTY);
+       g_assert_nonnull (prop);
+       e_cal_component_parameter_bag_fill_property (bag, prop);
+       g_assert_cmpint (i_cal_property_count_parameters (prop), ==, e_cal_component_parameter_bag_get_count 
(bag));
+       g_object_unref (prop);
+
+       bag2 = e_cal_component_parameter_bag_copy (bag);
+
+       while (e_cal_component_parameter_bag_get_count (bag) > 1) {
+               e_cal_component_parameter_bag_remove (bag, 1);
+       }
+
+       e_cal_component_parameter_bag_assign (bag2, bag);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 
e_cal_component_parameter_bag_get_count (bag2));
+       e_cal_component_parameter_bag_free (bag2);
+
+       prop = i_cal_property_new (I_CAL_ATTENDEE_PROPERTY);
+       g_assert_nonnull (prop);
+       e_cal_component_parameter_bag_fill_property (bag, prop);
+       g_assert_cmpint (i_cal_property_count_parameters (prop), ==, 1);
+       g_object_unref (prop);
+
+       e_cal_component_parameter_bag_clear (bag);
+
+       prop = i_cal_property_new (I_CAL_ATTENDEE_PROPERTY);
+       g_assert_nonnull (prop);
+       e_cal_component_parameter_bag_fill_property (bag, prop);
+       g_assert_cmpint (i_cal_property_count_parameters (prop), ==, 0);
+       g_object_unref (prop);
+
+       param = i_cal_parameter_new_cn ("234");
+       e_cal_component_parameter_bag_add (bag, param);
+       g_object_unref (param);
+
+       param = i_cal_parameter_new_cutype (I_CAL_CUTYPE_ROOM);
+       e_cal_component_parameter_bag_take (bag, param);
+
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 2);
+
+       for (ii = 0; ii < 2; ii++) {
+               ICalParameter *param2;
+
+               param2 = e_cal_component_parameter_bag_get (bag, ii);
+               if (ii == 0) {
+                       g_assert (param != param2);
+                       g_assert_cmpint (i_cal_parameter_isa (param2), ==, I_CAL_CN_PARAMETER);
+                       g_assert_cmpstr (i_cal_parameter_get_cn (param2), ==, "234");
+               } else {
+                       g_assert (param == param2);
+                       g_assert_cmpint (i_cal_parameter_isa (param2), ==, I_CAL_CUTYPE_PARAMETER);
+                       g_assert_cmpint (i_cal_parameter_get_cutype (param2), ==, I_CAL_CUTYPE_ROOM);
+               }
+       }
+
+       prop = i_cal_property_new (I_CAL_DESCRIPTION_PROPERTY);
+       g_assert_nonnull (prop);
+       e_cal_component_parameter_bag_fill_property (bag, prop);
+       g_assert_cmpint (i_cal_property_count_parameters (prop), ==, e_cal_component_parameter_bag_get_count 
(bag));
+       g_object_unref (prop);
+
+       e_cal_component_parameter_bag_clear (bag);
+
+       e_cal_component_parameter_bag_take (bag, i_cal_parameter_new_cutype (I_CAL_CUTYPE_ROOM));
+       e_cal_component_parameter_bag_take (bag, i_cal_parameter_new_cn ("111"));
+       e_cal_component_parameter_bag_take (bag, i_cal_parameter_new_cutype (I_CAL_CUTYPE_ROOM));
+       e_cal_component_parameter_bag_take (bag, i_cal_parameter_new_cutype (I_CAL_CUTYPE_RESOURCE));
+
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 4);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_first_by_kind (bag, I_CAL_CUTYPE_PARAMETER), ==, 
0);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_first_by_kind (bag, I_CAL_CN_PARAMETER), ==, 1);
+       g_assert_cmpint (e_cal_component_parameter_bag_remove_by_kind (bag, I_CAL_TZID_PARAMETER, FALSE), ==, 
0);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 4);
+       g_assert_cmpint (e_cal_component_parameter_bag_remove_by_kind (bag, I_CAL_TZID_PARAMETER, TRUE), ==, 
0);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 4);
+       g_assert_cmpint (e_cal_component_parameter_bag_remove_by_kind (bag, I_CAL_CUTYPE_PARAMETER, FALSE), 
==, 1);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 3);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_first_by_kind (bag, I_CAL_CN_PARAMETER), ==, 0);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_first_by_kind (bag, I_CAL_CUTYPE_PARAMETER), ==, 
1);
+       g_assert_cmpint (e_cal_component_parameter_bag_remove_by_kind (bag, I_CAL_CUTYPE_PARAMETER, TRUE), 
==, 2);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_count (bag), ==, 1);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_first_by_kind (bag, I_CAL_CN_PARAMETER), ==, 0);
+       g_assert_cmpint (e_cal_component_parameter_bag_get_first_by_kind (bag, I_CAL_CUTYPE_PARAMETER), >=, 
e_cal_component_parameter_bag_get_count (bag));
+
+       e_cal_component_parameter_bag_free (bag);
+}
+
+#undef X_PARAM_NAME
+#undef X_PARAM_VALUE
+
+static void
+test_component_struct_period (void)
+{
+       struct _values {
+               const gchar *start;
+               const gchar *end;
+               gint duration;
+       } values[] = {
+               { "20181215T111213Z", "20181215T121314Z", -1 },
+               { "20190131T121314Z", NULL, 10 * 24 * 60 * 60 },
+               { "20200708T010305Z", NULL, 2 * 60 * 60 },
+               { "20211215T101112", "20211215T121314", -1 },
+               { "20221110T090807", "20221110T100908", -1 },
+               { "20231009", "20241110", -1 },
+               { "20240908T070605", NULL, -1 },
+               { "20250807", NULL, -1 }
+       };
+       gint ii, set_kind, flipflop1 = 0, flipflop2 = 0;
+
+       for (set_kind = 0; set_kind < 6; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentPeriod *expected = NULL, *received;
+                       ICalTime *start, *end = NULL;
+                       ICalDuration *duration = NULL;
+
+                       start = i_cal_time_from_string (values[ii].start);
+                       g_assert_nonnull (start);
+                       if (values[ii].duration == -1) {
+                               if (values[ii].end) {
+                                       end = i_cal_time_from_string (values[ii].end);
+                                       g_assert_nonnull (end);
+                               }
+                       } else {
+                               duration = i_cal_duration_from_int (values[ii].duration);
+                               g_assert_nonnull (duration);
+                       }
+
+                       if ((set_kind % 3) == 1) {
+                               ICalTime *ttstart, *ttend;
+
+                               ttstart = i_cal_time_from_string ("19981019");
+                               ttend = i_cal_time_from_string ("19981019");
+
+                               g_assert_nonnull (ttstart);
+
+                               expected = e_cal_component_period_new_datetime (ttstart, ttend);
+
+                               g_clear_object (&ttstart);
+                               g_clear_object (&ttend);
+                       } else if ((set_kind % 3) == 2) {
+                               ICalTime *ttstart;
+                               ICalDuration *ttduration;
+
+                               ttstart = i_cal_time_from_string ("19981019");
+                               ttduration = i_cal_duration_from_int (123456);
+                               g_assert_nonnull (ttstart);
+                               g_assert_nonnull (ttduration);
+
+                               expected = e_cal_component_period_new_duration (ttstart, ttduration);
+
+                               g_clear_object (&ttstart);
+                               g_clear_object (&ttduration);
+                       }
+
+                       if (expected) {
+                               if (duration) {
+                                       if (e_cal_component_period_get_kind (expected) == 
E_CAL_COMPONENT_PERIOD_DURATION) {
+                                               flipflop1++;
+                                               if ((flipflop1 & 1) != 0) {
+                                                       e_cal_component_period_set_duration_full (expected, 
start, duration);
+                                               } else {
+                                                       e_cal_component_period_set_start (expected, start);
+                                                       e_cal_component_period_set_duration (expected, 
duration);
+                                               }
+                                       } else {
+                                               e_cal_component_period_set_duration_full (expected, start, 
duration);
+                                       }
+                               } else if (e_cal_component_period_get_kind (expected) == 
E_CAL_COMPONENT_PERIOD_DATETIME) {
+                                       flipflop2++;
+                                       if ((flipflop2 & 1) != 0) {
+                                               e_cal_component_period_set_datetime_full (expected, start, 
end);
+                                       } else {
+                                               e_cal_component_period_set_start (expected, start);
+                                               e_cal_component_period_set_end (expected, end);
+                                       }
+                               } else {
+                                       e_cal_component_period_set_datetime_full (expected, start, end);
+                               }
+                       } else {
+                               if (duration)
+                                       expected = e_cal_component_period_new_duration (start, duration);
+                               else
+                                       expected = e_cal_component_period_new_datetime (start, end);
+                       }
+
+                       g_assert_nonnull (expected);
+                       verify_ical_timetype_equal (start, e_cal_component_period_get_start (expected));
+                       if (duration) {
+                               g_assert_cmpint (e_cal_component_period_get_kind (expected), ==, 
E_CAL_COMPONENT_PERIOD_DURATION);
+                               verify_ical_durationtype_equal (duration, e_cal_component_period_get_duration 
(expected));
+                       } else {
+                               g_assert_cmpint (e_cal_component_period_get_kind (expected), ==, 
E_CAL_COMPONENT_PERIOD_DATETIME);
+                               verify_ical_timetype_equal (end, e_cal_component_period_get_end (expected));
+                       }
+
+                       g_clear_object (&start);
+                       g_clear_object (&end);
+                       g_clear_object (&duration);
+
+                       received = e_cal_component_period_copy (expected);
+                       verify_struct_period_equal (expected, received);
+                       e_cal_component_period_free (received);
+
+                       e_cal_component_period_free (expected);
+               }
+       }
+
+       g_assert_cmpint (flipflop1, >, 2);
+       g_assert_cmpint (flipflop2, >, 2);
+}
+
+#define X_PROP_NAME "X-PROP"
+#define X_PROP_VALUE "xVaLuE"
+
+static gboolean
+test_property_bag_filter_cb (ICalProperty *prop,
+                            gpointer user_data)
+{
+       ICalPropertyKind *expected = user_data, kind;
+       gint ii;
+
+       g_return_val_if_fail (expected != NULL, FALSE);
+
+       kind = i_cal_property_isa (prop);
+
+       for (ii = 0; expected[ii] != I_CAL_ANY_PROPERTY; ii++) {
+               if (kind == expected[ii])
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void
+test_check_property_bag (const ECalComponentPropertyBag *bag,
+                        const ICalPropertyKind *expected)
+{
+       ICalProperty *prop;
+       gint ii;
+
+       g_assert_nonnull (bag);
+       g_assert_nonnull (expected);
+
+       for (ii = 0; expected[ii] != I_CAL_ANY_PROPERTY; ii++) {
+               prop = e_cal_component_property_bag_get (bag, ii);
+
+               g_assert_nonnull (prop);
+               g_assert_cmpint (i_cal_property_isa (prop), ==, expected[ii]);
+               if (i_cal_property_isa (prop) == I_CAL_X_PROPERTY) {
+                       g_assert_cmpstr (i_cal_property_get_x_name (prop), ==, X_PROP_NAME);
+                       g_assert_cmpstr (i_cal_property_get_x (prop), ==, X_PROP_VALUE);
+               }
+       }
+
+       /* Out of bounds */
+       prop = e_cal_component_property_bag_get (bag, ii);
+       g_assert_null (prop);
+}
+
+static void
+test_component_struct_property_bag (void)
+{
+       const gchar *comp_str =
+               "BEGIN:VTODO\r\n"
+               "UID:1\r\n"
+               "STATUS:CANCELLED\r\n"
+               X_PROP_NAME ":" X_PROP_VALUE "\r\n"
+               "END:VTODO\r\n";
+       ICalPropertyKind expected_unfiltered[] = {
+               I_CAL_UID_PROPERTY,
+               I_CAL_STATUS_PROPERTY,
+               I_CAL_X_PROPERTY,
+               I_CAL_ANY_PROPERTY /* sentinel */
+       },
+       expected_filtered[] = {
+               I_CAL_STATUS_PROPERTY,
+               I_CAL_X_PROPERTY,
+               I_CAL_ANY_PROPERTY /* sentinel */
+       };
+       ICalComponent *icomp;
+       ICalProperty *prop;
+       ECalComponentPropertyBag *bag, *bag2;
+       gint ii;
+
+       icomp = i_cal_component_new_from_string (comp_str);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ANY_PROPERTY), ==, 3);
+
+       bag = e_cal_component_property_bag_new ();
+       g_assert_nonnull (bag);
+       e_cal_component_property_bag_set_from_component (bag, icomp, NULL, NULL);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, G_N_ELEMENTS (expected_unfiltered) 
- 1);
+       test_check_property_bag (bag, expected_unfiltered);
+
+       bag2 = e_cal_component_property_bag_copy (bag);
+       g_assert_nonnull (bag2);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag2), ==, G_N_ELEMENTS 
(expected_unfiltered) - 1);
+       test_check_property_bag (bag2, expected_unfiltered);
+       e_cal_component_property_bag_free (bag2);
+       e_cal_component_property_bag_free (bag);
+
+       bag = e_cal_component_property_bag_new_from_component (icomp, NULL, NULL);
+       g_assert_nonnull (bag);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, G_N_ELEMENTS (expected_unfiltered) 
- 1);
+       test_check_property_bag (bag, expected_unfiltered);
+       e_cal_component_property_bag_free (bag);
+
+       bag = e_cal_component_property_bag_new ();
+       g_assert_nonnull (bag);
+       e_cal_component_property_bag_set_from_component (bag, icomp, test_property_bag_filter_cb, 
expected_filtered);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, G_N_ELEMENTS (expected_filtered) - 
1);
+       test_check_property_bag (bag, expected_filtered);
+       e_cal_component_property_bag_free (bag);
+
+       bag = e_cal_component_property_bag_new_from_component (icomp, test_property_bag_filter_cb, 
expected_filtered);
+       g_assert_nonnull (bag);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, G_N_ELEMENTS (expected_filtered) - 
1);
+       test_check_property_bag (bag, expected_filtered);
+
+       g_object_unref (icomp);
+
+       icomp = i_cal_component_new_vevent ();
+       g_assert_nonnull (icomp);
+       e_cal_component_property_bag_fill_component (bag, icomp);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ANY_PROPERTY), ==, 
e_cal_component_property_bag_get_count (bag));
+       g_object_unref (icomp);
+
+       bag2 = e_cal_component_property_bag_copy (bag);
+
+       while (e_cal_component_property_bag_get_count (bag) > 1) {
+               e_cal_component_property_bag_remove (bag, 1);
+       }
+
+       e_cal_component_property_bag_assign (bag2, bag);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 
e_cal_component_property_bag_get_count (bag2));
+       e_cal_component_property_bag_free (bag2);
+
+       icomp = i_cal_component_new_vevent ();
+       g_assert_nonnull (icomp);
+       e_cal_component_property_bag_fill_component (bag, icomp);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ANY_PROPERTY), ==, 1);
+       g_object_unref (icomp);
+
+       e_cal_component_property_bag_clear (bag);
+
+       icomp = i_cal_component_new_vevent ();
+       g_assert_nonnull (icomp);
+       e_cal_component_property_bag_fill_component (bag, icomp);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ANY_PROPERTY), ==, 0);
+       g_object_unref (icomp);
+
+       prop = i_cal_property_new_uid ("234");
+       e_cal_component_property_bag_add (bag, prop);
+       g_object_unref (prop);
+
+       prop = i_cal_property_new_status (I_CAL_STATUS_CANCELLED);
+       e_cal_component_property_bag_take (bag, prop);
+
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 2);
+
+       for (ii = 0; ii < 2; ii++) {
+               ICalProperty *prop2;
+
+               prop2 = e_cal_component_property_bag_get (bag, ii);
+               if (ii == 0) {
+                       g_assert (prop != prop2);
+                       g_assert_cmpint (i_cal_property_isa (prop2), ==, I_CAL_UID_PROPERTY);
+                       g_assert_cmpstr (i_cal_property_get_uid (prop2), ==, "234");
+               } else {
+                       g_assert (prop == prop2);
+                       g_assert_cmpint (i_cal_property_isa (prop2), ==, I_CAL_STATUS_PROPERTY);
+                       g_assert_cmpint (i_cal_property_get_status (prop2), ==, I_CAL_STATUS_CANCELLED);
+               }
+       }
+
+       icomp = i_cal_component_new_vevent ();
+       g_assert_nonnull (icomp);
+       e_cal_component_property_bag_fill_component (bag, icomp);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ANY_PROPERTY), ==, 
e_cal_component_property_bag_get_count (bag));
+       g_object_unref (icomp);
+
+       e_cal_component_property_bag_clear (bag);
+
+       e_cal_component_property_bag_take (bag, i_cal_property_new_status (I_CAL_STATUS_CANCELLED));
+       e_cal_component_property_bag_take (bag, i_cal_property_new_uid ("111"));
+       e_cal_component_property_bag_take (bag, i_cal_property_new_status (I_CAL_STATUS_COMPLETED));
+       e_cal_component_property_bag_take (bag, i_cal_property_new_status (I_CAL_STATUS_INPROCESS));
+
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 4);
+       g_assert_cmpint (e_cal_component_property_bag_get_first_by_kind (bag, I_CAL_STATUS_PROPERTY), ==, 0);
+       g_assert_cmpint (e_cal_component_property_bag_get_first_by_kind (bag, I_CAL_UID_PROPERTY), ==, 1);
+       g_assert_cmpint (e_cal_component_property_bag_remove_by_kind (bag, I_CAL_TZID_PROPERTY, FALSE), ==, 
0);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 4);
+       g_assert_cmpint (e_cal_component_property_bag_remove_by_kind (bag, I_CAL_TZID_PROPERTY, TRUE), ==, 0);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 4);
+       g_assert_cmpint (e_cal_component_property_bag_remove_by_kind (bag, I_CAL_STATUS_PROPERTY, FALSE), ==, 
1);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 3);
+       g_assert_cmpint (e_cal_component_property_bag_get_first_by_kind (bag, I_CAL_UID_PROPERTY), ==, 0);
+       g_assert_cmpint (e_cal_component_property_bag_get_first_by_kind (bag, I_CAL_STATUS_PROPERTY), ==, 1);
+       g_assert_cmpint (e_cal_component_property_bag_remove_by_kind (bag, I_CAL_STATUS_PROPERTY, TRUE), ==, 
2);
+       g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 1);
+       g_assert_cmpint (e_cal_component_property_bag_get_first_by_kind (bag, I_CAL_UID_PROPERTY), ==, 0);
+       g_assert_cmpint (e_cal_component_property_bag_get_first_by_kind (bag, I_CAL_STATUS_PROPERTY), >=, 
e_cal_component_property_bag_get_count (bag));
+
+       e_cal_component_property_bag_free (bag);
+}
+
+#undef X_PROP_NAME
+#undef X_PROP_VALUE
+
+static void
+test_component_struct_range (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314", "Europe/Berlin" },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       ECalComponentRangeKind range_kinds[] = {
+               E_CAL_COMPONENT_RANGE_SINGLE,
+               E_CAL_COMPONENT_RANGE_THISPRIOR,
+               E_CAL_COMPONENT_RANGE_THISFUTURE
+       };
+       gint ii, jj, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       for (jj = 0; jj < G_N_ELEMENTS (range_kinds); jj++) {
+                               ECalComponentRange *expected = NULL, *received;
+                               ECalComponentDateTime *dt;
+
+                               if (set_kind == 2) {
+                                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string 
("19981019"), NULL);
+                                       expected = e_cal_component_range_new (E_CAL_COMPONENT_RANGE_SINGLE, 
dt);
+                                       e_cal_component_datetime_free (dt);
+                               } else if (set_kind == 3) {
+                                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string 
("19981019"), NULL);
+                                       expected = e_cal_component_range_new_take 
(E_CAL_COMPONENT_RANGE_SINGLE, dt);
+                               }
+
+                               dt = e_cal_component_datetime_new_take (i_cal_time_from_string 
(values[ii].time), g_strdup (values[ii].tzid));
+                               g_assert_nonnull (dt);
+
+                               if (expected) {
+                                       e_cal_component_range_set_kind (expected, range_kinds[jj]);
+
+                                       if (((set_kind + ii) & 1) != 0) {
+                                               e_cal_component_range_set_datetime (expected, dt);
+                                       } else {
+                                               ECalComponentDateTime *dtcopy;
+
+                                               dtcopy = e_cal_component_datetime_copy (dt);
+                                               g_assert_nonnull (dtcopy);
+
+                                               e_cal_component_range_take_datetime (expected, dtcopy);
+                                       }
+                               } else {
+                                       if (set_kind == 0) {
+                                               expected = e_cal_component_range_new (range_kinds[jj], dt);
+                                       } else {
+                                               ECalComponentDateTime *dtcopy;
+
+                                               dtcopy = e_cal_component_datetime_copy (dt);
+                                               g_assert_nonnull (dtcopy);
+
+                                               expected = e_cal_component_range_new_take (range_kinds[jj], 
dtcopy);
+                                       }
+                               }
+
+                               g_assert_nonnull (expected);
+
+                               verify_struct_datetime_equal (e_cal_component_range_get_datetime (expected), 
dt);
+                               g_assert_cmpint (e_cal_component_range_get_kind (expected), ==, 
range_kinds[jj]);
+
+                               e_cal_component_datetime_free (dt);
+
+                               received = e_cal_component_range_copy (expected);
+                               verify_struct_range_equal (expected, received);
+                               e_cal_component_range_free (received);
+
+                               e_cal_component_range_free (expected);
+                       }
+               }
+       }
+}
+
+static void
+test_component_struct_text (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *altrep;
+       } values[] = {
+               { "value1", NULL },
+               { "value2", "altrep1" },
+               { "value3", "altrep2" },
+               { "value4", NULL }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 3; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentText *expected = NULL, *received;
+
+                       if (set_kind == 1) {
+                               expected = e_cal_component_text_new ("non-empty", NULL);
+                       } else if (set_kind == 2) {
+                               expected = e_cal_component_text_new ("non-empty-text", "non-empty-altrep");
+                       }
+
+                       if (expected) {
+                               e_cal_component_text_set_value (expected, values[ii].value);
+                               e_cal_component_text_set_altrep (expected, values[ii].altrep);
+                       } else {
+                               expected = e_cal_component_text_new (values[ii].value, values[ii].altrep);
+                       }
+
+                       g_assert_nonnull (expected);
+                       g_assert_cmpstr (e_cal_component_text_get_value (expected), ==, values[ii].value);
+                       g_assert_cmpstr (e_cal_component_text_get_altrep (expected), ==, values[ii].altrep);
+
+                       received = e_cal_component_text_copy (expected);
+                       verify_struct_text_equal (expected, received);
+                       e_cal_component_text_free (received);
+
+                       e_cal_component_text_free (expected);
+               }
+       }
+}
+
+static void
+verify_changes (ECalComponent *comp,
+               void (* verify_func) (ECalComponent *comp,
+                                     gpointer user_data),
+               gpointer user_data)
+{
+       ECalComponent *clone;
+       ICalComponent *icalcomp;
+       gchar *icalstr;
+
+       e_cal_component_commit_sequence (comp);
+
+       clone = e_cal_component_clone (comp);
+       g_assert_nonnull (clone);
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       icalstr = e_cal_component_get_as_string (comp);
+       g_assert_nonnull (icalstr);
+       clone = e_cal_component_new_from_string (icalstr);
+       g_free (icalstr);
+       g_assert_nonnull (clone);
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       icalcomp = e_cal_component_get_icalcomponent (comp);
+       g_assert_nonnull (icalcomp);
+       clone = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icalcomp));
+       g_assert_nonnull (clone);
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       icalcomp = e_cal_component_get_icalcomponent (comp);
+       g_assert_nonnull (icalcomp);
+       icalcomp = i_cal_component_new_clone (icalcomp);
+       g_assert_nonnull (icalcomp);
+       clone = e_cal_component_new ();
+       g_assert_nonnull (clone);
+       g_assert (e_cal_component_set_icalcomponent (clone, icalcomp));
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       verify_func (comp, user_data);
+}
+
+static void
+verify_component_vtype (ECalComponent *comp,
+                       gpointer user_data)
+{
+       g_assert_cmpint (e_cal_component_get_vtype (comp), ==, GPOINTER_TO_INT (user_data));
+}
+
+static void
+test_component_vtype (void)
+{
+       ECalComponentVType values[] = {
+               E_CAL_COMPONENT_EVENT,
+               E_CAL_COMPONENT_TODO,
+               E_CAL_COMPONENT_JOURNAL,
+               E_CAL_COMPONENT_FREEBUSY,
+               E_CAL_COMPONENT_TIMEZONE
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new ();
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_new_vtype (comp, values[ii]);
+               verify_changes (comp, verify_component_vtype, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_uid (ECalComponent *comp,
+                     gpointer user_data)
+{
+       const gchar *uid = user_data;
+       ECalComponentId *id;
+
+       g_assert_cmpstr (e_cal_component_get_uid (comp), ==, uid);
+
+       id = e_cal_component_get_id (comp);
+       g_assert_nonnull (id);
+       g_assert_nonnull (e_cal_component_id_get_uid (id));
+       g_assert_null (e_cal_component_id_get_rid (id));
+
+       g_assert_cmpstr (e_cal_component_id_get_uid (id), ==, uid);
+
+       e_cal_component_id_free (id);
+}
+
+static void
+test_component_uid (void)
+{
+       ECalComponent *comp;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       e_cal_component_set_uid (comp, "123");
+       verify_changes (comp, verify_component_uid, (gpointer) "123");
+
+       e_cal_component_set_uid (comp, "456");
+       verify_changes (comp, verify_component_uid, (gpointer) "456");
+
+       g_object_unref (comp);
+}
+
+static GSList * /* gchar * */
+test_split_categories (const gchar *categories)
+{
+       GSList *list = NULL;
+       gchar **split;
+       gint ii;
+
+       if (!categories)
+               return NULL;
+
+       split = g_strsplit (categories, ",", -1);
+       if (split) {
+               for (ii = 0; split[ii]; ii++) {
+                       list = g_slist_prepend (list, g_strdup (split[ii]));
+               }
+
+               g_strfreev (split);
+       }
+
+       return g_slist_reverse (list);
+}
+
+static void
+verify_component_categories (ECalComponent *comp,
+                            gpointer user_data)
+{
+       const gchar *categories = user_data;
+       gchar *categories_str;
+       GSList *expected, *received, *link1, *link2;
+
+       categories_str = e_cal_component_get_categories (comp);
+       g_assert_cmpstr (categories_str, ==, categories);
+       g_free (categories_str);
+
+       expected = test_split_categories (categories);
+       received = e_cal_component_get_categories_list (comp);
+
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received;
+            link1 && link2;
+            link1 = g_slist_next (link1), link2 = g_slist_next (link2)) {
+               g_assert_cmpstr (link1->data, ==, link2->data);
+       }
+
+       g_assert (link1 == link2);
+
+       g_slist_free_full (expected, g_free);
+       g_slist_free_full (received, g_free);
+}
+
+static void
+test_component_categories (void)
+{
+       const gchar *values[] = {
+               "cat01",
+               "cat02",
+               NULL,
+               "cat03,cat04,cat05",
+               "cat06",
+               "cat07,cat08",
+               NULL
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               GSList *list;
+
+               comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+               g_assert_nonnull (comp);
+
+               e_cal_component_set_categories (comp, values[ii]);
+               verify_changes (comp, verify_component_categories, (gpointer) values[ii]);
+
+               g_object_unref (comp);
+
+               comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+               g_assert_nonnull (comp);
+
+               list = test_split_categories (values[ii]);
+               e_cal_component_set_categories_list (comp, list);
+               g_slist_free_full (list, g_free);
+
+               verify_changes (comp, verify_component_categories, (gpointer) values[ii]);
+
+               g_object_unref (comp);
+       }
+}
+
+static void
+verify_component_classification (ECalComponent *comp,
+                                gpointer user_data)
+{
+       g_assert_cmpint (e_cal_component_get_classification (comp), ==, GPOINTER_TO_INT (user_data));
+}
+
+static void
+test_component_classification (void)
+{
+       ECalComponentClassification values[] = {
+               E_CAL_COMPONENT_CLASS_NONE,
+               E_CAL_COMPONENT_CLASS_PUBLIC,
+               E_CAL_COMPONENT_CLASS_PRIVATE,
+               E_CAL_COMPONENT_CLASS_CONFIDENTIAL
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_classification (comp, values[ii]);
+               verify_changes (comp, verify_component_classification, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+/* Each part is separated by ':', text from its altrep is separated by '|' */
+static GSList * /* ECalComponentText * */
+test_split_texts (const gchar *value)
+{
+       GSList *result = NULL;
+       gchar **textsv;
+       gint ii;
+
+       if (!value)
+               return NULL;
+
+       textsv = g_strsplit (value, ":", -1);
+
+       if (textsv) {
+               for (ii = 0; textsv[ii]; ii++) {
+                       ECalComponentText *comptext;
+                       gchar *altrep;
+
+                       altrep = strchr (textsv[ii], '|');
+                       if (altrep) {
+                               *altrep = '\0';
+                               altrep++;
+                       }
+
+                       comptext = e_cal_component_text_new (textsv[ii], altrep);
+                       g_assert_nonnull (comptext);
+                       result = g_slist_prepend (result, comptext);
+               }
+
+               g_strfreev (textsv);
+       }
+
+       return g_slist_reverse (result);
+}
+
+static void
+verify_component_text_list (GSList * (* get_func) (ECalComponent *comp),
+                           ECalComponent *comp,
+                           gpointer user_data)
+{
+       GSList *expected, *received, *link1, *link2;
+
+       g_assert (get_func != NULL);
+
+       expected = user_data;
+       received = get_func (comp);
+
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received;
+            link1 && link2;
+            link1 = g_slist_next (link1), link2 = g_slist_next (link2)) {
+               ECalComponentText *text1 = link1->data, *text2 = link2->data;
+
+               g_assert_nonnull (text1);
+               g_assert_nonnull (text2);
+
+               verify_struct_text_equal (text1, text2);
+       }
+
+       g_assert (link1 == link2);
+
+       g_slist_free_full (received, e_cal_component_text_free);
+}
+
+static void
+test_component_text_list (void (* set_func) (ECalComponent *comp,
+                                            const GSList *values),
+                         void (* verify_func) (ECalComponent *comp,
+                                               gpointer user_data))
+{
+       const gchar *values[] = {
+               "text",
+               "line1\nline2|altrep",
+               "text|altrep",
+               "text1:text2|altrep2:text3a\ntext3b|altrep3",
+               NULL
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       g_assert (set_func != NULL);
+       g_assert (verify_func != NULL);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               GSList *expected = test_split_texts (values[ii]);
+
+               set_func (comp, expected);
+               verify_changes (comp, verify_func, expected);
+
+               g_slist_free_full (expected, e_cal_component_text_free);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_icaltime (ICalTime * (* get_func) (ECalComponent *comp),
+                          ECalComponent *comp,
+                          gpointer user_data)
+{
+       ICalTime *expected, *received;
+
+       g_assert (get_func != NULL);
+
+       expected = user_data;
+       received = get_func (comp);
+
+       verify_ical_timetype_equal (expected, received);
+
+       g_clear_object (&received);
+}
+
+static void
+test_component_icaltime (void (* set_func) (ECalComponent *comp,
+                                           const ICalTime *tt),
+                        void (* verify_func) (ECalComponent *comp,
+                                              gpointer user_data),
+                        gboolean can_null_value)
+{
+       const gchar *values[] = {
+               "20181215T111213Z",
+               "20190131T121314Z",
+               NULL,
+               "20200708T010305Z"
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       g_assert (set_func != NULL);
+       g_assert (verify_func != NULL);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ICalTime *tt;
+
+               if (values[ii]) {
+                       tt = i_cal_time_from_string (values[ii]);
+                       g_assert_nonnull (tt);
+               } else if (!can_null_value) {
+                       continue;
+               } else {
+                       tt = NULL;
+               }
+
+               set_func (comp, tt);
+               verify_changes (comp, verify_func, tt);
+
+               g_clear_object (&tt);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_datetime (ECalComponentDateTime * (* get_func) (ECalComponent *comp),
+                          ECalComponent *comp,
+                          gpointer user_data)
+{
+       ECalComponentDateTime *expected, *received;
+
+       g_assert (get_func != NULL);
+
+       expected = user_data;
+       received = get_func (comp);
+
+       verify_struct_datetime_equal (expected, received);
+
+       e_cal_component_datetime_free (received);
+}
+
+static void
+test_component_datetime (void (* set_func) (ECalComponent *comp,
+                                           const ECalComponentDateTime *dt),
+                        void (* verify_func) (ECalComponent *comp,
+                                              gpointer user_data))
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314Z", NULL },
+               { NULL, NULL },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       g_assert (set_func != NULL);
+       g_assert (verify_func != NULL);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentDateTime *dt;
+
+               if (values[ii].time) {
+                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string (values[ii].time), 
g_strdup (values[ii].tzid));
+                       g_assert_nonnull (dt);
+
+                       if (values[ii].tzid) {
+                               ICalTime *tt;
+                               ICalTimezone *zone;
+
+                               zone = i_cal_timezone_get_builtin_timezone (values[ii].tzid);
+                               if (zone) {
+                                       tt = e_cal_component_datetime_get_value (dt);
+                                       i_cal_time_set_timezone (tt, zone);
+                               }
+                       }
+               } else {
+                       dt = NULL;
+               }
+
+               set_func (comp, dt);
+
+               verify_changes (comp, verify_func, dt);
+
+               e_cal_component_datetime_free (dt);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_rules (GSList * (* get_func) (ECalComponent *comp),
+                       GSList * (* get_props_func) (ECalComponent *comp),
+                       gboolean is_exception,
+                       ECalComponent *comp,
+                       gpointer user_data)
+{
+       GSList *expected, *received, *received_props;
+
+       expected = user_data;
+       received = get_func (comp);
+       received_props = get_props_func (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert_null (received_props);
+               if (is_exception) {
+                       g_assert (!e_cal_component_has_exrules (comp));
+                       g_assert (!e_cal_component_has_exceptions (comp));
+               } else {
+                       g_assert (!e_cal_component_has_rrules (comp));
+                       g_assert (!e_cal_component_has_recurrences (comp));
+                       g_assert (e_cal_component_has_simple_recurrence (comp));
+               }
+       } else {
+               GSList *link1, *link2, *link3;
+
+               if (is_exception) {
+                       g_assert (e_cal_component_has_exrules (comp));
+                       g_assert (e_cal_component_has_exceptions (comp));
+                       g_assert (!e_cal_component_has_rrules (comp));
+               } else {
+                       g_assert (!e_cal_component_has_exrules (comp));
+                       g_assert (!e_cal_component_has_exceptions (comp));
+                       g_assert (e_cal_component_has_rrules (comp));
+                       g_assert (e_cal_component_has_recurrences (comp));
+                       if (expected->next)
+                               g_assert (!e_cal_component_has_simple_recurrence (comp));
+                       else
+                               g_assert (e_cal_component_has_simple_recurrence (comp));
+               }
+
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received_props));
+
+               for (link1 = expected, link2 = received, link3 = received_props;
+                    link1 && link2 && link3;
+                    link1 = g_slist_next (link1), link2 = g_slist_next (link2), link3 = g_slist_next 
(link3)) {
+                       ICalRecurrence *rt_expected, *rt_received, *rt_received_prop;
+                       ICalProperty *prop_received;
+                       gchar *str_expected, *str_received, *str_received_prop;
+
+                       rt_expected = link1->data;
+                       rt_received = link2->data;
+                       prop_received = link3->data;
+
+                       if (is_exception) {
+                               rt_received_prop = i_cal_property_get_exrule (prop_received);
+                       } else {
+                               rt_received_prop = i_cal_property_get_rrule (prop_received);
+                       }
+
+                       str_expected = i_cal_recurrence_as_string_r (rt_expected);
+                       str_received = i_cal_recurrence_as_string_r (rt_received);
+                       str_received_prop = i_cal_recurrence_as_string_r (rt_received_prop);
+
+                       g_assert_cmpstr (str_expected, ==, str_received);
+                       g_assert_cmpstr (str_expected, ==, str_received_prop);
+
+                       g_free (str_expected);
+                       g_free (str_received);
+                       g_free (str_received_prop);
+                       g_clear_object (&rt_received_prop);
+               }
+
+               g_assert (link1 == link2);
+               g_assert (link2 == link3);
+       }
+
+       g_slist_free_full (received, g_object_unref);
+       g_slist_free_full (received_props, g_object_unref);
+}
+
+static void
+test_component_rules (void (* set_func) (ECalComponent *comp,
+                                        const GSList *recur_list),
+                     void (* verify_func) (ECalComponent *comp,
+                                           gpointer user_data))
+{
+       const gchar *values[] = {
+               "FREQ=DAILY;COUNT=10;INTERVAL=6",
+               NULL, /* terminator */
+               NULL, /* terminator */
+               "FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3",
+               "FREQ=DAILY;BYDAY=1SU",
+               NULL /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *rules = NULL;
+       gint ii;
+
+       g_assert_nonnull (set_func);
+       g_assert_nonnull (verify_func);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii]) {
+                       ICalRecurrence *rt;
+
+                       rt = i_cal_recurrence_from_string (values[ii]);
+                       g_assert_nonnull (rt);
+
+                       rules = g_slist_prepend (rules, rt);
+               } else {
+                       rules = g_slist_reverse (rules);
+
+                       set_func (comp, rules);
+                       verify_changes (comp, verify_func, rules);
+
+                       g_slist_free_full (rules, g_object_unref);
+                       rules = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (rules);
+}
+
+static void
+verify_component_comments (ECalComponent *comp,
+                          gpointer user_data)
+{
+       verify_component_text_list (e_cal_component_get_comments, comp, user_data);
+}
+
+static void
+test_component_comments (void)
+{
+       test_component_text_list (e_cal_component_set_comments, verify_component_comments);
+}
+
+static void
+verify_component_completed (ECalComponent *comp,
+                           gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_completed, comp, user_data);
+}
+
+static void
+test_component_completed (void)
+{
+       test_component_icaltime (e_cal_component_set_completed, verify_component_completed, TRUE);
+}
+
+static void
+verify_component_contacts (ECalComponent *comp,
+                          gpointer user_data)
+{
+       verify_component_text_list (e_cal_component_get_contacts, comp, user_data);
+}
+
+static void
+test_component_contacts (void)
+{
+       test_component_text_list (e_cal_component_set_contacts, verify_component_contacts);
+}
+
+static void
+verify_component_created (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_created, comp, user_data);
+}
+
+static void
+test_component_created (void)
+{
+       test_component_icaltime (e_cal_component_set_created, verify_component_created, TRUE);
+}
+
+static void
+verify_component_descriptions (ECalComponent *comp,
+                              gpointer user_data)
+{
+       verify_component_text_list (e_cal_component_get_descriptions, comp, user_data);
+}
+
+static void
+test_component_descriptions (void)
+{
+       test_component_text_list (e_cal_component_set_descriptions, verify_component_descriptions);
+}
+
+static void
+verify_component_dtend (ECalComponent *comp,
+                       gpointer user_data)
+{
+       verify_component_datetime (e_cal_component_get_dtend, comp, user_data);
+}
+
+static void
+test_component_dtend (void)
+{
+       test_component_datetime (e_cal_component_set_dtend, verify_component_dtend);
+}
+
+static void
+verify_component_dtstamp (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_dtstamp, comp, user_data);
+}
+
+static void
+test_component_dtstamp (void)
+{
+       test_component_icaltime (e_cal_component_set_dtstamp, verify_component_dtstamp, FALSE);
+}
+
+static void
+verify_component_dtstart (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_datetime (e_cal_component_get_dtstart, comp, user_data);
+}
+
+static void
+test_component_dtstart (void)
+{
+       test_component_datetime (e_cal_component_set_dtstart, verify_component_dtstart);
+}
+
+static void
+verify_component_due (ECalComponent *comp,
+                     gpointer user_data)
+{
+       verify_component_datetime (e_cal_component_get_due, comp, user_data);
+}
+
+static void
+test_component_due (void)
+{
+       test_component_datetime (e_cal_component_set_due, verify_component_due);
+}
+
+static void
+verify_component_exdates (ECalComponent *comp,
+                         gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_exdates (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_exdates (comp));
+               g_assert (!e_cal_component_has_exceptions (comp));
+       } else {
+               GSList *link1, *link2;
+
+               g_assert (e_cal_component_has_exdates (comp));
+               g_assert (e_cal_component_has_exceptions (comp));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 
= g_slist_next (link2)) {
+                       ECalComponentDateTime *dt_expected = link1->data, *dt_received = link2->data;
+
+                       verify_struct_datetime_equal (dt_expected, dt_received);
+               }
+
+               g_assert (link1 == link2);
+       }
+
+       g_slist_free_full (received, e_cal_component_datetime_free);
+}
+
+static void
+test_component_exdates (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314Z", NULL },
+               { NULL, NULL }, /* terminator */
+               { NULL, NULL }, /* terminator */
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL },
+               { NULL, NULL } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *exdates = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].time) {
+                       ECalComponentDateTime *dt;
+
+                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string (values[ii].time), 
g_strdup (values[ii].tzid));
+                       g_assert_nonnull (dt);
+
+                       if (values[ii].tzid) {
+                               ICalTime *tt;
+                               ICalTimezone *zone;
+
+                               zone = i_cal_timezone_get_builtin_timezone (values[ii].tzid);
+                               if (zone) {
+                                       tt = e_cal_component_datetime_get_value (dt);
+                                       i_cal_time_set_timezone (tt, zone);
+                               }
+                       }
+
+                       exdates = g_slist_prepend (exdates, dt);
+               } else {
+                       exdates = g_slist_reverse (exdates);
+
+                       e_cal_component_set_exdates (comp, exdates);
+                       verify_changes (comp, verify_component_exdates, exdates);
+
+                       g_slist_free_full (exdates, e_cal_component_datetime_free);
+                       exdates = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (exdates);
+}
+
+static void
+verify_component_exrules (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_rules (e_cal_component_get_exrules, e_cal_component_get_exrule_properties, TRUE, 
comp, user_data);
+}
+
+static void
+test_component_exrules (void)
+{
+       test_component_rules (e_cal_component_set_exrules, verify_component_exrules);
+}
+
+static void
+verify_component_geo (ECalComponent *comp,
+                     gpointer user_data)
+{
+       ICalGeo *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_geo (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+       } else {
+               g_assert_nonnull (received);
+               g_assert_cmpfloat (i_cal_geo_get_lat (expected), ==, i_cal_geo_get_lat (received));
+               g_assert_cmpfloat (i_cal_geo_get_lon (expected), ==, i_cal_geo_get_lon (received));
+       }
+
+       g_clear_object (&received);
+}
+
+static void
+test_component_geo (void)
+{
+       struct _values {
+               gdouble lat;
+               gdouble lon;
+       } values[] = {
+               { 10.0, 20.0 },
+               { -1.0, -1.0 },
+               { 50.0, 30.0 }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ICalGeo *geo = NULL;
+
+               if (values[ii].lat > 0.0)
+                       geo = i_cal_geo_new (values[ii].lat, values[ii].lon);
+
+               e_cal_component_set_geo (comp, geo);
+               verify_changes (comp, verify_component_geo, geo);
+
+               g_clear_object (&geo);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_lastmodified (ECalComponent *comp,
+                              gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_last_modified, comp, user_data);
+}
+
+static void
+test_component_lastmodified (void)
+{
+       test_component_icaltime (e_cal_component_set_last_modified, verify_component_lastmodified, TRUE);
+}
+
+static void
+verify_component_organizer (ECalComponent *comp,
+                           gpointer user_data)
+{
+       ECalComponentOrganizer *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_organizer (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_organizer (comp));
+       } else {
+               g_assert_nonnull (received);
+               g_assert (e_cal_component_has_organizer (comp));
+               verify_struct_organizer_equal (expected, received);
+       }
+
+       e_cal_component_organizer_free (received);
+}
+
+static void
+test_component_organizer (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "mailto:org1";, NULL, "First Organizer", NULL },
+               { NULL, NULL, NULL, NULL },
+               { "mailto:org2","mailto:sentby2";, "Second Organizer", "en_US" }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentOrganizer *org = NULL;
+
+               if (values[ii].value) {
+                       org = e_cal_component_organizer_new_full (values[ii].value, values[ii].sentby, 
values[ii].cn, values[ii].language);
+
+                       if (ii == 0)
+                               test_component_add_params_to_bag (e_cal_component_organizer_get_parameter_bag 
(org), ii + 1);
+               }
+
+               e_cal_component_set_organizer (comp, org);
+               verify_changes (comp, verify_component_organizer, org);
+
+               e_cal_component_organizer_free (org);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_percentcomplete (ECalComponent *comp,
+                                 gpointer user_data)
+{
+       gint expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_percent_complete (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_percentcomplete (void)
+{
+       gint values[] = { 10, -1, 13, 0, 78, 99, -1, 100 };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_percent_complete (comp, values[ii]);
+               verify_changes (comp, verify_component_percentcomplete, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_priority (ECalComponent *comp,
+                          gpointer user_data)
+{
+       gint expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_priority (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_priority (void)
+{
+       gint values[] = { 8, 7, 6, 5, -1, 4, 3, 2, 1, 0, -1, 9 };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_priority (comp, values[ii]);
+               verify_changes (comp, verify_component_priority, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_recurid (ECalComponent *comp,
+                         gpointer user_data)
+{
+       ECalComponentRange *expected, *received;
+       ECalComponentId *id;
+       gchar *rid_str;
+
+       expected = user_data;
+       received = e_cal_component_get_recurid (comp);
+       rid_str = e_cal_component_get_recurid_as_string (comp);
+       id = e_cal_component_get_id (comp);
+
+       g_assert_nonnull (id);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert_null (rid_str);
+               g_assert_null (e_cal_component_id_get_rid (id));
+               g_assert (!e_cal_component_is_instance (comp));
+       } else {
+               g_assert_nonnull (rid_str);
+               g_assert_nonnull (e_cal_component_id_get_rid (id));
+               g_assert (e_cal_component_is_instance (comp));
+               g_assert_cmpstr (e_cal_component_id_get_rid (id), ==, rid_str);
+
+               verify_struct_range_equal (expected, received);
+       }
+
+       e_cal_component_range_free (received);
+       e_cal_component_id_free (id);
+       g_free (rid_str);
+}
+
+static void
+test_component_recurid (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314Z", NULL },
+               { NULL, NULL },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentRange *rid = NULL;
+
+               if (values[ii].time) {
+                       ECalComponentDateTime *dt;
+
+                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string (values[ii].time), 
g_strdup (values[ii].tzid));
+                       g_assert_nonnull (dt);
+
+                       if (values[ii].tzid) {
+                               ICalTime *tt;
+                               ICalTimezone *zone;
+
+                               zone = i_cal_timezone_get_builtin_timezone (values[ii].tzid);
+                               if (zone) {
+                                       tt = e_cal_component_datetime_get_value (dt);
+                                       i_cal_time_set_timezone (tt, zone);
+                               }
+                       }
+
+                       rid = e_cal_component_range_new_take (E_CAL_COMPONENT_RANGE_SINGLE, dt);
+               }
+
+               e_cal_component_set_recurid (comp, rid);
+               verify_changes (comp, verify_component_recurid, rid);
+
+               e_cal_component_range_free (rid);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_rdates (ECalComponent *comp,
+                        gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_rdates (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_rdates (comp));
+               g_assert (!e_cal_component_has_recurrences (comp));
+       } else {
+               GSList *link1, *link2;
+
+               g_assert (e_cal_component_has_rdates (comp));
+               g_assert (e_cal_component_has_recurrences (comp));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 
= g_slist_next (link2)) {
+                       ECalComponentPeriod *period_expected = link1->data, *period_received = link2->data;
+
+                       verify_struct_period_equal (period_expected, period_received);
+               }
+
+               g_assert (link1 == link2);
+       }
+
+       g_slist_free_full (received, e_cal_component_period_free);
+}
+
+static void
+test_component_rdates (void)
+{
+       struct _values {
+               const gchar *start;
+               const gchar *end;
+               gint duration;
+       } values[] = {
+               { "20181215T111213Z", "20181215T121314Z", -1 },
+               { "20190131T121314Z", NULL, 10 * 24 * 60 * 60 },
+               { NULL, NULL, -1 }, /* terminator */
+               { NULL, NULL, -1 }, /* terminator */
+               { "20200708T010305Z", NULL, 2 * 60 * 60 },
+               { "20211215T101112", "20211215T121314", -1 },
+               { "20221110T090807", "20221110T100908", -1 },
+               { "20231009", "20241110", -1 },
+               { NULL, NULL, -1 }, /* terminator */
+               { "20240908T070605", NULL, -1 },
+               { "20250807", NULL, -1 },
+               { NULL, NULL, -1 } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *rdates = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].start) {
+                       ICalTime *start, *end = NULL;
+                       ICalDuration *duration = NULL;
+                       ECalComponentPeriod *period;
+
+                       start = i_cal_time_from_string (values[ii].start);
+                       g_assert_nonnull (start);
+                       if (values[ii].duration == -1) {
+                               if (values[ii].end) {
+                                       end = i_cal_time_from_string (values[ii].end);
+                                       g_assert_nonnull (end);
+                               }
+                               period = e_cal_component_period_new_datetime (start, end);
+                       } else {
+                               duration = i_cal_duration_from_int (values[ii].duration);
+                               g_assert_nonnull (duration);
+                               period = e_cal_component_period_new_duration (start, duration);
+                       }
+
+                       g_assert_nonnull (period);
+
+                       rdates = g_slist_prepend (rdates, period);
+
+                       g_clear_object (&start);
+                       g_clear_object (&end);
+                       g_clear_object (&duration);
+               } else {
+                       rdates = g_slist_reverse (rdates);
+
+                       e_cal_component_set_rdates (comp, rdates);
+                       verify_changes (comp, verify_component_rdates, rdates);
+
+                       g_slist_free_full (rdates, e_cal_component_period_free);
+                       rdates = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (rdates);
+}
+
+static void
+verify_component_rrules (ECalComponent *comp,
+                        gpointer user_data)
+{
+       verify_component_rules (e_cal_component_get_rrules, e_cal_component_get_rrule_properties, FALSE, 
comp, user_data);
+}
+
+static void
+test_component_rrules (void)
+{
+       test_component_rules (e_cal_component_set_rrules, verify_component_rrules);
+}
+
+static void
+verify_component_sequence (ECalComponent *comp,
+                          gpointer user_data)
+{
+       gint expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_sequence (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_sequence (void)
+{
+       gint values[] = { 8, 7, 6, 5, -1, 4, 3, 2, 1, 0, -1, 9 };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_sequence (comp, values[ii]);
+               e_cal_component_abort_sequence (comp);
+               verify_changes (comp, verify_component_sequence, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_status (ECalComponent *comp,
+                        gpointer user_data)
+{
+       ICalPropertyStatus expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_status (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_status (void)
+{
+       ICalPropertyStatus values[] = {
+               I_CAL_STATUS_TENTATIVE,
+               I_CAL_STATUS_CONFIRMED,
+               I_CAL_STATUS_COMPLETED,
+               I_CAL_STATUS_NEEDSACTION,
+               I_CAL_STATUS_CANCELLED,
+               I_CAL_STATUS_INPROCESS,
+               I_CAL_STATUS_DRAFT,
+               I_CAL_STATUS_FINAL,
+               I_CAL_STATUS_NONE
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_status (comp, values[ii]);
+               verify_changes (comp, verify_component_status, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_summary (ECalComponent *comp,
+                         gpointer user_data)
+{
+       ECalComponentText *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_summary (comp);
+
+       if (expected) {
+               g_assert_nonnull (received);
+               verify_struct_text_equal (expected, received);
+       } else {
+               g_assert_null (received);
+       }
+
+       e_cal_component_text_free (received);
+}
+
+static void
+test_component_summary (void)
+{
+       const gchar *values[] = {
+               "text",
+               "line1\nline2|altrep",
+               "text|altrep",
+               NULL,
+               "text1:text2|altrep2:text3a\ntext3b|altrep3"
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               GSList *expected = test_split_texts (values[ii]), *link;
+
+               if (expected) {
+                       for (link = expected; link; link = g_slist_next (link)) {
+                               ECalComponentText *text = link->data;
+
+                               e_cal_component_set_summary (comp, text);
+                               verify_changes (comp, verify_component_summary, text);
+                       }
+               } else {
+                       e_cal_component_set_summary (comp, NULL);
+                       verify_changes (comp, verify_component_summary, NULL);
+               }
+
+               g_slist_free_full (expected, e_cal_component_text_free);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_transparency (ECalComponent *comp,
+                              gpointer user_data)
+{
+       ECalComponentTransparency expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_transparency (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_transparency (void)
+{
+       ECalComponentTransparency values[] = {
+               E_CAL_COMPONENT_TRANSP_TRANSPARENT,
+               E_CAL_COMPONENT_TRANSP_NONE,
+               E_CAL_COMPONENT_TRANSP_OPAQUE
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_transparency (comp, values[ii]);
+               verify_changes (comp, verify_component_transparency, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_url (ECalComponent *comp,
+                     gpointer user_data)
+{
+       gchar *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_url (comp);
+
+       g_assert_cmpstr (expected, ==, received);
+
+       g_free (received);
+}
+
+static void
+test_component_url (void)
+{
+       const gchar *values[] = {
+               "https://www.gnome.org";,
+               NULL,
+               "https://wiki.gnome.org/Apps/Evolution";
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_url (comp, values[ii]);
+               verify_changes (comp, verify_component_url, (gpointer) values[ii]);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_attendees (ECalComponent *comp,
+                           gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_attendees (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_attendees (comp));
+       } else {
+               GSList *link1, *link2;
+
+               g_assert_nonnull (received);
+               g_assert (e_cal_component_has_attendees (comp));
+
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 
= g_slist_next (link2)) {
+                       ECalComponentAttendee *att_expected = link1->data, *att_received = link2->data;
+
+                       verify_struct_attendee_equal (att_expected, att_received);
+               }
+
+               g_assert (link1 == link2);
+       }
+
+       g_slist_free_full (received, e_cal_component_attendee_free);
+}
+
+static void
+test_component_attendees (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *member;
+               ICalParameterCutype cutype;
+               ICalParameterRole role;
+               ICalParameterPartstat partstat;
+               gboolean rsvp;
+               const gchar *delegatedfrom;
+               const gchar *delegatedto;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+               gboolean with_parameters;
+       } values[] = {
+               { "mailto:att1";,
+                  "member",
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_CHAIR,
+                  I_CAL_PARTSTAT_NEEDSACTION,
+                  FALSE,
+                  "mailto:delgfrom";,
+                  "mailto:delgto";,
+                  "mailto:sentby";,
+                  "First attendee",
+                  "en_US",
+                  FALSE },
+               { NULL, NULL, I_CAL_CUTYPE_NONE, I_CAL_ROLE_NONE, I_CAL_PARTSTAT_NONE, FALSE, NULL, NULL, 
NULL, NULL, NULL, FALSE }, /* terminator */
+               { NULL, NULL, I_CAL_CUTYPE_NONE, I_CAL_ROLE_NONE, I_CAL_PARTSTAT_NONE, FALSE, NULL, NULL, 
NULL, NULL, NULL, FALSE }, /* terminator */
+               { "mailto:room";,
+                  NULL,
+                  I_CAL_CUTYPE_ROOM,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_ACCEPTED,
+                  FALSE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "Meeting room",
+                  NULL,
+                  TRUE },
+               { "mailto:att2";,
+                  NULL,
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_TENTATIVE,
+                  TRUE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "en_US",
+                  FALSE },
+               { NULL, NULL, I_CAL_CUTYPE_NONE, I_CAL_ROLE_NONE, I_CAL_PARTSTAT_NONE, FALSE, NULL, NULL, 
NULL, NULL, NULL, FALSE } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *attendees = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].value) {
+                       ECalComponentAttendee *att;
+
+                       att = e_cal_component_attendee_new_full (values[ii].value,
+                               values[ii].member,
+                               values[ii].cutype,
+                               values[ii].role,
+                               values[ii].partstat,
+                               values[ii].rsvp,
+                               values[ii].delegatedfrom,
+                               values[ii].delegatedto,
+                               values[ii].sentby,
+                               values[ii].cn,
+                               values[ii].language);
+
+                       if (values[ii].with_parameters)
+                               test_component_add_params_to_bag (e_cal_component_attendee_get_parameter_bag 
(att), ii + 1);
+
+                       attendees = g_slist_prepend (attendees, att);
+               } else {
+                       attendees = g_slist_reverse (attendees);
+
+                       e_cal_component_set_attendees (comp, attendees);
+                       verify_changes (comp, verify_component_attendees, attendees);
+
+                       g_slist_free_full (attendees, e_cal_component_attendee_free);
+                       attendees = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (attendees);
+}
+
+static void
+verify_component_location (ECalComponent *comp,
+                          gpointer user_data)
+{
+       gchar *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_location (comp);
+
+       g_assert_cmpstr (expected, ==, received);
+
+       g_free (received);
+}
+
+static void
+test_component_location (void)
+{
+       const gchar *values[] = {
+               "Headquarter",
+               NULL,
+               "Phone call, +123-456-7890"
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_location (comp, values[ii]);
+               verify_changes (comp, verify_component_location, (gpointer) values[ii]);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_attachments (ECalComponent *comp,
+                             gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_attachments (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_attachments (comp));
+       } else {
+               ECalComponent *clone;
+
+               g_assert_nonnull (received);
+               g_assert (e_cal_component_has_attachments (comp));
+
+               verify_ical_attach_list_equal (expected, received);
+
+               /* Also test whether the attachments can be accessed after the component is freed */
+               clone = e_cal_component_clone (comp);
+               g_assert_nonnull (clone);
+
+               g_slist_free_full (received, g_object_unref);
+               received = e_cal_component_get_attachments (clone);
+
+               g_object_unref (clone);
+
+               g_assert_nonnull (received);
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               verify_ical_attach_list_equal (expected, received);
+       }
+
+       g_slist_free_full (received, g_object_unref);
+}
+
+static void
+test_component_attachments (void)
+{
+       struct _values {
+               gboolean is_url;
+               const gchar *content;
+       } values[] = {
+               { TRUE, "https://www.gnome.org/index.html"; },
+               { FALSE, NULL }, /* terminator */
+               { FALSE, NULL }, /* terminator */
+               { FALSE, "0123456789ABCDEF" },
+               { TRUE, "http://www.example.com/files/data.dat"; },
+               { FALSE, NULL } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *attachments = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].content) {
+                       ICalAttach *attach;
+
+                       if (values[ii].is_url)
+                               attach = i_cal_attach_new_from_url (values[ii].content);
+                       else
+                               attach = i_cal_attach_new_from_data (values[ii].content, NULL, NULL);
+
+                       g_assert_nonnull (attach);
+
+                       attachments = g_slist_prepend (attachments, attach);
+               } else {
+                       attachments = g_slist_reverse (attachments);
+
+                       e_cal_component_set_attachments (comp, attachments);
+                       verify_changes (comp, verify_component_attachments, attachments);
+
+                       g_slist_free_full (attachments, g_object_unref);
+                       attachments = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (attachments);
+}
+
+static void
+verify_component_alarms (ECalComponent *comp,
+                        gpointer user_data)
+{
+       GSList *expected, *received, *received_uids;
+
+       expected = user_data;
+       received = e_cal_component_get_all_alarms (comp);
+       received_uids = e_cal_component_get_alarm_uids (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert_null (received_uids);
+               g_assert (!e_cal_component_has_alarms (comp));
+       } else {
+               GSList *link1, *link2, *link3;
+
+               g_assert_nonnull (received);
+               g_assert_nonnull (received_uids);
+               g_assert (e_cal_component_has_alarms (comp));
+
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received_uids));
+
+               for (link1 = expected, link2 = received, link3 = received_uids;
+                    link1 && link2 && link3;
+                    link1 = g_slist_next (link1), link2 = g_slist_next (link2), link3 = g_slist_next 
(link3)) {
+                       const ECalComponentAlarm *al_expected = link1->data;
+                       const ECalComponentAlarm *al_received = link2->data;
+                       const gchar *uid_received = link3->data;
+
+                       g_assert_nonnull (al_expected);
+                       g_assert_nonnull (al_received);
+                       g_assert_nonnull (uid_received);
+
+                       g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), ==, uid_received);
+                       g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), ==, 
e_cal_component_alarm_get_uid (al_received));
+
+                       verify_struct_alarm_equal (al_expected, al_received);
+               }
+
+               g_assert (link1 == link2);
+               g_assert (link1 == link3);
+
+               if (expected->next) {
+                       ECalComponentAlarm *al_expected;
+                       ECalComponentAlarm *al_received;
+
+                       al_expected = expected->next->data;
+                       al_received = e_cal_component_get_alarm (comp, e_cal_component_alarm_get_uid 
(al_expected));
+
+                       g_assert_nonnull (al_expected);
+                       g_assert_nonnull (al_received);
+                       g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), ==, 
e_cal_component_alarm_get_uid (al_received));
+
+                       e_cal_component_remove_alarm (comp, e_cal_component_alarm_get_uid (al_expected));
+
+                       e_cal_component_alarm_free (al_received);
+
+                       g_slist_free_full (received, e_cal_component_alarm_free);
+                       g_slist_free_full (received_uids, g_free);
+
+                       g_assert (e_cal_component_has_alarms (comp));
+
+                       received = e_cal_component_get_all_alarms (comp);
+                       received_uids = e_cal_component_get_alarm_uids (comp);
+
+                       g_assert_cmpint (g_slist_length (expected) - 1, ==, g_slist_length (received));
+                       g_assert_cmpint (g_slist_length (expected) - 1, ==, g_slist_length (received_uids));
+
+                       for (link1 = received, link2 = received_uids;
+                            link1 && link2;
+                            link1 = g_slist_next (link1), link2 = g_slist_next (link2)) {
+                               const gchar *uid_received;
+
+                               al_received = link1->data;
+                               uid_received = link2->data;
+
+                               g_assert_nonnull (al_received);
+                               g_assert_nonnull (uid_received);
+                               g_assert_cmpstr (e_cal_component_alarm_get_uid (al_received), ==, 
uid_received);
+                               g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), !=, 
uid_received);
+                               g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), !=, 
e_cal_component_alarm_get_uid (al_received));
+                       }
+
+                       g_assert (link1 == link2);
+               } else {
+                       e_cal_component_remove_alarm (comp, e_cal_component_alarm_get_uid (expected->data));
+
+                       g_assert (!e_cal_component_has_alarms (comp));
+                       g_assert_null (e_cal_component_get_all_alarms (comp));
+                       g_assert_null (e_cal_component_get_alarm_uids (comp));
+               }
+       }
+
+       g_slist_free_full (received, e_cal_component_alarm_free);
+       g_slist_free_full (received_uids, g_free);
+}
+
+static void
+test_component_alarms (void)
+{
+       struct _values {
+               const gchar *uid;
+               ECalComponentAlarmAction action;
+               const gchar *description;
+               gint trigger;
+               gboolean trigger_with_parameters;
+       } values[] = {
+               { "alarm1", E_CAL_COMPONENT_ALARM_DISPLAY, "display reminder", -5, TRUE },
+               { NULL, E_CAL_COMPONENT_ALARM_NONE, NULL, 0, FALSE }, /* terminator */
+               { NULL, E_CAL_COMPONENT_ALARM_NONE, NULL, 0, FALSE }, /* terminator */
+               { "alarm2", E_CAL_COMPONENT_ALARM_AUDIO, "audio reminder", 10, FALSE },
+               { "alarm3", E_CAL_COMPONENT_ALARM_EMAIL, "email reminder", 0, TRUE },
+               { "alarm4", E_CAL_COMPONENT_ALARM_PROCEDURE, "procedure reminder", -30, FALSE },
+               { NULL, E_CAL_COMPONENT_ALARM_NONE, NULL, 0, FALSE }, /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *alarms = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].uid) {
+                       ECalComponentAlarm *alarm;
+                       ECalComponentAlarmTriggerKind kind;
+                       ICalDuration *duration;
+
+                       duration = i_cal_duration_from_int (values[ii].trigger * 60);
+                       if (values[ii].trigger < 0)
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
+                       else
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END;
+
+                       alarm = e_cal_component_alarm_new ();
+                       e_cal_component_alarm_set_uid (alarm, values[ii].uid);
+                       e_cal_component_alarm_set_action (alarm, values[ii].action);
+                       e_cal_component_alarm_take_description (alarm, e_cal_component_text_new 
(values[ii].description, NULL));
+                       e_cal_component_alarm_take_trigger (alarm, e_cal_component_alarm_trigger_new_relative 
(kind, duration));
+
+                       if (values[ii].trigger_with_parameters) {
+                               ECalComponentAlarmTrigger *trigger;
+
+                               trigger = e_cal_component_alarm_get_trigger (alarm);
+                               test_component_add_params_to_bag 
(e_cal_component_alarm_trigger_get_parameter_bag (trigger), ii + 1);
+                       }
+
+                       if (values[ii].trigger < 0) {
+                               ECalComponentPropertyBag *bag;
+                               ICalProperty *prop;
+
+                               bag = e_cal_component_alarm_get_property_bag (alarm);
+
+                               prop = i_cal_property_new_url ("https://www.gnome.org";);
+                               e_cal_component_property_bag_take (bag, prop);
+
+                               prop = i_cal_property_new_carlevel (I_CAL_CARLEVEL_CARFULL1);
+                               e_cal_component_property_bag_take (bag, prop);
+
+                               g_assert_cmpint (e_cal_component_property_bag_get_count (bag), ==, 2);
+                       }
+
+                       e_cal_component_add_alarm (comp, alarm);
+                       alarms = g_slist_prepend (alarms, alarm);
+
+                       g_object_unref (duration);
+               } else {
+                       alarms = g_slist_reverse (alarms);
+
+                       verify_changes (comp, verify_component_alarms, alarms);
+
+                       e_cal_component_remove_all_alarms (comp);
+                       g_slist_free_full (alarms, e_cal_component_alarm_free);
+                       alarms = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (alarms);
+}
+
+static void
+test_component_striperrors (void)
+{
+       const gchar *vevent =
+               "BEGIN:VEVENT\r\n"
+               "DTSTART:20150102T100000Z\r\n"
+               "DTEND:20150102T100100Z\r\n"
+               "DTSTAMP:20150108T132939Z\r\n"
+               "UID:123\r\n"
+               "CREATED:20150102T181646Z\r\n"
+               "X-LIC-ERROR;X-LIC-ERRORTYPE=VALUE-PARSE-ERROR:No value for DESCRIPTION \r\n"
+               " property. Removing entire property:\r\n"
+               "LAST-MODIFIED:20150102T181722Z\r\n"
+               "X-LIC-ERROR;X-LIC-ERRORTYPE=VALUE-PARSE-ERROR:No value for LOCATION \r\n"
+               " property. Removing entire property:\r\n"
+               "SUMMARY:with errors\r\n"
+               "END:VEVENT\r\n";
+       ECalComponent *comp;
+       ICalComponent *icalcomp;
+
+       comp = e_cal_component_new_from_string (vevent);
+       g_assert_nonnull (comp);
+
+       icalcomp = e_cal_component_get_icalcomponent (comp);
+       g_assert_nonnull (icalcomp);
+
+       g_assert_cmpint (i_cal_component_count_properties (icalcomp, I_CAL_XLICERROR_PROPERTY), ==, 2);
+
+       e_cal_component_strip_errors (comp);
+
+       g_assert_cmpint (i_cal_component_count_properties (icalcomp, I_CAL_XLICERROR_PROPERTY), ==, 0);
+
+       g_object_unref (comp);
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       g_test_init (&argc, &argv, NULL);
+       g_test_bug_base ("https://bugzilla.gnome.org/";);
+
+       g_test_add_func ("/ECalComponent/struct/Alarm", test_component_struct_alarm);
+       g_test_add_func ("/ECalComponent/struct/Alarms", test_component_struct_alarms);
+       g_test_add_func ("/ECalComponent/struct/AlarmInstance", test_component_struct_alarm_instance);
+       g_test_add_func ("/ECalComponent/struct/AlarmRepeat", test_component_struct_alarm_repeat);
+       g_test_add_func ("/ECalComponent/struct/AlarmTrigger", test_component_struct_alarm_trigger);
+       g_test_add_func ("/ECalComponent/struct/Attendee", test_component_struct_attendee);
+       g_test_add_func ("/ECalComponent/struct/DateTime", test_component_struct_datetime);
+       g_test_add_func ("/ECalComponent/struct/Id", test_component_struct_id);
+       g_test_add_func ("/ECalComponent/struct/Organizer", test_component_struct_organizer);
+       g_test_add_func ("/ECalComponent/struct/ParameterBag", test_component_struct_parameter_bag);
+       g_test_add_func ("/ECalComponent/struct/Period", test_component_struct_period);
+       g_test_add_func ("/ECalComponent/struct/PropertyBag", test_component_struct_property_bag);
+       g_test_add_func ("/ECalComponent/struct/Range", test_component_struct_range);
+       g_test_add_func ("/ECalComponent/struct/Text", test_component_struct_text);
+       g_test_add_func ("/ECalComponent/vtype", test_component_vtype);
+       g_test_add_func ("/ECalComponent/uid", test_component_uid);
+       g_test_add_func ("/ECalComponent/categories", test_component_categories);
+       g_test_add_func ("/ECalComponent/classification", test_component_classification);
+       g_test_add_func ("/ECalComponent/comments", test_component_comments);
+       g_test_add_func ("/ECalComponent/completed", test_component_completed);
+       g_test_add_func ("/ECalComponent/contacts", test_component_contacts);
+       g_test_add_func ("/ECalComponent/created", test_component_created);
+       g_test_add_func ("/ECalComponent/descriptions", test_component_descriptions);
+       g_test_add_func ("/ECalComponent/dtend", test_component_dtend);
+       g_test_add_func ("/ECalComponent/dtstamp", test_component_dtstamp);
+       g_test_add_func ("/ECalComponent/dtstart", test_component_dtstart);
+       g_test_add_func ("/ECalComponent/due", test_component_due);
+       g_test_add_func ("/ECalComponent/exdates", test_component_exdates);
+       g_test_add_func ("/ECalComponent/exrules", test_component_exrules);
+       g_test_add_func ("/ECalComponent/geo", test_component_geo);
+       g_test_add_func ("/ECalComponent/lastmodified", test_component_lastmodified);
+       g_test_add_func ("/ECalComponent/organizer", test_component_organizer);
+       g_test_add_func ("/ECalComponent/percentcomplete", test_component_percentcomplete);
+       g_test_add_func ("/ECalComponent/priority", test_component_priority);
+       g_test_add_func ("/ECalComponent/recurid", test_component_recurid);
+       g_test_add_func ("/ECalComponent/rdates", test_component_rdates);
+       g_test_add_func ("/ECalComponent/rrules", test_component_rrules);
+       g_test_add_func ("/ECalComponent/sequence", test_component_sequence);
+       g_test_add_func ("/ECalComponent/status", test_component_status);
+       g_test_add_func ("/ECalComponent/summary", test_component_summary);
+       g_test_add_func ("/ECalComponent/transparency", test_component_transparency);
+       g_test_add_func ("/ECalComponent/url", test_component_url);
+       g_test_add_func ("/ECalComponent/attendees", test_component_attendees);
+       g_test_add_func ("/ECalComponent/location", test_component_location);
+       g_test_add_func ("/ECalComponent/attachments", test_component_attachments);
+       g_test_add_func ("/ECalComponent/alarms", test_component_alarms);
+       g_test_add_func ("/ECalComponent/striperrors", test_component_striperrors);
+
+       return g_test_run ();
+}
diff --git a/tests/libecal/test-cal-recur.c b/tests/libecal/test-cal-recur.c
new file mode 100644
index 000000000..b9d26097d
--- /dev/null
+++ b/tests/libecal/test-cal-recur.c
@@ -0,0 +1,407 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libecal/libecal.h>
+
+#include "e-test-server-utils.h"
+
+static ETestServerClosure test_closure = { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, 
FALSE, NULL, FALSE };
+
+static ICalComponent *
+create_component (const gchar *tz_location)
+{
+       const gchar *comp_str =
+               "BEGIN:VEVENT\r\n"
+               "SUMMARY:recurs\r\n"
+               "UID:recurs-id\r\n"
+               "DTSTART%s:20190107T080000%s\r\n"
+               "DTEND%s:20190107T090000%s\r\n"
+               "DTSTAMP:20190101T050000Z\r\n"
+               "CREATED:20190101T050000Z\r\n"
+               "LAST-MODIFIED:20190101T050000Z\r\n"
+               "RRULE:FREQ=DAILY;COUNT=5\r\n"
+               "END:VEVENT\r\n";
+       gchar *tzref = NULL, tzsuffix[2] = { 0, 0};
+       gchar *str;
+       ICalComponent *icomp;
+       ICalTimezone *zone = NULL;
+       ICalTime *itt;
+
+       if (tz_location) {
+               if (g_ascii_strcasecmp (tz_location, "UTC") == 0) {
+                       tzsuffix[0] = 'Z';
+                       zone = i_cal_timezone_get_utc_timezone ();
+               } else {
+                       const gchar *tzid;
+
+                       zone = i_cal_timezone_get_builtin_timezone (tz_location);
+                       g_assert_nonnull (zone);
+
+                       tzid = i_cal_timezone_get_tzid (zone);
+                       g_assert_nonnull (tzid);
+
+                       tzref = g_strconcat (";TZID=", tzid, NULL);
+               }
+       }
+
+       str = g_strdup_printf (comp_str, tzref ? tzref : "", tzsuffix, tzref ? tzref : "", tzsuffix);
+       icomp = i_cal_component_new_from_string (str);
+       g_assert_nonnull (icomp);
+
+       g_free (tzref);
+       g_free (str);
+
+       itt = i_cal_component_get_dtstart (icomp);
+       g_assert_nonnull (itt);
+       g_assert (i_cal_time_get_timezone (itt) == zone);
+       g_object_unref (itt);
+
+       itt = i_cal_component_get_dtend (icomp);
+       g_assert_nonnull (itt);
+       g_assert (i_cal_time_get_timezone (itt) == zone);
+       g_object_unref (itt);
+
+       return icomp;
+}
+
+static void
+setup_cal (ECalClient *cal_client,
+          const gchar *tz_location)
+{
+       ICalComponent *icomp;
+       gboolean success;
+       gchar *uid = NULL;
+       GError *error = NULL;
+
+       icomp = create_component (tz_location);
+
+       /* Ignore errors, it'll fail the first time, but will succeed all other times */
+       e_cal_client_remove_object_sync (cal_client, i_cal_component_get_uid (icomp), NULL, 
E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE, NULL, NULL);
+
+       success = e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL, 
&error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_nonnull (uid);
+
+       g_object_unref (icomp);
+       g_free (uid);
+}
+
+typedef struct _Instance {
+       ICalTime *start;
+       ICalTime *end;
+       ICalComponent *icomp;
+} Instance;
+
+static Instance *
+instance_new (ICalTime *start,
+             ICalTime *end,
+             ICalComponent *icomp)
+{
+       Instance *ins;
+
+       ins = g_new0 (Instance, 1);
+       ins->start = i_cal_time_new_clone (start);
+       ins->end = i_cal_time_new_clone (end);
+       ins->icomp = i_cal_component_new_clone (icomp);
+
+       return ins;
+}
+
+static void
+instance_free (gpointer ptr)
+{
+       Instance *ins = ptr;
+
+       if (ins) {
+               g_clear_object (&ins->start);
+               g_clear_object (&ins->end);
+               g_clear_object (&ins->icomp);
+               g_free (ins);
+       }
+}
+
+static guint
+instance_hash (gconstpointer ptr)
+{
+       /* Place everything into a single basket */
+       return 0;
+}
+
+static gboolean
+instance_equal (gconstpointer ptr1,
+               gconstpointer ptr2)
+{
+       Instance *ins1 = (Instance *) ptr1;
+       Instance *ins2 = (Instance *) ptr2;
+
+       if (!ins1 || !ins2)
+               return ins1 == ins2;
+
+       return i_cal_time_compare (ins1->start, ins2->start) == 0;
+}
+
+static void
+verify_received_instances (GHashTable *instances,
+                          ICalTimezone *comp_zone)
+{
+       const gchar *expected_times[] = {
+               "20190107T080000",
+               "20190108T080000",
+               "20190109T080000",
+               "20190110T080000",
+               "20190111T080000"
+       };
+       gint ii;
+
+       g_assert_nonnull (instances);
+
+       for (ii = 0; ii < G_N_ELEMENTS (expected_times); ii++) {
+               ICalTime *expected_start;
+               Instance ins = { 0, };
+
+               expected_start = i_cal_time_from_string (expected_times[ii]);
+               g_assert_nonnull (expected_start);
+
+               ins.start = expected_start;
+               g_assert (g_hash_table_remove (instances, &ins));
+
+               g_object_unref (expected_start);
+       }
+
+       g_assert_cmpint (g_hash_table_size (instances), ==, 0);
+}
+
+typedef struct _RecurData {
+       GHashTable *instances;
+} RecurData;
+
+static gboolean
+recur_instance_cb (ICalComponent *icomp,
+                  ICalTime *instance_start,
+                  ICalTime *instance_end,
+                  gpointer user_data,
+                  GCancellable *cancellable,
+                  GError **error)
+{
+       RecurData *rd = user_data;
+       Instance *ins;
+       gsize pre;
+
+       g_assert_nonnull (rd);
+
+       ins = instance_new (instance_start, instance_end, icomp);
+
+       pre = g_hash_table_size (rd->instances);
+       g_hash_table_insert (rd->instances, ins, NULL);
+
+       g_assert_cmpint (pre + 1, ==, g_hash_table_size (rd->instances));
+
+       return TRUE;
+}
+
+static void
+test_recur_plain_run (ECalClient *client,
+                     const gchar *default_tz,
+                     const gchar *comp_tz)
+{
+       ICalTimezone *default_zone, *comp_zone;
+       ICalComponent *icomp;
+       ICalTime *start, *end;
+       RecurData rd;
+       gboolean success;
+       GError *error = NULL;
+
+       default_zone = default_tz ? i_cal_timezone_get_builtin_timezone (default_tz) : NULL;
+       if (default_tz)
+               g_assert_nonnull (default_zone);
+
+       comp_zone = comp_tz ? i_cal_timezone_get_builtin_timezone (comp_tz) : NULL;
+       if (comp_tz)
+               g_assert_nonnull (comp_zone);
+
+       icomp = create_component (comp_tz);
+       start = i_cal_time_from_string ("20190103T080000Z");
+       end = i_cal_time_from_string ("20190115T080000Z");
+
+       rd.instances = g_hash_table_new_full (instance_hash, instance_equal, instance_free, NULL);
+
+       success = e_cal_recur_generate_instances_sync (icomp, start, end,
+               recur_instance_cb, &rd,
+               e_cal_client_tzlookup_cb, client,
+               default_zone, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       g_assert_cmpint (g_hash_table_size (rd.instances), ==, 5);
+
+       verify_received_instances (rd.instances, comp_zone);
+
+       g_hash_table_destroy (rd.instances);
+       g_clear_object (&icomp);
+       g_clear_object (&start);
+       g_clear_object (&end);
+}
+
+static void
+test_recur_client_run (ECalClient *client,
+                      const gchar *default_tz,
+                      const gchar *comp_tz)
+{
+       ICalTimezone *default_zone, *comp_zone;
+       ICalTime *start, *end;
+       ICalComponent *icomp;
+       RecurData rd;
+
+       default_zone = default_tz ? i_cal_timezone_get_builtin_timezone (default_tz) : NULL;
+       if (default_tz)
+               g_assert_nonnull (default_zone);
+
+       comp_zone = comp_tz ? i_cal_timezone_get_builtin_timezone (comp_tz) : NULL;
+       if (comp_tz)
+               g_assert_nonnull (comp_zone);
+
+       e_cal_client_set_default_timezone (client, default_zone);
+       setup_cal (client, comp_tz);
+
+       start = i_cal_time_from_string ("20190103T080000Z");
+       end = i_cal_time_from_string ("20190115T080000Z");
+
+       rd.instances = g_hash_table_new_full (instance_hash, instance_equal, instance_free, NULL);
+
+       e_cal_client_generate_instances_sync (client,
+               i_cal_time_as_timet (start),
+               i_cal_time_as_timet (end),
+               NULL, /* GCancellable * */
+               recur_instance_cb, &rd);
+
+       g_assert_cmpint (g_hash_table_size (rd.instances), ==, 5);
+
+       verify_received_instances (rd.instances, comp_zone);
+
+       g_hash_table_destroy (rd.instances);
+
+       icomp = create_component (comp_tz);
+       rd.instances = g_hash_table_new_full (instance_hash, instance_equal, instance_free, NULL);
+
+       e_cal_client_generate_instances_for_object_sync (client,
+               icomp,
+               i_cal_time_as_timet (start),
+               i_cal_time_as_timet (end),
+               NULL, /* GCancellable * */
+               recur_instance_cb, &rd);
+
+       g_assert_cmpint (g_hash_table_size (rd.instances), ==, 5);
+
+       verify_received_instances (rd.instances, comp_zone);
+
+       g_hash_table_destroy (rd.instances);
+       g_clear_object (&icomp);
+       g_clear_object (&start);
+       g_clear_object (&end);
+}
+
+static const gchar *timezones[] = {
+       NULL,                   /* floating time */
+       "Pacific/Midway",       /* UTC-11 */
+       "Pacific/Honolulu",     /* UTC-10 */
+       "America/Adak",         /* UTC-9 */
+       "America/Yakutat",      /* UTC-8 */
+       "America/Vancouver",    /* UTC-7 */
+       "America/Boise",        /* UTC-6 */
+       "America/Cancun",       /* UTC-5 */
+       "America/New_York",     /* UTC-4 */
+       "Atlantic/Bermuda",     /* UTC-3 */
+       "America/Noronha",      /* UTC-2 */
+       "Atlantic/Cape_Verde",  /* UTC-1 */
+       "Atlantic/Azores",      /* UTC */
+       "UTC",                  /* UTC */
+       "Africa/Casablanca",    /* UTC+1 */
+       "Europe/Malta",         /* UTC+2 */
+       "Europe/Athens",        /* UTC+3 */
+       "Asia/Baku",            /* UTC+4 */
+       "Asia/Qyzylorda",       /* UTC+5 */
+       "Asia/Urumqi",          /* UTC+6 */
+       "Asia/Hovd",            /* UTC+7 */
+       "Asia/Irkutsk",         /* UTC+8 */
+       "Asia/Seoul",           /* UTC+9 */
+       "Asia/Vladivostok",     /* UTC+10 */
+       "Asia/Sakhalin",        /* UTC+11 */
+       "Asia/Kamchatka",       /* UTC+12 */
+       "Pacific/Enderbury",    /* UTC+13 */
+       "Pacific/Kiritimati"    /* UTC+14 */
+};
+
+static void
+test_recur_plain (ETestServerFixture *fixture,
+                 gconstpointer user_data)
+{
+       ECalClient *cal;
+       gint deftz_ii, comptz_ii;
+
+       cal = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
+
+       for (deftz_ii = 0; deftz_ii < G_N_ELEMENTS (timezones); deftz_ii++) {
+               for (comptz_ii = 0; comptz_ii < G_N_ELEMENTS (timezones); comptz_ii++) {
+                       test_recur_plain_run (cal, timezones[deftz_ii], timezones[comptz_ii]);
+               }
+       }
+}
+
+static void
+test_recur_client (ETestServerFixture *fixture,
+                  gconstpointer user_data)
+{
+       ECalClient *cal;
+       gint deftz_ii, comptz_ii;
+
+       cal = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
+
+       for (deftz_ii = 0; deftz_ii < G_N_ELEMENTS (timezones); deftz_ii++) {
+               for (comptz_ii = 0; comptz_ii < G_N_ELEMENTS (timezones); comptz_ii++) {
+                       /* Skip the floating time for the client's default timezone */
+                       if (timezones[deftz_ii])
+                               test_recur_client_run (cal, timezones[deftz_ii], timezones[comptz_ii]);
+               }
+       }
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       g_test_init (&argc, &argv, NULL);
+       g_test_bug_base ("http://bugzilla.gnome.org/";);
+
+       g_test_add (
+               "/ECalRecur/Plain",
+               ETestServerFixture,
+               &test_closure,
+               e_test_server_utils_setup,
+               test_recur_plain,
+               e_test_server_utils_teardown);
+       g_test_add (
+               "/ECalRecur/Client",
+               ETestServerFixture,
+               &test_closure,
+               e_test_server_utils_setup,
+               test_recur_client,
+               e_test_server_utils_teardown);
+
+       return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-cal/components/event-8.ics b/tests/libedata-cal/components/event-8.ics
index 35887ad5d..77da02337 100644
--- a/tests/libedata-cal/components/event-8.ics
+++ b/tests/libedata-cal/components/event-8.ics
@@ -4,9 +4,9 @@ DTSTAMP:20170221T121736Z
 DTSTART:20170225T160000
 DTEND:20170225T160500
 SEQUENCE:2
-ORGANIZER;CN=Bob:MAILTO:bob@no.where
+ORGANIZER;CN=Bob:mailto:bob@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
- RSVP=TRUE;LANGUAGE=en:MAILTO:alice@no.where
+ RSVP=TRUE;LANGUAGE=en:mailto:alice@no.where
 SUMMARY:Meet Alice (Floating time)
 COMMENT:User commentary text
 TRANSP:OPAQUE
diff --git a/tests/libedata-cal/components/event-9.ics b/tests/libedata-cal/components/event-9.ics
index f0edf3c63..518d01821 100644
--- a/tests/libedata-cal/components/event-9.ics
+++ b/tests/libedata-cal/components/event-9.ics
@@ -4,11 +4,11 @@ DTSTAMP:20170221T121736Z
 DTSTART;TZID=America/New_York:20170225T160000
 DTEND;TZID=America/New_York:20170225T170000
 SEQUENCE:2
-ORGANIZER;CN=Alice:MAILTO:alice@no.where
+ORGANIZER;CN=Alice:mailto:alice@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
- RSVP=TRUE;CN=Bob;LANGUAGE=en:MAILTO:bob@no.where
+ RSVP=TRUE;CN=Bob;LANGUAGE=en:mailto:bob@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
- RSVP=TRUE;CN=Charlie;LANGUAGE=en:MAILTO:charlie@no.where
+ RSVP=TRUE;CN=Charlie;LANGUAGE=en:mailto:charlie@no.where
 SUMMARY:2-on-1
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-1.ics b/tests/libedata-cal/components/invite-1.ics
index 32267b609..d8da53279 100644
--- a/tests/libedata-cal/components/invite-1.ics
+++ b/tests/libedata-cal/components/invite-1.ics
@@ -9,9 +9,9 @@ DTSTAMP:20170308T175957Z
 DTSTART:20170321T120000Z
 DTEND:20170321T130000Z
 SEQUENCE:1
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Invite
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-2.ics b/tests/libedata-cal/components/invite-2.ics
index bf8423e94..d86fab39b 100644
--- a/tests/libedata-cal/components/invite-2.ics
+++ b/tests/libedata-cal/components/invite-2.ics
@@ -9,8 +9,8 @@ DTSTAMP:20170308T181958Z
 DTSTART:20170321T120000Z
 DTEND:20170321T130000Z
 SEQUENCE:1
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
-ATTENDEE;ROLE=OPT-PARTICIPANT;PARTSTAT=ACCEPTED:MAILTO:user@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
+ATTENDEE;ROLE=OPT-PARTICIPANT;PARTSTAT=ACCEPTED:mailto:user@no.where
 SUMMARY:Invite
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-3.ics b/tests/libedata-cal/components/invite-3.ics
index 80b65d2fd..15cd33ab2 100644
--- a/tests/libedata-cal/components/invite-3.ics
+++ b/tests/libedata-cal/components/invite-3.ics
@@ -9,9 +9,9 @@ DTSTAMP:20170308T180058Z
 DTSTART:20170321T130000Z
 DTEND:20170321T140000Z
 SEQUENCE:2
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Invite (modified)
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-4.ics b/tests/libedata-cal/components/invite-4.ics
index ab1092b16..2cb62aeae 100644
--- a/tests/libedata-cal/components/invite-4.ics
+++ b/tests/libedata-cal/components/invite-4.ics
@@ -9,9 +9,9 @@ DTSTAMP:20170308T180113Z
 DTSTART:20170321T130000Z
 DTEND:20170321T140000Z
 SEQUENCE:2
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Invite (modified)
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-5.ics b/tests/libedata-cal/components/invite-5.ics
index 135fb9111..8ed23aea8 100644
--- a/tests/libedata-cal/components/invite-5.ics
+++ b/tests/libedata-cal/components/invite-5.ics
@@ -10,9 +10,9 @@ DTSTART;VALUE=DATE:20180425
 DTEND;VALUE=DATE:20180426
 RRULE:FREQ=WEEKLY;UNTIL=20180627T220000Z;BYDAY=WE
 SEQUENCE:0
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Recurring invite
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-6.ics b/tests/libedata-cal/components/invite-6.ics
index ff402daeb..fb4005cb8 100644
--- a/tests/libedata-cal/components/invite-6.ics
+++ b/tests/libedata-cal/components/invite-6.ics
@@ -10,9 +10,9 @@ DTSTAMP:20170308T180122Z
 DTSTART:20180502T130000Z
 DTEND:20180502T133000Z
 SEQUENCE:2
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Detached instance of recurring invite
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/components/invite-7.ics b/tests/libedata-cal/components/invite-7.ics
index b4255218c..61f4d1574 100644
--- a/tests/libedata-cal/components/invite-7.ics
+++ b/tests/libedata-cal/components/invite-7.ics
@@ -10,9 +10,9 @@ DTSTAMP:20170308T180122Z
 DTSTART:20180502T130000Z
 DTEND:20180502T133000Z
 SEQUENCE:2
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Detached instance of recurring invite
 TRANSP:OPAQUE
 CLASS:PUBLIC
@@ -26,9 +26,9 @@ DTSTAMP:20170308T180113Z
 DTSTART:20180509T140000Z
 DTEND:20180509T143000Z
 SEQUENCE:3
-ORGANIZER;CN=Organizer:MAILTO:organizer@no.where
+ORGANIZER;CN=Organizer:mailto:organizer@no.where
 ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;
- RSVP=TRUE;CN=User;LANGUAGE=en:MAILTO:user@no.where
+ RSVP=TRUE;CN=User;LANGUAGE=en:mailto:user@no.where
 SUMMARY:Another detached instance of recurring invite
 TRANSP:OPAQUE
 CLASS:PUBLIC
diff --git a/tests/libedata-cal/test-cal-backend-sexp.c b/tests/libedata-cal/test-cal-backend-sexp.c
index db0d7a941..8e798f9be 100644
--- a/tests/libedata-cal/test-cal-backend-sexp.c
+++ b/tests/libedata-cal/test-cal-backend-sexp.c
@@ -28,6 +28,8 @@ test_query (const gchar *query)
        } else {
                printf ("%s: no time prunning possible\n", query);
        }
+
+       g_object_unref (sexp);
 }
 
 gint
diff --git a/tests/libedata-cal/test-cal-cache-getters.c b/tests/libedata-cal/test-cal-cache-getters.c
index b42a9fd8b..8c0a795e1 100644
--- a/tests/libedata-cal/test-cal-cache-getters.c
+++ b/tests/libedata-cal/test-cal-cache-getters.c
@@ -31,7 +31,7 @@ extract_id_from_component (ECalComponent *component)
 
        id = e_cal_component_get_id (component);
        g_assert (id != NULL);
-       g_assert (id->uid != NULL);
+       g_assert (e_cal_component_id_get_uid (id) != NULL);
 
        return id;
 }
@@ -80,10 +80,10 @@ test_get_one (ECalCache *cal_cache,
 
                id = extract_id_from_component (component);
 
-               g_assert_cmpstr (id->uid, ==, uid);
-               g_assert_cmpstr (id->rid, ==, rid && *rid ? rid : NULL);
+               g_assert_cmpstr (e_cal_component_id_get_uid (id), ==, uid);
+               g_assert_cmpstr (e_cal_component_id_get_rid (id), ==, rid && *rid ? rid : NULL);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
                g_object_unref (component);
        }
 
@@ -101,10 +101,10 @@ test_get_one (ECalCache *cal_cache,
 
                id = extract_id_from_string (icalstring);
 
-               g_assert_cmpstr (id->uid, ==, uid);
-               g_assert_cmpstr (id->rid, ==, rid && *rid ? rid : NULL);
+               g_assert_cmpstr (e_cal_component_id_get_uid (id), ==, uid);
+               g_assert_cmpstr (e_cal_component_id_get_rid (id), ==, rid && *rid ? rid : NULL);
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
                g_free (icalstring);
        }
 }
@@ -140,7 +140,7 @@ test_get_all (ECalCache *cal_cache,
        GError *error = NULL;
 
        expects = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc) 
e_cal_component_id_equal,
-               (GDestroyNotify) e_cal_component_free_id, NULL);
+               (GDestroyNotify) e_cal_component_id_free, NULL);
 
        va_start (va, uid);
        tmp = va_arg (va, const gchar *);
@@ -173,10 +173,10 @@ test_get_all (ECalCache *cal_cache,
                for (link = items; link; link = g_slist_next (link)) {
                        id = extract_id_from_component (link->data);
 
-                       g_assert_cmpstr (id->uid, ==, uid);
+                       g_assert_cmpstr (e_cal_component_id_get_uid (id), ==, uid);
                        g_assert (g_hash_table_contains (expects, id));
 
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
                }
 
                g_slist_free_full (items, g_object_unref);
@@ -201,10 +201,10 @@ test_get_all (ECalCache *cal_cache,
                for (link = items; link; link = g_slist_next (link)) {
                        id = extract_id_from_string (link->data);
 
-                       g_assert_cmpstr (id->uid, ==, uid);
+                       g_assert_cmpstr (e_cal_component_id_get_uid (id), ==, uid);
                        g_assert (g_hash_table_contains (expects, id));
 
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
                }
 
                g_slist_free_full (items, g_free);
diff --git a/tests/libedata-cal/test-cal-cache-intervals.c b/tests/libedata-cal/test-cal-cache-intervals.c
index ecf7ce850..28a05e7e3 100644
--- a/tests/libedata-cal/test-cal-cache-intervals.c
+++ b/tests/libedata-cal/test-cal-cache-intervals.c
@@ -73,26 +73,30 @@ search_in_intervals (ETimezoneCache *zone_cache,
                     time_t end)
 {
        ECalBackendSExp *sexp;
-       struct icaltimetype itt_start, itt_end;
+       ICalTime *itt_start, *itt_end;
        gchar *expr;
        GSList *link;
        GHashTable *res;
 
-       itt_start = icaltime_from_timet_with_zone (start, FALSE, NULL);
-       itt_end = icaltime_from_timet_with_zone (end, FALSE, NULL);
+       itt_start = i_cal_time_from_timet_with_zone (start, FALSE, NULL);
+       itt_end = i_cal_time_from_timet_with_zone (end, FALSE, NULL);
 
        expr = g_strdup_printf ("(occur-in-time-range? (make-time \"%04d%02d%02dT%02d%02d%02dZ\") (make-time 
\"%04d%02d%02dT%02d%02d%02dZ\"))",
-               itt_start.year, itt_start.month, itt_start.day, itt_start.hour, itt_start.minute, 
itt_start.second,
-               itt_end.year, itt_end.month, itt_end.day, itt_end.hour, itt_end.minute, itt_end.second);
+               i_cal_time_get_year (itt_start), i_cal_time_get_month (itt_start), i_cal_time_get_day 
(itt_start),
+               i_cal_time_get_hour (itt_start), i_cal_time_get_minute (itt_start), i_cal_time_get_second 
(itt_start),
+               i_cal_time_get_year (itt_end), i_cal_time_get_month (itt_end), i_cal_time_get_day (itt_end),
+               i_cal_time_get_hour (itt_end), i_cal_time_get_minute (itt_end), i_cal_time_get_second 
(itt_end));
 
        sexp = e_cal_backend_sexp_new (expr);
 
+       g_clear_object (&itt_start);
+       g_clear_object (&itt_end);
        g_free (expr);
 
        g_assert_nonnull (sexp);
 
        res = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc) 
e_cal_component_id_equal,
-               (GDestroyNotify) e_cal_component_free_id, g_object_unref);
+               (GDestroyNotify) e_cal_component_id_free, g_object_unref);
 
        for (link = intervals; link; link = g_slist_next (link)) {
                IntervalData *data = link->data;
@@ -130,7 +134,7 @@ check_search_results (GSList *ecalcomps,
 
                g_assert (g_hash_table_contains (from_intervals, id));
 
-               e_cal_component_free_id (id);
+               e_cal_component_id_free (id);
        }
 }
 
@@ -139,32 +143,40 @@ create_test_component (time_t start,
                       time_t end)
 {
        ECalComponent *comp;
-       ECalComponentText summary;
-       struct icaltimetype current, ittstart, ittend;
+       ECalComponentText *summary;
+       ICalTime *current, *ittstart, *ittend;
+       gchar *startstr, *endstr, *tmp;
 
        comp = e_cal_component_new ();
 
        e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
 
-       ittstart = icaltime_from_timet_with_zone (start, 0, NULL);
-       ittend = icaltime_from_timet_with_zone (end, 0, NULL);
+       ittstart = i_cal_time_from_timet_with_zone (start, 0, NULL);
+       ittend = i_cal_time_from_timet_with_zone (end, 0, NULL);
 
-       icalcomponent_set_dtstart (e_cal_component_get_icalcomponent (comp), ittstart);
-       if (end != _TIME_MAX)
-               icalcomponent_set_dtend (e_cal_component_get_icalcomponent (comp), ittend);
+       i_cal_component_set_dtstart (e_cal_component_get_icalcomponent (comp), ittstart);
+       i_cal_component_set_dtend (e_cal_component_get_icalcomponent (comp), ittend);
 
-       summary.value = g_strdup_printf ("%s - %s", icaltime_as_ical_string (ittstart), 
icaltime_as_ical_string (ittend));
-       summary.altrep = NULL;
+       startstr = i_cal_time_as_ical_string_r (ittstart);
+       endstr = i_cal_time_as_ical_string_r (ittend);
 
-       e_cal_component_set_summary (comp, &summary);
+       tmp = g_strdup_printf ("%s - %s", startstr, endstr);
+       summary = e_cal_component_text_new (tmp, NULL);
+       g_free (tmp);
 
-       g_free ((gchar *) summary.value);
+       g_object_unref (ittstart);
+       g_object_unref (ittend);
+       g_free (startstr);
+       g_free (endstr);
 
-       current = icaltime_from_timet_with_zone (time (NULL), 0, NULL);
-       e_cal_component_set_created (comp, &current);
-       e_cal_component_set_last_modified (comp, &current);
+       e_cal_component_set_summary (comp, summary);
 
-       e_cal_component_rescan (comp);
+       e_cal_component_text_free (summary);
+
+       current = i_cal_time_from_timet_with_zone (time (NULL), 0, NULL);
+       e_cal_component_set_created (comp, current);
+       e_cal_component_set_last_modified (comp, current);
+       g_object_unref (current);
 
        return comp;
 }
@@ -210,7 +222,7 @@ test_intervals (TCUFixture *fixture,
 
                intervals = g_slist_prepend (intervals, interval);
 
-               success = e_cal_cache_put_component (fixture->cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, 
&error);
+               success = e_cal_cache_put_component (fixture->cal_cache, comp, NULL, 0, E_CACHE_IS_ONLINE, 
NULL, &error);
                g_assert_no_error (error);
                g_assert (success);
        }
@@ -230,7 +242,7 @@ test_intervals (TCUFixture *fixture,
 
                intervals = g_slist_prepend (intervals, interval);
 
-               success = e_cal_cache_put_component (fixture->cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, 
&error);
+               success = e_cal_cache_put_component (fixture->cal_cache, comp, NULL, 0, E_CACHE_IS_ONLINE, 
NULL, &error);
                g_assert_no_error (error);
                g_assert (success);
        }
@@ -288,11 +300,12 @@ test_intervals (TCUFixture *fixture,
                        id = e_cal_component_get_id (comp);
                        g_assert (id != NULL);
 
-                       success = e_cal_cache_remove_component (fixture->cal_cache, id->uid, id->rid, 
E_CACHE_IS_ONLINE, NULL, &error);
+                       success = e_cal_cache_remove_component (fixture->cal_cache, 
e_cal_component_id_get_uid (id),
+                               e_cal_component_id_get_rid (id), 0, E_CACHE_IS_ONLINE, NULL, &error);
                        g_assert_no_error (error);
                        g_assert (success);
 
-                       e_cal_component_free_id (id);
+                       e_cal_component_id_free (id);
 
                        interval_data_free (interval);
                        intervals = g_slist_delete_link (intervals, l1);
diff --git a/tests/libedata-cal/test-cal-cache-offline.c b/tests/libedata-cal/test-cal-cache-offline.c
index 1fd837841..85489b916 100644
--- a/tests/libedata-cal/test-cal-cache-offline.c
+++ b/tests/libedata-cal/test-cal-cache-offline.c
@@ -71,17 +71,17 @@ test_check_search_result (const GSList *list,
 
                        component = e_cal_component_new_from_string (sd->object);
                        g_assert (E_IS_CAL_COMPONENT (component));
-                       g_assert_cmpstr (uid, ==, icalcomponent_get_uid (e_cal_component_get_icalcomponent 
(component)));
-                       g_assert_nonnull (icalcomponent_get_summary (e_cal_component_get_icalcomponent 
(component)));
+                       g_assert_cmpstr (uid, ==, e_cal_component_get_uid (component));
+                       g_assert_nonnull (i_cal_component_get_summary (e_cal_component_get_icalcomponent 
(component)));
 
                        g_clear_object (&component);
                } else {
                        const ECalComponentId *id = link->data;
 
                        g_assert (id != NULL);
-                       g_assert (id->uid != NULL);
+                       g_assert (e_cal_component_id_get_uid (id) != NULL);
 
-                       uid = id->uid;
+                       uid = e_cal_component_id_get_uid (id);
                }
 
                g_assert_nonnull (uid);
@@ -143,7 +143,7 @@ test_basic_search (TCUFixture *fixture,
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (list), ==, expect_total);
        test_check_search_result (list, flags | EXPECT_EVENT_2);
-       g_slist_free_full (list, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (list, e_cal_component_id_free);
        list = NULL;
 
        /* Only Party, aka event-5, as an in-summary query */
@@ -160,7 +160,7 @@ test_basic_search (TCUFixture *fixture,
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (list), ==, 1);
        test_check_search_result (list, EXPECT_DEFAULT);
-       g_slist_free_full (list, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (list, e_cal_component_id_free);
        list = NULL;
 
        /* Only Party, aka event-5, as a non-summarised query */
@@ -177,7 +177,7 @@ test_basic_search (TCUFixture *fixture,
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (list), ==, 1);
        test_check_search_result (list, EXPECT_DEFAULT);
-       g_slist_free_full (list, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (list, e_cal_component_id_free);
        list = NULL;
 
        /* Invalid expression */
@@ -272,7 +272,7 @@ test_check_edit_saved (TCUFixture *fixture,
        g_assert (e_cal_cache_get_component (fixture->cal_cache, uid, NULL, &component, NULL, &error));
        g_assert_no_error (error);
        g_assert_nonnull (component);
-       g_assert_cmpstr (icalcomponent_get_summary (e_cal_component_get_icalcomponent (component)), ==, 
summ_value);
+       g_assert_cmpstr (i_cal_component_get_summary (e_cal_component_get_icalcomponent (component)), ==, 
summ_value);
 
        g_clear_object (&component);
 }
@@ -315,7 +315,7 @@ test_verify_storage (TCUFixture *fixture,
        g_assert_no_error (error);
 
        g_assert_cmpstr (saved_extra, ==, expect_extra);
-       g_assert_cmpstr (icalcomponent_get_summary (e_cal_component_get_icalcomponent (component)), ==, 
expect_summ);
+       g_assert_cmpstr (i_cal_component_get_summary (e_cal_component_get_icalcomponent (component)), ==, 
expect_summ);
 
        g_clear_object (&component);
        g_free (saved_extra);
@@ -340,6 +340,7 @@ test_offline_basics (TCUFixture *fixture,
        gint ii;
        const gchar *uid;
        gchar *saved_extra = NULL, *tmp;
+       guint32 custom_flags;
        GSList *ids = NULL;
        GError *error = NULL;
 
@@ -372,7 +373,7 @@ test_offline_basics (TCUFixture *fixture,
        test_fill_cache (fixture, &component);
        g_assert_nonnull (component);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -392,12 +393,12 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (ids), ==, 1);
        g_assert_nonnull (ids->data);
-       g_assert_cmpstr (((ECalComponentId *) ids->data)->uid, ==, uid);
+       g_assert_cmpstr (e_cal_component_id_get_uid (ids->data), ==, uid);
 
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        ids = NULL;
 
-       icalcomponent_set_summary (e_cal_component_get_icalcomponent (component), "summ-0");
+       i_cal_component_set_summary (e_cal_component_get_icalcomponent (component), "summ-0");
 
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
@@ -429,6 +430,14 @@ test_offline_basics (TCUFixture *fixture,
                        g_free (saved_extra);
                        saved_extra = NULL;
 
+                       g_assert (e_cal_cache_set_component_custom_flags (fixture->cal_cache, uid, NULL, 123, 
NULL, &error));
+                       g_assert_no_error (error);
+
+                       custom_flags = 0;
+                       g_assert (e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, 
&custom_flags, NULL, &error));
+                       g_assert_no_error (error);
+                       g_assert_cmpint (custom_flags, ==, 123);
+
                        /* Search when locally deleted */
                        test_basic_search (fixture, EXPECT_DEFAULT);
                } else {
@@ -450,17 +459,17 @@ test_offline_basics (TCUFixture *fixture,
        test_check_offline_changes (fixture, NULL);
 
        /* Edit in online */
-       icalcomponent_set_summary (e_cal_component_get_icalcomponent (component), "summ-1");
+       i_cal_component_set_summary (e_cal_component_get_icalcomponent (component), "summ-1");
 
-       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, 0, E_CACHE_IS_ONLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_verify_storage (fixture, uid, "summ-1", NULL, E_OFFLINE_STATE_SYNCED);
        test_check_offline_changes (fixture, NULL);
 
-       icalcomponent_set_summary (e_cal_component_get_icalcomponent (component), "summ-2");
+       i_cal_component_set_summary (e_cal_component_get_icalcomponent (component), "summ-2");
 
-       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, "extra-2", E_CACHE_IS_ONLINE, 
NULL, &error));
+       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, "extra-2", 0, E_CACHE_IS_ONLINE, 
NULL, &error));
        g_assert_no_error (error);
 
        test_verify_storage (fixture, uid, "summ-2", "extra-2", E_OFFLINE_STATE_SYNCED);
@@ -470,19 +479,27 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (ids), ==, 1);
        g_assert_nonnull (ids->data);
-       g_assert_cmpstr (((ECalComponentId *) ids->data)->uid, ==, uid);
+       g_assert_cmpstr (e_cal_component_id_get_uid (ids->data), ==, uid);
 
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        ids = NULL;
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
        g_assert_no_error (error);
 
+       g_assert (e_cal_cache_set_component_custom_flags (fixture->cal_cache, uid, NULL, 234, NULL, &error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 234);
+
        /* Search before delete */
        test_basic_search (fixture, EXPECT_EVENT_1);
 
        /* Delete in online */
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 0, E_CACHE_IS_ONLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert (!e_cache_set_offline_state (E_CACHE (fixture->cal_cache), uid, 
E_OFFLINE_STATE_LOCALLY_MODIFIED, NULL, &error));
@@ -510,6 +527,14 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_null (ids);
        g_clear_error (&error);
 
+       g_assert (!e_cal_cache_set_component_custom_flags (fixture->cal_cache, uid, NULL, 456, NULL, &error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
+       g_assert (!e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, 
NULL, &error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
        g_clear_object (&component);
 
        /* Search after delete */
@@ -531,13 +556,13 @@ test_offline_add_one (TCUFixture *fixture,
                component = tcu_new_component_from_test_case (case_name);
                g_assert_nonnull (component);
 
-               uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+               uid = e_cal_component_get_uid (component);
                g_assert_nonnull (uid);
 
                test_check_offline_state (fixture, uid, E_OFFLINE_STATE_UNKNOWN);
 
                /* Add a component in offline */
-               g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, E_CACHE_IS_OFFLINE, 
NULL, &error));
+               g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, 0, 
E_CACHE_IS_OFFLINE, NULL, &error));
                g_assert_no_error (error);
        } else {
                uid = case_name;
@@ -614,9 +639,9 @@ test_offline_add_edit (TCUFixture *fixture,
                NULL);
 
        /* Modify added in offline */
-       icalcomponent_set_summary (e_cal_component_get_icalcomponent (component), "summ-2");
+       i_cal_component_set_summary (e_cal_component_get_icalcomponent (component), "summ-2");
 
-       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, 0, E_CACHE_IS_OFFLINE, 
NULL, &error));
        g_assert_no_error (error);
 
        test_offline_add_one (fixture, "event-3", 4, EXPECT_EVENT_3 | EXPECT_EVENT_1 | SKIP_COMPONENT_PUT, 
NULL);
@@ -635,6 +660,7 @@ test_offline_add_delete (TCUFixture *fixture,
                         gconstpointer user_data)
 {
        ECalComponent *component = NULL;
+       guint32 custom_flags = 0;
        const gchar *uid;
        GError *error = NULL;
 
@@ -654,18 +680,42 @@ test_offline_add_delete (TCUFixture *fixture,
                "event-3", E_OFFLINE_STATE_LOCALLY_CREATED,
                NULL);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        /* Delete added in offline */
 
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 1, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
+       g_assert (!e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, 
NULL, &error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
        test_offline_add_one (fixture, "event-3", 3, EXPECT_EVENT_1 | SKIP_COMPONENT_PUT, NULL);
 
        test_check_offline_changes (fixture, NULL);
 
+       /* Add in online */
+
+       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, 333, E_CACHE_IS_ONLINE, 
NULL, &error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 333);
+
+       /* Delete in offline */
+
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 246, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 246);
+
        g_clear_object (&component);
 }
 
@@ -693,11 +743,11 @@ test_offline_add_delete_add (TCUFixture *fixture,
                "event-3", E_OFFLINE_STATE_LOCALLY_CREATED,
                NULL);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        /* Delete added in offline */
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_offline_add_one (fixture, "event-3", 3, EXPECT_EVENT_1 | SKIP_COMPONENT_PUT, NULL);
@@ -752,6 +802,7 @@ test_offline_edit_common (TCUFixture *fixture,
                          gchar **out_uid)
 {
        ECalComponent *component = NULL;
+       guint32 custom_flags = 0;
        const gchar *uid;
        GError *error = NULL;
 
@@ -759,7 +810,7 @@ test_offline_edit_common (TCUFixture *fixture,
        test_fill_cache (fixture, &component);
        g_assert_nonnull (component);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -768,11 +819,21 @@ test_offline_edit_common (TCUFixture *fixture,
        test_check_offline_changes (fixture, NULL);
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
+       custom_flags = 0;
+       g_assert (e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 0);
+
        /* Modify in offline */
-       icalcomponent_set_summary (e_cal_component_get_icalcomponent (component), "summ-2");
+       i_cal_component_set_summary (e_cal_component_get_icalcomponent (component), "summ-2");
+
+       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, 369, E_CACHE_IS_OFFLINE, 
NULL, &error));
+       g_assert_no_error (error);
 
-       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       custom_flags = 0;
+       g_assert (e_cal_cache_get_component_custom_flags (fixture->cal_cache, uid, NULL, &custom_flags, NULL, 
&error));
        g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 369);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
        g_assert_no_error (error);
@@ -809,7 +870,7 @@ test_offline_edit_delete (TCUFixture *fixture,
        test_offline_edit_common (fixture, &uid);
 
        /* Delete the modified component in offline */
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -865,7 +926,7 @@ test_offline_delete (TCUFixture *fixture,
        test_fill_cache (fixture, &component);
        g_assert_nonnull (component);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -875,7 +936,7 @@ test_offline_delete (TCUFixture *fixture,
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
        /* Delete in offline */
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -903,7 +964,7 @@ test_offline_delete_add (TCUFixture *fixture,
        test_fill_cache (fixture, &component);
        g_assert_nonnull (component);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -914,7 +975,7 @@ test_offline_delete_add (TCUFixture *fixture,
 
        /* Delete locally created in offline */
        test_offline_add_one (fixture, "event-3", 4, EXPECT_EVENT_3 | EXPECT_EVENT_1, NULL);
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, "event-3", NULL, E_CACHE_IS_OFFLINE, 
NULL, &error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, "event-3", NULL, 0, E_CACHE_IS_OFFLINE, 
NULL, &error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -927,7 +988,7 @@ test_offline_delete_add (TCUFixture *fixture,
        test_check_offline_state (fixture, "event-3", E_OFFLINE_STATE_UNKNOWN);
 
        /* Delete synced in offline */
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -952,9 +1013,9 @@ test_offline_delete_add (TCUFixture *fixture,
        test_check_offline_state (fixture, "event-3", E_OFFLINE_STATE_LOCALLY_CREATED);
 
        /* Modify the previous component and add it again */
-       icalcomponent_set_summary (e_cal_component_get_icalcomponent (component), "summ-3");
+       i_cal_component_set_summary (e_cal_component_get_icalcomponent (component), "summ-3");
 
-       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_put_component (fixture->cal_cache, component, NULL, 0, E_CACHE_IS_OFFLINE, 
NULL, &error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 4);
@@ -986,7 +1047,7 @@ test_offline_delete_resync (TCUFixture *fixture,
        test_fill_cache (fixture, &component);
        g_assert_nonnull (component);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (component));
+       uid = e_cal_component_get_uid (component);
        g_assert_nonnull (uid);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -996,7 +1057,7 @@ test_offline_delete_resync (TCUFixture *fixture,
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
        /* Delete in offline */
-       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_cal_cache_remove_component (fixture->cal_cache, uid, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
diff --git a/tests/libedata-cal/test-cal-cache-search.c b/tests/libedata-cal/test-cal-cache-search.c
index 973966513..500b81a53 100644
--- a/tests/libedata-cal/test-cal-cache-search.c
+++ b/tests/libedata-cal/test-cal-cache-search.c
@@ -36,7 +36,7 @@ test_search_manual (ECalCache *cal_cache,
        GError *error = NULL;
 
        res = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc) 
e_cal_component_id_equal,
-               (GDestroyNotify) e_cal_component_free_id, g_object_unref);
+               e_cal_component_id_free, g_object_unref);
 
        zone_cache = E_TIMEZONE_CACHE (cal_cache);
 
@@ -92,8 +92,9 @@ test_search_dump_results (GSList *search_data,
        g_hash_table_iter_init (&iter, should_be);
        while (g_hash_table_iter_next (&iter, &key, NULL)) {
                ECalComponentId *id = key;
+               const gchar *rid = e_cal_component_id_get_rid (id);
 
-               printf ("      [%d]: %s%s%s\n", ii, id->uid, id->rid ? ", " : "", id->rid ? id->rid : "");
+               printf ("      [%d]: %s%s%s\n", ii, e_cal_component_id_get_uid (id), rid ? ", " : "", rid ? 
rid : "");
                ii++;
        }
 
@@ -120,15 +121,19 @@ search_data_check_cb (GHashTable *should_be,
                      gpointer item_data)
 {
        ECalCacheSearchData *sd = item_data;
-       ECalComponentId id;
+       ECalComponentId *id;
+       gboolean contains;
 
        g_assert (sd != NULL);
        g_assert (sd->uid != NULL);
 
-       id.uid = sd->uid;
-       id.rid = sd->rid;
+       id = e_cal_component_id_new (sd->uid, sd->rid);
+
+       contains = g_hash_table_contains (should_be, id);
+
+       e_cal_component_id_free (id);
 
-       return g_hash_table_contains (should_be, &id);
+       return contains;
 }
 
 static gboolean
@@ -139,16 +144,16 @@ component_check_cb (GHashTable *should_be,
        ECalComponentId *id;
        gboolean contains;
 
-       g_assert (comp != NULL);
+       g_assert_nonnull (comp);
 
        id = e_cal_component_get_id (comp);
 
-       g_assert (id != NULL);
-       g_assert (id->uid != NULL);
+       g_assert_nonnull (id);
+       g_assert_nonnull (e_cal_component_id_get_uid (id));
 
        contains = g_hash_table_contains (should_be, id);
 
-       e_cal_component_free_id (id);
+       e_cal_component_id_free (id);
 
        return contains;
 }
@@ -159,8 +164,8 @@ id_check_cb (GHashTable *should_be,
 {
        ECalComponentId *id = item_data;
 
-       g_assert (id != NULL);
-       g_assert (id->uid != NULL);
+       g_assert_nonnull (id);
+       g_assert_nonnull (e_cal_component_id_get_uid (id));
 
        return g_hash_table_contains (should_be, id);
 }
@@ -212,7 +217,7 @@ test_search_expr (TCUFixture *fixture,
                for (link = items; link; link = g_slist_next (link)) {
                        ECalComponentId *id = link->data;
 
-                       if (g_strcmp0 (id->uid, expects) == 0)
+                       if (g_strcmp0 (e_cal_component_id_get_uid (id), expects) == 0)
                                break;
                }
 
@@ -224,7 +229,7 @@ test_search_expr (TCUFixture *fixture,
 
        test_search_result_equal (items, should_be, id_check_cb);
 
-       g_slist_free_full (items, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (items, e_cal_component_id_free);
 
        g_hash_table_destroy (should_be);
 }
diff --git a/tests/libedata-cal/test-cal-cache-utils.c b/tests/libedata-cal/test-cal-cache-utils.c
index 037c1fb16..e497ee413 100644
--- a/tests/libedata-cal/test-cal-cache-utils.c
+++ b/tests/libedata-cal/test-cal-cache-utils.c
@@ -208,7 +208,7 @@ tcu_add_component_from_test_case (TCUFixture *fixture,
 
        component = tcu_new_component_from_test_case (case_name);
 
-       if (!e_cal_cache_put_component (fixture->cal_cache, component, case_name, E_CACHE_IS_ONLINE, NULL, 
&error))
+       if (!e_cal_cache_put_component (fixture->cal_cache, component, case_name, 0, E_CACHE_IS_ONLINE, NULL, 
&error))
                g_error ("Failed to add component: %s", error->message);
 
        if (out_component)
diff --git a/tests/libedata-cal/test-cal-meta-backend.c b/tests/libedata-cal/test-cal-meta-backend.c
index f13215443..abb9312ee 100644
--- a/tests/libedata-cal/test-cal-meta-backend.c
+++ b/tests/libedata-cal/test-cal-meta-backend.c
@@ -37,7 +37,7 @@ void _e_cal_backend_remove_cached_timezones (ECalBackend *cal_backend); /* e-cal
 typedef struct _ECalMetaBackendTest {
        ECalMetaBackend parent;
 
-       icalcomponent *vcalendar;
+       ICalComponent *vcalendar;
 
        gint sync_tag_index;
        gboolean can_connect;
@@ -70,7 +70,7 @@ ecmb_test_add_test_case (ECalMetaBackendTest *test_backend,
                         const gchar *case_name)
 {
        gchar *icalstr;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_assert_nonnull (test_backend);
        g_assert_nonnull (case_name);
@@ -78,11 +78,29 @@ ecmb_test_add_test_case (ECalMetaBackendTest *test_backend,
        icalstr = tcu_new_icalstring_from_test_case (case_name);
        g_assert_nonnull (icalstr);
 
-       icalcomp = icalcomponent_new_from_string (icalstr);
-       g_assert_nonnull (icalcomp);
+       icomp = i_cal_component_new_from_string (icalstr);
+       g_assert_nonnull (icomp);
        g_free (icalstr);
 
-       icalcomponent_add_component (test_backend->vcalendar, icalcomp);
+       i_cal_component_take_component (test_backend->vcalendar, icomp);
+}
+
+static gchar *
+ecmb_test_get_rid_as_string (ICalComponent *icomp)
+{
+       gchar *rid = NULL;
+
+       g_assert_nonnull (icomp);
+
+       if (e_cal_util_component_has_property (icomp, I_CAL_RECURRENCEID_PROPERTY)) {
+               ICalTime *itt;
+
+               itt = i_cal_component_get_recurrenceid (icomp);
+               rid = i_cal_time_as_ical_string_r (itt);
+               g_clear_object (&itt);
+       }
+
+       return rid;
 }
 
 static void
@@ -90,7 +108,7 @@ ecmb_test_remove_component (ECalMetaBackendTest *test_backend,
                            const gchar *uid,
                            const gchar *rid)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_assert_nonnull (test_backend);
        g_assert_nonnull (uid);
@@ -98,22 +116,27 @@ ecmb_test_remove_component (ECalMetaBackendTest *test_backend,
        if (rid && !*rid)
                rid = NULL;
 
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;) {
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;) {
                const gchar *server_uid;
+               gchar *server_rid;
 
-               server_uid = icalcomponent_get_uid (icalcomp);
+               server_uid = i_cal_component_get_uid (icomp);
                g_assert_nonnull (server_uid);
 
-               if (g_str_equal (server_uid, uid) && (!rid || !*rid ||
-                   (icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY) &&
-                   g_str_equal (rid, icaltime_as_ical_string (icalcomponent_get_recurrenceid (icalcomp)))))) 
{
-                       icalcomponent_remove_component (test_backend->vcalendar, icalcomp);
-                       icalcomponent_free (icalcomp);
+               server_rid = ecmb_test_get_rid_as_string (icomp);
+
+               if (g_str_equal (server_uid, uid) && (!rid || !*rid || (server_rid && g_str_equal (rid, 
server_rid)))) {
+                       i_cal_component_remove_component (test_backend->vcalendar, icomp);
+                       g_object_unref (icomp);
+                       g_free (server_rid);
 
-                       icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, 
ICAL_VEVENT_COMPONENT);
+                       icomp = i_cal_component_get_first_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT);
                } else {
-                       icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, 
ICAL_VEVENT_COMPONENT);
+                       g_object_unref (icomp);
+                       g_free (server_rid);
+
+                       icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT);
                }
        }
 }
@@ -125,7 +148,7 @@ ecmb_test_gather_ids (va_list args)
        const gchar *uid, *rid;
 
        expects = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc) 
e_cal_component_id_equal,
-               (GDestroyNotify) e_cal_component_free_id, NULL);
+               e_cal_component_id_free, NULL);
 
        uid = va_arg (args, const gchar *);
        while (uid) {
@@ -139,18 +162,18 @@ ecmb_test_gather_ids (va_list args)
 }
 
 static void
-ecmb_test_vcalendar_contains (icalcomponent *vcalendar,
+ecmb_test_vcalendar_contains (ICalComponent *vcalendar,
                              gboolean negate,
                              gboolean exact,
                              ...) /* <uid, rid> pairs, ended with NULL */
 {
        va_list args;
        GHashTable *expects;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        guint ntotal;
 
        g_return_if_fail (vcalendar != NULL);
-       g_return_if_fail (icalcomponent_isa (vcalendar) == ICAL_VCALENDAR_COMPONENT);
+       g_return_if_fail (i_cal_component_isa (vcalendar) == I_CAL_VCALENDAR_COMPONENT);
 
        va_start (args, exact);
        expects = ecmb_test_gather_ids (args);
@@ -158,25 +181,23 @@ ecmb_test_vcalendar_contains (icalcomponent *vcalendar,
 
        ntotal = g_hash_table_size (expects);
 
-       for (icalcomp = icalcomponent_get_first_component (vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;
-            icalcomp = icalcomponent_get_next_component (vcalendar, ICAL_VEVENT_COMPONENT)) {
-               ECalComponentId id;
+       for (icomp = i_cal_component_get_first_component (vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (vcalendar, 
I_CAL_VEVENT_COMPONENT)) {
+               ECalComponentId *id;
 
-               id.uid = (gpointer) icalcomponent_get_uid (icalcomp);
-               if (icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY))
-                       id.rid = (gpointer) icaltime_as_ical_string (icalcomponent_get_recurrenceid 
(icalcomp));
-               else
-                       id.rid = NULL;
+               id = e_cal_component_id_new_take (g_strdup (i_cal_component_get_uid (icomp)), 
ecmb_test_get_rid_as_string (icomp));
 
                if (exact) {
                        if (negate)
-                               g_assert (!g_hash_table_remove (expects, &id));
+                               g_assert (!g_hash_table_remove (expects, id));
                        else
-                               g_assert (g_hash_table_remove (expects, &id));
+                               g_assert (g_hash_table_remove (expects, id));
                } else {
-                       g_hash_table_remove (expects, &id);
+                       g_hash_table_remove (expects, id);
                }
+
+               e_cal_component_id_free (id);
        }
 
        if (negate)
@@ -211,7 +232,7 @@ ecmb_test_cache_contains (ECalCache *cal_cache,
 
                g_assert_nonnull (id);
 
-               if (e_cal_cache_contains (cal_cache, id->uid, id->rid, E_CACHE_EXCLUDE_DELETED))
+               if (e_cal_cache_contains (cal_cache, e_cal_component_id_get_uid (id), 
e_cal_component_id_get_rid (id), E_CACHE_EXCLUDE_DELETED))
                        found++;
        }
 
@@ -228,27 +249,29 @@ ecmb_test_cache_contains (ECalCache *cal_cache,
 
 static void
 ecmb_test_cache_and_server_equal (ECalCache *cal_cache,
-                                 icalcomponent *vcalendar,
+                                 ICalComponent *vcalendar,
                                  ECacheDeletedFlag deleted_flag)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_return_if_fail (E_IS_CAL_CACHE (cal_cache));
        g_return_if_fail (vcalendar != NULL);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (cal_cache), deleted_flag, NULL, NULL), ==,
-               icalcomponent_count_components (vcalendar, ICAL_VEVENT_COMPONENT));
+               i_cal_component_count_components (vcalendar, I_CAL_VEVENT_COMPONENT));
 
-       for (icalcomp = icalcomponent_get_first_component (vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;
-            icalcomp = icalcomponent_get_next_component (vcalendar, ICAL_VEVENT_COMPONENT)) {
-               const gchar *uid, *rid = NULL;
+       for (icomp = i_cal_component_get_first_component (vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (vcalendar, 
I_CAL_VEVENT_COMPONENT)) {
+               const gchar *uid;
+               gchar *rid = NULL;
 
-               uid = icalcomponent_get_uid (icalcomp);
-               if (icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY))
-                       rid = icaltime_as_ical_string (icalcomponent_get_recurrenceid (icalcomp));
+               uid = i_cal_component_get_uid (icomp);
+               rid = ecmb_test_get_rid_as_string (icomp);
 
                g_assert (e_cal_cache_contains (cal_cache, uid, rid, deleted_flag));
+
+               g_free (rid);
        }
 }
 
@@ -262,9 +285,9 @@ e_cal_meta_backend_test_get_backend_property (ECalBackend *cal_backend,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strjoin (",",
                        e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (cal_backend)),
-                       CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION,
+                       E_CAL_STATIC_CAPABILITY_ALARM_DESCRIPTION,
                        NULL);
-       } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
+       } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
                return g_strdup ("user@no.where");
        }
 
@@ -369,7 +392,7 @@ e_cal_meta_backend_test_list_existing_sync (ECalMetaBackend *meta_backend,
 {
        ECalMetaBackendTest *test_backend;
        ECalCache *cal_cache;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND_TEST (meta_backend), FALSE);
        g_return_val_if_fail (out_new_sync_tag, FALSE);
@@ -385,19 +408,19 @@ e_cal_meta_backend_test_list_existing_sync (ECalMetaBackend *meta_backend,
 
        *out_existing_objects = NULL;
 
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;
-            icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT)) {
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT)) {
                const gchar *uid;
                gchar *revision;
                ECalMetaBackendInfo *nfo;
 
                /* Detached instances are stored together with the master object */
-               if (icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY))
+               if (e_cal_util_component_has_property (icomp, I_CAL_RECURRENCEID_PROPERTY))
                        continue;
 
-               uid = icalcomponent_get_uid (icalcomp);
-               revision = e_cal_cache_dup_component_revision (cal_cache, icalcomp);
+               uid = i_cal_component_get_uid (icomp);
+               revision = e_cal_cache_dup_component_revision (cal_cache, icomp);
 
                nfo = e_cal_meta_backend_info_new (uid, revision, NULL, NULL);
                *out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
@@ -416,13 +439,14 @@ e_cal_meta_backend_test_save_component_sync (ECalMetaBackend *meta_backend,
                                             EConflictResolution conflict_resolution,
                                             const GSList *instances,
                                             const gchar *extra,
+                                            guint32 opflags,
                                             gchar **out_new_uid,
                                             gchar **out_new_extra,
                                             GCancellable *cancellable,
                                             GError **error)
 {
        ECalMetaBackendTest *test_backend;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        const gchar *uid;
        GSList *link;
 
@@ -435,28 +459,29 @@ e_cal_meta_backend_test_save_component_sync (ECalMetaBackend *meta_backend,
 
        g_assert (test_backend->is_connected);
 
-       uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (instances->data));
+       uid = e_cal_component_get_uid (instances->data);
        g_assert_nonnull (uid);
 
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;) {
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;) {
                const gchar *server_uid;
 
-               server_uid = icalcomponent_get_uid (icalcomp);
+               server_uid = i_cal_component_get_uid (icomp);
                g_assert_nonnull (server_uid);
 
                if (g_str_equal (server_uid, uid)) {
                        if (!overwrite_existing) {
-                               g_propagate_error (error, e_data_cal_create_error (ObjectIdAlreadyExists, 
NULL));
+                               g_propagate_error (error, e_cal_client_error_create 
(E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS, NULL));
                                return FALSE;
                        }
 
-                       icalcomponent_remove_component (test_backend->vcalendar, icalcomp);
-                       icalcomponent_free (icalcomp);
+                       i_cal_component_remove_component (test_backend->vcalendar, icomp);
+                       g_object_unref (icomp);
 
-                       icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, 
ICAL_VEVENT_COMPONENT);
+                       icomp = i_cal_component_get_first_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT);
                } else {
-                       icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, 
ICAL_VEVENT_COMPONENT);
+                       g_object_unref (icomp);
+                       icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT);
                }
        }
 
@@ -464,13 +489,13 @@ e_cal_meta_backend_test_save_component_sync (ECalMetaBackend *meta_backend,
                ECalComponent *comp = link->data;
                const gchar *comp_uid;
 
-               icalcomp = e_cal_component_get_icalcomponent (comp);
-               g_assert_nonnull (icalcomp);
+               icomp = e_cal_component_get_icalcomponent (comp);
+               g_assert_nonnull (icomp);
 
-               comp_uid = icalcomponent_get_uid (icalcomp);
+               comp_uid = i_cal_component_get_uid (icomp);
                g_assert_cmpstr (uid, ==, comp_uid);
 
-               icalcomponent_add_component (test_backend->vcalendar, icalcomponent_new_clone (icalcomp));
+               i_cal_component_take_component (test_backend->vcalendar, i_cal_component_new_clone (icomp));
        }
 
        *out_new_uid = g_strdup (uid);
@@ -482,13 +507,13 @@ static gboolean
 e_cal_meta_backend_test_load_component_sync (ECalMetaBackend *meta_backend,
                                             const gchar *uid,
                                             const gchar *extra,
-                                            icalcomponent **out_instances,
+                                            ICalComponent **out_instances,
                                             gchar **out_extra,
                                             GCancellable *cancellable,
                                             GError **error)
 {
        ECalMetaBackendTest *test_backend;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND_TEST (meta_backend), FALSE);
        g_return_val_if_fail (uid != NULL, FALSE);
@@ -502,19 +527,19 @@ e_cal_meta_backend_test_load_component_sync (ECalMetaBackend *meta_backend,
 
        *out_instances = NULL;
 
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;
-            icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT)) {
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT)) {
                const gchar *server_uid;
 
-               server_uid = icalcomponent_get_uid (icalcomp);
+               server_uid = i_cal_component_get_uid (icomp);
                g_assert_nonnull (server_uid);
 
                if (g_str_equal (server_uid, uid)) {
                        if (!*out_instances)
                                *out_instances = e_cal_util_new_top_level ();
 
-                       icalcomponent_add_component (*out_instances, icalcomponent_new_clone (icalcomp));
+                       i_cal_component_take_component (*out_instances, i_cal_component_new_clone (icomp));
                }
        }
 
@@ -522,7 +547,7 @@ e_cal_meta_backend_test_load_component_sync (ECalMetaBackend *meta_backend,
                *out_extra = g_strconcat ("extra for ", uid, NULL);
                return TRUE;
        } else {
-               g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, 
NULL));
        }
 
        return FALSE;
@@ -534,11 +559,12 @@ e_cal_meta_backend_test_remove_component_sync (ECalMetaBackend *meta_backend,
                                               const gchar *uid,
                                               const gchar *extra,
                                               const gchar *object,
+                                              guint32 opflags,
                                               GCancellable *cancellable,
                                               GError **error)
 {
        ECalMetaBackendTest *test_backend;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        gboolean success = FALSE;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND_TEST (meta_backend), FALSE);
@@ -550,11 +576,11 @@ e_cal_meta_backend_test_remove_component_sync (ECalMetaBackend *meta_backend,
 
        g_assert (test_backend->is_connected);
 
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;) {
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;) {
                const gchar *server_uid;
 
-               server_uid = icalcomponent_get_uid (icalcomp);
+               server_uid = i_cal_component_get_uid (icomp);
                g_assert_nonnull (server_uid);
 
                if (g_str_equal (server_uid, uid)) {
@@ -568,17 +594,18 @@ e_cal_meta_backend_test_remove_component_sync (ECalMetaBackend *meta_backend,
 
                        success = TRUE;
 
-                       icalcomponent_remove_component (test_backend->vcalendar, icalcomp);
-                       icalcomponent_free (icalcomp);
+                       i_cal_component_remove_component (test_backend->vcalendar, icomp);
+                       g_object_unref (icomp);
 
-                       icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, 
ICAL_VEVENT_COMPONENT);
+                       icomp = i_cal_component_get_first_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT);
                } else {
-                       icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, 
ICAL_VEVENT_COMPONENT);
+                       g_object_unref (icomp);
+                       icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT);
                }
        }
 
        if (!success)
-               g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
+               g_propagate_error (error, e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND, 
NULL));
 
        return success;
 }
@@ -618,7 +645,7 @@ e_cal_meta_backend_test_finalize (GObject *object)
 
        g_assert_nonnull (test_backend->vcalendar);
 
-       icalcomponent_free (test_backend->vcalendar);
+       g_object_unref (test_backend->vcalendar);
 
        /* Chain up to parent's method. */
        G_OBJECT_CLASS (e_cal_meta_backend_test_parent_class)->finalize (object);
@@ -788,12 +815,12 @@ e_cal_meta_backend_test_call_refresh (ECalMetaBackend *meta_backend)
 }
 
 static void
-assert_tzid_matches_cb (icalparameter *param,
+assert_tzid_matches_cb (ICalParameter *param,
                        gpointer user_data)
 {
        const gchar *expected_tzid = user_data;
 
-       g_assert_cmpstr (icalparameter_get_tzid (param), ==, expected_tzid);
+       g_assert_cmpstr (i_cal_parameter_get_tzid (param), ==, expected_tzid);
 }
 
 static void
@@ -802,8 +829,8 @@ test_merge_instances (TCUFixture *fixture,
 {
        ECalMetaBackend *meta_backend;
        GSList *instances = NULL;
-       icalcomponent *icalcomp, *subcomp;
-       icalproperty *prop;
+       ICalComponent *icomp, *subcomp;
+       ICalProperty *prop;
        gboolean success;
        GError *error = NULL;
 
@@ -817,28 +844,30 @@ test_merge_instances (TCUFixture *fixture,
        g_assert_nonnull (instances);
 
        /* TZID as is */
-       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, instances, FALSE);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_ANY_COMPONENT), ==, 1);
+       icomp = e_cal_meta_backend_merge_instances (meta_backend, instances, FALSE);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_ANY_COMPONENT), ==, 1);
 
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT);
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_ANY_COMPONENT);
        g_assert_nonnull (subcomp);
-       g_assert_cmpint (icalcomponent_isa (subcomp), ==, ICAL_VEVENT_COMPONENT);
+       g_assert_cmpint (i_cal_component_isa (subcomp), ==, I_CAL_VEVENT_COMPONENT);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (subcomp);
+       g_object_unref (icomp);
 
        /* TZID as location */
-       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_ANY_COMPONENT), ==, 1);
+       icomp = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_ANY_COMPONENT), ==, 1);
 
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT);
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_ANY_COMPONENT);
        g_assert_nonnull (subcomp);
-       g_assert_cmpint (icalcomponent_isa (subcomp), ==, ICAL_VEVENT_COMPONENT);
+       g_assert_cmpint (i_cal_component_isa (subcomp), ==, I_CAL_VEVENT_COMPONENT);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (subcomp);
+       g_object_unref (icomp);
 
        g_slist_free_full (instances, g_object_unref);
        instances = NULL;
@@ -850,48 +879,56 @@ test_merge_instances (TCUFixture *fixture,
        g_assert_nonnull (instances);
 
        /* TZID as is */
-       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, instances, FALSE);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_ANY_COMPONENT), ==, 2);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VTIMEZONE_COMPONENT), ==, 1);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VEVENT_COMPONENT), ==, 1);
-
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+       icomp = e_cal_meta_backend_merge_instances (meta_backend, instances, FALSE);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_ANY_COMPONENT), ==, 2);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VTIMEZONE_COMPONENT), ==, 1);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VEVENT_COMPONENT), ==, 1);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VTIMEZONE_COMPONENT);
        g_assert_nonnull (subcomp);
-       g_assert_cmpint (icalcomponent_isa (subcomp), ==, ICAL_VTIMEZONE_COMPONENT);
+       g_assert_cmpint (i_cal_component_isa (subcomp), ==, I_CAL_VTIMEZONE_COMPONENT);
 
-       prop = icalcomponent_get_first_property (subcomp, ICAL_TZID_PROPERTY);
+       prop = i_cal_component_get_first_property (subcomp, I_CAL_TZID_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_cmpstr (icalproperty_get_tzid (prop), ==, EXPECTED_TZID);
+       g_assert_cmpstr (i_cal_property_get_tzid (prop), ==, EXPECTED_TZID);
 
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT);
+       g_object_unref (prop);
+       g_object_unref (subcomp);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VEVENT_COMPONENT);
        g_assert_nonnull (subcomp);
-       icalcomponent_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) icalproperty_get_tzid (prop));
+       i_cal_component_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) EXPECTED_TZID);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (subcomp);
+       g_object_unref (icomp);
 
        /* TZID to location */
-       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_ANY_COMPONENT), ==, 2);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VTIMEZONE_COMPONENT), ==, 1);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VEVENT_COMPONENT), ==, 1);
-
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+       icomp = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_ANY_COMPONENT), ==, 2);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VTIMEZONE_COMPONENT), ==, 1);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VEVENT_COMPONENT), ==, 1);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VTIMEZONE_COMPONENT);
        g_assert_nonnull (subcomp);
-       g_assert_cmpint (icalcomponent_isa (subcomp), ==, ICAL_VTIMEZONE_COMPONENT);
+       g_assert_cmpint (i_cal_component_isa (subcomp), ==, I_CAL_VTIMEZONE_COMPONENT);
 
-       prop = icalcomponent_get_first_property (subcomp, ICAL_TZID_PROPERTY);
+       prop = i_cal_component_get_first_property (subcomp, I_CAL_TZID_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_cmpstr (icalproperty_get_tzid (prop), ==, EXPECTED_LOCATION);
+       g_assert_cmpstr (i_cal_property_get_tzid (prop), ==, EXPECTED_LOCATION);
+
+       g_object_unref (prop);
+       g_object_unref (subcomp);
 
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT);
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VEVENT_COMPONENT);
        g_assert_nonnull (subcomp);
-       icalcomponent_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) icalproperty_get_tzid (prop));
+       i_cal_component_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) EXPECTED_LOCATION);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (subcomp);
+       g_object_unref (icomp);
        g_slist_free_full (instances, g_object_unref);
        instances = NULL;
 
@@ -902,63 +939,74 @@ test_merge_instances (TCUFixture *fixture,
        g_assert_nonnull (instances);
 
        /* TZID as is */
-       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, instances, FALSE);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_ANY_COMPONENT), ==, 3);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VTIMEZONE_COMPONENT), ==, 1);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VEVENT_COMPONENT), ==, 2);
-
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+       icomp = e_cal_meta_backend_merge_instances (meta_backend, instances, FALSE);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_ANY_COMPONENT), ==, 3);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VTIMEZONE_COMPONENT), ==, 1);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VEVENT_COMPONENT), ==, 2);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VTIMEZONE_COMPONENT);
        g_assert_nonnull (subcomp);
-       g_assert_cmpint (icalcomponent_isa (subcomp), ==, ICAL_VTIMEZONE_COMPONENT);
+       g_assert_cmpint (i_cal_component_isa (subcomp), ==, I_CAL_VTIMEZONE_COMPONENT);
 
-       prop = icalcomponent_get_first_property (subcomp, ICAL_TZID_PROPERTY);
+       prop = i_cal_component_get_first_property (subcomp, I_CAL_TZID_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_cmpstr (icalproperty_get_tzid (prop), ==, EXPECTED_LOCATION);
+       g_assert_cmpstr (i_cal_property_get_tzid (prop), ==, EXPECTED_LOCATION);
 
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT);
+       g_object_unref (subcomp);
+       g_object_unref (prop);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VEVENT_COMPONENT);
        g_assert_nonnull (subcomp);
-       icalcomponent_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) icalproperty_get_tzid (prop));
+       i_cal_component_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) EXPECTED_LOCATION);
+
+       g_object_unref (subcomp);
 
-       subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VEVENT_COMPONENT);
+       subcomp = i_cal_component_get_next_component (icomp, I_CAL_VEVENT_COMPONENT);
        g_assert_nonnull (subcomp);
-       icalcomponent_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) icalproperty_get_tzid (prop));
+       i_cal_component_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) EXPECTED_LOCATION);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (subcomp);
+       g_object_unref (icomp);
 
        /* TZID to location */
-       icalcomp = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_ANY_COMPONENT), ==, 3);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VTIMEZONE_COMPONENT), ==, 1);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VEVENT_COMPONENT), ==, 2);
-
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+       icomp = e_cal_meta_backend_merge_instances (meta_backend, instances, TRUE);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_ANY_COMPONENT), ==, 3);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VTIMEZONE_COMPONENT), ==, 1);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VEVENT_COMPONENT), ==, 2);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VTIMEZONE_COMPONENT);
        g_assert_nonnull (subcomp);
-       g_assert_cmpint (icalcomponent_isa (subcomp), ==, ICAL_VTIMEZONE_COMPONENT);
+       g_assert_cmpint (i_cal_component_isa (subcomp), ==, I_CAL_VTIMEZONE_COMPONENT);
 
-       prop = icalcomponent_get_first_property (subcomp, ICAL_TZID_PROPERTY);
+       prop = i_cal_component_get_first_property (subcomp, I_CAL_TZID_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_cmpstr (icalproperty_get_tzid (prop), ==, EXPECTED_LOCATION);
+       g_assert_cmpstr (i_cal_property_get_tzid (prop), ==, EXPECTED_LOCATION);
+       g_object_unref (prop);
 
-       subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT);
+       g_object_unref (subcomp);
+
+       subcomp = i_cal_component_get_first_component (icomp, I_CAL_VEVENT_COMPONENT);
        g_assert_nonnull (subcomp);
-       icalcomponent_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) icalproperty_get_tzid (prop));
+       i_cal_component_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) EXPECTED_LOCATION);
+       g_object_unref (subcomp);
 
-       subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VEVENT_COMPONENT);
+       subcomp = i_cal_component_get_next_component (icomp, I_CAL_VEVENT_COMPONENT);
        g_assert_nonnull (subcomp);
-       icalcomponent_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) icalproperty_get_tzid (prop));
+       i_cal_component_foreach_tzid (subcomp, assert_tzid_matches_cb, (gpointer) EXPECTED_LOCATION);
+       g_object_unref (subcomp);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (icomp);
        g_slist_free_full (instances, g_object_unref);
 
        g_object_unref (meta_backend);
 }
 
 static void
-check_attachment_content (icalattach *attach,
+check_attachment_content (ICalAttach *attach,
                          const gchar *expected_content,
                          gsize expected_content_len)
 {
@@ -966,7 +1014,7 @@ check_attachment_content (icalattach *attach,
        g_assert_nonnull (expected_content);
        g_assert_cmpint (expected_content_len, >, 0);
 
-       if (icalattach_get_is_url (attach)) {
+       if (i_cal_attach_get_is_url (attach)) {
                const gchar *url;
                gboolean success;
                gchar *filename;
@@ -974,11 +1022,11 @@ check_attachment_content (icalattach *attach,
                gsize content_len = -1;
                GError *error = NULL;
 
-               url = icalattach_get_url (attach);
+               url = i_cal_attach_get_url (attach);
                g_assert_nonnull (url);
                g_assert (g_str_has_prefix (url, "file://"));
 
-               filename = g_filename_from_uri (icalattach_get_url (attach), NULL, &error);
+               filename = g_filename_from_uri (url, NULL, &error);
                g_assert_no_error (error);
                g_assert_nonnull (filename);
 
@@ -996,7 +1044,7 @@ check_attachment_content (icalattach *attach,
                guchar *base64;
                gsize base64_len;
 
-               base64 = g_base64_decode ((const gchar *) icalattach_get_data (attach), &base64_len);
+               base64 = g_base64_decode (i_cal_attach_get_data (attach), &base64_len);
                g_assert_nonnull (base64);
                g_assert_cmpmem (base64, base64_len, expected_content, expected_content_len);
 
@@ -1012,10 +1060,10 @@ test_attachments (TCUFixture *fixture,
        gchar *content = NULL;
        gsize content_len = 0;
        ECalComponent *comp = NULL;
-       icalcomponent *icalcomp;
-       icalproperty *prop;
-       icalparameter *param;
-       icalattach *attach;
+       ICalComponent *icomp;
+       ICalProperty *prop;
+       ICalParameter *param;
+       ICalAttach *attach;
        gchar *filename;
        const gchar *basename;
        gboolean success;
@@ -1030,19 +1078,19 @@ test_attachments (TCUFixture *fixture,
        g_assert (success);
        g_assert_nonnull (comp);
 
-       icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_count_properties (icalcomp, ICAL_ATTACH_PROPERTY), ==, 1);
+       icomp = i_cal_component_new_clone (e_cal_component_get_icalcomponent (comp));
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ATTACH_PROPERTY), ==, 1);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (icalattach_get_is_url (attach));
+       g_assert (i_cal_attach_get_is_url (attach));
 
-       filename = g_filename_from_uri (icalattach_get_url (attach), NULL, &error);
+       filename = g_filename_from_uri (i_cal_attach_get_url (attach), NULL, &error);
        g_assert_no_error (error);
        g_assert_nonnull (filename);
 
@@ -1056,115 +1104,139 @@ test_attachments (TCUFixture *fixture,
        g_assert_nonnull (content);
        g_assert_cmpint (content_len, >, 0);
 
-       success = e_cal_meta_backend_inline_local_attachments_sync (meta_backend, icalcomp, NULL, &error);
+       success = e_cal_meta_backend_inline_local_attachments_sync (meta_backend, icomp, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (icalcomponent_count_properties (icalcomp, ICAL_ATTACH_PROPERTY), ==, 1);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ATTACH_PROPERTY), ==, 1);
+
+       g_object_unref (attach);
+       g_object_unref (prop);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER));
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_ENCODING_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_VALUE_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_ENCODING_PARAMETER));
 
-       param = icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER);
-       g_assert_cmpstr (icalparameter_get_filename (param), ==, basename);
+       param = i_cal_property_get_first_parameter (prop, I_CAL_FILENAME_PARAMETER);
+       g_assert_cmpstr (i_cal_parameter_get_filename (param), ==, basename);
+       g_object_unref (param);
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (!icalattach_get_is_url (attach));
+       g_assert (!i_cal_attach_get_is_url (attach));
 
        check_attachment_content (attach, content, content_len);
 
-       success = e_cal_meta_backend_store_inline_attachments_sync (meta_backend, icalcomp, NULL, &error);
+       g_object_unref (attach);
+       g_object_unref (prop);
+
+       success = e_cal_meta_backend_store_inline_attachments_sync (meta_backend, icomp, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (icalcomponent_count_properties (icalcomp, ICAL_ATTACH_PROPERTY), ==, 1);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ATTACH_PROPERTY), ==, 1);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER));
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_ENCODING_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_VALUE_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_ENCODING_PARAMETER));
 
-       param = icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER);
-       g_assert_cmpstr (icalparameter_get_filename (param), ==, basename);
+       param = i_cal_property_get_first_parameter (prop, I_CAL_FILENAME_PARAMETER);
+       g_assert_cmpstr (i_cal_parameter_get_filename (param), ==, basename);
+       g_object_unref (param);
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (icalattach_get_is_url (attach));
+       g_assert (i_cal_attach_get_is_url (attach));
 
        check_attachment_content (attach, content, content_len);
 
+       g_object_unref (attach);
+       g_object_unref (prop);
+
        /* Add a URL attachment which is not pointing to a local file */
-       attach = icalattach_new_from_url (REMOTE_URL);
-       prop = icalproperty_new_attach (attach);
-       icalattach_unref (attach);
-       icalcomponent_add_property (icalcomp, prop);
+       attach = i_cal_attach_new_from_url (REMOTE_URL);
+       prop = i_cal_property_new_attach (attach);
+       g_object_unref (attach);
+       i_cal_component_take_property (icomp, prop);
 
-       g_assert_cmpint (icalcomponent_count_properties (icalcomp, ICAL_ATTACH_PROPERTY), ==, 2);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ATTACH_PROPERTY), ==, 2);
 
-       success = e_cal_meta_backend_inline_local_attachments_sync (meta_backend, icalcomp, NULL, &error);
+       success = e_cal_meta_backend_inline_local_attachments_sync (meta_backend, icomp, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (icalcomponent_count_properties (icalcomp, ICAL_ATTACH_PROPERTY), ==, 2);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ATTACH_PROPERTY), ==, 2);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER));
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_ENCODING_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_VALUE_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_ENCODING_PARAMETER));
 
-       param = icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER);
-       g_assert_cmpstr (icalparameter_get_filename (param), ==, basename);
+       param = i_cal_property_get_first_parameter (prop, I_CAL_FILENAME_PARAMETER);
+       g_assert_cmpstr (i_cal_parameter_get_filename (param), ==, basename);
+       g_object_unref (param);
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (!icalattach_get_is_url (attach));
+       g_assert (!i_cal_attach_get_is_url (attach));
 
        check_attachment_content (attach, content, content_len);
 
+       g_object_unref (attach);
+       g_object_unref (prop);
+
        /* Verify the remote URL did not change */
-       prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_next_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (icalattach_get_is_url (attach));
-       g_assert_cmpstr (icalattach_get_url (attach), ==, REMOTE_URL);
+       g_assert (i_cal_attach_get_is_url (attach));
+       g_assert_cmpstr (i_cal_attach_get_url (attach), ==, REMOTE_URL);
+
+       g_object_unref (attach);
+       g_object_unref (prop);
 
-       success = e_cal_meta_backend_store_inline_attachments_sync (meta_backend, icalcomp, NULL, &error);
+       success = e_cal_meta_backend_store_inline_attachments_sync (meta_backend, icomp, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (icalcomponent_count_properties (icalcomp, ICAL_ATTACH_PROPERTY), ==, 2);
+       g_assert_cmpint (i_cal_component_count_properties (icomp, I_CAL_ATTACH_PROPERTY), ==, 2);
 
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_first_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_nonnull (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER));
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_ENCODING_PARAMETER));
+       g_assert (e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_VALUE_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_ENCODING_PARAMETER));
 
-       param = icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER);
-       g_assert_cmpstr (icalparameter_get_filename (param), ==, basename);
+       param = i_cal_property_get_first_parameter (prop, I_CAL_FILENAME_PARAMETER);
+       g_assert_cmpstr (i_cal_parameter_get_filename (param), ==, basename);
+       g_object_unref (param);
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (icalattach_get_is_url (attach));
+       g_assert (i_cal_attach_get_is_url (attach));
 
        check_attachment_content (attach, content, content_len);
 
+       g_object_unref (attach);
+       g_object_unref (prop);
+
        /* Verify the remote URL did not change */
-       prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTACH_PROPERTY);
+       prop = i_cal_component_get_next_property (icomp, I_CAL_ATTACH_PROPERTY);
        g_assert_nonnull (prop);
-       g_assert_null (icalproperty_get_first_parameter (prop, ICAL_FILENAME_PARAMETER));
+       g_assert (!e_cal_util_property_has_parameter (prop, I_CAL_FILENAME_PARAMETER));
 
-       attach = icalproperty_get_attach (prop);
+       attach = i_cal_property_get_attach (prop);
        g_assert_nonnull (attach);
-       g_assert (icalattach_get_is_url (attach));
-       g_assert_cmpstr (icalattach_get_url (attach), ==, REMOTE_URL);
+       g_assert (i_cal_attach_get_is_url (attach));
+       g_assert_cmpstr (i_cal_attach_get_url (attach), ==, REMOTE_URL);
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (attach);
+       g_object_unref (prop);
+       g_object_unref (icomp);
        g_object_unref (meta_backend);
        g_object_unref (comp);
        g_free (filename);
@@ -1223,7 +1295,7 @@ test_empty_cache (TCUFixture *fixture,
        g_return_if_fail (backend_class->receive_objects_sync != NULL);
 
        /* This adds the object and the used timezone to the cache */
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, in_vcalobj, 
&error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, in_vcalobj, 0, 
&error);
        g_assert_no_error (error);
 
        zones = NULL;
@@ -1274,7 +1346,7 @@ test_send_objects (ECalMetaBackend *meta_backend)
        g_return_if_fail (backend_class->send_objects_sync != NULL);
 
        backend_class->send_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, calobj, &users, &modified_calobj, &error);
+               NULL, NULL, calobj, 0, &users, &modified_calobj, &error);
 
        g_assert_no_error (error);
        g_assert_null (users);
@@ -1301,7 +1373,7 @@ test_get_attachment_uris (ECalMetaBackend *meta_backend)
        backend_class->get_attachment_uris_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, "unknown-event", NULL, &uris, &error);
 
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (uris);
 
        g_clear_error (&error);
@@ -1345,7 +1417,7 @@ test_discard_alarm (ECalMetaBackend *meta_backend)
 
        /* Not implemented */
        backend_class->discard_alarm_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, "unknown-event", NULL, NULL, &error);
+               NULL, NULL, "unknown-event", NULL, NULL, 0, &error);
 
        g_assert_error (error, E_CLIENT_ERROR, E_CLIENT_ERROR_NOT_SUPPORTED);
 
@@ -1426,7 +1498,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        const gchar *in_tz2obj = TZSTRDEF (TZID2, TZLOC2);
        ECalBackendSyncClass *backend_class;
        ECalCache *cal_cache;
-       icalcomponent *vcalendar;
+       ICalComponent *vcalendar;
        ECalComponent *comp;
        gchar *tzobj = NULL;
        GList *zones;
@@ -1444,13 +1516,13 @@ test_timezones (ECalMetaBackend *meta_backend)
        /* Verify neither TZID, not LOCATION is in the timezone cache */
        backend_class->get_timezone_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, TZID1, &tzobj, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (tzobj);
        g_clear_error (&error);
 
        backend_class->get_timezone_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, TZLOC1, &tzobj, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (tzobj);
        g_clear_error (&error);
 
@@ -1470,7 +1542,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        /* As a non-built-in timezone it cannot be read with location, only with TZID */
        backend_class->get_timezone_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, TZLOC1, &tzobj, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (tzobj);
        g_clear_error (&error);
 
@@ -1486,7 +1558,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
        g_assert_nonnull (cal_cache);
 
-       vcalendar = icalcomponent_new_from_string (
+       vcalendar = i_cal_component_new_from_string (
                "BEGIN:VCALENDAR\r\n"
                "BEGIN:VTIMEZONE\r\n"
                "TZID:tzid1\r\n"
@@ -1593,7 +1665,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        zones = e_timezone_cache_list_timezones (E_TIMEZONE_CACHE (meta_backend));
        g_assert_cmpint (g_list_length (zones), ==, 0);
 
-       icalcomponent_free (vcalendar);
+       g_object_unref (vcalendar);
 
        /* And now when the timezones are actually referenced, thus should be part of the persistent cache */
 
@@ -1626,7 +1698,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_assert_nonnull (comp);
 
        /* Add a component which uses TZID1, thus it's in the cache */
-       success = e_cal_cache_put_component (cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       success = e_cal_cache_put_component (cal_cache, comp, NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -1661,7 +1733,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_assert_no_error (error);
 
        /* Add a component which uses TZID1 and TZID2, thus it's in the cache */
-       success = e_cal_cache_put_component (cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       success = e_cal_cache_put_component (cal_cache, comp, NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -1679,7 +1751,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_assert_cmpint (tcmb_get_tzid_ref_count (cal_cache, TZID2), ==, 1);
 
        /* Remove in offline doesn't modify timezone cache, because the component is still there */
-       success = e_cal_cache_remove_component (cal_cache, "tz1", NULL, E_CACHE_IS_OFFLINE, NULL, &error);
+       success = e_cal_cache_remove_component (cal_cache, "tz1", NULL, 0, E_CACHE_IS_OFFLINE, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -1687,7 +1759,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_assert_cmpint (tcmb_get_tzid_ref_count (cal_cache, TZID2), ==, 1);
 
        /* Remove in online modifies timezone cache */
-       success = e_cal_cache_remove_component (cal_cache, "tz1", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       success = e_cal_cache_remove_component (cal_cache, "tz1", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -1717,7 +1789,7 @@ test_timezones (ECalMetaBackend *meta_backend)
                "END:VEVENT\r\n");
        g_assert_nonnull (comp);
 
-       success = e_cal_cache_put_component (cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       success = e_cal_cache_put_component (cal_cache, comp, NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -1735,7 +1807,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_assert_cmpint (tcmb_get_tzid_ref_count (cal_cache, TZID2), ==, 1);
 
        /* Finally remove component straight in online, which removed the only one timezone too */
-       success = e_cal_cache_remove_component (cal_cache, "tz2", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       success = e_cal_cache_remove_component (cal_cache, "tz2", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -1772,6 +1844,7 @@ test_get_free_busy (ECalMetaBackend *meta_backend)
                "END:VFREEBUSY\r\n";
        ECalBackendSyncClass *backend_class;
        GSList *users, *objects = NULL;
+       ICalTime *itt;
        time_t start, end;
        GError *error = NULL;
 
@@ -1784,8 +1857,13 @@ test_get_free_busy (ECalMetaBackend *meta_backend)
        users = g_slist_prepend (NULL, (gpointer) "user@no.where");
        users = g_slist_prepend (users, (gpointer) "unknown@no.where");
 
-       start = icaltime_as_timet (icaltime_from_string ("20170102T080000Z"));
-       end = icaltime_as_timet (icaltime_from_string ("20170102T200000Z"));
+       itt = i_cal_time_from_string ("20170102T080000Z");
+       start = i_cal_time_as_timet (itt);
+       g_object_unref (itt);
+
+       itt = i_cal_time_from_string ("20170102T200000Z");
+       end = i_cal_time_as_timet (itt);
+       g_object_unref (itt);
 
        backend_class->get_free_busy_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, users, start, end, &objects, &error);
@@ -1819,11 +1897,11 @@ test_create_objects (ECalMetaBackend *meta_backend)
        g_assert_nonnull (cal_cache);
 
        /* Prepare cache and server content */
-       e_cal_cache_remove_component (cal_cache, "event-7", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-7", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
-       e_cal_cache_remove_component (cal_cache, "event-8", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-8", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
-       e_cal_cache_remove_component (cal_cache, "event-9", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-9", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        ecmb_test_remove_component (test_backend, "event-7", NULL);
@@ -1836,8 +1914,8 @@ test_create_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, tcu_new_icalstring_from_test_case ("event-1"));
 
        backend_class->create_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, &uids, &new_components, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectIdAlreadyExists);
+               NULL, NULL, objects, 0, &uids, &new_components, &error);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS);
        g_assert_null (uids);
        g_assert_null (new_components);
        g_clear_error (&error);
@@ -1849,7 +1927,7 @@ test_create_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, tcu_new_icalstring_from_test_case ("event-7"));
 
        backend_class->create_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, &uids, &new_components, &error);
+               NULL, NULL, objects, 0, &uids, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (uids), ==, 1);
        g_assert_cmpstr (uids->data, ==, "event-7");
@@ -1876,8 +1954,8 @@ test_create_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, tcu_new_icalstring_from_test_case ("event-7"));
 
        backend_class->create_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, &uids, &new_components, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectIdAlreadyExists);
+               NULL, NULL, objects, 0, &uids, &new_components, &error);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS);
        g_assert_null (uids);
        g_assert_null (new_components);
        g_clear_error (&error);
@@ -1889,7 +1967,7 @@ test_create_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, tcu_new_icalstring_from_test_case ("event-8"));
 
        backend_class->create_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, &uids, &new_components, &error);
+               NULL, NULL, objects, 0, &uids, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (uids), ==, 1);
        g_assert_cmpstr (uids->data, ==, "event-8");
@@ -1932,7 +2010,7 @@ test_create_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, calobj);
 
        backend_class->create_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, &uids, &new_components, &error);
+               NULL, NULL, objects, 0, &uids, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (uids), ==, 1);
        g_assert_cmpstr (uids->data, !=, "event-9");
@@ -1964,24 +2042,29 @@ ecmb_test_modify_case (const gchar *case_name,
                       const gchar *ridstr)
 {
        gchar *calobj;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
 
        g_assert_nonnull (case_name);
 
        calobj = tcu_new_icalstring_from_test_case (case_name);
        g_assert_nonnull (calobj);
-       icalcomp = icalcomponent_new_from_string (calobj);
-       g_assert_nonnull (icalcomp);
+       icomp = i_cal_component_new_from_string (calobj);
+       g_assert_nonnull (icomp);
        g_free (calobj);
 
-       icalcomponent_set_summary (icalcomp, MODIFIED_SUMMARY_STR);
-       icalcomponent_set_sequence (icalcomp, icalcomponent_get_sequence (icalcomp) + 1);
+       i_cal_component_set_summary (icomp, MODIFIED_SUMMARY_STR);
+       i_cal_component_set_sequence (icomp, i_cal_component_get_sequence (icomp) + 1);
 
-       if (ridstr)
-               icalcomponent_set_recurrenceid (icalcomp, icaltime_from_string (ridstr));
+       if (ridstr) {
+               ICalTime *itt;
+
+               itt = i_cal_time_from_string (ridstr);
+               i_cal_component_set_recurrenceid (icomp, itt);
+               g_object_unref (itt);
+       }
 
-       calobj = icalcomponent_as_ical_string_r (icalcomp);
-       icalcomponent_free (icalcomp);
+       calobj = i_cal_component_as_ical_string_r (icomp);
+       g_object_unref (icomp);
 
        return calobj;
 }
@@ -1994,7 +2077,7 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        ECalCache *cal_cache;
        GSList *objects, *old_components = NULL, *new_components = NULL, *offline_changes;
        gchar *calobj, *tmp;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        gint old_sequence;
        GError *error = NULL;
 
@@ -2018,8 +2101,8 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, calobj);
 
        backend_class->modify_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+               NULL, NULL, objects, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (old_components);
        g_assert_null (new_components);
        g_clear_error (&error);
@@ -2029,22 +2112,22 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, ecmb_test_modify_case ("event-1", NULL));
 
        backend_class->modify_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, objects, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 1);
        g_assert_cmpint (test_backend->save_count, ==, 1);
 
-       icalcomp = e_cal_component_get_icalcomponent (old_components->data);
-       old_sequence = icalcomponent_get_sequence (icalcomp);
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), !=, MODIFIED_SUMMARY_STR);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-1");
+       icomp = e_cal_component_get_icalcomponent (old_components->data);
+       old_sequence = i_cal_component_get_sequence (icomp);
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), !=, MODIFIED_SUMMARY_STR);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-1");
 
-       icalcomp = e_cal_component_get_icalcomponent (new_components->data);
-       g_assert_cmpint (old_sequence + 1, ==, icalcomponent_get_sequence (icalcomp));
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), ==, MODIFIED_SUMMARY_STR);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-1");
+       icomp = e_cal_component_get_icalcomponent (new_components->data);
+       g_assert_cmpint (old_sequence + 1, ==, i_cal_component_get_sequence (icomp));
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), ==, MODIFIED_SUMMARY_STR);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-1");
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
@@ -2061,22 +2144,22 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, ecmb_test_modify_case ("event-2", NULL));
 
        backend_class->modify_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, objects, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 0);
        g_assert_cmpint (test_backend->save_count, ==, 0);
 
-       icalcomp = e_cal_component_get_icalcomponent (old_components->data);
-       old_sequence = icalcomponent_get_sequence (icalcomp);
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), !=, MODIFIED_SUMMARY_STR);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-2");
+       icomp = e_cal_component_get_icalcomponent (old_components->data);
+       old_sequence = i_cal_component_get_sequence (icomp);
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), !=, MODIFIED_SUMMARY_STR);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-2");
 
-       icalcomp = e_cal_component_get_icalcomponent (new_components->data);
-       g_assert_cmpint (old_sequence + 1, ==, icalcomponent_get_sequence (icalcomp));
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), ==, MODIFIED_SUMMARY_STR);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-2");
+       icomp = e_cal_component_get_icalcomponent (new_components->data);
+       g_assert_cmpint (old_sequence + 1, ==, i_cal_component_get_sequence (icomp));
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), ==, MODIFIED_SUMMARY_STR);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-2");
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
@@ -2100,22 +2183,22 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, ecmb_test_modify_case ("event-4", NULL));
 
        backend_class->modify_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, objects, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 2);
        g_assert_cmpint (test_backend->save_count, ==, 2);
 
-       icalcomp = e_cal_component_get_icalcomponent (old_components->data);
-       old_sequence = icalcomponent_get_sequence (icalcomp);
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), !=, MODIFIED_SUMMARY_STR);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-4");
+       icomp = e_cal_component_get_icalcomponent (old_components->data);
+       old_sequence = i_cal_component_get_sequence (icomp);
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), !=, MODIFIED_SUMMARY_STR);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-4");
 
-       icalcomp = e_cal_component_get_icalcomponent (new_components->data);
-       g_assert_cmpint (old_sequence + 1, ==, icalcomponent_get_sequence (icalcomp));
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), ==, MODIFIED_SUMMARY_STR);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-4");
+       icomp = e_cal_component_get_icalcomponent (new_components->data);
+       g_assert_cmpint (old_sequence + 1, ==, i_cal_component_get_sequence (icomp));
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), ==, MODIFIED_SUMMARY_STR);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-4");
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
@@ -2127,8 +2210,8 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, ecmb_test_modify_case ("event-6", "20170227T134900"));
 
        backend_class->modify_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, E_CAL_OBJ_MOD_ONLY_THIS, &old_components, &new_components, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+               NULL, NULL, objects, E_CAL_OBJ_MOD_ONLY_THIS, 0, &old_components, &new_components, &error);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (old_components);
        g_assert_null (new_components);
        g_assert_cmpint (test_backend->load_count, ==, 2);
@@ -2140,22 +2223,22 @@ test_modify_objects (ECalMetaBackend *meta_backend)
        objects = g_slist_prepend (NULL, ecmb_test_modify_case ("event-6-a", NULL));
 
        backend_class->modify_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, objects, E_CAL_OBJ_MOD_ONLY_THIS, &old_components, &new_components, &error);
+               NULL, NULL, objects, E_CAL_OBJ_MOD_ONLY_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 3);
        g_assert_cmpint (test_backend->save_count, ==, 3);
 
-       icalcomp = e_cal_component_get_icalcomponent (old_components->data);
-       old_sequence = icalcomponent_get_sequence (icalcomp);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-6");
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), !=, MODIFIED_SUMMARY_STR);
+       icomp = e_cal_component_get_icalcomponent (old_components->data);
+       old_sequence = i_cal_component_get_sequence (icomp);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-6");
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), !=, MODIFIED_SUMMARY_STR);
 
-       icalcomp = e_cal_component_get_icalcomponent (new_components->data);
-       g_assert_cmpstr (icalcomponent_get_uid (icalcomp), ==, "event-6");
-       g_assert_cmpstr (icalcomponent_get_summary (icalcomp), ==, MODIFIED_SUMMARY_STR);
-       g_assert_cmpint (old_sequence + 1, ==, icalcomponent_get_sequence (icalcomp));
+       icomp = e_cal_component_get_icalcomponent (new_components->data);
+       g_assert_cmpstr (i_cal_component_get_uid (icomp), ==, "event-6");
+       g_assert_cmpstr (i_cal_component_get_summary (icomp), ==, MODIFIED_SUMMARY_STR);
+       g_assert_cmpint (old_sequence + 1, ==, i_cal_component_get_sequence (icomp));
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
@@ -2191,18 +2274,18 @@ test_remove_objects (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("unknown-event", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (old_components);
        g_assert_null (new_components);
        g_clear_error (&error);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
 
        /* Remove existing event */
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("event-1", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2217,7 +2300,7 @@ test_remove_objects (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2229,7 +2312,7 @@ test_remove_objects (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("event-6", "20170225T134900"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2248,7 +2331,7 @@ test_remove_objects (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2260,18 +2343,18 @@ test_remove_objects (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("event-6", "20170227T134900"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ONLY_THIS, &old_components, &new_components, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ONLY_THIS, 0, &old_components, &new_components, &error);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (old_components);
        g_assert_null (new_components);
        g_clear_error (&error);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
 
        /* Remove non-existing detached instance with THIS - changes master object */
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("event-6", "20170227T134900"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2290,7 +2373,7 @@ test_remove_objects (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2303,7 +2386,7 @@ test_remove_objects (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("event-3", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ONLY_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ONLY_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2321,7 +2404,7 @@ test_remove_objects (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2355,7 +2438,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        ECalBackendSyncClass *backend_class;
        ECalCache *cal_cache;
        gchar *calobj;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp, *firsticomp;
        GSList *ids, *old_components = NULL, *new_components = NULL;
        GError *error = NULL;
 
@@ -2375,14 +2458,18 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-1");
        g_assert_nonnull (calobj);
 
-       icalcomp = icalcomponent_new_from_string (calobj);
-       g_assert_nonnull (icalcomp);
-       g_assert_nonnull (icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT));
+       icomp = i_cal_component_new_from_string (calobj);
+       g_assert_nonnull (icomp);
+
+       firsticomp = i_cal_component_get_first_component (icomp, ICAL_VEVENT_COMPONENT);
+       g_assert_nonnull (firsticomp);
+
        g_free (calobj);
 
-       icalcomponent_add_component (test_backend->vcalendar, icalcomponent_new_clone 
(icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT)));
+       i_cal_component_take_component (test_backend->vcalendar, i_cal_component_new_clone (firsticomp));
 
-       icalcomponent_free (icalcomp);
+       g_object_unref (firsticomp);
+       g_object_unref (icomp);
 
        /* To get the 'invite' component into local cache */
        e_cal_meta_backend_test_call_refresh (meta_backend);
@@ -2406,7 +2493,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-2");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2429,7 +2516,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2440,7 +2527,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2457,7 +2544,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-1");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2487,7 +2574,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-3");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2517,7 +2604,7 @@ test_receive_objects (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-4");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2563,7 +2650,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-5");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2593,7 +2680,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2604,7 +2691,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2622,7 +2709,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        g_assert_nonnull (calobj);
 
        backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, calobj, &error);
+               NULL, NULL, calobj, 0, &error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2643,7 +2730,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2675,7 +2762,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180502T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2686,7 +2773,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2718,7 +2805,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2748,7 +2835,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2759,7 +2846,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2775,13 +2862,13 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = NULL;
        backend_class->get_object_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, "invite-detached", NULL, &calobj, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (calobj);
        g_clear_error (&error);
 
        backend_class->get_object_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, "invite-detached", "20180502T000000Z", &calobj, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (calobj);
        g_clear_error (&error);
 
@@ -2789,7 +2876,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2808,7 +2895,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2819,7 +2906,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2835,7 +2922,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2843,7 +2930,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", NULL));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2854,7 +2941,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2873,7 +2960,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2892,7 +2979,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180502T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2903,7 +2990,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2920,7 +3007,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2939,7 +3026,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180502T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2950,7 +3037,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -2967,7 +3054,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-7");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -2988,7 +3075,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180502T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -2999,7 +3086,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -3022,7 +3109,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-6");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -3031,7 +3118,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (ids, e_cal_component_id_new ("invite-detached", "20180509T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 2);
        g_assert_cmpint (g_slist_length (new_components), ==, 2);
@@ -3043,7 +3130,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -3062,7 +3149,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-7");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -3083,7 +3170,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180509T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -3094,7 +3181,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -3113,7 +3200,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-7");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -3142,7 +3229,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        calobj = tcu_new_icalstring_from_test_case ("invite-5");
        g_assert_nonnull (calobj);
 
-       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, &error);
+       backend_class->receive_objects_sync (E_CAL_BACKEND_SYNC (meta_backend), NULL, NULL, calobj, 0, 
&error);
        g_assert_no_error (error);
        g_free (calobj);
 
@@ -3167,7 +3254,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180509T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_THIS, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -3178,7 +3265,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free_full (new_components, g_object_unref);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -3203,7 +3290,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
        ids = g_slist_prepend (NULL, e_cal_component_id_new ("invite-detached", "20180502T000000Z"));
 
        backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
-               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, &old_components, &new_components, &error);
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
        g_assert_no_error (error);
        g_assert_cmpint (g_slist_length (old_components), ==, 1);
        g_assert_cmpint (g_slist_length (new_components), ==, 1);
@@ -3214,7 +3301,7 @@ test_receive_and_remove (ECalMetaBackend *meta_backend)
 
        g_slist_free_full (old_components, g_object_unref);
        g_slist_free (new_components);
-       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+       g_slist_free_full (ids, e_cal_component_id_free);
        old_components = NULL;
        new_components = NULL;
 
@@ -3240,7 +3327,7 @@ test_get_object (ECalMetaBackend *meta_backend)
        ECalMetaBackendTest *test_backend;
        ECalBackendSyncClass *backend_class;
        ECalCache *cal_cache;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        gchar *calobj = NULL;
        GError *error = NULL;
 
@@ -3254,11 +3341,11 @@ test_get_object (ECalMetaBackend *meta_backend)
        cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
        g_assert_nonnull (cal_cache);
 
-       e_cal_cache_remove_component (cal_cache, "event-7", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-7", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
-       e_cal_cache_remove_component (cal_cache, "event-8", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-8", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
-       e_cal_cache_remove_component (cal_cache, "event-9", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-9", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        /* Master object with its detached instances */
@@ -3270,11 +3357,11 @@ test_get_object (ECalMetaBackend *meta_backend)
        g_assert (strstr (calobj, "UID:event-6"));
        g_assert (strstr (calobj, "RECURRENCE-ID;TZID=America/New_York:20170225T134900"));
 
-       icalcomp = icalcomponent_new_from_string (calobj);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VCALENDAR_COMPONENT);
-       g_assert_cmpint (icalcomponent_count_components (icalcomp, ICAL_VEVENT_COMPONENT), ==, 2);
-       icalcomponent_free (icalcomp);
+       icomp = i_cal_component_new_from_string (calobj);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VCALENDAR_COMPONENT);
+       g_assert_cmpint (i_cal_component_count_components (icomp, I_CAL_VEVENT_COMPONENT), ==, 2);
+       g_object_unref (icomp);
 
        g_free (calobj);
        calobj = NULL;
@@ -3288,10 +3375,10 @@ test_get_object (ECalMetaBackend *meta_backend)
        g_assert (strstr (calobj, "UID:event-6"));
        g_assert (strstr (calobj, "RECURRENCE-ID;TZID=America/New_York:20170225T134900"));
 
-       icalcomp = icalcomponent_new_from_string (calobj);
-       g_assert_nonnull (icalcomp);
-       g_assert_cmpint (icalcomponent_isa (icalcomp), ==, ICAL_VEVENT_COMPONENT);
-       icalcomponent_free (icalcomp);
+       icomp = i_cal_component_new_from_string (calobj);
+       g_assert_nonnull (icomp);
+       g_assert_cmpint (i_cal_component_isa (icomp), ==, I_CAL_VEVENT_COMPONENT);
+       g_object_unref (icomp);
 
        g_free (calobj);
        calobj = NULL;
@@ -3305,7 +3392,7 @@ test_get_object (ECalMetaBackend *meta_backend)
 
        backend_class->get_object_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, "event-7", NULL, &calobj, &error);
-       g_assert_error (error, E_DATA_CAL_ERROR, ObjectNotFound);
+       g_assert_error (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND);
        g_assert_null (calobj);
        g_clear_error (&error);
        g_assert_cmpint (test_backend->connect_count, ==, 0);
@@ -3318,7 +3405,7 @@ test_get_object (ECalMetaBackend *meta_backend)
        g_assert (e_cal_cache_contains (cal_cache, "event-7", NULL, E_CACHE_EXCLUDE_DELETED));
 
        /* Remove it from the cache, thus it's loaded from the "server" on demand */
-       e_cal_cache_remove_component (cal_cache, "event-7", NULL, E_CACHE_IS_ONLINE, NULL, &error);
+       e_cal_cache_remove_component (cal_cache, "event-7", NULL, 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        g_assert_cmpint (test_backend->connect_count, ==, 1);
@@ -3385,7 +3472,7 @@ test_refresh (ECalMetaBackend *meta_backend)
        ECalCache *cal_cache;
        ECache *cache;
        guint count;
-       icalcomponent *icalcomp;
+       ICalComponent *icomp;
        gchar *sync_tag;
        GError *error = NULL;
 
@@ -3466,11 +3553,11 @@ test_refresh (ECalMetaBackend *meta_backend)
                NULL);
 
        /* Modify the master object, thus the detached instance will be recognized */
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;
-            icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT)) {
-               if (g_strcmp0 ("event-6", icalcomponent_get_uid (icalcomp)) == 0) {
-                       icalcomponent_set_sequence (icalcomp, icalcomponent_get_sequence (icalcomp) + 1);
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT)) {
+               if (g_strcmp0 ("event-6", i_cal_component_get_uid (icomp)) == 0) {
+                       i_cal_component_set_sequence (icomp, i_cal_component_get_sequence (icomp) + 1);
                }
        }
 
@@ -3531,12 +3618,12 @@ test_refresh (ECalMetaBackend *meta_backend)
        ecmb_test_remove_component (test_backend, "event-6", NULL);
        ecmb_test_remove_component (test_backend, "event-6", "20170225T134900");
 
-       for (icalcomp = icalcomponent_get_first_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT);
-            icalcomp;
-            icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT)) {
-               if (g_strcmp0 ("event-5", icalcomponent_get_uid (icalcomp)) == 0 ||
-                   g_strcmp0 ("event-9", icalcomponent_get_uid (icalcomp)) == 0) {
-                       icalcomponent_set_sequence (icalcomp, icalcomponent_get_sequence (icalcomp) + 1);
+       for (icomp = i_cal_component_get_first_component (test_backend->vcalendar, I_CAL_VEVENT_COMPONENT);
+            icomp;
+            g_object_unref (icomp), icomp = i_cal_component_get_next_component (test_backend->vcalendar, 
I_CAL_VEVENT_COMPONENT)) {
+               if (g_strcmp0 ("event-5", i_cal_component_get_uid (icomp)) == 0 ||
+                   g_strcmp0 ("event-9", i_cal_component_get_uid (icomp)) == 0) {
+                       i_cal_component_set_sequence (icomp, i_cal_component_get_sequence (icomp) + 1);
                }
        }
 
@@ -3689,10 +3776,6 @@ main (gint argc,
        g_assert (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
        setlocale (LC_ALL, "");
 
-#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT
-       icaltzutil_set_exact_vtimezones_support (0);
-#endif
-
        e_test_server_utils_prepare_run (0);
        e_test_server_utils_setup (&tsfixture, &tsclosure);
 
diff --git a/tests/libedata-cal/test-intervaltree.c b/tests/libedata-cal/test-intervaltree.c
index 8d90a3556..5f724d3fc 100644
--- a/tests/libedata-cal/test-intervaltree.c
+++ b/tests/libedata-cal/test-intervaltree.c
@@ -19,7 +19,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <libical/ical.h>
 #include <libedata-cal/libedata-cal.h>
 
 #define NUM_INTERVALS_CLOSED  100
@@ -71,12 +70,10 @@ search_in_list (GList *l,
        GList * result = NULL;
        EInterval *i, *i_new;
 
-       while (l)
-       {
+       while (l) {
                i = (EInterval *) l->data;
 
-               if (compare_intervals (start, end, i->start, i->end) == 0)
-               {
+               if (compare_intervals (start, end, i->start, i->end) == 0) {
                        i_new = g_new (EInterval, 1);
 
                        i_new->start = i->start;
@@ -108,8 +105,7 @@ compare_interval_lists (GList *list1,
 
        found = TRUE;
 
-       while (list1 != NULL && found)
-       {
+       while (list1 != NULL && found) {
                found = FALSE;
 
                l2 = list2;
@@ -117,8 +113,7 @@ compare_interval_lists (GList *list1,
                i1 = (EInterval *) list1->data;
                c1 = i1->comp;
 
-               while (!found && l2 != NULL)
-               {
+               while (!found && l2 != NULL) {
                        c2 = (ECalComponent *) l2->data;
 
                        found = (c1 == c2);
@@ -130,8 +125,7 @@ compare_interval_lists (GList *list1,
                        list1 = list1->next;
        }
 
-       if (!found)
-       {
+       if (!found) {
                i1 = (EInterval *) list1->data;
 
                g_message (G_STRLOC ": Not found %d - %d\n", i1->start, i1->end);
@@ -145,34 +139,35 @@ create_test_component (time_t start,
                        time_t end)
 {
        ECalComponent *comp = e_cal_component_new ();
-       ECalComponentText summary;
-       struct icaltimetype current;
+       ECalComponentText *summary;
+       ICalTime *current;
+       gchar *txt;
+       /* ECalComponentDateTime *dt; */
+
        e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
 
        /*
-       ECalComponentDateTime dtstart, dtend;
-       struct icaltimetype time_start, time_end;
- *
-       time_start = icaltime_from_timet_with_zone (start, 0, NULL);
-       dtstart.value = icaltime_from_timet_with_zone (start, 0, NULL);
-       dtstart.zone = icaltimezone_get_utc_timezone ();
- *
-       dtend.value = icaltime_from_timet_with_zone (end, 0, NULL);
-       dtend.value = icaltimezone_get_utc_timezone ();
-       e_cal_component_set_dtstart (comp, &dtstart);
-       e_cal_component_set_dtend (comp, &dtend);
+       dt = e_cal_component_datetime_new_take (i_cal_time_from_timet_with_zone (start, 0, NULL), NULL);
+       e_cal_component_set_dtstart (comp, dt);
+       e_cal_component_datetime_free (dt);
+
+       dt = e_cal_component_datetime_new_take (i_cal_time_from_timet_with_zone (end, 0, NULL), NULL);
+       e_cal_component_set_dtend (comp, dt);
+       e_cal_component_datetime_free (dt);
        */
 
-       summary.value = g_strdup_printf ("%" G_GINT64_FORMAT "- %" G_GINT64_FORMAT, (gint64) start, (gint64) 
end);
-       summary.altrep = NULL;
+       txt = g_strdup_printf ("%" G_GINT64_FORMAT "- %" G_GINT64_FORMAT, (gint64) start, (gint64) end);
 
-       e_cal_component_set_summary (comp, &summary);
+       summary = e_cal_component_text_new (txt, NULL);
+       e_cal_component_set_summary (comp, summary);
+       e_cal_component_text_free (summary);
 
-       g_free ((gchar *) summary.value);
+       g_free (txt);
 
-       current = icaltime_from_timet_with_zone (time (NULL), 0, NULL);
-       e_cal_component_set_created (comp, &current);
-       e_cal_component_set_last_modified (comp, &current);
+       current = i_cal_time_from_timet_with_zone (time (NULL), 0, NULL);
+       e_cal_component_set_created (comp, current);
+       e_cal_component_set_last_modified (comp, current);
+       g_clear_object (&current);
 
        return comp;
 }
@@ -190,24 +185,23 @@ unref_comp (gpointer data,
 static void
 print_nodes_list (GList *l1)
 {
-       while (l1)
-       {
+       while (l1) {
                ECalComponent *comp = l1->data;
-               ECalComponentText summary;
- *
-               e_cal_component_get_summary (comp, &summary);
-               g_print ("%s\n", summary.value);
+               ECalComponentText *summary;
+
+               summary = e_cal_component_get_summary (comp);
+               g_print ("%s\n", summary ? e_cal_component_text_get_value (summary) : NULL);
+               e_cal_component_text_free (summary);
                l1 = l1->next;
        }
 }
- *
+
 static void
 print_list (GList *l2)
 {
-       while (l2)
-       {
-               EInterval * i = l2->data;
- *
+       while (l2) {
+               EInterval *i = l2->data;
+
                g_print ("%d - %d\n", i->start, i->end);
                l2 = l2->next;
        }
@@ -234,14 +228,12 @@ random_test (void)
 
        tree = e_intervaltree_new ();
 
-       for (i = 0; i < NUM_INTERVALS_CLOSED; i++)
-       {
+       for (i = 0; i < NUM_INTERVALS_CLOSED; i++) {
                ECalComponent *comp;
                start = g_rand_int_range (myrand, 0, 1000);
                end = g_rand_int_range (myrand, start, 2000);
                comp = create_test_component (start, end);
-               if (!comp)
-               {
+               if (!comp) {
                        g_message (G_STRLOC ": error");
                        exit (-1);
                }
@@ -257,8 +249,7 @@ random_test (void)
        }
 
        /* insert open ended intervals */
-       for (i = 0; i < NUM_INTERVALS_OPEN; i++)
-       {
+       for (i = 0; i < NUM_INTERVALS_OPEN; i++) {
                ECalComponent *comp;
                start = g_rand_int_range (myrand, 0, 1000);
                comp = create_test_component (start, end);
@@ -280,8 +271,7 @@ random_test (void)
 
        g_print ("Number of intervals inserted: %d\n", NUM_INTERVALS_CLOSED + NUM_INTERVALS_OPEN);
 
-       for (i = 0; i < NUM_SEARCHES; i++)
-       {
+       for (i = 0; i < NUM_SEARCHES; i++) {
                start = g_rand_int_range (myrand, 0, 1000);
                end = g_rand_int_range (myrand, 2000, _TIME_MAX);
 
@@ -293,8 +283,7 @@ random_test (void)
 
                l2 = search_in_list (list, start, end);
 
-               if (!compare_interval_lists (l2, l1))
-               {
+               if (!compare_interval_lists (l2, l1)) {
                        e_intervaltree_dump (tree);
                        g_message (G_STRLOC "Error");
                        exit (-1);
@@ -308,8 +297,7 @@ random_test (void)
        }
 
        /* open-ended intervals */
-       for (i = 0; i < 20; i++)
-       {
+       for (i = 0; i < 20; i++) {
                start = g_rand_int_range (myrand, 0, 1000);
                end = _TIME_MAX;
 
@@ -321,8 +309,7 @@ random_test (void)
 
                l2 = search_in_list (list, start, end);
 
-               if (!compare_interval_lists (l2, l1))
-               {
+               if (!compare_interval_lists (l2, l1)) {
                        e_intervaltree_dump (tree);
                        g_message (G_STRLOC "Error");
                        exit (-1);
@@ -337,15 +324,13 @@ random_test (void)
 
        l1 = list;
 
-       while (l1)
-       {
+       while (l1) {
                /* perhaps we will delete l1 */
                next = l1->next;
 
-               if (g_rand_double (myrand) < pbality_delete)
-               {
+               if (g_rand_double (myrand) < pbality_delete) {
                        ECalComponent *comp;
-                       const gchar *uid = NULL;
+                       const gchar *uid;
                        gchar *rid;
                        interval = (EInterval *) l1->data;
                        comp = interval->comp;
@@ -357,9 +342,8 @@ random_test (void)
                         * */
 
                        rid = e_cal_component_get_recurid_as_string (comp);
-                       e_cal_component_get_uid (comp, &uid);
-                       if (!e_intervaltree_remove (tree, uid, rid))
-                       {
+                       uid = e_cal_component_get_uid (comp);
+                       if (!e_intervaltree_remove (tree, uid, rid)) {
                                g_free (rid);
                                e_intervaltree_dump (tree);
                                g_print (
@@ -432,7 +416,7 @@ mem_test (void)
        e_intervaltree_insert (tree, start, end, comp);
        g_assert (((GObject *) comp)->ref_count == 2);
 
-       e_cal_component_get_uid (comp, &uid);
+       uid = e_cal_component_get_uid (comp);
        rid = e_cal_component_get_recurid_as_string (comp);
        e_intervaltree_remove (tree, uid, rid);
        g_free (rid);
diff --git a/tests/test-server-utils/e-test-server-utils.c b/tests/test-server-utils/e-test-server-utils.c
index 09a00bee1..37ca5fbb6 100644
--- a/tests/test-server-utils/e-test-server-utils.c
+++ b/tests/test-server-utils/e-test-server-utils.c
@@ -96,7 +96,6 @@ add_weak_ref (ETestServerFixture *fixture,
        case E_TEST_SERVER_DIRECT_ADDRESS_BOOK:
        case E_TEST_SERVER_CALENDAR:
        case E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK:
-       case E_TEST_SERVER_DEPRECATED_CALENDAR:
 
                /* They're all the same object pointer */
                object = E_TEST_SERVER_UTILS_SERVICE (fixture, GObject);
@@ -152,7 +151,6 @@ assert_object_finalized (ETestServerFixture *fixture,
                ref = &fixture->client_ref;
                break;
        case E_TEST_SERVER_CALENDAR:
-       case E_TEST_SERVER_DEPRECATED_CALENDAR:
                message = "Timed out waiting for calendar client to finalize";
                ref = &fixture->client_ref;
                break;
@@ -380,7 +378,6 @@ e_test_server_utils_client_ready (GObject *source_object,
 
                break;
        case E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK:
-       case E_TEST_SERVER_DEPRECATED_CALENDAR:
        case E_TEST_SERVER_NONE:
                g_assert_not_reached ();
        }
@@ -490,29 +487,6 @@ e_test_server_utils_source_added (ESourceRegistry *registry,
 
                break;
 
-       case E_TEST_SERVER_DEPRECATED_CALENDAR:
-
-               /* Dont bother testing the Async apis for deprecated APIs */
-               pair->fixture->service.calendar = e_cal_new (source, pair->closure->calendar_source_type);
-               if (!pair->fixture->service.calendar) {
-                       if (pair->retries < 3)
-                               need_retry = TRUE;
-                       else
-                               g_error ("Unable to create the test calendar");
-
-                       break;
-               }
-
-               if (!e_cal_open (pair->fixture->service.calendar, FALSE, &error)) {
-                       if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
-                           pair->retries < 3)
-                               need_retry = TRUE;
-                       else
-                               g_error ("Unable to open calendar: %s", error->message);
-               }
-
-               break;
-
        case E_TEST_SERVER_NONE:
                return;
        }
@@ -588,7 +562,6 @@ e_test_server_utils_bootstrap_idle (FixturePair *pair)
 
                break;
        case E_TEST_SERVER_CALENDAR:
-       case E_TEST_SERVER_DEPRECATED_CALENDAR:
 
                if (!pair->fixture->source_name)
                        pair->fixture->source_name = generate_source_name ();
@@ -747,15 +720,6 @@ e_test_server_utils_teardown (ETestServerFixture *fixture,
                fixture->service.calendar_client = NULL;
                break;
 
-       case E_TEST_SERVER_DEPRECATED_CALENDAR:
-               if (!closure->keep_work_directory &&
-                   !e_cal_remove (fixture->service.calendar, &error)) {
-                       g_message ("Failed to remove test calendar: %s (ignoring)", error->message);
-                       g_clear_error (&error);
-               }
-               g_object_unref (fixture->service.calendar);
-               fixture->service.calendar = NULL;
-
        case E_TEST_SERVER_NONE:
                break;
        }
@@ -852,14 +816,9 @@ e_test_server_utils_finish_run (void)
 {
 #if GLOBAL_DBUS_DAEMON
        if (!test_installed_services ()) {
-               /* Teardown the D-Bus Daemon
-                *
-                * Note that we intentionally leak the TestDBus daemon
-                * in this case, presumably this is due to some leaked
-                * GDBusConnection reference counting
-                */
-               g_test_dbus_stop (global_test_dbus);
-               /* g_object_unref (global_test_dbus); */
+               /* Teardown the D-Bus Daemon */
+               g_test_dbus_down (global_test_dbus);
+               g_object_unref (global_test_dbus);
                global_test_dbus = NULL;
        }
 #endif
diff --git a/tests/test-server-utils/e-test-server-utils.h b/tests/test-server-utils/e-test-server-utils.h
index c8bc74928..f6b5f1c87 100644
--- a/tests/test-server-utils/e-test-server-utils.h
+++ b/tests/test-server-utils/e-test-server-utils.h
@@ -62,7 +62,6 @@ typedef void (* ETestSourceCustomizeFunc) (ESource            *scratch,
  * @E_TEST_SERVER_DIRECT_ADDRESS_BOOK: An #EBookClient in direct read access mode will be created and opened 
for the test
  * @E_TEST_SERVER_CALENDAR: An #ECalClient will be created and opened for the test
  * @E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK: An #EBook will be created and opened for the test
- * @E_TEST_SERVER_DEPRECATED_CALENDAR: An #ECal will be created and opened for the test
  *
  * The type of service to test
  */
@@ -71,16 +70,14 @@ typedef enum {
        E_TEST_SERVER_ADDRESS_BOOK,
        E_TEST_SERVER_DIRECT_ADDRESS_BOOK,
        E_TEST_SERVER_CALENDAR,
-       E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK,
-       E_TEST_SERVER_DEPRECATED_CALENDAR
+       E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK
 } ETestServiceType;
 
 /**
  * ETestServerClosure:
  * @type:                 An #ETestServiceType, type of the service
  * @customize:            An #ETestSourceCustomizeFunc to use to parameterize the scratch #ESource, or %NULL
- * @calendar_source_type: An #ECalClientSourceType or #ECalSourceType; for %E_TEST_SERVER_CALENDAR
- *                        and %E_TEST_SERVER_DEPRECATED_CALENDAR tests
+ * @calendar_source_type: An #ECalClientSourceType for %E_TEST_SERVER_CALENDAR tests
  * @keep_work_directory:  If specified, the work directory will not be deleted between tests
  * @destroy_closure_func: A function to destroy an allocated #ETestServerClosure, this it
  *                        typically used by sub-fixtures which embed this structure in their closures.
@@ -94,7 +91,7 @@ typedef enum {
 struct _ETestServerClosure {
        ETestServiceType         type;
        ETestSourceCustomizeFunc customize;
-       gint                     calendar_source_type;
+       ECalClientSourceType     calendar_source_type;
        gboolean                 keep_work_directory;
        GDestroyNotify           destroy_closure_func;
        gboolean                 use_async_connect;
@@ -106,7 +103,6 @@ struct _ETestServerClosure {
  * @book_client: An #EBookClient, created for %E_TEST_SERVER_ADDRESS_BOOK tests
  * @calendar_client: An #ECalClient, created for %E_TEST_SERVER_CALENDAR tests
  * @book: An #EBook, created for %E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK tests
- * @calendar: An #ECal, created for %E_TEST_SERVER_DEPRECATED_CALENDAR tests
  *
  * A union of service types, holds the object to test in a #ETestServerFixture.
  *
@@ -116,7 +112,6 @@ typedef union {
        EBookClient *book_client;
        ECalClient  *calendar_client;
        EBook       *book;
-       ECal        *calendar;
 } ETestService;
 
 /**
diff --git a/tests/test-server-utils/test-fixture.c b/tests/test-server-utils/test-fixture.c
index 335ae9379..f1b17127e 100644
--- a/tests/test-server-utils/test-fixture.c
+++ b/tests/test-server-utils/test-fixture.c
@@ -27,7 +27,6 @@ static ETestServerClosure registry_closure = { E_TEST_SERVER_NONE, NULL, 0 };
 static ETestServerClosure book_closure = { E_TEST_SERVER_ADDRESS_BOOK, NULL, 0 };
 static ETestServerClosure calendar_closure = { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS 
};
 static ETestServerClosure deprecated_book_closure = { E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK, NULL, 0 };
-static ETestServerClosure deprecated_calendar_closure = { E_TEST_SERVER_DEPRECATED_CALENDAR, NULL, 
E_CAL_SOURCE_TYPE_EVENT };
 
 static void
 empty_test (ETestServerFixture *fixture,
@@ -44,7 +43,6 @@ main (gint argc,
        gchar **book_keys;
        gchar **calendar_keys;
        gchar **deprecated_book_keys;
-       gchar **deprecated_calendar_keys;
        gint i;
        gint ret;
 
@@ -55,7 +53,6 @@ main (gint argc,
        book_keys = g_new0 (gchar *, N_CYCLES);
        calendar_keys = g_new0 (gchar *, N_CYCLES);
        deprecated_book_keys = g_new0 (gchar *, N_CYCLES);
-       deprecated_calendar_keys = g_new0 (gchar *, N_CYCLES);
 
        for (i = 0; i < N_CYCLES; i++) {
                registry_keys[i] = g_strdup_printf ("/Fixture/Registry%d", i);
@@ -101,17 +98,6 @@ main (gint argc,
                        e_test_server_utils_teardown);
        }
 
-       for (i = 0; i < N_CYCLES; i++) {
-               deprecated_calendar_keys[i] = g_strdup_printf ("/Fixture/Deprecated/Calendar%d", i);
-               g_test_add (
-                       deprecated_calendar_keys[i],
-                       ETestServerFixture,
-                       &deprecated_calendar_closure,
-                       e_test_server_utils_setup,
-                       empty_test,
-                       e_test_server_utils_teardown);
-       }
-
        ret = e_test_server_utils_run ();
 
        for (i = 0; i < N_CYCLES; i++) {
@@ -119,14 +105,12 @@ main (gint argc,
                g_free (book_keys[i]);
                g_free (calendar_keys[i]);
                g_free (deprecated_book_keys[i]);
-               g_free (deprecated_calendar_keys[i]);
        }
 
        g_free (registry_keys);
        g_free (book_keys);
        g_free (calendar_keys);
        g_free (deprecated_book_keys);
-       g_free (deprecated_calendar_keys);
 
        return ret;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]