Index: servers/google/libgdata-google/ChangeLog
===================================================================
--- servers/google/libgdata-google/ChangeLog	(revision 9443)
+++ servers/google/libgdata-google/ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2008-08-28  Milan Crha  <mcrha@redhat.com>
+
+	** Part of fix for bug #508496
+
+	* gdata-google-service.c:
+	(gdata_google_service_update_entry_with_link): Better error string.
+
 2008-08-16  Jörgen Scheibengruber  <mfcn@gmx.de>
 
 	* gdata-google-service.c (gdata_google_service_insert_entry):
Index: servers/google/libgdata-google/gdata-google-service.c
===================================================================
--- servers/google/libgdata-google/gdata-google-service.c	(revision 9443)
+++ servers/google/libgdata-google/gdata-google-service.c	(working copy)
@@ -376,9 +376,9 @@ gdata_google_service_update_entry_with_l
 	gchar *entry_xml;
 	GDataEntry *updated_entry = NULL;
 
-	g_return_val_if_fail (service !=NULL, FALSE);
-	g_return_val_if_fail (GDATA_IS_GOOGLE_SERVICE (service), FALSE);
-	g_return_val_if_fail (edit_link !=NULL, FALSE);
+	g_return_val_if_fail (service != NULL, NULL);
+	g_return_val_if_fail (GDATA_IS_GOOGLE_SERVICE (service), NULL);
+	g_return_val_if_fail (edit_link != NULL, NULL);
 
 	if (!service_is_authenticated( GDATA_GOOGLE_SERVICE(service) )) {
 		if (FALSE == gdata_google_service_authenticate(GDATA_GOOGLE_SERVICE(service), error))
@@ -419,7 +419,7 @@ gdata_google_service_update_entry_with_l
 
 	if (NULL == updated_entry) {
 		g_set_error (error, GDATA_GOOGLE_ERROR,
-					 -1, "GData protocol error");
+					 -1, (msg->response_body && msg->response_body->data) ? msg->response_body->data : "GData protocol error");
 	}
 
 	g_object_unref (msg);
Index: servers/google/libgdata/gdata-entry.c
===================================================================
--- servers/google/libgdata/gdata-entry.c	(revision 9443)
+++ servers/google/libgdata/gdata-entry.c	(working copy)
@@ -53,13 +53,14 @@ struct _GDataEntryPrivate {
 	gchar *send_notification;
 	gchar *transparency;
 	gchar *id;
+	gchar *recurrent_part;
+	int sequence;
 
 	gboolean entry_needs_update;
 	gboolean has_attendees;
 	gchar *entry_xml;
 
 	gboolean dispose_has_run;
-	gboolean is_recurrent;
 
 	/* Contacts Data */
 
@@ -195,7 +196,8 @@ static void gdata_entry_init (GTypeInsta
 	priv->field_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 	priv->entry_needs_update = FALSE;
 	priv->entry_xml = NULL;
-	priv->is_recurrent = FALSE;
+	priv->recurrent_part = NULL;
+	priv->sequence = -1;
 }
 
 static void gdata_entry_dispose (GObject *obj)
@@ -266,6 +268,11 @@ static void gdata_entry_finalize (GObjec
 	if (priv->field_table != NULL)
 		g_hash_table_destroy(priv->field_table);
 
+	if (priv->recurrent_part) {
+		g_free (priv->recurrent_part);
+		priv->recurrent_part = NULL;
+	}
+
 	if (priv->entry_xml != NULL)
 		g_free(priv->entry_xml);
 
@@ -914,6 +921,7 @@ gdata_entry_new_from_xmlptr (xmlDocPtr d
 	}
 
 	priv->entry_xml = g_strdup (xmlString);
+
 	cur = cur->xmlChildrenNode;
 	while (cur != NULL) {
 
@@ -938,12 +946,22 @@ gdata_entry_new_from_xmlptr (xmlDocPtr d
 		else if (!xmlStrcmp (cur->name, (xmlChar *)"when")) {
 			priv->start_time = (gchar *)xmlGetProp (cur, (xmlChar *)"startTime");
 			priv->end_time = (gchar *)xmlGetProp (cur, (xmlChar *)"endTime");
-		}
-		else if (!xmlStrcmp (cur->name, (xmlChar *)"recurrence")) {
-			priv->is_recurrent = TRUE;
-		}
+		} else if (!xmlStrcmp (cur->name, (xmlChar *)"sequence")) {
+			gchar *value = (gchar *)xmlGetProp (cur, (xmlChar *)"value");
+
+			if (!value || atoi (value) == 0)
+				priv->sequence = (value && g_str_equal (value, "0")) ? 0 : -1;
+			else
+				priv->sequence = atoi (value);
+		} else if (!xmlStrcmp (cur->name, (xmlChar *)"recurrence")) {
+			xmlChar *value = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+
+			if (value && *value) {
+				priv->recurrent_part = g_strdup ((const char *)value);
+			}
 
-		else if (!xmlStrcmp (cur->name, (xmlChar *)"who")) {
+			xmlFree (value);
+		} else if (!xmlStrcmp (cur->name, (xmlChar *)"who")) {
 			priv->attendees = g_slist_prepend (priv->attendees, xmlnode_to_attendee (doc, cur));
 			priv->has_attendees = TRUE;
 		}
@@ -1100,6 +1118,7 @@ gdata_entry_generate_xml (GDataEntry *en
 
 	xmlSetProp (root, (xmlChar *)"xmlns", (xmlChar *)"http://www.w3.org/2005/Atom");
 	ns =  xmlNewNs (root, (xmlChar *)"http://schemas.google.com/g/2005", (xmlChar *)"gd");
+	xmlNewNs (root, (xmlChar *)"http://schemas.google.com/gCal/2005", (xmlChar *)"gCal");
 	xmlDocSetRootElement (doc, root);
 	cur = root;
 
@@ -1130,8 +1149,21 @@ gdata_entry_generate_xml (GDataEntry *en
 		xmlSetProp (cur_child, (xmlChar *)"value", (xmlChar *)priv->status);
 	}
 
-	if (priv->start_time || priv->end_time || priv->reminder) {
-		cur_child = xmlNewChild(root, NULL, (xmlChar *)"when", NULL);
+	if (priv->sequence >= 0) {
+		char *value = g_strdup_printf ("%d", priv->sequence);
+
+		cur_child = xmlNewChild(root, NULL, (xmlChar *)"sequence", NULL);
+		xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gCal"));
+		xmlSetProp (cur_child, (xmlChar *)"value", (xmlChar *)value);
+
+		g_free (value);
+	}
+
+	if (priv->recurrent_part) {
+		cur_child = xmlNewChild (root, NULL, (xmlChar *)"recurrence", (xmlChar *)priv->recurrent_part);
+		xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gd"));
+	} else if (priv->start_time || priv->end_time || priv->reminder) {
+		cur_child = xmlNewChild (root, NULL, (xmlChar *)"when", NULL);
 		xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gd"));
 		xmlSetProp (cur_child, (xmlChar *)"startTime", (xmlChar *)priv->start_time);
 		xmlSetProp (cur_child, (xmlChar *)"endTime", (xmlChar *)priv->end_time);
@@ -1202,7 +1234,7 @@ gdata_entry_generate_xml (GDataEntry *en
 	 */
 
 	xmlDocDumpMemory(doc, &xmlString, &xml_buffer_size);
-    g_free (priv->entry_xml);
+	g_free (priv->entry_xml);
 	priv->entry_xml = g_strdup((gchar *)xmlString);
 
 	xmlFree(xmlString);
@@ -1737,7 +1769,7 @@ gdata_entry_set_author (GDataEntry *entr
  * Sets the list of authors.
  **/
 void
-gdata_entry_set_id (GDataEntry *entry, gchar *id)
+gdata_entry_set_id (GDataEntry *entry, const gchar *id)
 {
 	GDataEntryPrivate *priv;
 
@@ -2029,7 +2061,63 @@ gdata_entry_is_recurrent (GDataEntry *en
 	g_return_val_if_fail (GDATA_IS_ENTRY (entry), 0);
 
 	priv = GDATA_ENTRY_GET_PRIVATE (entry);
-	return priv->is_recurrent;
+	return priv->recurrent_part != NULL;
+}
+
+const gchar *
+gdata_entry_get_recurrent_part (GDataEntry *entry)
+{
+	GDataEntryPrivate *priv;
+
+	g_return_val_if_fail (entry != NULL, NULL);
+	g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL);
+
+	priv = GDATA_ENTRY_GET_PRIVATE (entry);
+	return priv->recurrent_part;
+}
+
+/* Sets the recurrent part, no checking for validity; can be NULL to unset. */
+void
+gdata_entry_set_recurrent_part (GDataEntry *entry, const gchar *recurrent_part)
+{
+	GDataEntryPrivate *priv;
+
+	g_return_if_fail (entry != NULL);
+	g_return_if_fail (GDATA_IS_ENTRY (entry));
+
+	priv = GDATA_ENTRY_GET_PRIVATE (entry);
+
+	g_free (priv->recurrent_part);
+
+	priv->recurrent_part = g_strdup (recurrent_part);
+	priv->entry_needs_update = TRUE;
+}
+
+/* returns sequence number of the entry; lower than zero means no sequence number set */
+int
+gdata_entry_get_sequence (GDataEntry *entry)
+{
+	GDataEntryPrivate *priv;
+
+	g_return_val_if_fail (entry != NULL, -1);
+	g_return_val_if_fail (GDATA_IS_ENTRY (entry), -1);
+
+	priv = GDATA_ENTRY_GET_PRIVATE (entry);
+	return priv->sequence;
+}
+
+/* sets sequence number for the entry; set to lower than zero to avoid using this number in XML */
+void
+gdata_entry_set_sequence (GDataEntry *entry, int sequence)
+{
+	GDataEntryPrivate *priv;
+
+	g_return_if_fail (entry != NULL);
+	g_return_if_fail (GDATA_IS_ENTRY (entry));
+
+	priv = GDATA_ENTRY_GET_PRIVATE (entry);
+	priv->sequence = sequence;
+	priv->entry_needs_update = TRUE;
 }
 
 GSList *
@@ -2183,4 +2271,5 @@ gdata_entry_set_custom (GDataEntry *entr
 
 	priv = GDATA_ENTRY_GET_PRIVATE (entry);
 	g_hash_table_insert (priv->field_table, g_strdup (name), g_strdup (value ? value : ""));
+	priv->entry_needs_update = TRUE;
 }
Index: servers/google/libgdata/gdata-entry.h
===================================================================
--- servers/google/libgdata/gdata-entry.h	(revision 9443)
+++ servers/google/libgdata/gdata-entry.h	(working copy)
@@ -199,6 +199,11 @@ GSList * gdata_entry_get_attendee_list (
 GSList * gdata_entries_new_from_xml (const gchar *feedXML, const gint length);
 
 gboolean gdata_entry_is_recurrent (GDataEntry *entry);
+const gchar *gdata_entry_get_recurrent_part (GDataEntry *entry);
+void gdata_entry_set_recurrent_part (GDataEntry *entry, const gchar *recurrent_part);
+
+int  gdata_entry_get_sequence (GDataEntry *entry);
+void gdata_entry_set_sequence (GDataEntry *entry, int sequence);
 
 void gdata_entry_set_author (GDataEntry *entry, GSList *author);
 
@@ -230,7 +235,7 @@ void gdata_entry_create_authors (GDataEn
 
 void gdata_entry_create_categories (GDataEntry *entry, const gchar *scheme, const gchar *label , const gchar *term);
 
-void gdata_entry_set_id (GDataEntry *entry, gchar *id);
+void gdata_entry_set_id (GDataEntry *entry, const gchar *id);
 
 void  gdata_entry_set_email_addresses (GDataEntry *entry, GSList *emails);
 
Index: servers/google/libgdata/ChangeLog
===================================================================
--- servers/google/libgdata/ChangeLog	(revision 9443)
+++ servers/google/libgdata/ChangeLog	(working copy)
@@ -1,3 +1,17 @@
+2008-08-28  Milan Crha  <mcrha@redhat.com>
+
+	** Part of fix for bug #508496
+
+	* gdata-entry.h: (gdata_entry_get_recurrent_part),
+	(gdata_entry_set_recurrent_part), (gdata_entry_get_sequence),
+	(gdata_entry_set_sequence), (gdata_entry_set_id):
+	* gdata-entry.c: (struct _GDataEntryPrivate), (gdata_entry_init),
+	(gdata_entry_finalize), (gdata_entry_new_from_xmlptr),
+	(gdata_entry_generate_xml), (gdata_entry_set_id),
+	(gdata_entry_get_recurrent_part), (gdata_entry_set_recurrent_part),
+	(gdata_entry_get_sequence), (gdata_entry_set_sequence),
+	(gdata_entry_set_custom): Read/write data for recurring events.
+
 2008-08-07  Milan Crha  <mcrha@redhat.com>
 
 	** Part of fix for bug #535745
Index: calendar/ChangeLog
===================================================================
--- calendar/ChangeLog	(revision 9443)
+++ calendar/ChangeLog	(working copy)
@@ -1,3 +1,21 @@
+2008-08-28  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #508496
+
+	* backends/google/e-cal-backend-google-utils.c:
+	(e_cal_backend_google_utils_update), (gdata_entry_update_entry_by_id),
+	(utils_update_changes): Update components in cache when any difference
+	found from the component on the server.
+	* backends/google/e-cal-backend-google-utils.h:
+	(gdata_entry_update_entry_by_id):
+	* backends/google/e-cal-backend-google-utils.c: (append_property),
+	(e_go_item_to_cal_component), (e_go_item_from_cal_component):
+	Support basic recurring events.
+	* backends/google/e-cal-backend-google.c:
+	(e_cal_backend_google_modify_object),
+	(e_cal_backend_google_get_static_capabilities): Update objects properly
+	and report appropriate capabilities for the backend.
+
 2008-08-18  Matthew Barnes  <mbarnes@redhat.com>
 
 	* backends/groupwise/e-cal-backend-groupwise-utils.c
Index: calendar/backends/google/e-cal-backend-google-utils.c
===================================================================
--- calendar/backends/google/e-cal-backend-google-utils.c	(revision 9443)
+++ calendar/backends/google/e-cal-backend-google-utils.c	(working copy)
@@ -75,6 +75,7 @@ static gchar * utils_form_query (const g
 static gboolean get_deltas_timeout (gpointer cbgo);
 static void utils_update_insertion (ECalBackendGoogle *cbgo, ECalBackendCache *cache, EGoItem *item, GSList *cache_keys);
 static void utils_update_deletion (ECalBackendGoogle *cbgo, ECalBackendCache *cache, GSList *cache_keys);
+static void utils_update_changes  (ECalBackendGoogle *cbgo, ECalBackendCache *cache, EGoItem *item, GSList *keys);
 
 /**
  *
@@ -183,7 +184,7 @@ e_cal_backend_google_utils_update (gpoin
 	icalcomponent_kind kind;
 
 	GSList *ids_list = NULL, *cache_keys = NULL, *entries_list = NULL;
-	GSList *uid_list = NULL, *iter_list = NULL, *remove = NULL;
+	GSList *uid_list = NULL, *iter_list = NULL, *remove = NULL, *known = NULL;
 	gboolean needs_to_insert = FALSE;
 	gchar *uri;
 
@@ -225,6 +226,7 @@ e_cal_backend_google_utils_update (gpoin
 			uid_list = g_slist_prepend (uid_list, g_strdup ((gchar *)iter_list->data));
 			needs_to_insert = TRUE;
 		}else {
+			known = g_slist_prepend (known, remove->data);
 			cache_keys = g_slist_remove_link (cache_keys, remove);
 		}
 
@@ -232,6 +234,9 @@ e_cal_backend_google_utils_update (gpoin
 			g_slist_free (remove);
 	}
 
+	/* check for changes and update cache properly */
+	utils_update_changes (cbgo, cache, item, known);
+
 	/* Update the deleted entries */
 	utils_update_deletion (cbgo, cache, cache_keys);
 
@@ -241,6 +246,8 @@ e_cal_backend_google_utils_update (gpoin
 		needs_to_insert = FALSE;
 	}
 
+	g_slist_free (known);
+
 	if (ids_list) {
 		ids_list = NULL;
 		g_slist_free (ids_list);
@@ -435,13 +442,80 @@ e_go_item_to_cal_component (EGoItem *ite
 	if (gd_date_to_ical (item, gdata_entry_get_custom (item->entry, "updated"), &itt, &dt, default_zone))
 		e_cal_component_set_dtstamp (comp, &itt);
 
-	/* Start time */
-	if (gd_date_to_ical (item, gdata_entry_get_start_time (item->entry), &itt, &dt, default_zone))
-		e_cal_component_set_dtstart (comp, &dt);
-
-	/* End time */
-	if (gd_date_to_ical (item, gdata_entry_get_end_time (item->entry), &itt, &dt, default_zone))
-		e_cal_component_set_dtend (comp, &dt);
+	if (gdata_entry_is_recurrent (item->entry)) {
+		/* get start and end time from the recurrent part for recurrent events */
+		char *txt;
+		ECalComponent *rec_comp;
+		int sequence;
+
+		txt = g_strconcat ("BEGIN:VEVENT\n",
+				   "UID:temp_uid\n",
+				   gdata_entry_get_recurrent_part (item->entry), "\n",
+				   "END:VEVENT\n",
+				   NULL);
+
+		rec_comp = e_cal_component_new_from_string (txt);
+		if (rec_comp) {
+			ECalComponentDateTime dt;
+			GSList *slist;
+			icalcomponent *subcomp, *icomp, *irec_comp;
+
+			e_cal_component_get_dtstart (rec_comp, &dt);
+			e_cal_component_set_dtstart (comp, &dt);
+			e_cal_component_free_datetime (&dt);
+
+			e_cal_component_get_dtend (rec_comp, &dt);
+			e_cal_component_set_dtend (comp, &dt);
+			e_cal_component_free_datetime (&dt);
+
+			if (e_cal_component_has_rrules (rec_comp)) {
+				slist = NULL;
+				e_cal_component_get_rrule_list (rec_comp, &slist);
+				e_cal_component_set_rrule_list (comp, slist);
+				e_cal_component_free_recur_list (slist);
+			}
+
+			if (e_cal_component_has_exdates (rec_comp)) {
+				slist = NULL;
+				e_cal_component_get_exdate_list (rec_comp, &slist);
+				e_cal_component_set_exdate_list (comp, slist);
+				e_cal_component_free_exdate_list (slist);
+			}
+
+			if (e_cal_component_has_exrules (rec_comp)) {
+				slist = NULL;
+				e_cal_component_get_exrule_list (rec_comp, &slist);
+				e_cal_component_set_exrule_list (comp, slist);
+				e_cal_component_free_recur_list (slist);
+			}
+
+			/* transfer also all timezone entries to the resulting component */
+			icomp = e_cal_component_get_icalcomponent (comp);
+			irec_comp = e_cal_component_get_icalcomponent (rec_comp);
+			subcomp = icalcomponent_get_first_component (irec_comp, ICAL_VTIMEZONE_COMPONENT);
+			while (subcomp) {
+				icalcomponent_add_component (icomp, icalcomponent_new_clone (subcomp));
+				subcomp = icalcomponent_get_next_component (irec_comp, ICAL_VTIMEZONE_COMPONENT);
+			}
+		} else {
+			g_warning ("%s: cannot parse recurrent part! ---%s---", G_STRFUNC, txt);
+		}
+
+		g_free (txt);
+
+		/* sequence number */
+		sequence = gdata_entry_get_sequence (item->entry);
+		if (sequence >= 0)
+			e_cal_component_set_sequence (comp, &sequence);
+	} else {
+		/* Start time */
+		if (gd_date_to_ical (item, gdata_entry_get_start_time (item->entry), &itt, &dt, default_zone))
+			e_cal_component_set_dtstart (comp, &dt);
+
+		/* End time */
+		if (gd_date_to_ical (item, gdata_entry_get_end_time (item->entry), &itt, &dt, default_zone))
+			e_cal_component_set_dtend (comp, &dt);
+	}
 
 	/* Summary of the Entry */
 	text.value = gdata_entry_get_title (item->entry);
@@ -518,16 +592,6 @@ e_go_item_to_cal_component (EGoItem *ite
 	/* Location */
 	e_cal_component_set_location (comp, gdata_entry_get_location (item->entry));
 
-#if 0
-	/* temp hack to see how recurrence work */
-	ECalComponentRange *recur_id;
-	recur_id = g_new0 (ECalComponentRange, 1);
-	recur_id->datetime = dt;
-	recur_id->type = E_CAL_COMPONENT_RANGE_THISFUTURE;
-	e_cal_component_set_recurid (comp, recur_id);
-#endif
-	e_cal_component_set_dtend (comp, &dt);
-
 	uid = gdata_entry_get_id (item->entry);
 	e_cal_component_set_uid (comp, (const char *)uid);
 	e_cal_component_commit_sequence (comp);
@@ -535,6 +599,28 @@ e_go_item_to_cal_component (EGoItem *ite
 	return comp;
 }
 
+static void
+append_property (GString *values, icalcomponent *icalcomp, icalproperty_kind kind, gboolean all)
+{
+	icalproperty *prop;
+
+	g_return_if_fail (values != NULL);
+	g_return_if_fail (icalcomp != NULL);
+
+	for (prop = icalcomponent_get_first_property (icalcomp, kind); prop; prop = icalcomponent_get_next_property (icalcomp, kind)) {
+		char *str = icalproperty_as_ical_string (prop);
+
+		if (str) {
+			/* it contains new line at the end already */
+			g_string_append (values, str);
+		}
+
+		g_free (str);
+
+		if (!all)
+			break;
+	}
+}
 
 /**
  *
@@ -573,19 +659,61 @@ e_go_item_from_cal_component (ECalBacken
 
 	default_zone = e_cal_backend_google_get_default_zone (cbgo);
 
-	/* Start time */
-	e_cal_component_get_dtstart (comp, &dt);
-	itt = icaltime_convert_to_zone (*dt.value, default_zone);
-	dt.value = &itt;
-	temp = get_date (dt);
-	gdata_entry_set_start_time (entry, temp);
-
-	/* End Time */
-	e_cal_component_get_dtend (comp, &dt);
-	itt = icaltime_convert_to_zone (*dt.value, default_zone);
-	dt.value = &itt;
-	temp = get_date (dt);
-	gdata_entry_set_end_time (entry, temp);
+	if (e_cal_component_has_rrules (comp)) {
+		GString *recurrent_part = g_string_new ("");
+		int *sequence;
+		icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp), *subcomp;
+
+		/* this will leak a bit, but should not happen and if so, then better than crash */
+		g_return_val_if_fail (icalcomp != NULL, NULL);
+
+		append_property (recurrent_part, icalcomp, ICAL_DTSTART_PROPERTY, FALSE);
+		append_property (recurrent_part, icalcomp, ICAL_DTEND_PROPERTY, FALSE);
+		append_property (recurrent_part, icalcomp, ICAL_RRULE_PROPERTY, FALSE);
+		append_property (recurrent_part, icalcomp, ICAL_EXDATE_PROPERTY, TRUE);
+		append_property (recurrent_part, icalcomp, ICAL_EXRULE_PROPERTY, TRUE);
+
+		/* this will add all timezone subcomponents to the recurrent part,
+		   which can be redundant, but who cares? */
+		subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+		while (subcomp) {
+			char *str = icalcomponent_as_ical_string (subcomp);
+
+			if (str) {
+				/* it contains new line at the end already */
+				g_string_append (recurrent_part, str);
+			}
+
+			g_free (str);
+			subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
+		}
+
+		if (recurrent_part->str && *recurrent_part->str) {
+			gdata_entry_set_recurrent_part (entry, recurrent_part->str);
+		}
+
+		g_string_free (recurrent_part, TRUE);
+
+		/* sequence number */
+		sequence = NULL;
+		e_cal_component_get_sequence (comp, &sequence);
+		if (sequence && *sequence >= 0)
+			gdata_entry_set_sequence (entry, *sequence);
+	} else {
+		/* Start time */
+		e_cal_component_get_dtstart (comp, &dt);
+		itt = icaltime_convert_to_zone (*dt.value, default_zone);
+		dt.value = &itt;
+		temp = get_date (dt);
+		gdata_entry_set_start_time (entry, temp);
+
+		/* End Time */
+		e_cal_component_get_dtend (comp, &dt);
+		itt = icaltime_convert_to_zone (*dt.value, default_zone);
+		dt.value = &itt;
+		temp = get_date (dt);
+		gdata_entry_set_end_time (entry, temp);
+	}
 
 	/* Content / Description */
 	e_cal_component_get_description_list (comp, &list);
@@ -597,7 +725,7 @@ e_go_item_from_cal_component (ECalBacken
 		gdata_entry_set_content (entry, "");
 
 	e_cal_component_get_uid (comp, &uid);
-	gdata_entry_set_id (entry, g_strdup(uid));
+	gdata_entry_set_id (entry, uid);
 
 	/* Location */
 	e_cal_component_get_location (comp, &location);
@@ -680,6 +808,25 @@ gdata_entry_get_entry_by_id (GSList *ent
 	return NULL;
 }
 
+void
+gdata_entry_update_entry_by_id (GSList *entries, const gchar *id, GDataEntry *new_entry)
+{
+	GSList *l;
+
+	g_return_if_fail (entries != NULL);
+	g_return_if_fail (id != NULL);
+	g_return_if_fail (new_entry != NULL);
+
+	for (l = entries; l != NULL; l = l->next) {
+		if (!strcmp (gdata_entry_get_id ((GDataEntry *)l->data), id)) {
+			g_object_unref (l->data);
+			l->data = new_entry;
+			return;
+		}
+	}
+
+	g_warning ("%s: Entry with id %s not found!", G_STRFUNC, id);
+}
 
 /***************************************************************** Utility Functions *********************************************/
 
@@ -766,6 +913,60 @@ utils_update_deletion (ECalBackendGoogle
 	}
 }
 
+static void
+utils_update_changes (ECalBackendGoogle *cbgo, ECalBackendCache *cache, EGoItem *item, GSList *keys)
+{
+	GSList *k, *entries;
+	GDataEntry *old_entry;
+
+	g_return_if_fail (cbgo != NULL);
+	g_return_if_fail (cache != NULL);
+	g_return_if_fail (item != NULL);
+
+	entries = gdata_feed_get_entries (item->feed);
+	if (!entries)
+		return;
+
+	old_entry = item->entry;
+
+	for (k = keys; k; k = k->next) {
+		GDataEntry *entry;
+		ECalComponent *cache_comp, *entry_comp;
+
+		entry = gdata_entry_get_entry_by_id (entries, k->data);
+		if (!entry)
+			continue;
+
+		cache_comp = e_cal_backend_cache_get_component (cache, k->data, NULL);
+		item->entry = entry;
+		entry_comp = e_go_item_to_cal_component (item, cbgo);
+
+		if (cache_comp && entry_comp) {
+			char *c, *e;
+
+			c = e_cal_component_get_as_string (cache_comp);
+			e = e_cal_component_get_as_string (entry_comp);
+
+			if (c && e && !g_str_equal (c, e)) {
+				/* they differ, use the server component */
+				e_cal_backend_cache_put_component (cache, entry_comp);
+				e_cal_backend_notify_object_modified (E_CAL_BACKEND (cbgo), c, e);
+			}
+
+			g_free (c);
+			g_free (e);
+		}
+
+		if (cache_comp)
+			g_object_unref (cache_comp);
+		if (entry_comp)
+			g_object_unref (entry_comp);
+	}
+
+	item->entry = old_entry;
+}
+
+
 /**
  * get_date: Returns date in gdata format '2006-04-17T17:00:00.000Z'
  * @dt a #ECalComponentDateTime value
Index: calendar/backends/google/e-cal-backend-google.c
===================================================================
--- calendar/backends/google/e-cal-backend-google.c	(revision 9443)
+++ calendar/backends/google/e-cal-backend-google.c	(working copy)
@@ -947,14 +947,31 @@ e_cal_backend_google_modify_object (ECal
 				return GNOME_Evolution_Calendar_OtherError;
 			}
 
+			GError *error = NULL;
+
 			edit_link = gdata_entry_get_edit_link (entry_from_server);
 			updated_entry = gdata_service_update_entry_with_link (GDATA_SERVICE (priv->service), 
-					entry, edit_link, NULL);
+					entry, edit_link, &error);
 
 			if (updated_entry) {
-				/* FIXME Response from server contains, additional info about GDataEntry 
-				 * Store and use them later
-				 */
+				GDataEntry *old_entry = item->entry;
+
+				item->entry = updated_entry;
+
+				gdata_entry_update_entry_by_id (l, uid, updated_entry);
+				g_object_unref (comp);
+				comp = e_go_item_to_cal_component (item, cbgo);
+
+				item->entry = old_entry;
+
+				e_cal_backend_cache_put_component (priv->cache, comp);
+			}
+
+			if (error) {
+				g_warning ("Failed to update item, error: %s", error->message);
+				g_error_free (error);
+				g_object_unref (comp);
+				return GNOME_Evolution_Calendar_OtherError;
 			}
 
 			break;
@@ -1135,8 +1152,11 @@ e_cal_backend_google_get_ldap_attribute 
 static ECalBackendSyncStatus
 e_cal_backend_google_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, char **capabilities)
 {
-	/* FIXME */
-	*capabilities = NULL;
+	*capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+				  CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+				  CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS ","
+				  CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS);
+
 	return GNOME_Evolution_Calendar_Success;
 }
 
Index: calendar/backends/google/e-cal-backend-google-utils.h
===================================================================
--- calendar/backends/google/e-cal-backend-google-utils.h	(revision 9443)
+++ calendar/backends/google/e-cal-backend-google-utils.h	(working copy)
@@ -48,6 +48,8 @@ e_cal_backend_google_utils_update (gpoin
 GDataEntry *
 gdata_entry_get_entry_by_id (GSList *entries, const gchar *id);
 
+void gdata_entry_update_entry_by_id (GSList *entries, const gchar *id, GDataEntry *new_entry);
+
 ECalBackendSyncStatus
 e_cal_backend_google_utils_connect (ECalBackendGoogle *cbgo);
 
