[evolution-mapi] Implement SExp parser for contacts backend
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Implement SExp parser for contacts backend
- Date: Tue, 29 Nov 2011 17:16:15 +0000 (UTC)
commit c20420c6536bde58f772a212217c01add71fc3f1
Author: Milan Crha <mcrha redhat com>
Date: Tue Nov 29 18:15:31 2011 +0100
Implement SExp parser for contacts backend
configure.ac | 19 +-
src/addressbook/e-book-backend-mapi-contacts.c | 140 +--------
src/addressbook/e-book-backend-mapi.c | 412 +++++++++++++++++++++++-
src/addressbook/e-book-backend-mapi.h | 4 +
src/libexchangemapi/e-mapi-connection.c | 12 +-
5 files changed, 445 insertions(+), 142 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d39b93d..0ceac14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -134,7 +134,7 @@ AC_SUBST(LIBMAPI_CFLAGS)
AC_SUBST(LIBMAPI_LIBS)
dnl ****************************
-dnl Check for struct StringArrayW_r function
+dnl Check for struct StringArrayW_r availability
dnl ****************************
AC_MSG_CHECKING([libmapi struct StringArrayW_r])
save_cflags=$CFLAGS; CFLAGS=$LIBMAPI_CFLAGS
@@ -151,7 +151,7 @@ LIBS=$save_libs
AC_MSG_RESULT([$ac_cv_have_saw])
dnl ****************************
-dnl Check for struct mapi_SLPSTRArrayW function
+dnl Check for struct mapi_SLPSTRArrayW availability
dnl ****************************
AC_MSG_CHECKING([libmapi struct mapi_SLPSTRArrayW])
save_cflags=$CFLAGS; CFLAGS=$LIBMAPI_CFLAGS
@@ -168,6 +168,21 @@ LIBS=$save_libs
AC_MSG_RESULT([$ac_cv_have_msaw])
dnl ****************************
+dnl Check for struct mapi_SNotRestriction availability
+dnl see http://tracker.openchange.org/issues/377
+dnl ****************************
+AC_MSG_CHECKING([libmapi struct mapi_SNotRestriction])
+save_cflags=$CFLAGS; CFLAGS=$LIBMAPI_CFLAGS
+save_libs=$LIBS; LIBS="$LIBMAPI_LIBS"
+AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[#include <libmapi/libmapi.h>]],
+ [[struct mapi_SNotRestriction snot; snot.res->rt = RES_NOT]])],
+ [AC_DEFINE(HAVE_RES_NOT_SUPPORTED, 1, [libmapi supports RES_NOT restrictions]) ac_cv_have_rns=yes],[ac_cv_have_rns=no])
+CFLAGS=$save_cflags
+LIBS=$save_libs
+AC_MSG_RESULT([$ac_cv_have_rns])
+
+dnl ****************************
dnl Expose version information
dnl ****************************
API_VERSION=$EDS_PACKAGE
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index 4f0df9e..076763d 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -57,7 +57,7 @@ struct _EBookBackendMAPIContactsPrivate
};
static gboolean
-build_restriction_emails_contains (EMapiConnection *conn,
+build_restriction_from_sexp_query (EMapiConnection *conn,
mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
@@ -65,135 +65,15 @@ build_restriction_emails_contains (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror)
{
- struct mapi_SRestriction *restriction;
- const gchar *query = user_data;
- gchar *email = NULL, *to_free, *tmp, *tmp1;
-
- g_return_val_if_fail (query != NULL, FALSE);
-
- /* This currently supports "email foo bar soo" */
- to_free = strdup (query);
-
- tmp = strstr (to_free, "email");
- if (tmp ) {
- tmp = strchr (tmp, '\"');
- if (tmp && ++tmp) {
- tmp = strchr (tmp, '\"');
- if (tmp && ++tmp) {
- tmp1 = tmp;
- tmp1 = strchr (tmp1, '\"');
- if (tmp1) {
- *tmp1 = 0;
- email = tmp;
- }
- }
- }
- }
-
- if (email == NULL || !strchr (email, '@')) {
- g_free (to_free);
- return FALSE;
- }
-
- if (!restrictions) {
- g_free (to_free);
- return TRUE;
- }
-
- restriction = talloc_zero (mem_ctx, struct mapi_SRestriction);
- g_return_val_if_fail (restriction != NULL, FALSE);
+ const gchar *sexp_query = user_data;
- restriction->rt = RES_PROPERTY;
- restriction->res.resProperty.relop = RES_PROPERTY;
- restriction->res.resProperty.ulPropTag = PROP_TAG(PT_UNICODE, 0x801f); /* EMAIL */
- restriction->res.resProperty.lpProp.ulPropTag = PROP_TAG(PT_UNICODE, 0x801f); /* EMAIL*/
- restriction->res.resProperty.lpProp.value.lpszA = talloc_strdup (mem_ctx, email);
+ g_return_val_if_fail (sexp_query != NULL, FALSE);
- *restrictions = restriction;
-
- g_free (to_free);
+ *restrictions = mapi_book_utils_sexp_to_restriction (mem_ctx, sexp_query);
return TRUE;
}
-#if 0
-static gboolean
-build_multiple_restriction_emails_contains (EMapiConnection *conn, mapi_id_t fid, struct mapi_SRestriction *res,
- struct mapi_SRestriction_or *or_res,
- const gchar *query, gchar **to_free)
-{
- gchar *email=NULL, *tmp, *tmp1;
- //Number of restriction to apply
- guint res_count = 6;
-
- g_return_val_if_fail (to_free != NULL, FALSE);
-
- /* This currently supports "email foo bar soo" */
- *to_free = strdup (query);
-
- tmp = strstr (*to_free, "email");
- if (tmp ) {
- tmp = strchr (tmp, '\"');
- if (tmp && ++tmp) {
- tmp = strchr (tmp, '\"');
- if (tmp && ++tmp) {
- tmp1 = tmp;
- tmp1 = strchr (tmp1, '\"');
- if (tmp1) {
- *tmp1 = 0;
- email = tmp;
- }
- }
- }
- }
-
- if (email==NULL || !strchr (email, '@')) {
- g_free (*to_free);
- *to_free = NULL;
-
- return FALSE;
- }
-
- or_res[0].rt = RES_CONTENT;
- or_res[0].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
- or_res[0].res.resContent.ulPropTag = PR_EMS_AB_MANAGER_T_UNICODE;
- or_res[0].res.resContent.lpProp.value.lpszA = email;
-
- or_res[1].rt = RES_CONTENT;
- or_res[1].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
- or_res[1].res.resContent.ulPropTag = PR_DISPLAY_NAME_UNICODE;
- or_res[1].res.resContent.lpProp.value.lpszA = email;
-
- or_res[2].rt = RES_CONTENT;
- or_res[2].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
- or_res[2].res.resContent.ulPropTag = PR_GIVEN_NAME_UNICODE;
- or_res[2].res.resContent.lpProp.value.lpszA = email;
-
- or_res[3].rt = RES_CONTENT;
- or_res[3].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
- or_res[3].res.resContent.ulPropTag = e_mapi_connection_resolve_named_prop (conn, fid, PidLidEmail1OriginalDisplayName, NULL, NULL);
- or_res[3].res.resContent.lpProp.value.lpszA = email;
-
- or_res[4].rt = RES_CONTENT;
- or_res[4].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
- or_res[4].res.resContent.ulPropTag = e_mapi_connection_resolve_named_prop (conn, fid, PidLidEmail2OriginalDisplayName, NULL, NULL);
- or_res[4].res.resContent.lpProp.value.lpszA = email;
-
- or_res[5].rt = RES_CONTENT;
- or_res[5].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
- or_res[5].res.resContent.ulPropTag = e_mapi_connection_resolve_named_prop (conn, fid, PidLidEmail3OriginalDisplayName, NULL, NULL);
- or_res[5].res.resContent.lpProp.value.lpszA = email;
-
- res = g_new0 (struct mapi_SRestriction, 1);
-
- res->rt = RES_OR;
- res->res.resOr.cRes = res_count;
- res->res.resOr.res = or_res;
-
- return TRUE;
-}
-#endif
-
static uint32_t
string_to_bin (TALLOC_CTX *mem_ctx, const gchar *str, uint8_t **lpb)
{
@@ -1069,7 +949,7 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
EBookBackendMAPIContactsPrivate *priv;
EMapiConnection *conn;
GError *mapi_error = NULL;
- gboolean get_all, status;
+ gboolean status;
mapi_object_t obj_folder;
GSList *mids = NULL;
struct TransferContactsData tcd = { 0 };
@@ -1110,14 +990,6 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
tcd.ebma = ebma;
tcd.cards = vCards;
- get_all = g_ascii_strcasecmp (query, "(contains \"x-evolution-any-field\" \"\")") == 0;
- if (!get_all && !build_restriction_emails_contains (NULL, 0, NULL, NULL, (gpointer) query, NULL, NULL)) {
- e_book_backend_mapi_unlock_connection (ebma);
- /* g_propagate_error (error, EDB_ERROR (OTHER_ERROR)); */
-
- return;
- }
-
if (priv->is_public_folder)
status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
else
@@ -1125,7 +997,7 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
if (status) {
status = e_mapi_connection_list_objects (conn, &obj_folder,
- get_all ? NULL : build_restriction_emails_contains, (gpointer) query,
+ build_restriction_from_sexp_query, (gpointer) query,
gather_contact_mids_cb, &mids,
cancellable, &mapi_error);
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index e5324aa..bf28e95 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -34,6 +34,7 @@
#include <libebook/e-contact.h>
#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-sexp.h>
#include <camel/camel.h>
#include <e-mapi-operation-queue.h>
@@ -75,8 +76,8 @@ struct _EBookBackendMAPIPrivate
static const struct field_element_mapping {
EContactField field_id;
- gint element_type;
- gint mapi_id;
+ uint32_t element_type;
+ uint32_t mapi_id;
gint contact_type;
} mappings [] = {
@@ -1965,3 +1966,410 @@ mapi_book_utils_timet_to_string (time_t tt)
return g_time_val_to_iso8601 (&tv);
}
+
+struct EMapiSExpParserData
+{
+ TALLOC_CTX *mem_ctx;
+ /* parser results in ints, indexes to res_parts */
+ GPtrArray *res_parts;
+};
+
+static ESExpResult *
+term_eval_and (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ struct EMapiSExpParserData *esp = user_data;
+ ESExpResult *r;
+ gint ii, jj, valid = 0;
+
+ r = e_sexp_result_new (f, ESEXP_RES_INT);
+ r->value.number = -1;
+
+ for (ii = 0; ii < argc; ii++) {
+ if (argv[ii]->type == ESEXP_RES_INT &&
+ argv[ii]->value.number >= 0 &&
+ argv[ii]->value.number < esp->res_parts->len) {
+ jj = argv[ii]->value.number;
+ valid++;
+ }
+ }
+
+ if (valid == 1) {
+ r->value.number = jj;
+ } else if (valid > 0) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_AND;
+ res->res.resAnd.cRes = valid;
+ res->res.resAnd.res = talloc_zero_array (esp->mem_ctx, struct mapi_SRestriction_and, res->res.resAnd.cRes + 1);
+
+ jj = 0;
+
+ for (ii = 0; ii < argc; ii++) {
+ if (argv[ii]->type == ESEXP_RES_INT &&
+ argv[ii]->value.number >= 0 &&
+ argv[ii]->value.number < esp->res_parts->len) {
+ struct mapi_SRestriction *subres = g_ptr_array_index (esp->res_parts, argv[ii]->value.number);
+
+ res->res.resAnd.res[jj].rt = subres->rt;
+ res->res.resAnd.res[jj].res = subres->res;
+
+ jj++;
+ }
+ }
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ }
+
+ return r;
+}
+
+static ESExpResult *
+term_eval_or (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ struct EMapiSExpParserData *esp = user_data;
+ ESExpResult *r;
+ gint ii, jj = -1, valid = 0;
+
+ r = e_sexp_result_new (f, ESEXP_RES_INT);
+ r->value.number = -1;
+
+ for (ii = 0; ii < argc; ii++) {
+ if (argv[ii]->type == ESEXP_RES_INT &&
+ argv[ii]->value.number >= 0 &&
+ argv[ii]->value.number < esp->res_parts->len) {
+ jj = argv[ii]->value.number;
+ valid++;
+ }
+ }
+
+ if (valid == 1) {
+ r->value.number = jj;
+ } else if (valid > 0) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_OR;
+ res->res.resOr.cRes = valid;
+ res->res.resOr.res = talloc_zero_array (esp->mem_ctx, struct mapi_SRestriction_or, res->res.resOr.cRes + 1);
+
+ jj = 0;
+
+ for (ii = 0; ii < argc; ii++) {
+ if (argv[ii]->type == ESEXP_RES_INT &&
+ argv[ii]->value.number >= 0 &&
+ argv[ii]->value.number < esp->res_parts->len) {
+ struct mapi_SRestriction *subres = g_ptr_array_index (esp->res_parts, argv[ii]->value.number);
+
+ res->res.resOr.res[jj].rt = subres->rt;
+ res->res.resOr.res[jj].res = subres->res;
+
+ jj++;
+ }
+ }
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ }
+
+ return r;
+}
+
+static ESExpResult *
+term_eval_not (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ struct EMapiSExpParserData *esp = user_data;
+ ESExpResult *r;
+
+ r = e_sexp_result_new (f, ESEXP_RES_INT);
+ r->value.number = -1;
+
+ #ifdef HAVE_RES_NOT_SUPPORTED
+ if (argc == 1 && argv[0]->type == ESEXP_RES_INT) {
+ gint idx = argv[0]->value.number;
+
+ if (idx >= 0 && idx < esp->res_parts->len) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_NOT;
+ res->res.resNot.res = g_ptr_array_index (esp->res_parts, idx);
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ }
+ }
+ #endif
+
+ return r;
+}
+
+static uint32_t
+get_proptag_from_field_name (const gchar *field_name, gboolean is_contact_field)
+{
+ EContactField cfid;
+ gint ii;
+
+ if (is_contact_field)
+ cfid = e_contact_field_id (field_name);
+ else
+ cfid = e_contact_field_id_from_vcard (field_name);
+
+ for (ii = 0; ii < G_N_ELEMENTS (mappings); ii++) {
+ if (mappings[ii].field_id == cfid) {
+ return mappings[ii].mapi_id;
+ }
+ }
+
+ return MAPI_E_RESERVED;
+}
+
+static ESExpResult *
+func_eval_text_compare (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data,
+ uint32_t fuzzy)
+{
+ struct EMapiSExpParserData *esp = user_data;
+ ESExpResult *r;
+
+ r = e_sexp_result_new (f, ESEXP_RES_INT);
+ r->value.number = -1;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ const gchar *propname = argv[0]->value.string;
+ const gchar *propvalue = argv[1]->value.string;
+
+ if (propname && propvalue && g_ascii_strcasecmp (propname, "x-evolution-any-field") != 0) {
+ uint32_t proptag = get_proptag_from_field_name (propname, TRUE);
+
+ if (proptag != MAPI_E_RESERVED && ((proptag & 0xFFFF) == PT_UNICODE || (proptag & 0xFFFF) == PT_STRING8)) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_CONTENT;
+ res->res.resContent.fuzzy = fuzzy | FL_IGNORECASE;
+ res->res.resContent.ulPropTag = proptag;
+ res->res.resContent.lpProp.ulPropTag = proptag;
+ res->res.resContent.lpProp.value.lpszW = talloc_strdup (esp->mem_ctx, propvalue);
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ } else if (g_ascii_strcasecmp (propname, "email") == 0) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_OR;
+ res->res.resOr.cRes = 3;
+ res->res.resOr.res = talloc_zero_array (esp->mem_ctx, struct mapi_SRestriction_or, res->res.resOr.cRes + 1);
+
+ proptag = get_proptag_from_field_name ("email_1", TRUE);
+ res->res.resOr.res[0].rt = RES_CONTENT;
+ res->res.resOr.res[0].res.resContent.fuzzy = fuzzy | FL_IGNORECASE;
+ res->res.resOr.res[0].res.resContent.ulPropTag = proptag;
+ res->res.resOr.res[0].res.resContent.lpProp.ulPropTag = proptag;
+ res->res.resOr.res[0].res.resContent.lpProp.value.lpszW = talloc_strdup (esp->mem_ctx, propvalue);
+
+ proptag = get_proptag_from_field_name ("email_2", TRUE);
+ res->res.resOr.res[1].rt = RES_CONTENT;
+ res->res.resOr.res[1].res.resContent.fuzzy = fuzzy | FL_IGNORECASE;
+ res->res.resOr.res[1].res.resContent.ulPropTag = proptag;
+ res->res.resOr.res[1].res.resContent.lpProp.ulPropTag = proptag;
+ res->res.resOr.res[1].res.resContent.lpProp.value.lpszW = talloc_strdup (esp->mem_ctx, propvalue);
+
+ proptag = get_proptag_from_field_name ("email_3", TRUE);
+ res->res.resOr.res[2].rt = RES_CONTENT;
+ res->res.resOr.res[2].res.resContent.fuzzy = fuzzy | FL_IGNORECASE;
+ res->res.resOr.res[2].res.resContent.ulPropTag = proptag;
+ res->res.resOr.res[2].res.resContent.lpProp.ulPropTag = proptag;
+ res->res.resOr.res[2].res.resContent.lpProp.value.lpszW = talloc_strdup (esp->mem_ctx, propvalue);
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ }
+ }
+ }
+
+ return r;
+}
+
+static ESExpResult *
+func_eval_contains (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ return func_eval_text_compare (f, argc, argv, user_data, FL_SUBSTRING);
+}
+
+static ESExpResult *
+func_eval_is (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ return func_eval_text_compare (f, argc, argv, user_data, FL_FULLSTRING);
+}
+static ESExpResult *
+func_eval_beginswith (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ return func_eval_text_compare (f, argc, argv, user_data, FL_PREFIX);
+}
+static ESExpResult *
+func_eval_endswith (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ /* no suffix, thus at least substring is used */
+ return func_eval_text_compare (f, argc, argv, user_data, FL_SUBSTRING);
+}
+
+static ESExpResult *
+func_eval_field_exists (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data,
+ gboolean is_contact_field)
+{
+ struct EMapiSExpParserData *esp = user_data;
+ ESExpResult *r;
+
+ r = e_sexp_result_new (f, ESEXP_RES_INT);
+ r->value.number = -1;
+
+ if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
+ const gchar *propname = argv[0]->value.string;
+ uint32_t proptag = get_proptag_from_field_name (propname, is_contact_field);
+
+ if (proptag != MAPI_E_RESERVED) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_EXIST;
+ res->res.resExist.ulPropTag = proptag;
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ } else if (g_ascii_strcasecmp (propname, "email") == 0) {
+ struct mapi_SRestriction *res = talloc_zero (esp->mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (res != NULL, NULL);
+
+ res->rt = RES_OR;
+ res->res.resOr.cRes = 3;
+ res->res.resOr.res = talloc_zero_array (esp->mem_ctx, struct mapi_SRestriction_or, res->res.resOr.cRes + 1);
+
+ res->res.resOr.res[0].rt = RES_EXIST;
+ res->res.resOr.res[0].res.resExist.ulPropTag = get_proptag_from_field_name ("email_1", TRUE);
+
+ res->res.resOr.res[1].rt = RES_EXIST;
+ res->res.resOr.res[1].res.resExist.ulPropTag = get_proptag_from_field_name ("email_2", TRUE);
+
+ res->res.resOr.res[2].rt = RES_EXIST;
+ res->res.resOr.res[2].res.resExist.ulPropTag = get_proptag_from_field_name ("email_3", TRUE);
+
+ g_ptr_array_add (esp->res_parts, res);
+ r->value.number = esp->res_parts->len - 1;
+ }
+ }
+
+ return r;
+}
+
+static ESExpResult *
+func_eval_exists (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ return func_eval_field_exists (f, argc, argv, user_data, TRUE);
+}
+
+static ESExpResult *
+func_eval_exists_vcard (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer user_data)
+{
+ return func_eval_field_exists (f, argc, argv, user_data, FALSE);
+}
+
+struct mapi_SRestriction *
+mapi_book_utils_sexp_to_restriction (TALLOC_CTX *mem_ctx, const gchar *sexp_query)
+{
+ /* 'builtin' functions */
+ static const struct {
+ const gchar *name;
+ ESExpFunc *func;
+ gint type; /* set to 1 if a function can perform shortcut evaluation, or
+ doesn't execute everything, 0 otherwise */
+ } check_symbols[] = {
+ { "and", term_eval_and, 0 },
+ { "or", term_eval_or, 0 },
+ { "not", term_eval_not, 0 },
+
+ { "contains", func_eval_contains, 0 },
+ { "is", func_eval_is, 0 },
+ { "beginswith", func_eval_beginswith, 0 },
+ { "endswith", func_eval_endswith, 0 },
+ { "exists", func_eval_exists, 0 },
+ { "exists_vcard", func_eval_exists_vcard, 0 }
+ };
+
+ gint i;
+ ESExp *sexp;
+ ESExpResult *r;
+ struct EMapiSExpParserData esp;
+ struct mapi_SRestriction *restriction;
+
+ g_return_val_if_fail (sexp_query != NULL, NULL);
+
+ esp.mem_ctx = mem_ctx;
+ sexp = e_sexp_new ();
+
+ for (i = 0; i < G_N_ELEMENTS (check_symbols); i++) {
+ if (check_symbols[i].type == 1) {
+ e_sexp_add_ifunction (sexp, 0, check_symbols[i].name,
+ (ESExpIFunc *) check_symbols[i].func, &esp);
+ } else {
+ e_sexp_add_function (sexp, 0, check_symbols[i].name,
+ check_symbols[i].func, &esp);
+ }
+ }
+
+ e_sexp_input_text (sexp, sexp_query, strlen (sexp_query));
+ if (e_sexp_parse (sexp) == -1) {
+ e_sexp_unref (sexp);
+ return NULL;
+ }
+
+ esp.res_parts = g_ptr_array_new ();
+ r = e_sexp_eval (sexp);
+
+ restriction = NULL;
+ if (r && r->type == ESEXP_RES_INT && r->value.number >= 0 && r->value.number < esp.res_parts->len)
+ restriction = g_ptr_array_index (esp.res_parts, r->value.number);
+
+ e_sexp_result_free (sexp, r);
+
+ e_sexp_unref (sexp);
+ g_ptr_array_free (esp.res_parts, TRUE);
+
+ return restriction;
+}
diff --git a/src/addressbook/e-book-backend-mapi.h b/src/addressbook/e-book-backend-mapi.h
index 5a65f95..4e84bcb 100644
--- a/src/addressbook/e-book-backend-mapi.h
+++ b/src/addressbook/e-book-backend-mapi.h
@@ -149,6 +149,10 @@ EContact *mapi_book_utils_contact_from_props (EMapiConnection *conn, mapi_id_t f
free returned pointer with g_free() */
gchar *mapi_book_utils_timet_to_string (time_t tt);
+/* converts sexp_query into mapi_SRestriction, which is completely
+ allocated on the given mem_ctx */
+struct mapi_SRestriction *mapi_book_utils_sexp_to_restriction (TALLOC_CTX *mem_ctx, const gchar *sexp_query);
+
G_END_DECLS
#endif /* __E_BOOK_BACKEND_MAPI_H__ */
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index 4688091..30285cc 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -1980,9 +1980,11 @@ gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
}
break;
- /*case RES_NOT:
+ #ifdef HAVE_RES_NOT_SUPPORTED
+ case RES_NOT:
gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) restriction->res.resNot.res, named_ids_list, named_ids_len);
- break;*/
+ break;
+ #endif
case RES_CONTENT:
maybe_add_named_id_tag (restriction->res.resContent.ulPropTag, named_ids_list, named_ids_len);
maybe_add_named_id_tag (restriction->res.resContent.lpProp.ulPropTag, named_ids_list, named_ids_len);
@@ -2048,9 +2050,11 @@ replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
}
break;
- /*case RES_NOT:
+ #ifdef HAVE_RES_NOT_SUPPORTED
+ case RES_NOT:
replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, named_ids_list, named_ids_len);
- break;*/
+ break;
+ #endif
case RES_CONTENT:
maybe_replace_named_id_tag (&restriction->res.resContent.ulPropTag, named_ids_list, named_ids_len);
maybe_replace_named_id_tag (&restriction->res.resContent.lpProp.ulPropTag, named_ids_list, named_ids_len);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]