member_compare (EContact *contact_new,
                EContact *contact_current)
{
	GList *members_new, *members_cur, *l1, *l2, *p_new, *p_cur;
	gint len1 = 0, len2 = 0;
	gchar *list_name1, *list_name2;
	gboolean equal;

	if (!(e_contact_get (contact_new, E_CONTACT_IS_LIST)))
		return TRUE;
	if (!(e_contact_get (contact_current, E_CONTACT_IS_LIST)))
		return TRUE;

	list_name1 = e_contact_get (contact_new, E_CONTACT_FULL_NAME);
	list_name2 = e_contact_get (contact_current, E_CONTACT_FULL_NAME);
	if (list_name1 && list_name2)
		equal = !strcmp (list_name1, list_name2);
	else
		equal = (!!list_name1 == !!list_name2);

	g_free (list_name1);
	g_free (list_name2);

	if (!equal)
		return equal;

	members_new = e_contact_get_attributes (contact_new, E_CONTACT_EMAIL);
	len1 = g_list_length (members_new);
	members_cur = e_contact_get_attributes (contact_current, E_CONTACT_EMAIL);
	len2 = g_list_length (members_cur);
	if (len1 != len2) {
		g_list_free_full (members_new, (GDestroyNotify) e_vcard_attribute_free);
		g_list_free_full (members_cur, (GDestroyNotify) e_vcard_attribute_free);

		return FALSE;
	}

	for (l1 = members_new; l1 != NULL; l1 = g_list_next (l1)) {
		EVCardAttribute *attr_new = l1->data;
		gchar *dn_new = NULL;

		for (p_new = e_vcard_attribute_get_params (attr_new); p_new; p_new = p_new->next) {
			EVCardAttributeParam *param = p_new->data;
			const gchar *param_name1 = e_vcard_attribute_param_get_name (param);

			if (!g_ascii_strcasecmp (param_name1, EVC_X_DEST_CONTACT_UID)) {
				gboolean found = FALSE;
				GList *v = e_vcard_attribute_param_get_values (param);
				dn_new = v ? v->data : NULL;
				if (dn_new) {
					for (l2 = members_cur; l2 != NULL; l2 = g_list_next (l2)) {
						EVCardAttribute *attr_cur = l2->data;
						gchar *dn_cur = NULL;

						for (p_cur = e_vcard_attribute_get_params (attr_cur); p_cur; p_cur = p_cur->next) {
							EVCardAttributeParam *param2 = p_cur->data;
							const gchar *param_name2 = e_vcard_attribute_param_get_name (param2);

							if (!g_ascii_strcasecmp (param_name2, EVC_X_DEST_CONTACT_UID)) {
								GList *v2 = e_vcard_attribute_param_get_values (param2);
								dn_cur = v2 ? v2->data : NULL;

								if (dn_cur) {
									if (!g_ascii_strcasecmp (dn_new, dn_cur)) {
										found = TRUE;
										members_cur = g_list_remove (members_cur, attr_cur);
										goto next_member;
									}
								}
							}
						}
					}
					if (!found) {
						g_list_free_full (members_new, (GDestroyNotify) e_vcard_attribute_free);
						g_list_free_full (members_cur, (GDestroyNotify) e_vcard_attribute_free);
						return FALSE;
					}
				}
			}
		}
		next_member:
		continue;
	}

	g_list_free_full (members_new, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free_full (members_cur, (GDestroyNotify) e_vcard_attribute_free);

	return TRUE;
}
member_compare (EContact *contact_new,
                EContact *contact_current)
{
	GList *members_new, *members_cur, *l1, *l2, *p_new, *p_cur;
	gint len1 = 0, len2 = 0;
	gchar *list_name1, *list_name2;
	gboolean equal;

	if (!(e_contact_get (contact_new, E_CONTACT_IS_LIST)))
		return TRUE;
	if (!(e_contact_get (contact_current, E_CONTACT_IS_LIST)))
		return TRUE;

	list_name1 = e_contact_get (contact_new, E_CONTACT_FULL_NAME);
	list_name2 = e_contact_get (contact_current, E_CONTACT_FULL_NAME);
	if (list_name1 && list_name2)
		equal = !strcmp (list_name1, list_name2);
	else
		equal = (!!list_name1 == !!list_name2);

	g_free (list_name1);
	g_free (list_name2);

	if (!equal)
		return equal;

	members_new = e_contact_get_attributes (contact_new, E_CONTACT_EMAIL);
	len1 = g_list_length (members_new);
	members_cur = e_contact_get_attributes (contact_current, E_CONTACT_EMAIL);
	len2 = g_list_length (members_cur);
	if (len1 != len2) {
		g_list_free_full (members_new, (GDestroyNotify) e_vcard_attribute_free);
		g_list_free_full (members_cur, (GDestroyNotify) e_vcard_attribute_free);

		return FALSE;
	}

	for (l1 = members_new; l1 != NULL; l1 = g_list_next (l1)) {
		EVCardAttribute *attr_new = l1->data;
		gchar *dn_new = NULL;

		for (p_new = e_vcard_attribute_get_params (attr_new); p_new; p_new = p_new->next) {
			EVCardAttributeParam *param = p_new->data;
			const gchar *param_name1 = e_vcard_attribute_param_get_name (param);

			if (!g_ascii_strcasecmp (param_name1, EVC_X_DEST_CONTACT_UID)) {
				gboolean found = FALSE;
				GList *v = e_vcard_attribute_param_get_values (param);
				dn_new = v ? v->data : NULL;
				if (dn_new) {
					for (l2 = members_cur; l2 != NULL; l2 = g_list_next (l2)) {
						EVCardAttribute *attr_cur = l2->data;
						gchar *dn_cur = NULL;

						for (p_cur = e_vcard_attribute_get_params (attr_cur); p_cur; p_cur = p_cur->next) {
							EVCardAttributeParam *param2 = p_cur->data;
							const gchar *param_name2 = e_vcard_attribute_param_get_name (param2);

							if (!g_ascii_strcasecmp (param_name2, EVC_X_DEST_CONTACT_UID)) {
								GList *v2 = e_vcard_attribute_param_get_values (param2);
								dn_cur = v2 ? v2->data : NULL;

								if (dn_cur) {
									if (!g_ascii_strcasecmp (dn_new, dn_cur)) {
										found = TRUE;
										members_cur = g_list_remove (members_cur, attr_cur);
										goto next_member;
									}
								}
							}
						}
					}
					if (!found) {
						g_list_free_full (members_new, (GDestroyNotify) e_vcard_attribute_free);
						g_list_free_full (members_cur, (GDestroyNotify) e_vcard_attribute_free);
						return FALSE;
					}
				}
			}
		}
		next_member:
		continue;
	}

	g_list_free_full (members_new, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free_full (members_cur, (GDestroyNotify) e_vcard_attribute_free);

	return TRUE;
}