[evolution-patches] Importer patches



Hi,

Here are two patches, one for the vcard importer (utf16.diff), the other
for the "import" druid (.
The vcard importer one lets the user importer UTF-16 encoded vcards
(MacOSX addressbook creates such vcards).
The import druid patch sorts the various available importers by name so
that the order of the items in the "file type" combo box isn't random.
Index: addressbook/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/addressbook/ChangeLog,v
retrieving revision 1.1684
diff -u -r1.1684 ChangeLog
--- addressbook/ChangeLog	30 Apr 2004 18:23:16 -0000	1.1684
+++ addressbook/ChangeLog	1 May 2004 10:43:39 -0000
@@ -1,3 +1,8 @@
+2004-05-01  Christophe Fergeau  <teuf gnome org>
+
+	* importers/evolution-vcard-importer.c: import vcards which are UTF-16
+	encoded or encoded in the user (multi byte) locale. (fixes #54825)
+
 2004-04-30  Chris Toshok  <toshok ximian com>
 
 	* util/e-destination.c (e_destination_set_contact): don't use
Index: addressbook/importers/evolution-vcard-importer.c
===================================================================
RCS file: /cvs/gnome/evolution/addressbook/importers/evolution-vcard-importer.c,v
retrieving revision 1.5
diff -u -r1.5 evolution-vcard-importer.c
--- addressbook/importers/evolution-vcard-importer.c	9 Apr 2004 17:25:39 -0000	1.5
+++ addressbook/importers/evolution-vcard-importer.c	1 May 2004 10:43:39 -0000
@@ -147,35 +147,129 @@
 	NULL
 };
 
-/* Actually check the contents of this file */
+#define BOM (gunichar2)0xFEFF
+#define ANTIBOM (gunichar2)0xFFFE
+
 static gboolean
-check_file_is_vcard (const char *filename)
+has_bom (const gunichar2 *utf16)
+{
+	guchar *line =(guchar *)utf16;
+
+	if ((utf16 == NULL) || (*utf16 == '\0')) {
+		return FALSE;
+	}
+
+	return ((*utf16 == BOM) || (*utf16 == ANTIBOM));
+}
+
+static void
+fix_utf16_endianness (gunichar2 *utf16)
+{
+	gunichar2 *it;
+
+
+	if ((utf16 == NULL) || (*utf16 == '\0')) {
+		return;		
+	}
+
+	if (*utf16 != ANTIBOM) {
+		return;
+	}
+
+	for (it = utf16; *it != '\0'; it++) {
+		*it = GUINT16_SWAP_LE_BE (*it);
+	}
+}
+
+/* Converts an UTF-16 string to an UTF-8 string removing the BOM character 
+ * WARNING: this may modify the utf16 argument if the function detects the
+ * string isn't using the local endianness
+ */
+static gchar *
+utf16_to_utf8 (gunichar2 *utf16)
+{
+	gchar *result;
+
+	if (utf16 == NULL) {
+		return NULL;
+	}
+
+	fix_utf16_endianness (utf16);
+
+	if (*utf16 == BOM) {
+		utf16++;
+	}
+
+	return g_utf16_to_utf8 (utf16, -1, NULL, NULL, NULL);
+}
+
+
+enum _VCardEncoding {
+	VCARD_ENCODING_NONE,
+	VCARD_ENCODING_UTF8,
+	VCARD_ENCODING_UTF16,
+	VCARD_ENCODING_LOCALE
+};
+
+typedef enum _VCardEncoding VCardEncoding;
+
+
+/* Actually check the contents of this file */
+static VCardEncoding
+guess_vcard_encoding (const char *filename)
 {
 	FILE *handle;
 	char line[4096];
-	gboolean result;
+	char *line_utf8;
+	VCardEncoding encoding = VCARD_ENCODING_NONE;
 
 	handle = fopen (filename, "r");
 	if (handle == NULL) {
 		g_print ("\n");
-		return FALSE;
+		return VCARD_ENCODING_NONE;
 	}
 		
 	fgets (line, 4096, handle);
 	if (line == NULL) {
 		fclose (handle);
 		g_print ("\n");
-		return FALSE;
+		return VCARD_ENCODING_NONE;
 	}
-
-	if (g_ascii_strncasecmp (line, "BEGIN:VCARD", 11) == 0) {
-		result = TRUE;
+	fclose (handle);
+	
+	if (has_bom ((gunichar2*)line)) {
+		gunichar2 *utf16 = (gunichar2*)line;
+		/* Check for a BOM to try to detect UTF-16 encoded vcards
+		 * (MacOSX address book creates such vcards for example)
+		 */
+		line_utf8 = utf16_to_utf8 (utf16);
+		if (line_utf8 == NULL) {
+			return VCARD_ENCODING_NONE;
+		}
+		encoding = VCARD_ENCODING_UTF16;
+	} else if (g_utf8_validate (line, -1, NULL)) {
+		line_utf8 = g_strdup (line);
+		encoding = VCARD_ENCODING_UTF8;
 	} else {
-		result = FALSE;
+		line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL);
+		if (line_utf8 == NULL) {
+			return VCARD_ENCODING_NONE;
+		}
+		encoding = VCARD_ENCODING_LOCALE;
 	}
 
-	fclose (handle);
-	return result;
+	if (g_ascii_strncasecmp (line_utf8, "BEGIN:VCARD", 11) != 0) {
+		encoding = VCARD_ENCODING_NONE;
+	}
+
+	g_free (line_utf8);
+	return encoding;
+}
+
+static gboolean 
+check_file_is_vcard (const char *filename)
+{
+	return guess_vcard_encoding (filename) != VCARD_ENCODING_NONE;
 }
 
 static void
@@ -234,8 +328,9 @@
 		return check_file_is_vcard (filename);
 	}
 	for (i = 0; supported_extensions[i] != NULL; i++) {
-		if (g_ascii_strcasecmp (supported_extensions[i], ext) == 0)
+		if (g_ascii_strcasecmp (supported_extensions[i], ext) == 0) {
 			return check_file_is_vcard (filename);
+		}
 	}
 
 	return FALSE;
@@ -266,8 +361,10 @@
 {
 	VCardImporter *gci;
 	char *contents;
-	
-	if (check_file_is_vcard (filename) == FALSE) {
+	VCardEncoding encoding;
+
+	encoding = guess_vcard_encoding (filename);
+	if (encoding == VCARD_ENCODING_NONE) {
 		return FALSE;
 	}
 
@@ -288,7 +385,21 @@
 	if (!g_file_get_contents (filename, &contents, NULL, NULL)) {
 		g_message (G_STRLOC ":Couldn't read file.");
 		return FALSE;
-	}	
+	}
+
+	if (encoding == VCARD_ENCODING_UTF16) {
+		gchar *tmp;
+		gunichar2 *contents_utf16 = (gunichar2*)contents;
+		tmp = utf16_to_utf8 (contents_utf16);
+		g_free (contents);
+		contents = tmp;
+	} else if (encoding == VCARD_ENCODING_LOCALE) {
+		gchar *tmp;
+		tmp = g_locale_to_utf8 (contents, -1, NULL, NULL, NULL);
+		g_free (contents);
+		contents = tmp;
+	}
+
 	gci->contactlist = eab_contact_list_from_string (contents);
 	g_free (contents);
 
Index: shell/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/shell/ChangeLog,v
retrieving revision 1.1426
diff -u -r1.1426 ChangeLog
--- shell/ChangeLog	30 Apr 2004 19:07:22 -0000	1.1426
+++ shell/ChangeLog	1 May 2004 10:42:26 -0000
@@ -1,3 +1,9 @@
+2004-05-01  Christophe Fergeau  <teuf gnome org>
+
+	* e-shell-importer.c: sort the various available importer plugins by
+	name in the importer druid combo box so that the list doesn't change
+	from one evolution run to another.
+
 2004-04-30  Dan Winship  <danw ximian com>
 
 	* apps_evolution_shell.schemas.in.in: Remove default folders,
Index: shell/e-shell-importer.c
===================================================================
RCS file: /cvs/gnome/evolution/shell/e-shell-importer.c,v
retrieving revision 1.70
diff -u -r1.70 e-shell-importer.c
--- shell/e-shell-importer.c	19 Apr 2004 21:51:34 -0000	1.70
+++ shell/e-shell-importer.c	1 May 2004 10:42:26 -0000
@@ -536,6 +536,15 @@
 		data->choosen_iid = g_strdup (iid);
 }
 
+static gint
+compare_info_array (gconstpointer a, gconstpointer b)
+{
+	const gchar **arr1 = a;
+	const gchar **arr2 = b;
+
+	return g_utf8_collate (arr1[0], arr2[0]);
+}
+
 static GtkWidget *
 create_plugin_menu (ImportData *data)
 {
@@ -544,6 +553,8 @@
 	int i;
 	GtkWidget *menu;
 	GtkWidget *item;
+	GList *name_list = NULL;
+	GList *it;
 
 	menu = gtk_menu_new ();
 	item = gtk_menu_item_new_with_label (_("Automatic"));
@@ -555,6 +566,7 @@
 	for (i = 0; i < info_list->_length; i++) {
 		const Bonobo_ServerInfo *info;
 		char *name = NULL;
+		char **info_array;
 
 		info = info_list->_buffer + i;
 
@@ -562,17 +574,27 @@
 		if (name == NULL) {
 			name = g_strdup (info->iid);
 		}
-
-		item = gtk_menu_item_new_with_label (name);
-		g_free (name);
+		info_array = g_malloc (2 * sizeof (char*));
+		info_array[0] = name;
+		info_array[1] = g_strdup (info->iid);
+		name_list = g_list_insert_sorted (name_list, info_array, 
+						  compare_info_array);
+	}
+       
+	for (it = name_list; it != NULL; it = it->next) {
+		gchar **arr = (gchar**)it->data;
+		item = gtk_menu_item_new_with_label (arr[0]);
+		g_free (arr[0]);
 		gtk_widget_show (item);
 		g_signal_connect (item, "activate",
 				  G_CALLBACK (item_selected), data);
 
-		g_object_set_data_full ((GObject *)item, "bonoboiid", g_strdup (info->iid), g_free);
+		g_object_set_data_full ((GObject *)item, "bonoboiid", arr[1], g_free);
 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+		g_free (arr);
 	}
 	CORBA_free (info_list);
+	g_list_free (name_list);
 
 	return menu;
 }

Attachment: signature.asc
Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=



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