Index: addressbook/gui/contact-editor/e-contact-quick-add.c
===================================================================
--- addressbook/gui/contact-editor/e-contact-quick-add.c	(revision 35066)
+++ addressbook/gui/contact-editor/e-contact-quick-add.c	(working copy)
@@ -49,6 +49,7 @@
 struct _QuickAdd {
 	gchar *name;
 	gchar *email;
+	gchar *vcard;
 	EContact *contact;
 	EBook *book;
 
@@ -92,6 +93,7 @@
 		if (qa->refs == 0) {
 			g_free (qa->name);
 			g_free (qa->email);
+			g_free (qa->vcard);
 			g_object_unref (qa->contact);
 			g_free (qa);
 		}
@@ -119,6 +121,16 @@
 }
 
 static void
+quick_add_set_vcard (QuickAdd *qa, const gchar *vcard)
+{
+	if (vcard == qa->vcard)
+		return;
+
+	g_free (qa->vcard);
+	qa->vcard = g_strdup (vcard);
+}
+
+static void
 merge_cb (EBook *book, EBookStatus status, gpointer closure)
 {
 	QuickAdd *qa = (QuickAdd *) closure;
@@ -232,7 +244,7 @@
 	QuickAdd *qa = (QuickAdd *) closure;
 
 	/* Get data out of entries. */
-	if (button == GTK_RESPONSE_OK || button == QUICK_ADD_RESPONSE_EDIT_FULL) {
+	if (!qa->vcard && (button == GTK_RESPONSE_OK || button == QUICK_ADD_RESPONSE_EDIT_FULL)) {
 		gchar *name = NULL;
 		gchar *email = NULL;
 
@@ -341,11 +353,16 @@
 	if (qa->name)
 		gtk_entry_set_text (GTK_ENTRY (qa->name_entry), qa->name);
 
-
 	qa->email_entry = gtk_entry_new ();
 	if (qa->email)
 		gtk_entry_set_text (GTK_ENTRY (qa->email_entry), qa->email);
 
+	if (qa->vcard) {
+		/* when adding vCard, then do not allow change name or email */
+		gtk_widget_set_sensitive (qa->name_entry, FALSE);
+		gtk_widget_set_sensitive (qa->email_entry, FALSE);
+	}
+
 	gconf_client = gconf_client_get_default ();
 	source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/addressbook/sources");
 	g_object_unref (gconf_client);
@@ -555,3 +572,58 @@
 	g_free (name);
 	g_free (email);
 }
+
+void
+e_contact_quick_add_vcard (const gchar *vcard, EContactQuickAddCallback cb, gpointer closure)
+{
+	QuickAdd *qa;
+	GtkWidget *dialog;
+	EContact *contact;
+
+	/* We need to have *something* to work with. */
+	if (vcard == NULL) {
+		if (cb)
+			cb (NULL, closure);
+		return;
+	}
+
+	qa = quick_add_new ();
+	qa->cb = cb;
+	qa->closure = closure;
+	quick_add_set_vcard (qa, vcard);
+
+	contact = e_contact_new_from_vcard (qa->vcard);
+
+	if (contact) {
+		GList *emails;
+		char *name;
+		EContactName *contact_name;
+
+		g_object_unref (qa->contact);
+		qa->contact = contact;
+
+		contact_name = e_contact_get (qa->contact, E_CONTACT_NAME);
+		name = e_contact_name_to_string (contact_name);
+		quick_add_set_name (qa, name);
+		g_free (name);
+		e_contact_name_free (contact_name);
+
+		emails = e_contact_get (qa->contact, E_CONTACT_EMAIL);
+		if (emails) {
+			quick_add_set_email (qa, emails->data);
+
+			g_list_foreach (emails, (GFunc)g_free, NULL);
+			g_list_free (emails);
+		}
+	} else {
+		if (cb)
+			cb (NULL, closure);
+
+		quick_add_unref (qa);
+		g_warning ("Contact's vCard parsing failed!");
+		return;
+	}
+
+	dialog = build_quick_add_dialog (qa);
+	gtk_widget_show_all (dialog);
+}
Index: addressbook/gui/contact-editor/e-contact-quick-add.h
===================================================================
--- addressbook/gui/contact-editor/e-contact-quick-add.h	(revision 35066)
+++ addressbook/gui/contact-editor/e-contact-quick-add.h	(working copy)
@@ -36,5 +36,7 @@
 
 void e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, gpointer closure);
 
+void e_contact_quick_add_vcard (const gchar *vcard, EContactQuickAddCallback cb, gpointer closure);
+
 #endif /* __E_CONTACT_QUICK_ADD_H__ */
 
Index: addressbook/gui/widgets/eab-popup-control.c
===================================================================
--- addressbook/gui/widgets/eab-popup-control.c	(revision 35066)
+++ addressbook/gui/widgets/eab-popup-control.c	(working copy)
@@ -57,6 +57,7 @@
 
 static void eab_popup_control_set_name (EABPopupControl *pop, const gchar *name);
 static void eab_popup_control_set_email (EABPopupControl *pop, const gchar *email);
+static void eab_popup_control_set_vcard (EABPopupControl *pop, const gchar *vcard);
 
 static GtkObjectClass *parent_class;
 
@@ -110,6 +111,9 @@
 
 	g_free (pop->email);
 	pop->email = NULL;
+
+	g_free (pop->vcard);
+	pop->vcard = NULL;
 }
 
 static void
@@ -253,6 +257,26 @@
 	eab_popup_control_schedule_refresh (pop);
 }
 
+static void
+eab_popup_control_set_vcard (EABPopupControl *pop, const gchar *vcard)
+{
+	g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop));
+
+	/* We only allow the vcard to be set once. */
+	if (pop->vcard)
+		return;
+
+	g_free (pop->name);
+	g_free (pop->email);
+
+	pop->name = NULL;
+	pop->email = NULL;
+
+	pop->vcard = g_strdup (vcard);
+
+	eab_popup_control_schedule_refresh (pop);
+}
+
 void
 eab_popup_control_construct (EABPopupControl *pop)
 {
@@ -332,7 +356,9 @@
 static void
 eab_popup_control_no_matches (EABPopupControl *pop)
 {
-	if (pop->email && *pop->email) {
+	if (pop->vcard && *pop->vcard)
+		e_contact_quick_add_vcard (pop->vcard, NULL, NULL);
+	else if (pop->email && *pop->email) {
 		if (pop->name && *pop->name)
 			e_contact_quick_add (pop->name, pop->email, NULL, NULL);
 		else
@@ -361,7 +387,8 @@
 enum {
 	PROPERTY_NAME,
 	PROPERTY_EMAIL,
-	PROPERTY_TRANSITORY
+	PROPERTY_TRANSITORY,
+	PROPERTY_VCARD
 };
 
 static void
@@ -379,6 +406,10 @@
 		eab_popup_control_set_email (pop, BONOBO_ARG_GET_STRING (arg));
 		break;
 
+	case PROPERTY_VCARD:
+		eab_popup_control_set_vcard (pop, BONOBO_ARG_GET_STRING (arg));
+		break;
+
 	default:
 		g_return_if_reached ();
 	}
@@ -403,6 +434,10 @@
 		BONOBO_ARG_SET_BOOLEAN (arg, pop->transitory);
 		break;
 
+	case PROPERTY_VCARD:
+		BONOBO_ARG_SET_STRING (arg, pop->vcard);
+		break;
+
 	default:
 		g_return_if_reached ();
 	}
@@ -435,7 +470,11 @@
 				 BONOBO_ARG_BOOLEAN, NULL, NULL,
 				 BONOBO_PROPERTY_READABLE);
 
-        bonobo_control_set_properties (control, bonobo_object_corba_objref (BONOBO_OBJECT (bag)), NULL);
+	bonobo_property_bag_add (bag, "vcard", PROPERTY_VCARD,
+                                 BONOBO_ARG_STRING, NULL, NULL,
+                                 BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE);
+
+	bonobo_control_set_properties (control, bonobo_object_corba_objref (BONOBO_OBJECT (bag)), NULL);
         bonobo_object_unref (BONOBO_OBJECT (bag));
 
 	addy->es = bonobo_event_source_new ();
Index: addressbook/gui/widgets/eab-popup-control.h
===================================================================
--- addressbook/gui/widgets/eab-popup-control.h	(revision 35066)
+++ addressbook/gui/widgets/eab-popup-control.h	(working copy)
@@ -50,6 +50,7 @@
 
 	gchar *name;
 	gchar *email;
+	gchar *vcard;
 
 	GtkWidget *name_widget;
 	GtkWidget *email_widget;
Index: addressbook/ChangeLog
===================================================================
--- addressbook/ChangeLog	(revision 35066)
+++ addressbook/ChangeLog	(working copy)
@@ -1,3 +1,20 @@
+2008-02-21  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #273177
+
+	* gui/contact-editor/e-contact-quick-add.h:
+	(e_contact_quick_add_vcard):
+	* gui/contact-editor/e-contact-quick-add.c: (struct _QuickAdd),
+	(quick_add_unref), (quick_add_set_vcard), (clicked_cb),
+	(build_quick_add_dialog), (e_contact_quick_add_vcard):
+	Allow adding also whole vCard with this dialog.
+	* gui/widgets/eab-popup-control.h: (struct _EABPopupControl):
+	* gui/widgets/eab-popup-control.c: (eab_popup_control_set_vcard),
+	(eab_popup_control_cleanup), (eab_popup_control_set_vcard),
+	(eab_popup_control_no_matches), (set_prop), (get_prop),
+	(eab_popup_control_new):
+	New property 'vcard', if set, has higher precedence than name/email.
+
 2008-02-20  Srinivasa Ragavan  <sragavan@novell.com>
 
 	** Fix for bug #517458
Index: mail/ChangeLog
===================================================================
--- mail/ChangeLog	(revision 35066)
+++ mail/ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2008-02-21  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #273177
+
+	* em-utils.h: (em_utils_add_vcard):
+	* em-utils.c: (emu_add_address_or_vcard),
+	(em_utils_add_address), (em_utils_add_vcard):
+	New function to add whole vCard to addressbook.
+	* em-popup.c: (emp_add_vcard), (emp_standard_menu_factory):
+	Add popup menu item to vcard attachments.
+
 2008-02-20  Srinivasa Ragavan  <sragavan@novell.com>
 
 	** Fix for bug #469292
Index: mail/em-utils.c
===================================================================
--- mail/em-utils.c	(revision 35066)
+++ mail/em-utils.c	(working copy)
@@ -666,40 +666,52 @@
 	g_free(type);
 }
 
-/**
- * em_utils_add_address:
- * @parent:
- * @email:
- *
- * Add address @email to the addressbook.
- **/
-void em_utils_add_address(struct _GtkWidget *parent, const char *email)
+/* one of email or vcard should be always NULL, never both of them */
+static void
+emu_add_address_or_vcard (struct _GtkWidget *parent, const char *email, const char *vcard)
 {
-	CamelInternetAddress *cia;
 	GtkWidget *win;
 	GtkWidget *control;
 	/*GtkWidget *socket;*/
-	char *buf;
+	char *email_buf = NULL;
 
-	cia = camel_internet_address_new ();
-	if (camel_address_decode ((CamelAddress *) cia, email) == -1) {
+	if (email) {
+		CamelInternetAddress *cia;
+
+		cia = camel_internet_address_new ();
+		if (camel_address_decode ((CamelAddress *) cia, email) == -1) {
+			camel_object_unref (cia);
+			return;
+		}
+
+		email_buf = camel_address_format ((CamelAddress *) cia);
 		camel_object_unref (cia);
-		return;
 	}
 
-	buf = camel_address_format ((CamelAddress *) cia);
-	camel_object_unref (cia);
-
 	win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 	gtk_window_set_title((GtkWindow *)win, _("Add address"));
-	gtk_window_set_transient_for((GtkWindow *)win, ((GtkWindow *)parent));
+
+	if (parent && !GTK_IS_WINDOW (parent)) {
+		parent = gtk_widget_get_toplevel (parent);
+		if (!parent || !(GTK_WIDGET_TOPLEVEL (parent)))
+			parent = NULL;
+	}
+
+	if (parent)
+		gtk_window_set_transient_for((GtkWindow *)win, ((GtkWindow *)parent));
+
 	gtk_window_set_position((GtkWindow *)win, GTK_WIN_POS_CENTER_ON_PARENT);
 	gtk_window_set_type_hint((GtkWindow *)win, GDK_WINDOW_TYPE_HINT_DIALOG);
 
 	control = bonobo_widget_new_control("OAFIID:GNOME_Evolution_Addressbook_AddressPopup:" BASE_VERSION, CORBA_OBJECT_NIL);
-	bonobo_widget_set_property((BonoboWidget *)control, "email", TC_CORBA_string, buf, NULL);
-	g_free (buf);
 
+	if (email_buf)
+		bonobo_widget_set_property ((BonoboWidget *) control, "email", TC_CORBA_string, email_buf, NULL);
+	else
+		bonobo_widget_set_property ((BonoboWidget *) control, "vcard", TC_CORBA_string, vcard, NULL);
+
+	g_free (email_buf);
+
 	bonobo_event_source_client_add_listener(bonobo_widget_get_objref((BonoboWidget *)control), emu_add_address_cb, NULL, NULL, win);
 
 	/*socket = find_socket (GTK_CONTAINER (control));
@@ -709,6 +721,29 @@
 	gtk_widget_show_all(win);
 }
 
+/**
+ * em_utils_add_address:
+ * @parent:
+ * @email:
+ *
+ * Add address @email to the addressbook.
+ **/
+void
+em_utils_add_address (struct _GtkWidget *parent, const char *email)
+{
+	emu_add_address_or_vcard (parent, email, NULL);
+}
+
+/**
+ * em_utils_add_vcard:
+ * Adds whole vCard to the addressbook.
+ **/
+void
+em_utils_add_vcard (struct _GtkWidget *parent, const char *vcard)
+{
+	emu_add_address_or_vcard (parent, NULL, vcard);
+}
+
 /* ********************************************************************** */
 /* Flag-for-Followup... */
 
Index: mail/em-utils.h
===================================================================
--- mail/em-utils.h	(revision 35066)
+++ mail/em-utils.h	(working copy)
@@ -61,6 +61,7 @@
 void em_utils_save_messages (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids);
 
 void em_utils_add_address(struct _GtkWidget *parent, const char *email);
+void em_utils_add_vcard(struct _GtkWidget *parent, const char *vcard);
 
 void em_utils_flag_for_followup (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids);
 void em_utils_flag_for_followup_clear (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids);
Index: mail/em-popup.c
===================================================================
--- mail/em-popup.c	(revision 35066)
+++ mail/em-popup.c	(working copy)
@@ -56,6 +56,7 @@
 #include <camel/camel-mime-utils.h>
 #include <camel/camel-mime-part.h>
 #include <camel/camel-url.h>
+#include <camel/camel-stream-mem.h>
 
 #include <camel/camel-vee-folder.h>
 #include <camel/camel-vtrash-folder.h>
@@ -697,6 +698,40 @@
 }
 
 static void
+emp_add_vcard (EPopup *ep, EPopupItem *item, void *data)
+{
+	EPopupTarget *target = ep->target;
+	CamelMimePart *part;
+	CamelDataWrapper *content;
+	CamelStreamMem *mem;
+	
+
+	if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
+		part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
+	else
+		part = ((EMPopupTargetPart *) target)->part;
+
+	if (!part)
+		return;
+
+	content = camel_medium_get_content_object (CAMEL_MEDIUM (part));
+	mem = CAMEL_STREAM_MEM (camel_stream_mem_new ());
+
+	if (camel_data_wrapper_decode_to_stream (content, CAMEL_STREAM (mem)) == -1 ||
+	    !mem->buffer->data)
+		g_warning ("Read part's content failed!");
+	else {
+		GString *vcard = g_string_new_len ((const gchar *) mem->buffer->data, mem->buffer->len);
+
+		em_utils_add_vcard (target->widget, vcard->str);
+
+		g_string_free (vcard, TRUE);
+	}
+
+	camel_object_unref (mem);
+}
+
+static void
 emp_standard_menu_factory(EPopup *emp, void *data)
 {
 	int i, len;
@@ -768,7 +803,6 @@
 					apps = gnome_vfs_mime_get_all_applications(name_type);
 			}
 		}
-		g_free (mime_type);
 
 		if (apps) {
 			GString *label = g_string_new("");
@@ -800,6 +834,23 @@
 			g_string_free(label, TRUE);
 			g_list_free(apps);
 		}
+
+		if (g_ascii_strcasecmp (mime_type, "text/x-vcard") == 0||
+		    g_ascii_strcasecmp (mime_type, "text/vcard") == 0) {
+			EPopupItem *item;
+
+			item = g_malloc0 (sizeof (*item));
+			item->type = E_POPUP_ITEM;
+			item->path = "00.00.vcf.00"; /* make it first item */
+			item->label = _("_Add to Address Book");
+			item->activate = emp_add_vcard;
+			item->user_data = NULL;
+			item->image = "contact-new";
+
+			e_popup_add_items (emp, g_slist_append (NULL, item), NULL, NULL, NULL);
+		}
+
+		g_free (mime_type);
 	}
 
 	for (i=0;i<len;i++) {
