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



commit 60da3351d7b0590a1aace8a381fece288cbb38dc
Author: Milan Crha <mcrha redhat com>
Date:   Wed Apr 10 11:49:55 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                | 1466 ++--
 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                  | 1940 +++---
 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                            |   89 +
 src/vala/ECal-2.0.metadata                         |    2 +
 src/vala/EDataCal-2.0.metadata                     |    0
 src/vala/libecal-2.0.deps                          |    2 +
 src/vala/libedata-cal-2.0.deps                     |    3 +
 tests/libecal/CMakeLists.txt                       |  108 +-
 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-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 -
 172 files changed, 22947 insertions(+), 21991 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af435132a..42f4414d0 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..46f639f9c 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
+ * @custom_msg: (nullable): 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.
- *
- * 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);
+                       kind = i_cal_component_isa (icalcomp);
+                       if (kind != I_CAL_VFREEBUSY_COMPONENT) {
+                               i_cal_component_free (icalcomp);
                                continue;
                        }
 
-                       comp = e_cal_component_new ();
-                       if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
-                               icalcomponent_free (icalcomp);
-                               g_object_unref (comp);
-                               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")) {
@@ -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);
@@ -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,104 +2154,7 @@ 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_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);
-}
-
-/**
- * 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)
-{
-       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);
-
-       if (local_error != NULL) {
-               g_debug (
-                       "%s: Failed to find '%s' timezone: %s",
-                       G_STRFUNC, tzid, local_error->message);
-               g_error_free (local_error);
-       }
-
-       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;
+               E_CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
 }
 
 struct comp_instance {
@@ -2329,113 +2165,118 @@ struct comp_instance {
 
 struct instances_info {
        GSList **instances;
-       icaltimezone *start_zone;
-       icaltimezone *end_zone;
-       icaltimezone *default_zone;
+       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));
-
        /* 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) {
+               g_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)) {
                ECalComponentRange *range;
-               struct icaltimetype itt;
-               ECalComponentDateTime dtstart, dtend;
-
-               /* update DTSTART */
-               dtstart.value = NULL;
-               dtstart.tzid = NULL;
+               ICalTime *itt;
+               ECalComponentDateTime *dtstart, *dtend;
 
-               e_cal_component_get_dtstart (comp, &dtstart);
+               dtstart = e_cal_component_get_dtstart (ci->comp);
 
                if (instances_hold->start_zone) {
-                       itt = icaltime_from_timet_with_zone (
-                               start, dtstart.value && dtstart.value->is_date,
+                       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (start),
+                               dtstart && e_cal_component_datetime_get_value (dtstart) && i_cal_time_is_date 
(e_cal_component_datetime_get_value (dtstart)),
                                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) {
+                       if (dtstart)
+                               e_cal_component_datetime_set_tzid (dtstart, i_cal_timezone_get_tzid 
(instances_hold->start_zone));
+               } else if (dtstart && instances_hold->default_zone &&
+                          e_cal_component_datetime_get_value (dtstart) &&
+                          i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)) &&
+                          !e_cal_component_datetime_get_tzid (dtstart)) {
                        /* Floating date, set in the default zone */
-                       itt = icaltime_from_timet_with_zone (start, TRUE, instances_hold->default_zone);
+                       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (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;
-                       }
+                       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (start),
+                               dtstart && e_cal_component_datetime_get_value (dtstart) && i_cal_time_is_date 
(e_cal_component_datetime_get_value (dtstart)),
+                               NULL);
+                       if (dtstart)
+                               e_cal_component_datetime_set_tzid (dtstart, NULL);
                }
 
-               g_free (dtstart.value);
-               dtstart.value = &itt;
-               e_cal_component_set_dtstart (ci->comp, &dtstart);
+               if (dtstart)
+                       e_cal_component_datetime_set_value (dtstart, itt);
+               else
+                       dtstart = e_cal_component_datetime_new (itt, instances_hold->start_zone ? 
i_cal_timezone_get_tzid (instances_hold->start_zone) : NULL);
+
+               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);
+               g_clear_object (&itt);
 
                /* Update DTEND */
-               dtend.value = NULL;
-               dtend.tzid = NULL;
 
-               e_cal_component_get_dtend (comp, &dtend);
+               dtend = e_cal_component_get_dtend (ci->comp);
 
                if (instances_hold->end_zone) {
-                       itt = icaltime_from_timet_with_zone (
-                               end, dtend.value && dtend.value->is_date,
+                       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (end),
+                               dtend && e_cal_component_datetime_get_value (dtend) && i_cal_time_is_date 
(e_cal_component_datetime_get_value (dtend)),
                                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) {
+                       if (dtend)
+                               e_cal_component_datetime_set_tzid (dtend, i_cal_timezone_get_tzid 
(instances_hold->end_zone));
+               } else if (dtend && instances_hold->default_zone &&
+                          e_cal_component_datetime_get_value (dtend) &&
+                          i_cal_time_is_date (e_cal_component_datetime_get_value (dtend)) &&
+                          !e_cal_component_datetime_get_tzid (dtend)) {
                        /* Floating date, set in the default zone */
-                       itt = icaltime_from_timet_with_zone (end, TRUE, instances_hold->default_zone);
+                       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (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;
-                       }
+                       itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (end),
+                               dtend && e_cal_component_datetime_get_value (dtend) && i_cal_time_is_date 
(e_cal_component_datetime_get_value (dtend)),
+                               NULL);
+                       if (dtend)
+                               e_cal_component_datetime_set_tzid (dtend, NULL);
                }
 
-               g_free (dtend.value);
-               dtend.value = &itt;
-               e_cal_component_set_dtend (ci->comp, &dtend);
+               if (dtend)
+                       e_cal_component_datetime_set_value (dtend, itt);
+               else
+                       dtend = e_cal_component_datetime_new (itt, instances_hold->end_zone ? 
i_cal_timezone_get_tzid (instances_hold->end_zone) : NULL);
+
+               e_cal_component_set_dtend (ci->comp, dtend);
 
-               g_free ((gchar *) dtend.tzid);
+               e_cal_component_datetime_free (dtend);
+               g_clear_object (&itt);
        }
 
-       ci->start = start;
-       ci->end = end;
+       ci->start = i_cal_time_as_timet (start);
+       ci->end = i_cal_time_as_timet (end);
 
        *list = g_slist_prepend (*list, ci);
 
@@ -2459,33 +2300,43 @@ compare_comp_instance (gconstpointer a,
 
 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 ();
+               if (zone)
+                       g_object_ref (zone);
+       } 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 ? g_object_ref (default_timezone) : NULL;
+
+       tt = i_cal_time_as_timet_with_zone (value, zone);
+
+       g_clear_object (&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 +2345,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 +2369,16 @@ process_detached_instances (GSList *instances,
                        gint cmp;
 
                        ci = il->data;
-                       e_cal_component_get_uid (ci->comp, &instance_uid);
-
-                       if (strcmp (uid, instance_uid) == 0) {
-                               ECalComponentRange instance_recur_id;
+                       instance_uid = e_cal_component_get_uid (ci->comp);
 
-                               instance_recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
-                               instance_recur_id.datetime.value = NULL;
+                       if (g_strcmp0 (uid, instance_uid) == 0) {
+                               ECalComponentRange *instance_recur_id;
 
-                               e_cal_component_get_recurid (ci->comp, &instance_recur_id);
+                               instance_recur_id = e_cal_component_get_recurid (ci->comp);
 
-                               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,13 +2386,13 @@ 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);
                                        ci->comp = g_object_ref (cid->comp);
                                        ci->start = cid->start;
@@ -2549,15 +2401,12 @@ process_detached_instances (GSList *instances,
                                        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 +2414,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);
@@ -2597,13 +2446,13 @@ 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;
 
        priv = client->priv;
 
@@ -2612,7 +2461,7 @@ 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 ();
 
        for (l = objects; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
                ECalComponent *comp;
@@ -2620,98 +2469,90 @@ 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;
+                       ICalTimezone *start_zone = NULL, *end_zone = NULL;
 
                        /* 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);
+                       dtstart = e_cal_component_get_dtstart (comp);
+                       dtend = e_cal_component_get_dtend (comp);
 
                        /* 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 (dtstart && e_cal_component_datetime_get_tzid (dtstart) && 
e_cal_component_datetime_get_value (dtstart) &&
+                           !i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart))) {
+                               start_zone = e_cal_client_tzlookup_cb (e_cal_component_datetime_get_tzid 
(dtstart), client, cancellable, NULL);
                                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 (dtend && e_cal_component_datetime_get_tzid (dtend) && 
e_cal_component_datetime_get_value (dtend) &&
+                           !i_cal_time_is_date (e_cal_component_datetime_get_value (dtend))) {
+                               end_zone = e_cal_client_tzlookup_cb (e_cal_component_datetime_get_tzid 
(dtend), client, cancellable, NULL);
                                if (!end_zone)
                                        end_zone = default_zone;
                        } else {
                                end_zone = default_zone;
                        }
 
-                       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);
+                               e_cal_component_datetime_free (dtstart);
+                               e_cal_component_datetime_free (dtend);
                                g_object_unref (G_OBJECT (ci->comp));
                                g_free (ci);
 
                                continue;
                        }
 
-                       if (dtstart.value) {
-                               ci->start = icaltime_as_timet_with_zone (
-                                       *dtstart.value, start_zone);
-                       }
+                       ci->start = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value 
(dtstart), start_zone);
 
-                       if (dtend.value)
-                               ci->end = icaltime_as_timet_with_zone (
-                                       *dtend.value, end_zone);
-                       else if (dtstart.value && icaltime_is_date (*dtstart.value))
+                       if (dtend && e_cal_component_datetime_get_value (dtend))
+                               ci->end = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value 
(dtend), end_zone);
+                       else if (i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)))
                                ci->end = time_day_end (ci->start);
                        else
                                ci->end = ci->start;
 
-                       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);
+                               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);
                        }
                } else {
-                       ECalComponentDateTime datetime;
-                       icaltimezone *start_zone = NULL, *end_zone = NULL;
+                       ECalComponentDateTime *datetime;
+                       ICalTimezone *start_zone = NULL, *end_zone = NULL;
+                       ICalTime *starttt, *endtt;
                        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);
+                       datetime = e_cal_component_get_dtstart (comp);
+                       if (datetime && e_cal_component_datetime_get_tzid (datetime))
+                               e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid 
(datetime), &start_zone, cancellable, NULL);
                        else
                                start_zone = NULL;
-                       e_cal_component_free_datetime (&datetime);
+                       e_cal_component_datetime_free (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);
+                       datetime = e_cal_component_get_dtend (comp);
+                       if (datetime && e_cal_component_datetime_get_tzid (datetime))
+                               e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid 
(datetime), &end_zone, cancellable, NULL);
                        else
                                end_zone = NULL;
-                       e_cal_component_free_datetime (&datetime);
+                       e_cal_component_datetime_free (datetime);
 
                        instances_hold = g_new0 (struct instances_info, 1);
                        instances_hold->instances = &instances;
@@ -2719,33 +2560,44 @@ generate_instances (ECalClient *client,
                        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);
+                       starttt = i_cal_time_from_timet_with_zone (start, FALSE, NULL);
+                       endtt = i_cal_time_from_timet_with_zone (end, FALSE, NULL);
+
+                       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_clear_object (&starttt);
+                       g_clear_object (&endtt);
                        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) {
                struct comp_instance *ci;
+               ICalTime *starttt, *endtt;
                gboolean result;
 
                ci = l->data;
 
-               result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+               starttt = i_cal_time_from_timet_with_zone (ci->start, FALSE, default_zone);
+               endtt = i_cal_time_from_timet_with_zone (ci->end, FALSE, default_zone);
+
+               result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), starttt, endtt, cb_data, 
cancellable, NULL);
+
+               g_clear_object (&starttt);
+               g_clear_object (&endtt);
 
                if (!result)
                        break;
@@ -2832,15 +2684,15 @@ 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;
+       ICalTimezone *start_zone;
+       ICalTimezone *end_zone;
        ECalComponent *comp;
 };
 
@@ -3006,7 +2858,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 +2873,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 +2910,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 +2927,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 +2944,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);
 
@@ -3121,13 +2977,26 @@ process_instances (ECalComponent *comp,
                ci = instances->data;
 
                if (result) {
+                       ICalTime *starttt = NULL, *endtt = NULL;
+
                        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) {
+                                       starttt = i_cal_time_from_timet_with_zone (ci->start, FALSE, 
client->priv->default_zone);
+                                       endtt = i_cal_time_from_timet_with_zone (ci->end, FALSE, 
client->priv->default_zone);
+
+                                       result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), 
starttt, endtt, cb_data, NULL, NULL);
+                               }
+                       } else {
+                               starttt = i_cal_time_from_timet_with_zone (ci->start, FALSE, 
client->priv->default_zone);
+                               endtt = i_cal_time_from_timet_with_zone (ci->end, FALSE, 
client->priv->default_zone);
+
+                               result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), starttt, 
endtt, cb_data, NULL, NULL);
+                       }
+
+                       g_clear_object (&starttt);
+                       g_clear_object (&endtt);
                }
 
                /* remove instance from list */
@@ -3159,11 +3028,11 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
        /* 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 +3053,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 +3066,18 @@ 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;
+       ECalComponentDateTime *datetime;
+       ICalTimezone *start_zone = NULL, *end_zone = NULL;
        struct get_objects_async_data *goad;
        GCancellable *use_cancellable;
 
@@ -3219,50 +3087,47 @@ 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);
+
+       uid = e_cal_component_get_uid (comp);
 
        /* Get the start timezone */
-       e_cal_component_get_dtstart (comp, &datetime);
-       if (datetime.tzid)
+       datetime = e_cal_component_get_dtstart (comp);
+       if (datetime && e_cal_component_datetime_get_tzid (datetime))
                e_cal_client_get_timezone_sync (
-                       client, datetime.tzid, &start_zone, NULL, NULL);
+                       client, e_cal_component_datetime_get_tzid (datetime), &start_zone, cancellable, NULL);
        else
                start_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
+       e_cal_component_datetime_free (datetime);
 
        /* Get the end timezone */
-       e_cal_component_get_dtend (comp, &datetime);
-       if (datetime.tzid)
+       datetime = e_cal_component_get_dtend (comp);
+       if (datetime && e_cal_component_datetime_get_tzid (datetime))
                e_cal_client_get_timezone_sync (
-                       client, datetime.tzid, &end_zone, NULL, NULL);
+                       client, e_cal_component_datetime_get_tzid (datetime), &end_zone, cancellable, NULL);
        else
                end_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
+       e_cal_component_datetime_free (datetime);
 
        use_cancellable = cancellable;
        if (!use_cancellable)
@@ -3293,11 +3158,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 +3174,19 @@ 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;
+       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,47 +3194,43 @@ 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);
+
+       uid = e_cal_component_get_uid (comp);
 
        /* 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);
+       datetime = e_cal_component_get_dtstart (comp);
+       if (datetime && e_cal_component_datetime_get_tzid (datetime))
+               e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid (datetime), 
&start_zone, cancellable, NULL);
        else
                start_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
+       e_cal_component_datetime_free (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);
+       datetime = e_cal_component_get_dtend (comp);
+       if (datetime && e_cal_component_datetime_get_tzid (datetime))
+               e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid (datetime), 
&end_zone, cancellable, NULL);
        else
                end_zone = NULL;
-       e_cal_component_free_datetime (&datetime);
+       e_cal_component_datetime_free (datetime);
 
        instances_hold = g_new0 (struct instances_info, 1);
        instances_hold->instances = &instances;
@@ -3380,10 +3242,10 @@ e_cal_client_generate_instances_for_object_sync (ECalClient *client,
        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 +3262,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 +3286,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 +3331,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 +3348,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 +3369,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 +3418,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 +3457,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 +3472,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 +3502,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 +3516,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 +3528,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 +3541,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 +3642,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 +3661,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 +3693,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 +3715,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 +3730,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 +3756,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 +3771,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 +3917,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 +3964,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 +3977,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 +3987,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 +4008,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 +4023,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 +4104,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 +4146,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 +4190,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 +4221,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 +4243,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 +4344,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 +4390,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 +4405,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 +4421,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. */
+               comp = e_cal_component_new_from_icalcomponent (icalcomp);
+               if (comp)
+                       *out_ecalcomps = g_slist_prepend (*out_ecalcomps, comp);
 
-               /* 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;
-               }
-
-               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 +4637,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 +4663,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 +4682,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 +4697,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 +4710,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 +4731,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 +4777,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 +4795,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 +4809,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 +4818,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 +4840,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 +4858,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 +4875,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 +4888,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 +4911,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 +4954,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 +4975,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 +4993,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 +5003,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 +5012,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 +5022,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 +5052,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 +5071,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 +5091,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 +5105,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 +5160,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 +5178,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 +5190,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 +5208,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 +5225,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 +5247,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 +5258,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 +5315,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 +5335,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 +5408,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 +5428,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 +5449,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 +5465,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 +5519,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 +5538,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 +5572,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 +5594,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 +5613,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 +5625,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 +5682,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 +5699,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 +5727,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 +5752,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 +5770,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 +5801,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 +5818,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 +5835,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 +5848,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 +5900,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 +5915,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 +5926,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 +5959,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 +5978,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 +5993,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 +6006,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 +6029,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 +6048,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 +6083,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 +6096,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 +6104,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 +6122,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 +6144,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 +6362,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 +6391,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 +6410,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 +6427,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 +6442,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 +6497,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 +6513,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 +6535,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 +6823,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 +6837,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 +6868,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 +6882,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 +6922,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 +6935,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 +6955,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 +6963,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 +7013,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 +7045,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 +7100,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 +7112,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 +7123,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 +7132,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..86ee33f44
--- /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;
+
+       g_return_if_fail (id != NULL);
+
+       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