[evolution-data-server] Bug #635825 - Ensure valid UTF8 strings are passed to GDBus/GVariant



commit 5063941043097120dbe80cdeb50aa89563870652
Author: Milan Crha <mcrha redhat com>
Date:   Fri Nov 26 17:25:06 2010 +0100

    Bug #635825 - Ensure valid UTF8 strings are passed to GDBus/GVariant

 .../backends/webdav/e-book-backend-webdav.c        |   18 ++-
 addressbook/libebook/e-book.c                      |  164 ++++++++++++++------
 addressbook/libedata-book/e-data-book-view.c       |   95 ++++++++----
 addressbook/libedata-book/e-data-book.c            |   38 +++--
 calendar/libecal/e-cal.c                           |  152 ++++++++++++++----
 calendar/libedata-cal/e-data-cal-view.c            |   18 ++-
 calendar/libedata-cal/e-data-cal.c                 |  111 ++++++++++----
 libedataserver/e-data-server-util.c                |  105 +++++++++++++
 libedataserver/e-data-server-util.h                |    2 +
 9 files changed, 539 insertions(+), 164 deletions(-)
---
diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c b/addressbook/backends/webdav/e-book-backend-webdav.c
index c1940ab..f98051d 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -1368,12 +1368,18 @@ e_book_backend_webdav_dispose (GObject *object)
 	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (object);
 	EBookBackendWebdavPrivate *priv   = webdav->priv;
 
-	g_object_unref (priv->session);
-	g_object_unref (priv->proxy);
-	g_object_unref (priv->cache);
-	g_free (priv->uri);
-	g_free (priv->username);
-	g_free (priv->password);
+	#define do_unref(x) { if (x) g_object_unref (x); x = NULL; }
+	#define do_free(x) { if (x) g_free (x); x = NULL; }
+
+	do_unref (priv->session);
+	do_unref (priv->proxy);
+	do_unref (priv->cache);
+	do_free (priv->uri);
+	do_free (priv->username);
+	do_free (priv->password);
+
+	#undef do_unref
+	#undef do_free
 
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index 291d2bc..9d41259 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -394,15 +394,17 @@ e_book_add_contact (EBook           *book,
 		    GError         **error)
 {
 	GError *err = NULL;
-	gchar *vcard, *uid = NULL;
+	gchar *vcard, *uid = NULL, *gdbus_vcard = NULL;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
 	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-	e_gdbus_book_call_add_contact_sync (book->priv->gdbus_book, vcard, &uid, NULL, &err);
+	e_gdbus_book_call_add_contact_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (vcard, &gdbus_vcard), &uid, NULL, &err);
 	g_free (vcard);
+	g_free (gdbus_vcard);
+
 	if (uid) {
 		e_contact_set (contact, E_CONTACT_UID, uid);
 		g_free (uid);
@@ -468,7 +470,7 @@ e_book_async_add_contact (EBook                 *book,
 			  EBookIdCallback        cb,
 			  gpointer               closure)
 {
-	gchar *vcard;
+	gchar *vcard, *gdbus_vcard = NULL;
 	AsyncData *data;
 
 	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
@@ -482,9 +484,10 @@ e_book_async_add_contact (EBook                 *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_add_contact (book->priv->gdbus_book, vcard, NULL, add_contact_reply, data);
+	e_gdbus_book_call_add_contact (book->priv->gdbus_book, e_util_ensure_gdbus_string (vcard, &gdbus_vcard), NULL, add_contact_reply, data);
 
 	g_free (vcard);
+	g_free (gdbus_vcard);
 
 	return 0;
 }
@@ -509,7 +512,7 @@ e_book_add_contact_async (EBook                *book,
 			  EBookIdAsyncCallback  cb,
 			  gpointer              closure)
 {
-	gchar *vcard;
+	gchar *vcard, *gdbus_vcard = NULL;
 	AsyncData *data;
 
 	e_return_ex_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
@@ -523,9 +526,10 @@ e_book_add_contact_async (EBook                *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_add_contact (book->priv->gdbus_book, vcard, NULL, add_contact_reply, data);
+	e_gdbus_book_call_add_contact (book->priv->gdbus_book, e_util_ensure_gdbus_string (vcard, &gdbus_vcard), NULL, add_contact_reply, data);
 
 	g_free (vcard);
+	g_free (gdbus_vcard);
 
 	return TRUE;
 }
@@ -547,15 +551,16 @@ e_book_commit_contact (EBook           *book,
 		       GError         **error)
 {
 	GError *err = NULL;
-	gchar *vcard;
+	gchar *vcard, *gdbus_vcard = NULL;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
 	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-	e_gdbus_book_call_modify_contact_sync (book->priv->gdbus_book, vcard, NULL, &err);
+	e_gdbus_book_call_modify_contact_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (vcard, &gdbus_vcard), NULL, &err);
 	g_free (vcard);
+	g_free (gdbus_vcard);
 
 	return unwrap_gerror (err, error);
 }
@@ -610,7 +615,7 @@ e_book_async_commit_contact (EBook                 *book,
 			     EBookCallback          cb,
 			     gpointer               closure)
 {
-	gchar *vcard;
+	gchar *vcard, *gdbus_vcard = NULL;
 	AsyncData *data;
 
 	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
@@ -624,9 +629,10 @@ e_book_async_commit_contact (EBook                 *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_modify_contact (book->priv->gdbus_book, vcard, NULL, modify_contact_reply, data);
+	e_gdbus_book_call_modify_contact (book->priv->gdbus_book, e_util_ensure_gdbus_string (vcard, &gdbus_vcard), NULL, modify_contact_reply, data);
 
 	g_free (vcard);
+	g_free (gdbus_vcard);
 
 	return 0;
 }
@@ -652,7 +658,7 @@ e_book_commit_contact_async (EBook              *book,
 			     EBookAsyncCallback  cb,
 			     gpointer            closure)
 {
-	gchar *vcard;
+	gchar *vcard, *gdbus_vcard = NULL;
 	AsyncData *data;
 
 	e_return_ex_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
@@ -666,9 +672,10 @@ e_book_commit_contact_async (EBook              *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_modify_contact (book->priv->gdbus_book, vcard, NULL, modify_contact_reply, data);
+	e_gdbus_book_call_modify_contact (book->priv->gdbus_book, e_util_ensure_gdbus_string (vcard, &gdbus_vcard), NULL, modify_contact_reply, data);
 
 	g_free (vcard);
+	g_free (gdbus_vcard);
 
 	return TRUE;
 }
@@ -1107,11 +1114,19 @@ e_book_authenticate_user (EBook         *book,
 			  GError       **error)
 {
 	GError *err = NULL;
+	gchar *gdbus_user = NULL, *gdbus_passwd = NULL, *gdbus_auth_method = NULL;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	e_gdbus_book_call_authenticate_user_sync (book->priv->gdbus_book, user, passwd, auth_method, NULL, &err);
+	e_gdbus_book_call_authenticate_user_sync (book->priv->gdbus_book,
+		e_util_ensure_gdbus_string (user, &gdbus_user),
+		e_util_ensure_gdbus_string (passwd, &gdbus_passwd),
+		e_util_ensure_gdbus_string (auth_method, &gdbus_auth_method), NULL, &err);
+
+	g_free (gdbus_user);
+	g_free (gdbus_passwd);
+	g_free (gdbus_auth_method);
 
 	return unwrap_gerror (err, error);
 }
@@ -1172,6 +1187,7 @@ e_book_async_authenticate_user (EBook                 *book,
 				gpointer              closure)
 {
 	AsyncData *data;
+	gchar *gdbus_user = NULL, *gdbus_passwd = NULL, *gdbus_auth_method = NULL;
 
 	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_async_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -1184,7 +1200,14 @@ e_book_async_authenticate_user (EBook                 *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_authenticate_user (book->priv->gdbus_book, user, passwd, auth_method, NULL, authenticate_user_reply, data);
+	e_gdbus_book_call_authenticate_user (book->priv->gdbus_book,
+		e_util_ensure_gdbus_string (user, &gdbus_user),
+		e_util_ensure_gdbus_string (passwd, &gdbus_passwd),
+		e_util_ensure_gdbus_string (auth_method, &gdbus_auth_method), NULL, authenticate_user_reply, data);
+
+	g_free (gdbus_user);
+	g_free (gdbus_passwd);
+	g_free (gdbus_auth_method);
 
 	return 0;
 }
@@ -1217,6 +1240,7 @@ e_book_authenticate_user_async (EBook              *book,
 				gpointer            closure)
 {
 	AsyncData *data;
+	gchar *gdbus_user = NULL, *gdbus_passwd = NULL, *gdbus_auth_method = NULL;
 
 	e_return_ex_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_ex_async_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -1229,7 +1253,14 @@ e_book_authenticate_user_async (EBook              *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_authenticate_user (book->priv->gdbus_book, user, passwd, auth_method, NULL, authenticate_user_reply, data);
+	e_gdbus_book_call_authenticate_user (book->priv->gdbus_book,
+		e_util_ensure_gdbus_string (user, &gdbus_user),
+		e_util_ensure_gdbus_string (passwd, &gdbus_passwd),
+		e_util_ensure_gdbus_string (auth_method, &gdbus_auth_method), NULL, authenticate_user_reply, data);
+
+	g_free (gdbus_user);
+	g_free (gdbus_passwd);
+	g_free (gdbus_auth_method);
 
 	return TRUE;
 }
@@ -1253,12 +1284,14 @@ e_book_get_contact (EBook       *book,
 		    GError     **error)
 {
 	GError *err = NULL;
-	gchar *vcard = NULL;
+	gchar *vcard = NULL, *gdbus_id = NULL;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	e_gdbus_book_call_get_contact_sync (book->priv->gdbus_book, id, &vcard, NULL, &err);
+	e_gdbus_book_call_get_contact_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (id, &gdbus_id), &vcard, NULL, &err);
+
+	g_free (gdbus_id);
 
 	if (vcard) {
 		*contact = e_contact_new_from_vcard (vcard);
@@ -1323,6 +1356,7 @@ e_book_async_get_contact (EBook                 *book,
 			  gpointer               closure)
 {
 	AsyncData *data;
+	gchar *gdbus_id = NULL;
 
 	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -1333,7 +1367,9 @@ e_book_async_get_contact (EBook                 *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_contact (book->priv->gdbus_book, id, NULL, get_contact_reply, data);
+	e_gdbus_book_call_get_contact (book->priv->gdbus_book, e_util_ensure_gdbus_string (id, &gdbus_id), NULL, get_contact_reply, data);
+
+	g_free (gdbus_id);
 
 	return 0;
 }
@@ -1359,6 +1395,7 @@ e_book_get_contact_async (EBook                     *book,
 			  gpointer                   closure)
 {
 	AsyncData *data;
+	gchar *gdbus_id = NULL;
 
 	e_return_ex_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_ex_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -1369,7 +1406,9 @@ e_book_get_contact_async (EBook                     *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_contact (book->priv->gdbus_book, id, NULL, get_contact_reply, data);
+	e_gdbus_book_call_get_contact (book->priv->gdbus_book, e_util_ensure_gdbus_string (id, &gdbus_id), NULL, get_contact_reply, data);
+
+	g_free (gdbus_id);
 
 	return TRUE;
 }
@@ -1396,11 +1435,13 @@ e_book_remove_contact (EBook       *book,
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
 
-	l[0] = id;
+	l[0] = e_util_utf8_make_valid (id);
 	l[1] = NULL;
 
 	e_gdbus_book_call_remove_contacts_sync (book->priv->gdbus_book, (const gchar * const *) l, NULL, &err);
 
+	g_free ((gchar *) l[0]);
+
 	return unwrap_gerror (err, error);
 }
 
@@ -1461,7 +1502,7 @@ e_book_remove_contacts (EBook    *book,
 
 	e_gdbus_book_call_remove_contacts_sync (book->priv->gdbus_book, (const gchar * const *) l, NULL, &err);
 
-	g_free (l);
+	g_strfreev (l);
 
 	return unwrap_gerror (err, error);
 }
@@ -1493,7 +1534,7 @@ e_book_async_remove_contact (EBook                 *book,
 	e_return_async_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_async_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
-	l[0] = e_contact_get_const (contact, E_CONTACT_UID);
+	l[0] = e_util_utf8_make_valid (e_contact_get_const (contact, E_CONTACT_UID));
 	l[1] = NULL;
 
 	data = g_slice_new0 (AsyncData);
@@ -1503,6 +1544,8 @@ e_book_async_remove_contact (EBook                 *book,
 
 	e_gdbus_book_call_remove_contacts (book->priv->gdbus_book, (const gchar * const *) l, NULL, remove_contact_reply, data);
 
+	g_free ((gchar *) l[0]);
+
 	return 0;
 }
 #endif
@@ -1533,7 +1576,7 @@ e_book_remove_contact_async (EBook              *book,
 	e_return_ex_async_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_ex_async_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
-	l[0] = e_contact_get_const (contact, E_CONTACT_UID);
+	l[0] = e_util_utf8_make_valid (e_contact_get_const (contact, E_CONTACT_UID));
 	l[1] = NULL;
 
 	data = g_slice_new0 (AsyncData);
@@ -1543,6 +1586,8 @@ e_book_remove_contact_async (EBook              *book,
 
 	e_gdbus_book_call_remove_contacts (book->priv->gdbus_book, (const gchar * const *) l, NULL, remove_contact_reply, data);
 
+	g_free ((gchar *) l[0]);
+
 	return TRUE;
 }
 
@@ -1601,7 +1646,7 @@ e_book_async_remove_contact_by_id (EBook                 *book,
 	e_return_async_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_async_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
 
-	l[0] = id;
+	l[0] = e_util_utf8_make_valid (id);
 	l[1] = NULL;
 
 	data = g_slice_new0 (AsyncData);
@@ -1611,6 +1656,8 @@ e_book_async_remove_contact_by_id (EBook                 *book,
 
 	e_gdbus_book_call_remove_contacts (book->priv->gdbus_book, (const gchar * const *) l, NULL, remove_contact_by_id_reply, data);
 
+	g_free ((gchar *) l[0]);
+
 	return 0;
 }
 #endif
@@ -1641,7 +1688,7 @@ e_book_remove_contact_by_id_async (EBook              *book,
 	e_return_ex_async_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 	e_return_ex_async_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
 
-	l[0] = id;
+	l[0] = e_util_utf8_make_valid (id);
 	l[1] = NULL;
 
 	data = g_slice_new0 (AsyncData);
@@ -1651,6 +1698,8 @@ e_book_remove_contact_by_id_async (EBook              *book,
 
 	e_gdbus_book_call_remove_contacts (book->priv->gdbus_book, (const gchar * const *) l, NULL, remove_contact_by_id_reply, data);
 
+	g_free ((gchar *) l[0]);
+
 	return TRUE;
 }
 
@@ -1726,7 +1775,7 @@ e_book_async_remove_contacts (EBook                 *book,
 
 	e_gdbus_book_call_remove_contacts (book->priv->gdbus_book, (const gchar * const *) l, NULL, remove_contacts_reply, data);
 
-	g_free (l);
+	g_strfreev (l);
 
 	return 0;
 }
@@ -1775,7 +1824,7 @@ e_book_remove_contacts_async (EBook              *book,
 
 	e_gdbus_book_call_remove_contacts (book->priv->gdbus_book, (const gchar *const *) l, NULL, remove_contacts_reply, data);
 
-	g_free (l);
+	g_strfreev (l);
 
 	return TRUE;
 }
@@ -1805,7 +1854,7 @@ e_book_get_book_view (EBook       *book,
 {
 	GError *err = NULL;
 	EGdbusBookView *gdbus_bookview;
-	gchar *sexp, *view_path;
+	gchar *sexp, *view_path = NULL, *gdbus_sexp = NULL;
 	gboolean ret = TRUE;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
@@ -1813,9 +1862,10 @@ e_book_get_book_view (EBook       *book,
 
 	sexp = e_book_query_to_string (query);
 
-	if (!e_gdbus_book_call_get_book_view_sync (book->priv->gdbus_book, sexp, max_results, &view_path, NULL, &err)) {
+	if (!e_gdbus_book_call_get_book_view_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), max_results, &view_path, NULL, &err)) {
 		*book_view = NULL;
 		g_free (sexp);
+		g_free (gdbus_sexp);
 
 		return unwrap_gerror (err, error);
 	}
@@ -1838,6 +1888,7 @@ e_book_get_book_view (EBook       *book,
 
 	g_free (view_path);
 	g_free (sexp);
+	g_free (gdbus_sexp);
 
 	return ret;
 }
@@ -1911,7 +1962,7 @@ e_book_async_get_book_view (EBook                 *book,
 			    gpointer               closure)
 {
 	AsyncData *data;
-	gchar *sexp;
+	gchar *sexp, *gdbus_sexp = NULL;
 
 	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -1924,9 +1975,11 @@ e_book_async_get_book_view (EBook                 *book,
 
 	sexp = e_book_query_to_string (query);
 
-	e_gdbus_book_call_get_book_view (book->priv->gdbus_book, sexp, max_results, NULL, get_book_view_reply, data);
+	e_gdbus_book_call_get_book_view (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), max_results, NULL, get_book_view_reply, data);
 
 	g_free (sexp);
+	g_free (gdbus_sexp);
+
 	return 0;
 }
 #endif
@@ -1956,7 +2009,7 @@ e_book_get_book_view_async (EBook                      *book,
 			    gpointer                    closure)
 {
 	AsyncData *data;
-	gchar *sexp;
+	gchar *sexp, *gdbus_sexp = NULL;
 
 	e_return_ex_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_ex_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -1969,9 +2022,10 @@ e_book_get_book_view_async (EBook                      *book,
 
 	sexp = e_book_query_to_string (query);
 
-	e_gdbus_book_call_get_book_view (book->priv->gdbus_book, sexp, max_results, NULL, get_book_view_reply, data);
+	e_gdbus_book_call_get_book_view (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), max_results, NULL, get_book_view_reply, data);
 
 	g_free (sexp);
+	g_free (gdbus_sexp);
 
 	return TRUE;
 }
@@ -1996,16 +2050,17 @@ e_book_get_contacts (EBook       *book,
 {
 	GError *err = NULL;
 	gchar **list = NULL;
-	gchar *sexp;
+	gchar *sexp, *gdbus_sexp = NULL;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
 	sexp = e_book_query_to_string (query);
 
-	e_gdbus_book_call_get_contact_list_sync (book->priv->gdbus_book, sexp, &list, NULL, &err);
+	e_gdbus_book_call_get_contact_list_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &list, NULL, &err);
 
 	g_free (sexp);
+	g_free (gdbus_sexp);
 
 	if (!err) {
 		GList *l = NULL;
@@ -2085,7 +2140,7 @@ e_book_async_get_contacts (EBook             *book,
 			   gpointer           closure)
 {
 	AsyncData *data;
-	gchar *sexp;
+	gchar *sexp, *gdbus_sexp = NULL;
 
 	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -2098,9 +2153,10 @@ e_book_async_get_contacts (EBook             *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_contact_list (book->priv->gdbus_book, sexp, NULL, get_contacts_reply, data);
+	e_gdbus_book_call_get_contact_list (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), NULL, get_contacts_reply, data);
 
 	g_free (sexp);
+	g_free (gdbus_sexp);
 
 	return 0;
 }
@@ -2126,7 +2182,7 @@ e_book_get_contacts_async (EBook                  *book,
 			   gpointer                closure)
 {
 	AsyncData *data;
-	gchar *sexp;
+	gchar *sexp, *gdbus_sexp = NULL;
 
 	e_return_ex_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_ex_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -2139,9 +2195,10 @@ e_book_get_contacts_async (EBook                  *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_contact_list (book->priv->gdbus_book, sexp, NULL, get_contacts_reply, data);
+	e_gdbus_book_call_get_contact_list (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), NULL, get_contacts_reply, data);
 
 	g_free (sexp);
+	g_free (gdbus_sexp);
 
 	return TRUE;
 }
@@ -2197,11 +2254,14 @@ e_book_get_changes (EBook       *book,
 {
 	GError *err = NULL;
 	GVariant *var_changes = NULL;
+	gchar *gdbus_changeid = NULL;
 
 	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	e_gdbus_book_call_get_changes_sync (book->priv->gdbus_book, changeid, &var_changes, NULL, &err);
+	e_gdbus_book_call_get_changes_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), &var_changes, NULL, &err);
+
+	g_free (gdbus_changeid);
 
 	if (!err) {
 		*changes = parse_changes_array (var_changes);
@@ -2272,6 +2332,7 @@ e_book_async_get_changes (EBook             *book,
 			  gpointer           closure)
 {
 	AsyncData *data;
+	gchar *gdbus_changeid = NULL;
 
 	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -2281,7 +2342,9 @@ e_book_async_get_changes (EBook             *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_changes (book->priv->gdbus_book, changeid, NULL, get_changes_reply, data);
+	e_gdbus_book_call_get_changes (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), NULL, get_changes_reply, data);
+
+	g_free (gdbus_changeid);
 
 	return 0;
 }
@@ -2308,6 +2371,7 @@ e_book_get_changes_async (EBook                  *book,
 			  gpointer                closure)
 {
 	AsyncData *data;
+	gchar *gdbus_changeid = NULL;
 
 	e_return_ex_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
 	e_return_ex_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
@@ -2317,7 +2381,9 @@ e_book_get_changes_async (EBook                  *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_changes (book->priv->gdbus_book, changeid, NULL, get_changes_reply, data);
+	e_gdbus_book_call_get_changes (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), NULL, get_changes_reply, data);
+
+	g_free (gdbus_changeid);
 
 	return TRUE;
 }
@@ -3069,7 +3135,7 @@ e_book_new (ESource *source, GError **error)
 {
 	GError *err = NULL;
 	EBook *book;
-	gchar *path, *xml;
+	gchar *path = NULL, *xml, *gdbus_xml = NULL;
 	GDBusConnection *connection;
 
 	e_return_error_if_fail (E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG);
@@ -3089,9 +3155,10 @@ e_book_new (ESource *source, GError **error)
 
 	xml = e_source_to_standalone_xml (source);
 
-	if (!e_gdbus_book_factory_call_get_book_sync (book_factory_proxy, xml, &path, NULL, &err)) {
+	if (!e_gdbus_book_factory_call_get_book_sync (book_factory_proxy, e_util_ensure_gdbus_string (xml, &gdbus_xml), &path, NULL, &err)) {
 		unwrap_gerror (err, &err);
 		g_free (xml);
+		g_free (gdbus_xml);
 		g_warning (G_STRLOC ": cannot get book from factory: %s", err ? err->message : "[no error]");
 		if (err)
 			g_propagate_error (error, err);
@@ -3100,6 +3167,7 @@ e_book_new (ESource *source, GError **error)
 		return NULL;
 	}
 	g_free (xml);
+	g_free (gdbus_xml);
 
 	book->priv->gdbus_book = e_gdbus_book_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
 						      G_DBUS_PROXY_FLAGS_NONE,
@@ -3462,7 +3530,7 @@ unwrap_gerror (GError *error, GError **client_error)
 }
 
 /**
- * Turn a GList of strings into an array of strings.
+ * Turn a GList of strings into an array of strings. Free with g_strfreev().
  */
 static gchar **
 flatten_stringlist (GList *list)
@@ -3471,7 +3539,7 @@ flatten_stringlist (GList *list)
 	GList *l = list;
 	gint i = 0;
 	while (l != NULL) {
-		array[i++] = l->data;
+		array[i++] = e_util_utf8_make_valid (l->data);
 		l = l->next;
 	}
 	return array;
@@ -3486,7 +3554,7 @@ array_to_stringlist (gchar **list)
 	GList *l = NULL;
 	gchar **i = list;
 	while (*i != NULL) {
-		l = g_list_prepend (l, g_strdup (*i++));
+		l = g_list_prepend (l, e_util_utf8_make_valid (*i++));
 	}
 	return g_list_reverse (l);
 }
@@ -3502,7 +3570,7 @@ array_to_elist (gchar **list)
 		return elst;
 
 	while (*i != NULL) {
-		e_list_append (elst, g_strdup (*i++));
+		e_list_append (elst, e_util_utf8_make_valid (*i++));
 	}
 
 	return elst;
diff --git a/addressbook/libedata-book/e-data-book-view.c b/addressbook/libedata-book/e-data-book-view.c
index 6aa6cd3..3b2a850 100644
--- a/addressbook/libedata-book/e-data-book-view.c
+++ b/addressbook/libedata-book/e-data-book-view.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 #include <libebook/e-contact.h>
+#include "libedataserver/e-data-server-util.h"
 #include "e-data-book-view.h"
 
 #include "e-gdbus-egdbusbookview.h"
@@ -176,13 +177,14 @@ ensure_pending_flush_timeout (EDataBookView *view)
 }
 
 /*
- * Queue @vcard to be sent as a change notification. This takes ownership of
- * @vcard.
+ * Queue @vcard to be sent as a change notification.
  */
 static void
-notify_change (EDataBookView *view, gchar *vcard)
+notify_change (EDataBookView *view, const gchar *vcard)
 {
 	EDataBookViewPrivate *priv = view->priv;
+	gchar *utf8_vcard;
+
 	send_pending_adds (view);
 	send_pending_removes (view);
 
@@ -190,18 +192,20 @@ notify_change (EDataBookView *view, gchar *vcard)
 		send_pending_changes (view);
 	}
 
-	g_array_append_val (priv->changes, vcard);
+	utf8_vcard = e_util_utf8_make_valid (vcard);
+	g_array_append_val (priv->changes, utf8_vcard);
 
 	ensure_pending_flush_timeout (view);
 }
 
 /*
- * Queue @id to be sent as a change notification. This takes ownership of @id.
+ * Queue @id to be sent as a change notification.
  */
 static void
-notify_remove (EDataBookView *view, gchar *id)
+notify_remove (EDataBookView *view, const gchar *id)
 {
 	EDataBookViewPrivate *priv = view->priv;
+	gchar *valid_id;
 
 	send_pending_adds (view);
 	send_pending_changes (view);
@@ -210,20 +214,22 @@ notify_remove (EDataBookView *view, gchar *id)
 		send_pending_removes (view);
 	}
 
-	g_array_append_val (priv->removes, id);
-	g_hash_table_remove (priv->ids, id);
+	valid_id = e_util_utf8_make_valid (id);
+	g_array_append_val (priv->removes, valid_id);
+	g_hash_table_remove (priv->ids, valid_id);
 
 	ensure_pending_flush_timeout (view);
 }
 
 /*
- * Queue @id and @vcard to be sent as a change notification. This takes ownership of
- * @vcard but not @id.
+ * Queue @id and @vcard to be sent as a change notification.
  */
 static void
-notify_add (EDataBookView *view, const gchar *id, gchar *vcard)
+notify_add (EDataBookView *view, const gchar *id, const gchar *vcard)
 {
 	EDataBookViewPrivate *priv = view->priv;
+	gchar *utf8_vcard;
+
 	send_pending_changes (view);
 	send_pending_removes (view);
 
@@ -231,8 +237,9 @@ notify_add (EDataBookView *view, const gchar *id, gchar *vcard)
 		send_pending_adds (view);
 	}
 
-	g_array_append_val (priv->adds, vcard);
-	g_hash_table_insert (priv->ids, g_strdup (id),
+	utf8_vcard = e_util_utf8_make_valid (vcard);
+	g_array_append_val (priv->adds, utf8_vcard);
+	g_hash_table_insert (priv->ids, e_util_utf8_make_valid (id),
 			     GUINT_TO_POINTER (1));
 
 	ensure_pending_flush_timeout (view);
@@ -254,6 +261,22 @@ reset_array (GArray *array)
 	g_array_set_size (array, 0);
 }
 
+static gboolean
+id_is_in_view (EDataBookView *book_view, const gchar *id)
+{
+	gchar *valid_id;
+	gboolean res;
+
+	g_return_val_if_fail (book_view != NULL, FALSE);
+	g_return_val_if_fail (id != NULL, FALSE);
+
+	valid_id = e_util_utf8_make_valid (id);
+	res = g_hash_table_lookup (book_view->priv->ids, valid_id) != NULL;
+	g_free (valid_id);
+
+	return res;
+}
+
 /**
  * e_data_book_view_notify_update:
  * @book_view: an #EDataBookView
@@ -281,8 +304,7 @@ e_data_book_view_notify_update (EDataBookView *book_view,
 
 	id = e_contact_get_const (contact, E_CONTACT_UID);
 
-	currently_in_view =
-		g_hash_table_lookup (priv->ids, id) != NULL;
+	currently_in_view = id_is_in_view (book_view, id);
 	want_in_view =
 		e_book_backend_sexp_match_contact (priv->card_sexp, contact);
 
@@ -294,9 +316,11 @@ e_data_book_view_notify_update (EDataBookView *book_view,
 			notify_change (book_view, vcard);
 		else
 			notify_add (book_view, id, vcard);
+
+		g_free (vcard);
 	} else {
 		if (currently_in_view)
-			notify_remove (book_view, g_strdup (id));
+			notify_remove (book_view, id);
 		/* else nothing; we're removing a card that wasn't there */
 	}
 
@@ -324,15 +348,16 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
 	const gchar *id;
 	EContact *contact;
 
-	if (!priv->running)
+	if (!priv->running) {
+		g_free (vcard);
 		return;
+	}
 
 	g_mutex_lock (priv->pending_mutex);
 
 	contact = e_contact_new_from_vcard (vcard);
 	id = e_contact_get_const (contact, E_CONTACT_UID);
-	currently_in_view =
-		g_hash_table_lookup (priv->ids, id) != NULL;
+	currently_in_view = id_is_in_view (book_view, id);
 	want_in_view =
 		e_book_backend_sexp_match_contact (priv->card_sexp, contact);
 
@@ -343,13 +368,12 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
 			notify_add (book_view, id, vcard);
 	} else {
 		if (currently_in_view)
-			notify_remove (book_view, g_strdup (id));
-		else
-			/* else nothing; we're removing a card that wasn't there */
-			g_free (vcard);
+			notify_remove (book_view, id);
 	}
+
 	/* Do this last so that id is still valid when notify_ is called */
 	g_object_unref (contact);
+	g_free (vcard);
 
 	g_mutex_unlock (priv->pending_mutex);
 }
@@ -380,19 +404,22 @@ e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, cons
 	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view;
 
-	if (!priv->running)
+	if (!priv->running) {
+		g_free (vcard);
 		return;
+	}
 
 	g_mutex_lock (priv->pending_mutex);
 
-	currently_in_view =
-		g_hash_table_lookup (priv->ids, id) != NULL;
+	currently_in_view = id_is_in_view (book_view, id);
 
 	if (currently_in_view)
 		notify_change (book_view, vcard);
 	else
 		notify_add (book_view, id, vcard);
 
+	g_free (vcard);
+
 	g_mutex_unlock (priv->pending_mutex);
 }
 
@@ -414,8 +441,8 @@ e_data_book_view_notify_remove (EDataBookView *book_view, const gchar *id)
 
 	g_mutex_lock (priv->pending_mutex);
 
-	if (g_hash_table_lookup (priv->ids, id))
-		notify_remove (book_view, g_strdup (id));
+	if (id_is_in_view (book_view, id))
+		notify_remove (book_view, id);
 
 	g_mutex_unlock (priv->pending_mutex);
 }
@@ -433,6 +460,7 @@ void
 e_data_book_view_notify_complete (EDataBookView *book_view, const GError *error)
 {
 	EDataBookViewPrivate *priv = book_view->priv;
+	gchar *gdbus_error_msg = NULL;
 
 	if (!priv->running)
 		return;
@@ -448,7 +476,9 @@ e_data_book_view_notify_complete (EDataBookView *book_view, const GError *error)
 	/* We're done now, so tell the backend to stop?  TODO: this is a bit different to
 	   how the CORBA backend works... */
 
-	e_gdbus_book_view_emit_complete (priv->gdbus_object, error ? error->code : 0, error ? error->message : "");
+	e_gdbus_book_view_emit_complete (priv->gdbus_object, error ? error->code : 0, e_util_ensure_gdbus_string (error ? error->message : "", &gdbus_error_msg));
+
+	g_free (gdbus_error_msg);
 }
 
 /**
@@ -464,11 +494,14 @@ void
 e_data_book_view_notify_status_message (EDataBookView *book_view, const gchar *message)
 {
 	EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
+	gchar *gdbus_message = NULL;
 
 	if (!priv->running)
 		return;
 
-	e_gdbus_book_view_emit_status_message (priv->gdbus_object, message ? message : "");
+	e_gdbus_book_view_emit_status_message (priv->gdbus_object, e_util_ensure_gdbus_string (message, &gdbus_message));
+
+	g_free (gdbus_message);
 }
 
 /**
@@ -494,7 +527,7 @@ e_data_book_view_new (EDataBook *book, const gchar *card_query, EBookBackendSExp
 	/* Attach a weak reference to the book, so if it dies the book view is destroyed too */
 	g_object_weak_ref (G_OBJECT (priv->book), book_destroyed_cb, view);
 	priv->backend = g_object_ref (e_data_book_get_backend (book));
-	priv->card_query = g_strdup (card_query);
+	priv->card_query = e_util_utf8_make_valid (card_query);
 	priv->card_sexp = card_sexp;
 	priv->max_results = max_results;
 
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 9d58510..2a48c18 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -26,6 +26,8 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 
+#include "libedataserver/e-data-server-util.h"
+
 #include "e-data-book-enumtypes.h"
 #include "e-data-book-factory.h"
 #include "e-data-book.h"
@@ -380,7 +382,11 @@ e_data_book_respond_get_contact (EDataBook *book, guint32 opid, GError *error, c
 		data_book_return_error  (invocation, error, _("Cannot get contact: %s"));
 		g_error_free (error);
 	} else {
-		e_gdbus_book_complete_get_contact (book->priv->gdbus_object, invocation, vcard);
+		gchar *gdbus_vcard = NULL;
+
+		e_gdbus_book_complete_get_contact (book->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (vcard, &gdbus_vcard));
+
+		g_free (gdbus_vcard);
 	}
 }
 
@@ -430,9 +436,11 @@ data_book_return_error (GDBusMethodInvocation *invocation, const GError *perror,
 {
 	GError *error;
 
-	g_return_if_fail (perror != NULL);
+	if (perror == NULL)
+		error = g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_OTHER_ERROR, error_fmt, _("Unknown error"));
+	else
+		error = g_error_new (E_DATA_BOOK_ERROR, perror->code, error_fmt, perror->message);
 
-	error = g_error_new (E_DATA_BOOK_ERROR, perror->code, error_fmt, perror->message);
 	g_dbus_method_invocation_return_gerror (invocation, error);
 
 	g_error_free (error);
@@ -482,10 +490,14 @@ e_data_book_respond_create (EDataBook *book, guint32 opid, GError *error, EConta
 		data_book_return_error (invocation, error, _("Cannot add contact: %s"));
 		g_error_free (error);
 	} else {
+		gchar *gdbus_uid = NULL;
+
 		e_book_backend_notify_update (e_data_book_get_backend (book), contact);
 		e_book_backend_notify_complete (e_data_book_get_backend (book));
 
-		e_gdbus_book_complete_add_contact (book->priv->gdbus_object, invocation, e_contact_get_const (contact, E_CONTACT_UID));
+		e_gdbus_book_complete_add_contact (book->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (e_contact_get_const (contact, E_CONTACT_UID), &gdbus_uid));
+
+		g_free (gdbus_uid);
 	}
 }
 
@@ -572,10 +584,12 @@ static gboolean
 impl_Book_getStaticCapabilities (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
 {
 	gchar *capabilities = e_book_backend_get_static_capabilities (e_data_book_get_backend (book));
+	gchar *gdbus_capabilities = NULL;
 
-	e_gdbus_book_complete_get_static_capabilities (object, invocation, capabilities ? capabilities : "");
+	e_gdbus_book_complete_get_static_capabilities (object, invocation, e_util_ensure_gdbus_string (capabilities, &gdbus_capabilities));
 
 	g_free (capabilities);
+	g_free (gdbus_capabilities);
 
 	return TRUE;
 }
@@ -705,9 +719,11 @@ e_data_book_respond_get_changes (EDataBook *book, guint32 opid, GError *error, G
 
 		while (changes != NULL) {
 			EDataBookChange *change = (EDataBookChange *) changes->data;
+			gchar *gdbus_vcard = NULL;
 
-			g_variant_builder_add (builder, "(us)", change->change_type, change->vcard ? change->vcard : "");
+			g_variant_builder_add (builder, "(us)", change->change_type, e_util_ensure_gdbus_string (change->vcard, &gdbus_vcard));
 
+			g_free (gdbus_vcard);
 			g_free (change->vcard);
 			g_free (change);
 
@@ -798,16 +814,14 @@ return_error_and_list (EGdbusBook *gdbus_object, void (* complete_func) (EGdbusB
 
 		array = g_new0 (gchar *, g_list_length (list) + 1);
 		for (l = list; l != NULL; l = l->next) {
-			array[i++] = l->data;
+			array[i++] = e_util_utf8_make_valid (l->data);
+			if (free_data)
+				g_free (l->data);
 		}
 
 		complete_func (gdbus_object, invocation, (const gchar * const *) array);
 
-		if (free_data) {
-			g_strfreev (array);
-		} else {
-			g_free (array);
-		}
+		g_strfreev (array);
 	}
 }
 
diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c
index b94d8f9..ecbcd49 100644
--- a/calendar/libecal/e-cal.c
+++ b/calendar/libecal/e-cal.c
@@ -1282,15 +1282,25 @@ open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
 	*status = E_CALENDAR_STATUS_OK;
 	#endif
 	if (!async) {
-		if (!e_gdbus_cal_call_open_sync (priv->gdbus_cal, only_if_exists, username ? username : "", password ? password : "", NULL, error)) {
+		gchar *gdbus_username = NULL, *gdbus_password = NULL;
+
+		if (!e_gdbus_cal_call_open_sync (priv->gdbus_cal, only_if_exists, e_util_ensure_gdbus_string (username, &gdbus_username), e_util_ensure_gdbus_string (password, &gdbus_password), NULL, error)) {
 			#ifndef E_CAL_DISABLE_DEPRECATED
 			*status = E_CALENDAR_STATUS_DBUS_EXCEPTION;
 			#endif
 		}
 		if (!*error)
 			priv->load_state = E_CAL_LOAD_LOADED;
+
+		g_free (gdbus_username);
+		g_free (gdbus_password);
 	} else {
-		e_gdbus_cal_call_open (priv->gdbus_cal, only_if_exists, username ? username : "", password ? password : "", NULL, (GAsyncReadyCallback) async_open_ready_cb, ecal);
+		gchar *gdbus_username = NULL, *gdbus_password = NULL;
+
+		e_gdbus_cal_call_open (priv->gdbus_cal, only_if_exists, e_util_ensure_gdbus_string (username, &gdbus_username), e_util_ensure_gdbus_string (password, &gdbus_password), NULL, (GAsyncReadyCallback) async_open_ready_cb, ecal);
+
+		g_free (gdbus_username);
+		g_free (gdbus_password);
 	}
 
 	g_free (password);
@@ -2042,7 +2052,7 @@ e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
 {
 	ECalPrivate *priv;
 	ECalendarStatus status;
-	gchar *object;
+	gchar *object = NULL;
 
 	e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
@@ -2093,6 +2103,7 @@ e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gchar *rid,
 	ECalPrivate *priv;
 	ECalendarStatus status;
 	gchar **list_array;
+	gchar *gdbus_uid = NULL, *gdbus_rid = NULL;
 
 	e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (list != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2105,10 +2116,16 @@ e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gchar *rid,
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_attachment_list_sync (priv->gdbus_cal, uid, rid ? rid: "", &list_array, NULL, error)) {
+	if (!e_gdbus_cal_call_get_attachment_list_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (rid, &gdbus_rid), &list_array, NULL, error)) {
+		g_free (gdbus_uid);
+		g_free (gdbus_rid);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_uid);
+	g_free (gdbus_rid);
+
 	if (list_array) {
 		gchar **string;
 		for (string = list_array; *string; string++) {
@@ -2140,7 +2157,7 @@ e_cal_get_object (ECal *ecal, const gchar *uid, const gchar *rid, icalcomponent
 {
 	ECalPrivate *priv;
 	ECalendarStatus status;
-	gchar *object;
+	gchar *object = NULL, *gdbus_uid = NULL, *gdbus_rid = NULL;
 	icalcomponent *tmp_icalcomp;
 	icalcomponent_kind kind;
 
@@ -2155,10 +2172,16 @@ e_cal_get_object (ECal *ecal, const gchar *uid, const gchar *rid, icalcomponent
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, uid, rid ? rid : "", &object, NULL, error)) {
+	if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (rid, &gdbus_rid), &object, NULL, error)) {
+		g_free (gdbus_uid);
+		g_free (gdbus_rid);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_uid);
+	g_free (gdbus_rid);
+
 	status = E_CALENDAR_STATUS_OK;
 	tmp_icalcomp = icalparser_parse_string (object);
 	if (!tmp_icalcomp) {
@@ -2219,7 +2242,7 @@ e_cal_get_objects_for_uid (ECal *ecal, const gchar *uid, GList **objects, GError
 {
 	ECalPrivate *priv;
 	ECalendarStatus status;
-	gchar *object;
+	gchar *object = NULL, *gdbus_uid = NULL;
 
 	e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2232,10 +2255,14 @@ e_cal_get_objects_for_uid (ECal *ecal, const gchar *uid, GList **objects, GError
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, uid, "", &object, NULL, error)) {
+	if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), "", &object, NULL, error)) {
+		g_free (gdbus_uid);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_uid);
+
 	status = E_CALENDAR_STATUS_OK;
 	{
 		icalcomponent *icalcomp;
@@ -2335,6 +2362,7 @@ e_cal_get_changes (ECal *ecal, const gchar *change_id, GList **changes, GError *
 {
 	ECalPrivate *priv;
 	gchar **additions = NULL, **modifications = NULL, **removals = NULL;
+	gchar *gdbus_change_id = NULL;
 
 	e_return_error_if_fail (changes != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (change_id != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2347,10 +2375,14 @@ e_cal_get_changes (ECal *ecal, const gchar *change_id, GList **changes, GError *
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_changes_sync (priv->gdbus_cal, change_id, &additions, &modifications, &removals, NULL, error)) {
+	if (!e_gdbus_cal_call_get_changes_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (change_id, &gdbus_change_id), &additions, &modifications, &removals, NULL, error)) {
+		g_free (gdbus_change_id);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_change_id);
+
 	/* TODO: Be more elegant and split this into a function */
 	/* Mostly copied from the old e-cal-listener.c */
 	if ((additions)&&(modifications)&&(removals)) {
@@ -2449,7 +2481,7 @@ gboolean
 e_cal_get_object_list (ECal *ecal, const gchar *query, GList **objects, GError **error)
 {
 	ECalPrivate *priv;
-	gchar **object_array;
+	gchar **object_array = NULL, *gdbus_query = NULL;
 
 	e_return_error_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (query, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2462,10 +2494,14 @@ e_cal_get_object_list (ECal *ecal, const gchar *query, GList **objects, GError *
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_object_list_sync (priv->gdbus_cal, query, &object_array, NULL, error)) {
+	if (!e_gdbus_cal_call_get_object_list_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (query, &gdbus_query), &object_array, NULL, error)) {
+		g_free (gdbus_query);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_query);
+
 	if (object_array) {
 		icalcomponent *comp;
 		gchar **object;
@@ -2594,7 +2630,7 @@ e_cal_get_free_busy (ECal *ecal, GList *users, time_t start, time_t end,
 {
 	ECalPrivate *priv;
 	gchar **users_list;
-	gchar **freebusy_array;
+	gchar **freebusy_array = NULL;
 	GList *l;
 	gint i;
 
@@ -2611,7 +2647,7 @@ e_cal_get_free_busy (ECal *ecal, GList *users, time_t start, time_t end,
 
 	users_list = g_new0 (gchar *, g_list_length (users) + 1);
 	for (l = users, i = 0; l; l = l->next, i++)
-		users_list[i] = g_strdup (l->data);
+		users_list[i] = e_util_utf8_make_valid (l->data);
 
 	if (!e_gdbus_cal_call_get_free_busy_sync (priv->gdbus_cal, (const gchar * const *) users_list, start, end, &freebusy_array, NULL, error)) {
 		g_strfreev (users_list);
@@ -3332,7 +3368,8 @@ gboolean
 e_cal_discard_alarm (ECal *ecal, ECalComponent *comp, const gchar *auid, GError **error)
 {
 	ECalPrivate *priv;
-	const gchar *uid;
+	const gchar *uid = NULL;
+	gchar *gdbus_uid = NULL, *gdbus_auid = NULL;
 
 	e_return_error_if_fail (ecal != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
@@ -3348,10 +3385,16 @@ e_cal_discard_alarm (ECal *ecal, ECalComponent *comp, const gchar *auid, GError
 
 	e_cal_component_get_uid (comp, &uid);
 
-	if (!e_gdbus_cal_call_discard_alarm_sync (priv->gdbus_cal, uid ? uid : "", auid, NULL, error)) {
+	if (!e_gdbus_cal_call_discard_alarm_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (auid, &gdbus_auid), NULL, error)) {
+		g_free (gdbus_uid);
+		g_free (gdbus_auid);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_uid);
+	g_free (gdbus_auid);
+
 	E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
 }
 
@@ -3538,7 +3581,7 @@ gboolean
 e_cal_create_object (ECal *ecal, icalcomponent *icalcomp, gchar **uid, GError **error)
 {
 	ECalPrivate *priv;
-	gchar *obj, *muid = NULL;
+	gchar *obj, *muid = NULL, *gdbus_obj = NULL;
 
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3551,12 +3594,15 @@ e_cal_create_object (ECal *ecal, icalcomponent *icalcomp, gchar **uid, GError **
 	}
 
 	obj = icalcomponent_as_ical_string_r (icalcomp);
-	if (!e_gdbus_cal_call_create_object_sync (priv->gdbus_cal, obj, &muid, NULL, error)) {
+	if (!e_gdbus_cal_call_create_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), &muid, NULL, error)) {
 		g_free (obj);
+		g_free (gdbus_obj);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
 	g_free (obj);
+	g_free (gdbus_obj);
 
 	if (!muid) {
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
@@ -3593,7 +3639,7 @@ gboolean
 e_cal_modify_object (ECal *ecal, icalcomponent *icalcomp, CalObjModType mod, GError **error)
 {
 	ECalPrivate *priv;
-	gchar *obj;
+	gchar *obj, *gdbus_obj = NULL;
 
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (icalcomp, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3607,12 +3653,16 @@ e_cal_modify_object (ECal *ecal, icalcomponent *icalcomp, CalObjModType mod, GEr
 	}
 
 	obj = icalcomponent_as_ical_string_r (icalcomp);
-	if (!e_gdbus_cal_call_modify_object_sync (priv->gdbus_cal, obj, mod, NULL, error)) {
+	if (!e_gdbus_cal_call_modify_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), mod, NULL, error)) {
 		g_free (obj);
+		g_free (gdbus_obj);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
 	g_free (obj);
+	g_free (gdbus_obj);
+
 	E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
 }
 
@@ -3640,6 +3690,7 @@ e_cal_remove_object_with_mod (ECal *ecal, const gchar *uid,
 			      const gchar *rid, CalObjModType mod, GError **error)
 {
 	ECalPrivate *priv;
+	gchar *gdbus_uid = NULL, *gdbus_rid = NULL;
 
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (uid, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3651,10 +3702,16 @@ e_cal_remove_object_with_mod (ECal *ecal, const gchar *uid,
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_remove_object_sync (priv->gdbus_cal, uid, rid ? rid : "", mod, NULL, error)) {
+	if (!e_gdbus_cal_call_remove_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (rid, &gdbus_rid), mod, NULL, error)) {
+		g_free (gdbus_uid);
+		g_free (gdbus_rid);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_uid);
+	g_free (gdbus_rid);
+
 	E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
 }
 
@@ -3695,6 +3752,7 @@ gboolean
 e_cal_receive_objects (ECal *ecal, icalcomponent *icalcomp, GError **error)
 {
 	ECalPrivate *priv;
+	gchar *obj, *gdbus_obj = NULL;
 
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (icalcomp, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3706,10 +3764,17 @@ e_cal_receive_objects (ECal *ecal, icalcomponent *icalcomp, GError **error)
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_receive_objects_sync (priv->gdbus_cal, icalcomponent_as_ical_string (icalcomp), NULL, error)) {
+	obj = icalcomponent_as_ical_string_r (icalcomp);
+	if (!e_gdbus_cal_call_receive_objects_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), NULL, error)) {
+		g_free (obj);
+		g_free (gdbus_obj);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (obj);
+	g_free (gdbus_obj);
+
 	E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
 }
 
@@ -3732,8 +3797,8 @@ e_cal_send_objects (ECal *ecal, icalcomponent *icalcomp, GList **users, icalcomp
 {
 	ECalPrivate *priv;
 	ECalendarStatus status;
-	gchar **users_array;
-	gchar *object;
+	gchar **users_array = NULL;
+	gchar *object = NULL, *obj, *gdbus_obj = NULL;
 
 	e_return_error_if_fail (users != NULL, E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (modified_icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3749,10 +3814,17 @@ e_cal_send_objects (ECal *ecal, icalcomponent *icalcomp, GList **users, icalcomp
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_send_objects_sync (priv->gdbus_cal, icalcomponent_as_ical_string (icalcomp), &users_array, &object, NULL, error)) {
+	obj = icalcomponent_as_ical_string_r (icalcomp);
+	if (!e_gdbus_cal_call_send_objects_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), &users_array, &object, NULL, error)) {
+		g_free (obj);
+		g_free (gdbus_obj);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (obj);
+	g_free (gdbus_obj);
+
 	status = E_CALENDAR_STATUS_OK;
 	if (users_array) {
 		gchar **user;
@@ -3786,7 +3858,7 @@ e_cal_get_timezone (ECal *ecal, const gchar *tzid, icaltimezone **zone, GError *
 	ECalPrivate *priv;
 	ECalendarStatus status = E_CALENDAR_STATUS_OK;
 	icalcomponent *icalcomp = NULL;
-	gchar *object;
+	gchar *object = NULL, *gdbus_tzid = NULL;
 	const gchar *systzid = NULL;
 
 	e_return_error_if_fail (zone, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3829,11 +3901,15 @@ e_cal_get_timezone (ECal *ecal, const gchar *tzid, icaltimezone **zone, GError *
 	systzid = e_cal_match_tzid (tzid);
 	if (!systzid) {
 		/* call the backend */
-		if (!e_gdbus_cal_call_get_timezone_sync (priv->gdbus_cal, tzid, &object, NULL, error)) {
+		if (!e_gdbus_cal_call_get_timezone_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (tzid, &gdbus_tzid), &object, NULL, error)) {
+			g_free (gdbus_tzid);
+
 			UNLOCK_CACHE ();
 			E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 		}
 
+		g_free (gdbus_tzid);
+
 		icalcomp = icalparser_parse_string (object);
 		if (!icalcomp)
 			status = E_CALENDAR_STATUS_INVALID_OBJECT;
@@ -3901,7 +3977,7 @@ gboolean
 e_cal_add_timezone (ECal *ecal, icaltimezone *izone, GError **error)
 {
 	ECalPrivate *priv;
-	gchar *tzobj;
+	gchar *tzobj, *gdbus_tzobj = NULL;
 	icalcomponent *icalcomp;
 
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
@@ -3928,12 +4004,16 @@ e_cal_add_timezone (ECal *ecal, icaltimezone *izone, GError **error)
 	tzobj = icalcomponent_as_ical_string_r (icalcomp);
 
 	/* call the backend */
-	if (!e_gdbus_cal_call_add_timezone_sync (priv->gdbus_cal, tzobj, NULL, error)) {
+	if (!e_gdbus_cal_call_add_timezone_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (tzobj, &gdbus_tzobj), NULL, error)) {
 		g_free (tzobj);
+		g_free (gdbus_tzobj);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
 	g_free (tzobj);
+	g_free (gdbus_tzobj);
+
 	E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
 }
 
@@ -3954,7 +4034,7 @@ e_cal_get_query (ECal *ecal, const gchar *sexp, ECalView **query, GError **error
 {
 	ECalPrivate *priv;
 	ECalendarStatus status;
-	gchar *query_path;
+	gchar *query_path = NULL, *gdbus_sexp = NULL;
 	EGdbusCalView *gdbus_calview;
 
 	e_return_error_if_fail (sexp, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3968,10 +4048,14 @@ e_cal_get_query (ECal *ecal, const gchar *sexp, ECalView **query, GError **error
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_query_sync (priv->gdbus_cal, sexp, &query_path, NULL, error)) {
+	if (!e_gdbus_cal_call_get_query_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &query_path, NULL, error)) {
+		g_free (gdbus_sexp);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
+	g_free (gdbus_sexp);
+
 	status = E_CALENDAR_STATUS_OK;
 
 	gdbus_calview = e_gdbus_cal_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
@@ -4010,7 +4094,7 @@ e_cal_set_default_timezone (ECal *ecal, icaltimezone *zone, GError **error)
 {
 	ECalPrivate *priv;
 	icalcomponent *icalcomp = NULL;
-	gchar *tzobj;
+	gchar *tzobj, *gdbus_tzobj = NULL;
 
 	e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
 	e_return_error_if_fail (zone, E_CALENDAR_STATUS_INVALID_ARG);
@@ -4031,12 +4115,16 @@ e_cal_set_default_timezone (ECal *ecal, icaltimezone *zone, GError **error)
 	tzobj = icalcomponent_as_ical_string_r (icalcomp);
 
 	/* call the backend */
-	if (!e_gdbus_cal_call_set_default_timezone_sync (priv->gdbus_cal, tzobj, NULL, error)) {
+	if (!e_gdbus_cal_call_set_default_timezone_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (tzobj, &gdbus_tzobj), NULL, error)) {
 		g_free (tzobj);
+		g_free (gdbus_tzobj);
+
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
 	g_free (tzobj);
+	g_free (gdbus_tzobj);
+
 	priv->default_zone = zone;
 
 	E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
diff --git a/calendar/libedata-cal/e-data-cal-view.c b/calendar/libedata-cal/e-data-cal-view.c
index 52de14f..7fed039 100644
--- a/calendar/libedata-cal/e-data-cal-view.c
+++ b/calendar/libedata-cal/e-data-cal-view.c
@@ -30,6 +30,7 @@
 
 #include <glib-object.h>
 #include <libedataserver/e-debug-log.h>
+#include "libedataserver/e-data-server-util.h"
 #include "e-cal-backend-sexp.h"
 #include "e-data-cal-view.h"
 #include "e-gdbus-egdbuscalview.h"
@@ -278,7 +279,7 @@ notify_remove (EDataCalView *view, ECalComponentId *id)
 	}
 
 	/* TODO: store ECalComponentId instead of just uid*/
-	uid = g_strdup (id->uid);
+	uid = e_util_utf8_make_valid (id->uid);
 	g_array_append_val (priv->removes, uid);
 
 	g_hash_table_remove (priv->ids, id);
@@ -289,11 +290,15 @@ notify_remove (EDataCalView *view, ECalComponentId *id)
 static void
 notify_done (EDataCalView *view, const GError *error)
 {
+	gchar *gdbus_error_msg = NULL;
+
 	send_pending_adds (view);
 	send_pending_changes (view);
 	send_pending_removes (view);
 
-	e_gdbus_cal_view_emit_done (view->priv->gdbus_object, error ? error->code : 0, error ? error->message : "");
+	e_gdbus_cal_view_emit_done (view->priv->gdbus_object, error ? error->code : 0, e_util_ensure_gdbus_string (error ? error->message : "", &gdbus_error_msg));
+
+	g_free (gdbus_error_msg);
 }
 
 static gboolean
@@ -604,7 +609,7 @@ e_data_cal_view_notify_objects_added (EDataCalView *view, const GList *objects)
 	g_mutex_lock (priv->pending_mutex);
 
 	for (l = objects; l; l = l->next) {
-		notify_add (view, g_strdup (l->data));
+		notify_add (view, e_util_utf8_make_valid (l->data));
 	}
 
 	g_mutex_unlock (priv->pending_mutex);
@@ -652,7 +657,7 @@ e_data_cal_view_notify_objects_modified (EDataCalView *view, const GList *object
 
 	for (l = objects; l; l = l->next) {
 		/* TODO: send add/remove/change as relevant, based on ->ids */
-		notify_change (view, g_strdup (l->data));
+		notify_change (view, e_util_utf8_make_valid (l->data));
 	}
 
 	g_mutex_unlock (priv->pending_mutex);
@@ -738,6 +743,7 @@ void
 e_data_cal_view_notify_progress (EDataCalView *view, const gchar *message, gint percent)
 {
 	EDataCalViewPrivate *priv;
+	gchar *gdbus_message = NULL;
 
 	g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
 	priv = view->priv;
@@ -745,7 +751,9 @@ e_data_cal_view_notify_progress (EDataCalView *view, const gchar *message, gint
 	if (!priv->started || priv->stopped)
 		return;
 
-	e_gdbus_cal_view_emit_progress (view->priv->gdbus_object, message ? message : "", percent);
+	e_gdbus_cal_view_emit_progress (view->priv->gdbus_object, e_util_ensure_gdbus_string (message, &gdbus_message), percent);
+
+	g_free (gdbus_message);
 }
 
 /**
diff --git a/calendar/libedata-cal/e-data-cal.c b/calendar/libedata-cal/e-data-cal.c
index c8246f6..9736e6d 100644
--- a/calendar/libedata-cal/e-data-cal.c
+++ b/calendar/libedata-cal/e-data-cal.c
@@ -32,6 +32,7 @@
 
 #include <glib-object.h>
 #include <libedataserver/e-debug-log.h>
+#include <libedataserver/e-data-server-util.h>
 #include "e-data-cal.h"
 #include "e-data-cal-enumtypes.h"
 #include "e-gdbus-egdbuscal.h"
@@ -537,7 +538,7 @@ impl_Cal_setDefaultTimezone (EGdbusCal *object, GDBusMethodInvocation *invocatio
 	return TRUE;
 }
 
-/* free returned pointer with g_free() */
+/* free returned pointer with g_strfreev() */
 static gchar **
 create_str_array_from_glist (GList *lst)
 {
@@ -547,13 +548,13 @@ create_str_array_from_glist (GList *lst)
 
 	seq = g_new0 (gchar *, g_list_length (lst) + 1);
 	for (l = lst, i = 0; l; l = l->next, i++) {
-		seq[i] = l->data;
+		seq[i] = e_util_utf8_make_valid (l->data);
 	}
 
 	return seq;
 }
 
-/* free returned pointer with g_free() */
+/* free returned pointer with g_strfreev() */
 static gchar **
 create_str_array_from_gslist (GSList *lst)
 {
@@ -563,7 +564,7 @@ create_str_array_from_gslist (GSList *lst)
 
 	seq = g_new0 (gchar *, g_slist_length (lst) + 1);
 	for (l = lst, i = 0; l; l = l->next, i++) {
-		seq[i] = l->data;
+		seq[i] = e_util_utf8_make_valid (l->data);
 	}
 
 	return seq;
@@ -607,8 +608,13 @@ e_data_cal_notify_cal_address (EDataCal *cal, EServerMethodContext context, GErr
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Cannot retrieve calendar address: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_cal_address (cal->priv->gdbus_object, invocation, address ? address : "");
+	} else {
+		gchar *gdbus_address = NULL;
+
+		e_gdbus_cal_complete_get_cal_address (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (address, &gdbus_address));
+
+		g_free (gdbus_address);
+	}
 }
 
 /**
@@ -627,8 +633,13 @@ e_data_cal_notify_alarm_email_address (EDataCal *cal, EServerMethodContext conte
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Cannot retrieve calendar alarm e-mail address: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_alarm_email_address (cal->priv->gdbus_object, invocation, address ? address : "");
+	} else {
+		gchar *gdbus_address = NULL;
+
+		e_gdbus_cal_complete_get_alarm_email_address (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (address, &gdbus_address));
+
+		g_free (gdbus_address);
+	}
 }
 
 /**
@@ -647,8 +658,13 @@ e_data_cal_notify_ldap_attribute (EDataCal *cal, EServerMethodContext context, G
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Cannot retrieve calendar's LDAP attribute: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_ldap_attribute (cal->priv->gdbus_object, invocation, attribute ? attribute : "");
+	} else {
+		gchar *gdbus_attribute = NULL;
+
+		e_gdbus_cal_complete_get_ldap_attribute (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (attribute, &gdbus_attribute));
+
+		g_free (gdbus_attribute);
+	}
 }
 
 /**
@@ -667,8 +683,13 @@ e_data_cal_notify_static_capabilities (EDataCal *cal, EServerMethodContext conte
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Cannot retrieve calendar scheduling information: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_scheduling_information (cal->priv->gdbus_object, invocation, capabilities ? capabilities : "");
+	} else {
+		gchar *gdbus_capabilities = NULL;
+
+		e_gdbus_cal_complete_get_scheduling_information (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (capabilities, &gdbus_capabilities));
+
+		g_free (gdbus_capabilities);
+	}
 }
 
 /**
@@ -748,8 +769,12 @@ e_data_cal_notify_object_created (EDataCal *cal, EServerMethodContext context, G
 		data_cal_return_error (invocation, error, _("Cannot create calendar object: %s"));
 		g_error_free (error);
 	} else {
+		gchar *gdbus_uid = NULL;
+
 		e_cal_backend_notify_object_created (cal->priv->backend, object);
-		e_gdbus_cal_complete_create_object (cal->priv->gdbus_object, invocation, uid ? uid : "");
+		e_gdbus_cal_complete_create_object (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (uid, &gdbus_uid));
+
+		g_free (gdbus_uid);
 	}
 }
 
@@ -860,10 +885,12 @@ e_data_cal_notify_objects_sent (EDataCal *cal, EServerMethodContext context, GEr
 		g_error_free (error);
 	} else {
 		gchar **users_array = create_str_array_from_glist (users);
+		gchar *gdbus_calobj = NULL;
 
-		e_gdbus_cal_complete_send_objects (cal->priv->gdbus_object, invocation, (const gchar * const *) users_array, calobj ? calobj : "");
+		e_gdbus_cal_complete_send_objects (cal->priv->gdbus_object, invocation, (const gchar * const *) users_array, e_util_ensure_gdbus_string (calobj, &gdbus_calobj));
 
-		g_free (users_array);
+		g_free (gdbus_calobj);
+		g_strfreev (users_array);
 	}
 }
 
@@ -883,8 +910,13 @@ e_data_cal_notify_default_object (EDataCal *cal, EServerMethodContext context, G
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Cannot retrieve default calendar object path: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_default_object (cal->priv->gdbus_object, invocation, object ? object : "");
+	} else {
+		gchar *gdbus_object = NULL;
+
+		e_gdbus_cal_complete_get_default_object (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (object, &gdbus_object));
+
+		g_free (gdbus_object);
+	}
 }
 
 /**
@@ -903,8 +935,13 @@ e_data_cal_notify_object (EDataCal *cal, EServerMethodContext context, GError *e
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Cannot retrieve calendar object path: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_object (cal->priv->gdbus_object, invocation, object ? object : "");
+	} else {
+		gchar *gdbus_object = NULL;
+
+		e_gdbus_cal_complete_get_object (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (object, &gdbus_object));
+
+		g_free (gdbus_object);
+	}
 }
 
 /**
@@ -928,7 +965,7 @@ e_data_cal_notify_object_list (EDataCal *cal, EServerMethodContext context, GErr
 
 		e_gdbus_cal_complete_get_object_list (cal->priv->gdbus_object, invocation, (const gchar * const *) seq);
 
-		g_free (seq);
+		g_strfreev (seq);
 	}
 }
 
@@ -954,7 +991,7 @@ e_data_cal_notify_attachment_list (EDataCal *cal, EServerMethodContext context,
 	} else
 		e_gdbus_cal_complete_get_attachment_list (cal->priv->gdbus_object, invocation, (const gchar * const *) seq);
 
-	g_free (seq);
+	g_strfreev (seq);
 }
 
 /**
@@ -977,8 +1014,13 @@ e_data_cal_notify_query (EDataCal *cal, EServerMethodContext context, GError *er
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Could not complete calendar query: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_query (cal->priv->gdbus_object, invocation, query);
+	} else {
+		gchar *gdbus_query = NULL;
+
+		e_gdbus_cal_complete_get_query (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (query, &gdbus_query));
+
+		g_free (gdbus_query);
+	}
 }
 
 /**
@@ -997,8 +1039,13 @@ e_data_cal_notify_timezone_requested (EDataCal *cal, EServerMethodContext contex
 		/* Translators: The '%s' is replaced with a detailed error message */
 		data_cal_return_error (invocation, error, _("Could not retrieve calendar time zone: %s"));
 		g_error_free (error);
-	} else
-		e_gdbus_cal_complete_get_timezone (cal->priv->gdbus_object, invocation, object ? object : "");
+	} else {
+		gchar *gdbus_object = NULL;
+
+		e_gdbus_cal_complete_get_timezone (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (object, &gdbus_object));
+
+		g_free (gdbus_object);
+	}
 }
 
 /**
@@ -1068,9 +1115,9 @@ e_data_cal_notify_changes (EDataCal *cal, EServerMethodContext context, GError *
 
 		e_gdbus_cal_complete_get_changes (cal->priv->gdbus_object, invocation, (const gchar * const *) additions, (const gchar * const *) modifications, (const gchar * const *) removals);
 
-		g_free (additions);
-		g_free (modifications);
-		g_free (removals);
+		g_strfreev (additions);
+		g_strfreev (modifications);
+		g_strfreev (removals);
 	}
 }
 
@@ -1097,7 +1144,7 @@ e_data_cal_notify_free_busy (EDataCal *cal, EServerMethodContext context, GError
 
 		e_gdbus_cal_complete_get_free_busy (cal->priv->gdbus_object, invocation, (const gchar * const *) seq);
 
-		g_free (seq);
+		g_strfreev (seq);
 	}
 }
 
@@ -1145,10 +1192,14 @@ e_data_cal_notify_auth_required (EDataCal *cal)
 void
 e_data_cal_notify_error (EDataCal *cal, const gchar *message)
 {
+	gchar *gdbus_message = NULL;
+
 	g_return_if_fail (cal != NULL);
 	g_return_if_fail (E_IS_DATA_CAL (cal));
 
-	e_gdbus_cal_emit_backend_error (cal->priv->gdbus_object, message);
+	e_gdbus_cal_emit_backend_error (cal->priv->gdbus_object, e_util_ensure_gdbus_string (message, &gdbus_message));
+
+	g_free (gdbus_message);
 }
 
 /* Instance init */
diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c
index b72a906..e5f5b1d 100644
--- a/libedataserver/e-data-server-util.c
+++ b/libedataserver/e-data-server-util.c
@@ -412,6 +412,111 @@ e_util_utf8_remove_accents (const gchar *str)
 }
 
 /**
+ * e_util_utf8_make_valid:
+ *
+ * Returns newly allocates string, copy of 'str', which
+ * is UTF8 valid string. Invalid letters are replaced
+ * with question marks U+FFFD.
+ *
+ * Since: 2.92
+ **/
+gchar *
+e_util_utf8_make_valid (const gchar *str)
+{
+	/* almost identical copy of glib's _g_utf8_make_valid() */
+	GString *string;
+	const gchar *remainder, *invalid;
+	gint remaining_bytes, valid_bytes, total_bytes, len = -1;
+
+	g_return_val_if_fail (str != NULL, NULL);
+
+	string = NULL;
+	remainder = str;
+	if (len == -1) {
+		remaining_bytes = strlen (str);
+	} else {
+		const gchar *start = str, *end = str;
+
+		while (len > 0) {
+			gunichar uc = g_utf8_get_char_validated (end, -1);
+
+			if (uc == (gunichar) -2 || uc == (gunichar) -1) {
+				end++;
+			} else if (uc == 0) {
+				break;
+			} else {
+				end = g_utf8_next_char (end);
+			}
+
+			len--;
+		}
+
+		remaining_bytes = end - start;
+	}
+
+	total_bytes = remaining_bytes;
+
+	while (remaining_bytes != 0) {
+		if (g_utf8_validate (remainder, remaining_bytes, &invalid))
+			break;
+		valid_bytes = invalid - remainder;
+
+		if (string == NULL)
+			string = g_string_sized_new (remaining_bytes);
+
+		g_string_append_len (string, remainder, valid_bytes);
+		/* append U+FFFD REPLACEMENT CHARACTER */
+		g_string_append (string, "\357\277\275");
+
+		remaining_bytes -= valid_bytes + 1;
+		remainder = invalid + 1;
+	}
+
+	if (string == NULL)
+		return g_strndup (str, total_bytes);
+
+	g_string_append (string, remainder);
+
+	g_assert (g_utf8_validate (string->str, -1, NULL));
+
+	return g_string_free (string, FALSE);
+}
+
+/**
+ * e_util_ensure_gdbus_string:
+ * @str: What to convert, if NULL, then returns empty string.
+ * @gdbus_str: In case that 'str' is not valid UTF8 string
+ *   and new memory allocated, then it is returned in this
+ *   variable, and its value should be freed with g_free().
+ *   It cannot be NULL.
+ *
+ * Returns string usable for GDBus, or more precisely GVariant,
+ * which requires UTF8 encoded strings for a transfer.
+ * If the str is not UTF8 valid, then new string is allocated
+ * and returned in gdbus_str, on which is supposed to be called
+ * g_free().
+ *
+ * Since: 2.92
+ **/
+const gchar *
+e_util_ensure_gdbus_string (const gchar *str, gchar **gdbus_str)
+{
+	g_return_val_if_fail (gdbus_str != NULL, NULL);
+
+	*gdbus_str = NULL;
+
+	if (!str || !*str)
+		return "";
+
+	if (g_utf8_validate (str, -1, NULL))
+		return str;
+
+	*gdbus_str = e_util_utf8_make_valid (str);
+
+	return *gdbus_str;
+}
+
+/**
  * e_strftime:
  * @string: The string array to store the result in.
  * @max: The size of array @s.
diff --git a/libedataserver/e-data-server-util.h b/libedataserver/e-data-server-util.h
index dd50d6b..7ac1667 100644
--- a/libedataserver/e-data-server-util.h
+++ b/libedataserver/e-data-server-util.h
@@ -44,6 +44,8 @@ const gchar *	e_util_utf8_strstrcasedecomp	(const gchar *haystack,
 gint		e_util_utf8_strcasecmp		(const gchar *s1,
 						 const gchar *s2);
 gchar *		e_util_utf8_remove_accents	(const gchar *str);
+gchar *		e_util_utf8_make_valid		(const gchar *str);
+const gchar *   e_util_ensure_gdbus_string	(const gchar *str, gchar **gdbus_str);
 guint64		e_util_gthread_id		(GThread *thread);
 void		e_filename_make_safe		(gchar *string);
 



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