static void cache_cb(EBook *book, EBookStatus estatus, GList *contacts,
							void *user_data)
{
	struct query_context *data = user_data;
	GList *l;

	if (estatus == E_BOOK_ERROR_CANCELLED) {
		error("E-Book operation was cancelled: status %d", estatus);
		goto fail;
	}

	data->completed = TRUE;

	if (estatus != E_BOOK_ERROR_OK) {
		error("E-Book query failed: status %d", estatus);
		goto done;
	}

	for (l = contacts; l; l = g_list_next(l)) {
		EContact *contact = E_CONTACT(l->data);
		EVCard *evcard = E_VCARD(contact);
		EVCardAttribute *attrib;
		char *uid, *tel, *name;

		name = evcard_name_attribute_to_string(evcard);
		if (!name)
			continue;

		attrib = e_vcard_get_attribute(evcard, EVC_UID);
		if (!attrib)
			continue;

		uid =  e_vcard_attribute_get_value(attrib);
		if (!uid)
			continue;

		attrib = e_vcard_get_attribute(evcard, EVC_TEL);
		if (!attrib)
			continue;

		tel =  e_vcard_attribute_get_value(attrib);

		data->entry_cb(uid, PHONEBOOK_INVALID_HANDLE, name, NULL,
							tel, data->user_data);
		g_free(name);
		g_free(uid);
		g_free(tel);
	}
done:
	data->ready_cb(data->user_data);

fail:
	if (data->completed)
		g_free(data);
}
static ESExpResult *
func_exists_vcard (struct _ESExp *f,
                   gint argc,
                   struct _ESExpResult **argv,
                   gpointer data)
{
	SearchContext *ctx = data;
	ESExpResult *r;
	gint truth = FALSE;

	if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
		const gchar *attr_name;
		EVCardAttribute *attr;
		GList *values;
		gchar *s;

		attr_name = argv[0]->value.string;
		attr = e_vcard_get_attribute (E_VCARD (ctx->contact), attr_name);
		if (attr) {
			values = e_vcard_attribute_get_values (attr);
			if (g_list_length (values) > 0) {
				s = values->data;
				if (s[0] != '\0') {
					truth = TRUE;
				}
			}
		}
	}

	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
	r->value.boolean = truth;

	return r;
}
static char *evcard_name_attribute_to_string(EVCard *evcard)
{
	EVCardAttribute *attrib;
	GList *l;
	GString *name = NULL;

	attrib = e_vcard_get_attribute(evcard, EVC_N);
	if (!attrib)
		return NULL;

	for (l = e_vcard_attribute_get_values(attrib); l; l = l->next) {
		const char *value = l->data;

		if (!strlen(value))
			continue;

		if (!name)
			name = g_string_new(value);
		else {
			name = g_string_append(name, ";");
			name = g_string_append(name, l->data);
		}
	}

	if (!name)
		return NULL;

	return g_string_free(name, FALSE);
}
static void
verify_premodify_and_prepare_contact (EContact *contact)
{
	EVCardAttribute *attr;

	/* ensure there is no email address to begin with, then add one */
	g_assert (!e_vcard_get_attribute (E_VCARD (contact), EVC_EMAIL));
	attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
	e_vcard_add_attribute_with_value (E_VCARD (contact), attr, EMAIL_ADD);
}
static void
verify_commit (EContact *contact)
{
	EVCardAttribute *attr;
	gchar *email_value;

	g_assert ((attr = e_vcard_get_attribute (E_VCARD (contact), EVC_EMAIL)));
	g_assert (e_vcard_attribute_is_single_valued (attr));
	email_value = e_vcard_attribute_get_value (attr);
	g_assert (!g_strcmp0 (email_value, EMAIL_ADD));
}
static gboolean
compare_single_value (EVCard *vcard,
                      const gchar *attrname,
                      const gchar *expected_value)
{
	EVCardAttribute *attr;
	gchar *str;

	g_return_val_if_fail (vcard != NULL, FALSE);
	g_return_val_if_fail (attrname != NULL, FALSE);
	g_return_val_if_fail (expected_value != NULL, FALSE);

	attr = e_vcard_get_attribute (vcard, attrname);
	g_return_val_if_fail (attr != NULL, FALSE);

	str = e_vcard_attribute_get_value (attr);
	g_return_val_if_fail (str != NULL, FALSE);
	g_return_val_if_fail (g_strcmp0 (str, expected_value) == 0, FALSE);

	g_free (str);

	return TRUE;
}
static gboolean
test_vcard (const gchar *vcard_str)
{
	EVCard *vc1, *vc2;
	gchar *str;

	/* Do not parse */
	vc1 = e_vcard_new_from_string (vcard_str);
	str = e_vcard_to_string (vc1, EVC_FORMAT_VCARD_30);
	g_return_val_if_fail (str != NULL, FALSE);
	g_return_val_if_fail (g_ascii_strcasecmp (str, vcard_str) == 0, FALSE);
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == FALSE, FALSE);

	g_free (str);

	/* parse */
	e_vcard_get_attribute (vc1, "UID");
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == TRUE, FALSE);
	str = e_vcard_to_string (vc1, EVC_FORMAT_VCARD_30);
	g_return_val_if_fail (str != NULL, FALSE);
	g_return_val_if_fail (g_ascii_strcasecmp (str, vcard_str) == 0, FALSE);

	g_free (str);

	/* parse */
	e_vcard_get_attribute (vc1, "FN");
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == TRUE, FALSE);
	str = e_vcard_to_string (vc1, EVC_FORMAT_VCARD_30);
	g_return_val_if_fail (str != NULL, FALSE);
	g_return_val_if_fail (g_ascii_strcasecmp (str, vcard_str) == 0, FALSE);

	g_free (str);
	g_object_unref (vc1);

	/* do not parse */
	vc1 = e_vcard_new_from_string (vcard_str);
	/* Setting the UID does not cause vCard parsing */
	e_vcard_append_attribute_with_value (vc1, e_vcard_attribute_new (NULL, "UID"), "other-uid");
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == FALSE, FALSE);
	/* Retrieving the UID should not cause vCard parsing either */
	g_return_val_if_fail (compare_single_value (vc1, "UID", "other-uid"), FALSE);
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == FALSE, FALSE);
	/* Getting FN attribute WILL cause parsing */
	e_vcard_get_attribute (vc1, "FN");
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == TRUE, FALSE);
	g_object_unref (vc1);

	/* parse */
	vc1 = e_vcard_new_from_string (vcard_str);
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == FALSE, FALSE);
	e_vcard_remove_attributes (vc1, NULL, "UID");
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == TRUE, FALSE);
	e_vcard_append_attribute_with_value (vc1, e_vcard_attribute_new (NULL, "UID"), "other-uid");
	g_return_val_if_fail (compare_single_value (vc1, "UID", "other-uid"), FALSE);
	str = e_vcard_to_string (vc1, EVC_FORMAT_VCARD_30);
	vc2 = e_vcard_new_from_string (str);
	g_free (str);

	g_return_val_if_fail (compare_single_value (vc2, "UID", "other-uid"), FALSE);

	g_object_unref (vc2);

	/* parse */
	e_vcard_get_attribute (vc1, "FN");
	g_return_val_if_fail (e_vcard_is_parsed (vc1) == TRUE, FALSE);
	g_return_val_if_fail (compare_single_value (vc1, "UID", "other-uid"), FALSE);
	str = e_vcard_to_string (vc1, EVC_FORMAT_VCARD_30);
	vc2 = e_vcard_new_from_string (str);
	g_return_val_if_fail (e_vcard_is_parsed (vc2) == FALSE, FALSE);
	g_free (str);

	g_return_val_if_fail (compare_single_value (vc2, "UID", "other-uid"), FALSE);
	g_return_val_if_fail (has_only_one (vc1, "UID"), FALSE);
	g_return_val_if_fail (has_only_one (vc2, "UID"), FALSE);

	g_object_unref (vc2);
	g_object_unref (vc1);

	return TRUE;
}
static ESExpResult *
func_exists (struct _ESExp *f,
             gint argc,
             struct _ESExpResult **argv,
             gpointer data)
{
	SearchContext *ctx = data;
	ESExpResult *r;
	gint truth = FALSE;

	if (argc == 1
	    && argv[0]->type == ESEXP_RES_STRING) {
		const gchar *propname;
		struct prop_info *info = NULL;
		gint i;
		gboolean saw_any = FALSE;

		propname = argv[0]->value.string;

		for (i = 0; i < G_N_ELEMENTS (prop_info_table); i++) {
			if (!strcmp (prop_info_table[i].query_prop, propname)) {
				saw_any = TRUE;
				info = &prop_info_table[i];

				if (info->prop_type == PROP_TYPE_NORMAL) {
					const gchar *prop = NULL;
					/* searches where the query's property
					 * maps directly to an ecard property */

					prop = e_contact_get_const (ctx->contact, info->field_id);

					if (prop && *prop)
						truth = TRUE;
				}
				else if (info->prop_type == PROP_TYPE_LIST) {
					/* the special searches that match any of the list elements */
					truth = info->list_compare (ctx->contact, "", NULL, exists_helper);
				}
				else if (info->prop_type == PROP_TYPE_DATE) {
					EContactDate *date;

					date = e_contact_get (ctx->contact, info->field_id);

					if (date) {
						truth = TRUE;
						e_contact_date_free (date);
					}
				} else {
					g_warn_if_reached ();

					saw_any = FALSE;
				}

				break;
			}
		}

		if (!saw_any) {
			/* propname didn't match to any of our known "special" properties,
			 * so try to find if it isn't a real field and if so, then check
			 * against value in this field only */
			EContactField fid = e_contact_field_id (propname);

			if (fid >= E_CONTACT_FIELD_FIRST && fid < E_CONTACT_FIELD_LAST &&
			    e_contact_field_is_string (fid)) {
				const gchar *prop = e_contact_get_const (ctx->contact, fid);

				if (prop && *prop)
					truth = TRUE;
			} else {
				/* is is not a known EContact field, try with EVCard attributes */
				EVCardAttribute *attr;
				GList *l, *values;

				if (fid >= E_CONTACT_FIELD_FIRST && fid < E_CONTACT_FIELD_LAST)
					propname = e_contact_vcard_attribute (fid);

				attr = e_vcard_get_attribute (E_VCARD (ctx->contact), propname);
				values = attr ? e_vcard_attribute_get_values (attr) : NULL;

				for (l = values; l && !truth; l = l->next) {
					const gchar *value = l->data;

					if (value && *value)
						truth = TRUE;
				}
			}
		}
	}
	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
	r->value.boolean = truth;

	return r;
}
void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
		phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
{
	struct query_context *data;
	EBookQuery *query;
	GSList *l;
	EContact *me;
	EVCard *evcard;
	GError *gerr = NULL;
	EBook *eb;
	EVCardAttribute *attrib;
	char *uid, *tel, *cname;

	if (g_strcmp0(PB_CONTACTS_FOLDER, name) != 0) {
		if (err)
			*err = -ENOENT;

		return NULL;
	}

	DBG("");

	query = e_book_query_any_field_contains("");

	data = g_new0(struct query_context, 1);
	data->entry_cb = entry_cb;
	data->ready_cb = ready_cb;
	data->user_data = user_data;
	data->query = query;
	data->ebooks = open_ebooks();

	/* Add 0.vcf */
	if (e_book_get_self(&me, &eb, &gerr) == FALSE) {
		g_error_free(gerr);
		goto next;
	}

	evcard = E_VCARD(me);

	cname = evcard_name_attribute_to_string(evcard);
	if (!cname)
		cname = g_strdup("");

	attrib = e_vcard_get_attribute(evcard, EVC_UID);
	uid = e_vcard_attribute_get_value(attrib);
	if (!uid)
		uid = g_strdup("");

	attrib = e_vcard_get_attribute(evcard, EVC_TEL);
	if (attrib)
		tel =  e_vcard_attribute_get_value(attrib);
	else
		tel = g_strdup("");

	data->entry_cb(uid, 0, cname, NULL, tel, data->user_data);

	data->count++;

	g_free(cname);
	g_free(uid);
	g_free(tel);
	g_object_unref(eb);

next:
	for (l = data->ebooks; l != NULL; l = g_slist_next(l)) {
		EBook *ebook = l->data;

		if (e_book_is_opened(ebook) == FALSE)
			continue;

		if (e_book_get_contacts_async(ebook, query,
						cache_cb, data) == TRUE)
			data->queued_calls++;
	}

	if (err)
		*err = (data->queued_calls == 0 ? -ENOENT : 0);

	return data;
}
static void cache_cb(EBook *book, const GError *gerr, GList *contacts,
							void *user_data)
{
	struct query_context *data = user_data;
	GList *l;

	data->queued_calls--;

	if (data->canceled)
		goto canceled;

	if (gerr != NULL) {
		error("E-Book operation failed: %s", gerr->message);
		goto done;
	}

	DBG("");

	for (l = contacts; l; l = g_list_next(l)) {
		EContact *contact = E_CONTACT(l->data);
		EVCard *evcard = E_VCARD(contact);
		EVCardAttribute *attrib;
		char *uid, *tel, *name;

		name = evcard_name_attribute_to_string(evcard);
		if (!name)
			continue;

		attrib = e_vcard_get_attribute(evcard, EVC_UID);
		if (!attrib)
			continue;

		uid = e_vcard_attribute_get_value(attrib);
		if (!uid)
			continue;

		attrib = e_vcard_get_attribute(evcard, EVC_TEL);
		if (attrib)
			tel = e_vcard_attribute_get_value(attrib);
		else
			tel = g_strdup("");

		data->entry_cb(uid, PHONEBOOK_INVALID_HANDLE, name, NULL,
							tel, data->user_data);

		g_free(name);
		g_free(uid);
		g_free(tel);
	}

	g_list_free_full(contacts, g_object_unref);

done:
	if (data->queued_calls == 0)
		data->ready_cb(data->user_data);

	return;

canceled:
	if (data->queued_calls == 0)
		free_query_context(data);
}
Exemple #11
0
static void
contacts_entry_changed (GtkWidget *widget, EContactChangeData *data)
{
	GList *v, *values = contacts_entries_get_values (data->widget, NULL);
	
	e_vcard_attribute_remove_values (data->attr);
	/* Note: First element of a structured field is type, so remove it */
	if (g_list_length (values) > 1) {
		GList *type = g_list_last (values);
		values = g_list_remove_link (values, type);
		g_free (type->data);
		g_list_free (type);
	}
		
	for (v = g_list_last (values); v; v = v->prev) {
		e_vcard_attribute_add_value (data->attr,
					     (const gchar *)v->data);
	}

	if (!g_ascii_strcasecmp (e_vcard_attribute_get_name (data->attr), EVC_FN))
	{
		/* add N and X-EVOLUTION-FILE-AS attributes */
		ENameWestern *name;
		gchar *file_as;
		EVCardAttribute *attr;
		EVCard *evc = E_VCARD (data->contact);

		name = e_name_western_parse ((char*)values->data);
		
		/* Add "N" attribute */
		attr = e_vcard_get_attribute (evc, EVC_N);
		if (attr)
			e_vcard_attribute_remove_values (attr);
		else
		{
			attr = e_vcard_attribute_new ("", EVC_N);
			e_vcard_add_attribute (evc, attr);
		}
#define SAFESTR(x) (x) ? x : ""
		e_vcard_attribute_add_value (attr, SAFESTR (name->last));
		e_vcard_attribute_add_value (attr, SAFESTR (name->first));
		e_vcard_attribute_add_value (attr, SAFESTR (name->middle));
		e_vcard_attribute_add_value (attr, SAFESTR (name->prefix));
		e_vcard_attribute_add_value (attr, SAFESTR (name->suffix));

		/* Add file-as attribute for evolution */
		file_as = g_strdup_printf ("%s, %s", name->last, name->first);
		attr = e_vcard_get_attribute (evc, EVC_X_FILE_AS);
		if (attr)
			e_vcard_remove_attribute (evc, attr);
		attr = e_vcard_attribute_new ("", EVC_X_FILE_AS);
		e_vcard_add_attribute_with_value (evc, attr, file_as);
		g_free (file_as);

		g_free (name);
	}

	g_list_foreach (values, (GFunc)g_free, NULL);
	g_list_free (values);
	*data->changed = TRUE;
}