[evolution-kolab] libekolabconv: added XFB decoding/validation util function



commit 3ae441a9f7b3be69d71d408490ef43daff002611
Author: Christian Hilberg <hilberg kernelconcepts de>
Date:   Sat Nov 24 19:40:51 2012 +0100

    libekolabconv: added XFB decoding/validation util function
    
    * new function to base64 decode and to (forcibly) make
      UTF-8 conformant the XFB data contained in the F/B
      responses from the Kolab server
    * base64 decoding may be Kolab specific, so we need to
      do that in the backend (other groupware servers may
      not base64 encode XFB data, and Evolution expects
      decoded data)
    * (forced) UTF-8 validation is a bit of guessing. The
      icalendar specs mandate that UTF-8 to be assumed if
      no encoding hints are given (which is the case for
      us)

 src/libekolabconv/main/src/util.c |  116 +++++++++++++++++++++++++++++++++++++
 src/libekolabconv/main/src/util.h |    5 ++
 2 files changed, 121 insertions(+), 0 deletions(-)
---
diff --git a/src/libekolabconv/main/src/util.c b/src/libekolabconv/main/src/util.c
index 84313ef..ea50073 100644
--- a/src/libekolabconv/main/src/util.c
+++ b/src/libekolabconv/main/src/util.c
@@ -27,11 +27,21 @@
 
 #define _BSD_SOURCE
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <libedataserver/libedataserver.h>
+
 #include <ctype.h>
 #include "util.h"
 #include "logging.h"
 #include "./structs/common.h"
 
+#define KOLAB_FREE_BUSY_XPROP_SUMMARY  "X-SUMMARY"
+#define KOLAB_FREE_BUSY_XPROP_LOCATION "X-LOCATION"
+
 /**
  * Tokenize string.
  *
@@ -290,3 +300,109 @@ time_gm(struct tm *tm)
 	return ret;
 #endif
 }
+
+static gchar*
+xfb_utf8_string_new_from_ical (const gchar *icalstring)
+{
+	guchar *u_tmp = NULL;
+	gchar *tmp = NULL;
+	gsize in_len = 0;
+	gsize out_len = 0;
+	GError *tmp_err = NULL;
+
+	if (icalstring == NULL)
+		return NULL;
+
+	/* The icalstring may or may not be base64 encoded,
+	 * which leaves us with guessing - we try decoding, if
+	 * that fails we try plain. If icalstring is meant to
+	 * be plain, but is valid base64 nonetheless, then we've
+	 * lost (since we cannot reliably detect that case)
+	 */
+
+	u_tmp = g_base64_decode (icalstring, &out_len);
+	if (u_tmp == NULL)
+		u_tmp = (guchar *) g_strdup (icalstring);
+
+	/* ical does not carry charset hints, so we
+	 * try UTF-8 first, then conversion using
+	 * system locale info.
+	 */
+
+	/* if we have valid UTF-8, we're done converting */
+	if (g_utf8_validate ((const gchar *) u_tmp, -1, NULL))
+		goto valid;
+
+	/* no valid UTF-8, trying to convert to it
+	 * according to system locale
+	 */
+	tmp = g_locale_to_utf8 ((const gchar *) u_tmp,
+	                        -1,
+	                        &in_len,
+	                        &out_len,
+	                        &tmp_err);
+
+	if (tmp_err == NULL)
+		goto valid;
+
+	g_warning ("%s: %s", G_STRFUNC, tmp_err->message);
+	g_error_free (tmp_err);
+
+	/* still no success, forcing it into UTF-8, using
+	 * replacement chars to replace invalid ones
+	 */
+	tmp = e_util_utf8_data_make_valid ((const gchar *) u_tmp,
+	                                   strlen ((const gchar *) u_tmp));
+ valid:
+	if (tmp == NULL)
+		tmp = (gchar *) u_tmp;
+	else
+		g_free (u_tmp);
+
+	return tmp;
+}
+
+void
+klb_conv_xfb_base64_make_utf8_valid (icalcomponent *icalcomp_vfb)
+{
+	icalproperty *ip = NULL;
+#if 0
+	gchar *summary = NULL;
+	gchar *location = NULL;
+#endif
+
+	g_return_if_fail (icalcomp_vfb != NULL);
+
+	ip = icalcomponent_get_first_property (icalcomp_vfb,
+	                                       ICAL_FREEBUSY_PROPERTY);
+	while (ip != NULL) {
+		const gchar *tmp = NULL;
+		gchar *summary = NULL;
+		gchar *location = NULL;
+
+		tmp = icalproperty_get_parameter_as_string (ip,
+		                                            KOLAB_FREE_BUSY_XPROP_SUMMARY);
+		summary = xfb_utf8_string_new_from_ical (tmp);
+		tmp = icalproperty_get_parameter_as_string (ip,
+		                                            KOLAB_FREE_BUSY_XPROP_LOCATION);
+		location = xfb_utf8_string_new_from_ical (tmp);
+
+		if ((summary == NULL) && (location == NULL))
+			goto skip;
+
+		if (summary != NULL)
+			icalproperty_set_parameter_from_string (ip,
+			                                        KOLAB_FREE_BUSY_XPROP_SUMMARY,
+			                                        summary);
+		if (location != NULL)
+			icalproperty_set_parameter_from_string (ip,
+			                                        KOLAB_FREE_BUSY_XPROP_LOCATION,
+			                                        location);
+		g_free (summary);
+		g_free (location);
+
+	skip:
+		ip = icalcomponent_get_next_property (icalcomp_vfb,
+		                                      ICAL_FREEBUSY_PROPERTY);
+	}
+}
diff --git a/src/libekolabconv/main/src/util.h b/src/libekolabconv/main/src/util.h
index bcae115..a78fa26 100644
--- a/src/libekolabconv/main/src/util.h
+++ b/src/libekolabconv/main/src/util.h
@@ -53,4 +53,9 @@ Kolab_conv_mail_part* clone_kolab_conv_mail_part(Kolab_conv_mail_part *mpart);
 GList *klb_conv_mail_to_g_list (const Kolab_conv_mail* klb_mail);
 time_t time_gm(struct tm *tm);
 
+/*
+ * XFB helpers
+ */
+void klb_conv_xfb_base64_make_utf8_valid (icalcomponent *icalcomp_vfb);
+
 #endif /* UTIL_H_ */



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