evolution r34863 - in trunk/addressbook: . gui/widgets



Author: mcrha
Date: Mon Jan 21 10:21:29 2008
New Revision: 34863
URL: http://svn.gnome.org/viewvc/evolution?rev=34863&view=rev

Log:
2008-01-21  Milan Crha  <mcrha redhat com>

	** Fix for bug #324604 inspired by patch of makuchaku (Mayank)

	* gui/widgets/eab-gui-util.h:
	* gui/widgets/eab-gui-util.c: (eab_parse_qp_email),
	(eab_parse_qp_email_to_html): New helper functions for decoding
	email addresses from RFC822 or RFC2047 form to UTF-8.
	* gui/widgets/e-minicard.c: (add_email_field):
	* gui/widgets/eab-contact-display.c: (render_contact_list),
	(render_contact), (eab_contact_display_render_compact):
	* gui/widgets/e-addressbook-table-adapter.c:
	(struct _EAddressbookTableAdapterPrivate), (addressbook_dispose),
	(addressbook_value_at), (addressbook_set_value_at), (remove_contacts),
	(modify_contact), (model_changed), (eab_table_adapter_construct):
	* gui/widgets/eab-gui-util.c: (get_email),
	(eab_send_contact_list_as_attachment):
	Ensure the print of the email is transformed from RFC822 or RFC2047.



Modified:
   trunk/addressbook/ChangeLog
   trunk/addressbook/gui/widgets/e-addressbook-table-adapter.c
   trunk/addressbook/gui/widgets/e-minicard.c
   trunk/addressbook/gui/widgets/eab-contact-display.c
   trunk/addressbook/gui/widgets/eab-gui-util.c
   trunk/addressbook/gui/widgets/eab-gui-util.h

Modified: trunk/addressbook/gui/widgets/e-addressbook-table-adapter.c
==============================================================================
--- trunk/addressbook/gui/widgets/e-addressbook-table-adapter.c	(original)
+++ trunk/addressbook/gui/widgets/e-addressbook-table-adapter.c	Mon Jan 21 10:21:29 2008
@@ -15,6 +15,8 @@
 	EABModel *model;
 
 	int create_contact_id, remove_contact_id, modify_contact_id, model_changed_id;
+
+	GHashTable *emails;
 };
 
 #define PARENT_TYPE e_table_model_get_type()
@@ -54,6 +56,9 @@
 	if (adapter->priv) {
 		unlink_model(adapter);
 
+		g_hash_table_remove_all (adapter->priv->emails);
+		g_hash_table_destroy (adapter->priv->emails);
+
 		g_free (adapter->priv);
 		adapter->priv = NULL;
 	}
@@ -92,6 +97,28 @@
 
 	value = e_contact_get_const((EContact*)eab_model_contact_at (priv->model, row), col);
 
+	if (value && *value && (col == E_CONTACT_EMAIL_1 || col == E_CONTACT_EMAIL_2 || col == E_CONTACT_EMAIL_3)) {
+		char *val = g_hash_table_lookup (priv->emails, value);
+
+		if (val) {
+			/* we have this already cached, so use value from the cache */
+			value = val;
+		} else {
+			char *name = NULL, *mail = NULL;
+
+			if (eab_parse_qp_email (value, &name, &mail))
+				val = g_strdup_printf ("%s <%s>", name, mail);
+			else
+				val = g_strdup (value);
+
+			g_free (name);
+			g_free (mail);
+
+			g_hash_table_insert (priv->emails, g_strdup (value), val);
+			value = val;
+		}
+	}
+
 	return (void *)(value ? value : "");
 }
 
@@ -122,9 +149,17 @@
 
 		e_table_model_pre_change(etc);
 
+		if (col == E_CONTACT_EMAIL_1 || col == E_CONTACT_EMAIL_2 || col == E_CONTACT_EMAIL_3) {
+			const char *old_value = e_contact_get_const (contact, col);
+
+			/* remove old value from cache and use new one */
+			if (old_value && *old_value)
+				g_hash_table_remove (priv->emails, old_value);
+		}
+
 		e_contact_set(contact, col, (void *) val);
 		eab_merging_book_commit_contact (eab_model_get_ebook (priv->model),
-						 contact, contact_modified_cb, NULL);
+						 contact, contact_modified_cb, etc);
 
 		g_object_unref (contact);
 
@@ -266,6 +301,8 @@
 	GArray *indices = (GArray *) data;
 	int count = indices->len;
 
+	/* clear whole cache */
+	g_hash_table_remove_all (adapter->priv->emails);
 
 	e_table_model_pre_change (E_TABLE_MODEL (adapter));
 	if (count == 1)
@@ -279,6 +316,9 @@
 		gint index,
 		EAddressbookTableAdapter *adapter)
 {
+	/* clear whole cache */
+	g_hash_table_remove_all (adapter->priv->emails);
+
 	e_table_model_pre_change (E_TABLE_MODEL (adapter));
 	e_table_model_row_changed (E_TABLE_MODEL (adapter), index);
 }
@@ -287,6 +327,9 @@
 model_changed (EABModel *model,
 	       EAddressbookTableAdapter *adapter)
 {
+	/* clear whole cache */
+	g_hash_table_remove_all (adapter->priv->emails);
+
 	e_table_model_pre_change (E_TABLE_MODEL (adapter));
 	e_table_model_changed (E_TABLE_MODEL (adapter));
 }
@@ -340,6 +383,8 @@
 						  "model_changed",
 						  G_CALLBACK(model_changed),
 						  adapter);
+
+	priv->emails = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_free);
 }
 
 ETableModel *

Modified: trunk/addressbook/gui/widgets/e-minicard.c
==============================================================================
--- trunk/addressbook/gui/widgets/e-minicard.c	(original)
+++ trunk/addressbook/gui/widgets/e-minicard.c	Mon Jan 21 10:21:29 2008
@@ -839,7 +839,6 @@
 	GnomeCanvasGroup *group;
 	EMinicardField *minicard_field;
 	char *name;
-	char *string;
 	GList *l, *le;
 	int count =0;
 	GList *emails = e_contact_get (e_minicard->contact, E_CONTACT_EMAIL);
@@ -847,20 +846,32 @@
 
 	for (l=email_list, le=emails; l!=NULL && count < limit && le!=NULL; l = l->next, le=le->next) {
 		const gchar *tmp;
+		char *email = NULL;
+		char *string = NULL;
+		char *full_string = NULL;
+		gboolean parser_check;
 
 		tmp = get_email_location ((EVCardAttribute *) l->data);
 		if (tmp)
 			name = g_strdup_printf ("%s:", tmp);
 		else
 			name = g_strdup ("");
-		string = e_text_to_html (le->data, 0);
+
+		parser_check = eab_parse_qp_email ((const gchar *) le->data, &string, &email);
+		if (parser_check) {
+			/* if true, we had a quoted printable mail address */
+			full_string = g_strdup_printf ("%s <%s>", string, email);
+		} else {
+			/* we got a NON-quoted printable string */
+			string = g_strdup (le->data);
+		}
 
 		new_item = e_minicard_label_new(group);
 
 		gnome_canvas_item_set( new_item,
 				       "width", e_minicard->width - 4.0,
 				       "fieldname", name,
-				       "field", string,
+				       "field", parser_check ? full_string : string,
 				       "max_field_name_length", left_width,
 				       "editable", FALSE /* e_minicard->editable */,
 				       NULL );
@@ -882,8 +893,10 @@
 		e_minicard->fields = g_list_append( e_minicard->fields, minicard_field);
 		e_canvas_item_move_absolute(new_item, 2, e_minicard->height);
 		count++;
-		g_free(name);
-		g_free(string);
+		g_free (name);
+		g_free (string);
+		g_free (full_string);
+		g_free (email);
 	}
 	g_list_foreach (emails, (GFunc) g_free, NULL);
 	g_list_free (emails);

Modified: trunk/addressbook/gui/widgets/eab-contact-display.c
==============================================================================
--- trunk/addressbook/gui/widgets/eab-contact-display.c	(original)
+++ trunk/addressbook/gui/widgets/eab-contact-display.c	Mon Jan 21 10:21:29 2008
@@ -488,10 +488,18 @@
 
 	email_list = e_contact_get (contact, E_CONTACT_EMAIL);
 	for (l = email_list; l; l = l->next) {
-		char *html = e_text_to_html (l->data, E_TEXT_TO_HTML_CONVERT_ADDRESSES);
-		gtk_html_stream_printf (html_stream, "%s<br>", html);
-		g_free (html);
+		gchar *value;
+
+		value = eab_parse_qp_email_to_html (l->data);
+
+		if (!value)
+			value = e_text_to_html (l->data, E_TEXT_TO_HTML_CONVERT_ADDRESSES);
+
+		gtk_html_stream_printf (html_stream, "%s<br>", value);
+
+		g_free (value);
 	}
+
 	gtk_html_stream_printf (html_stream, "</td></tr></table>");
 }
 
@@ -542,18 +550,35 @@
 	email_attr_list = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
 
 	for (l = email_list, al=email_attr_list; l && al; l = l->next, al = al->next) {
-#ifdef HANDLE_MAILTO_INTERNALLY
-		char *html = e_text_to_html (l->data, 0);
+		char *html = NULL, *name = NULL, *mail = NULL;
 		char *attr_str = (char *)get_email_location ((EVCardAttribute *) al->data);
-		g_string_append_printf (accum, "%s<a href=\"internal-mailto:%d\";>%s</a> <font color=" HEADER_COLOR ">(%s)</font>", nl, email_num, html, attr_str?attr_str:"");
-		email_num ++;
-		g_free (html);
-		nl = "<br>";
 
+#ifdef HANDLE_MAILTO_INTERNALLY
+		if (!eab_parse_qp_email (l->data, &name, &mail))
+			mail = e_text_to_html (l->data, 0);
+
+		g_string_append_printf (accum, "%s%s%s<a href=\"internal-mailto:%d\";>%s</a>%s <font color=" HEADER_COLOR ">(%s)</font>", 
+						nl,
+						name ? name : "",
+						name ? " &lt;" : "",
+						email_num,
+						mail,
+						name ? "&gt;" : "",
+						attr_str ? attr_str : "");
+		email_num ++;
 #else
-		g_string_append_printf (accum, "%s%s <font color=" HEADER_COLOR ">(%s)</font>", nl, (char*)l->data, get_email_location ((EVCardAttribute *) al->data));
-		nl = "\n";
+		html = eab_parse_qp_email_to_html (l->data);
+
+		if (!html)
+			html = e_text_to_html (l->data, E_TEXT_TO_HTML_CONVERT_ADDRESSES);
+
+		g_string_append_printf (accum, "%s%s <font color=" HEADER_COLOR ">(%s)</font>", nl, html, attr_str ? attr_str : "");
 #endif
+		nl = "<br>";
+
+		g_free (html);
+		g_free (name);
+		g_free (mail);
 	}
 	g_list_foreach (email_list, (GFunc)g_free, NULL);
 	g_list_free (email_list);
@@ -821,29 +846,34 @@
 				g_free (html);
 			}
 
+			#define print_email() {								\
+				html = eab_parse_qp_email_to_html (str);				\
+													\
+				if (!html)								\
+					html = e_text_to_html (str, 0); 				\
+													\
+				gtk_html_stream_printf (html_stream, "%s%s", comma ? ", " : "", html);	\
+				g_free (html);								\
+				comma = TRUE;								\
+			}
+
 			gtk_html_stream_printf (html_stream, "<b>%s:</b> ", _("Email"));
 			str = e_contact_get_const (contact, E_CONTACT_EMAIL_1);
-			if (str) {
-				html = e_text_to_html (str, 0);
-				gtk_html_stream_printf (html_stream, "%s", str);
-				g_free (html);
-				comma = TRUE;
-			}
+			if (str)
+				print_email ();
+
 			str = e_contact_get_const (contact, E_CONTACT_EMAIL_2);
-			if (str) {
-				html = e_text_to_html (str, 0);
-				gtk_html_stream_printf (html_stream, "%s%s", comma ? ", " : "", str);
-				g_free (html);
-				comma = TRUE;
-			}
+			if (str)
+				print_email ();
+
 			str = e_contact_get_const (contact, E_CONTACT_EMAIL_3);
-			if (str) {
-				html = e_text_to_html (str, 0);
-				gtk_html_stream_printf (html_stream, "%s%s", comma ? ", " : "", str);
-				g_free (html);
-			}
+			if (str)
+				print_email ();
+
 			gtk_html_stream_write (html_stream, "<br>", 4);
 
+			#undef print_email
+
 			str = e_contact_get_const (contact, E_CONTACT_HOMEPAGE_URL);
 			if (str) {
 				html = e_text_to_html (str, E_TEXT_TO_HTML_CONVERT_URLS);

Modified: trunk/addressbook/gui/widgets/eab-gui-util.c
==============================================================================
--- trunk/addressbook/gui/widgets/eab-gui-util.c	(original)
+++ trunk/addressbook/gui/widgets/eab-gui-util.c	Mon Jan 21 10:21:29 2008
@@ -34,11 +34,15 @@
 #include "util/eab-book-util.h"
 #include <libebook/e-destination.h>
 #include "e-util/e-error.h"
+#include "e-util/e-html-utils.h"
 #include "misc/e-image-chooser.h"
 #include <e-util/e-icon-factory.h>
 #include "eab-contact-merging.h"
 #include <gnome.h>
 
+/* we link to camel for decoding quoted printable email addresses */
+#include <camel/camel-mime-utils.h>
+
 #include "addressbook/gui/contact-editor/eab-editor.h"
 #include "addressbook/gui/contact-editor/e-contact-editor.h"
 #include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
@@ -932,6 +936,25 @@
 	CORBA_exception_free (&ev);
 }
 
+static const char *
+get_email (EContact *contact, EContactField field_id, gchar **to_free)
+{
+	char *name = NULL, *mail = NULL;
+	const char *value = e_contact_get_const (contact, field_id);
+
+	*to_free = NULL;
+
+	if (eab_parse_qp_email (value, &name, &mail)) {
+		*to_free = g_strdup_printf ("%s <%s>", name, mail);
+		value = *to_free;
+	}
+
+	g_free (name);
+	g_free (mail);
+
+	return value;
+}
+
 static void
 eab_send_contact_list_as_attachment (GList *contacts)
 {
@@ -1005,18 +1028,25 @@
 	} else {
 		EContact *contact = contacts->data;
 		const gchar *tempstr2;
+		gchar *tempfree = NULL;
 
 		tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS);
 		if (!tempstr2 || !*tempstr2)
 			tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
 		if (!tempstr2 || !*tempstr2)
 			tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG);
-		if (!tempstr2 || !*tempstr2)
-			tempstr2 = e_contact_get_const (contact, E_CONTACT_EMAIL_1);
-		if (!tempstr2 || !*tempstr2)
-			tempstr2 = e_contact_get_const (contact, E_CONTACT_EMAIL_2);
-		if (!tempstr2 || !*tempstr2)
-			tempstr2 = e_contact_get_const (contact, E_CONTACT_EMAIL_3);
+		if (!tempstr2 || !*tempstr2) {
+			g_free (tempfree);
+			tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree);
+		}
+		if (!tempstr2 || !*tempstr2) {
+			g_free (tempfree);
+			tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree);
+		}
+		if (!tempstr2 || !*tempstr2) {
+			g_free (tempfree);
+			tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree);
+		}
 
 		if (!tempstr2 || !*tempstr2)
 			tempstr = g_strdup_printf (_("Contact information"));
@@ -1024,6 +1054,7 @@
 			tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2);
 		subject = CORBA_string_dup (tempstr);
 		g_free (tempstr);
+		g_free (tempfree);
 	}
 
 	GNOME_Evolution_Composer_setHeaders (composer_server, "", to_list, cc_list, bcc_list, subject, &ev);
@@ -1118,3 +1149,57 @@
 
 	return w;
 }
+
+/* To parse something like...
+=?UTF-8?Q?=E0=A4=95=E0=A4=95=E0=A4=AC=E0=A5=82=E0=A5=8B=E0=A5=87?=\t\n=?UTF-8?Q?=E0=A4=B0?=\t\n<aa aa ccom>
+and return the decoded representation of name & email parts.
+*/
+gboolean
+eab_parse_qp_email (const gchar *string, gchar **name, gchar **email)
+{
+	struct _camel_header_address *address;
+	gboolean res = FALSE;
+
+	address = camel_header_address_decode (string, "UTF-8");
+
+	if (!address)
+		return FALSE;
+
+	/* report success only when we have filled both name and email address */
+	if (address->type == CAMEL_HEADER_ADDRESS_NAME  && address->name && *address->name && address->v.addr && *address->v.addr) {
+		*name = g_strdup (address->name);
+		*email = g_strdup (address->v.addr);
+		res = TRUE;
+	}
+
+	camel_header_address_unref (address);
+
+	return res;
+}
+
+/* This is only wrapper to parse_qp_mail, it decodes string and if returned TRUE,
+   then makes one string and returns it, otherwise returns NULL.
+   Returned string is usable to place directly into GtkHtml stream.
+   Returned value should be freed with g_free. */
+char *
+eab_parse_qp_email_to_html (const gchar *string)
+{
+	char *name = NULL, *mail = NULL;
+	char *html_name, *html_mail;
+	char *value;
+
+	if (!eab_parse_qp_email (string, &name, &mail))
+		return NULL;
+
+	html_name = e_text_to_html (name, 0);
+	html_mail = e_text_to_html (mail, E_TEXT_TO_HTML_CONVERT_ADDRESSES);
+
+	value = g_strdup_printf ("%s &lt;%s&gt;", html_name, html_mail);
+
+	g_free (html_name);
+	g_free (html_mail);
+	g_free (name);
+	g_free (mail);
+
+	return value;
+}

Modified: trunk/addressbook/gui/widgets/eab-gui-util.h
==============================================================================
--- trunk/addressbook/gui/widgets/eab-gui-util.h	(original)
+++ trunk/addressbook/gui/widgets/eab-gui-util.h	Mon Jan 21 10:21:29 2008
@@ -77,6 +77,10 @@
 ESource            *eab_select_source             (const gchar *title, const gchar *message,
 						   const gchar *select_uid, GtkWindow *parent);
 
+/* To parse quoted printable address & return email & name fields */						
+gboolean eab_parse_qp_email (const gchar *string, gchar **name, gchar **email);
+char *eab_parse_qp_email_to_html (const gchar *string);
+
 G_END_DECLS
 
 #endif /* __E_ADDRESSBOOK_UTIL_H__ */



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