[evolution-mapi] Rewrite GAL to support restrictions and partial search results
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Rewrite GAL to support restrictions and partial search results
- Date: Wed, 21 Dec 2011 18:36:06 +0000 (UTC)
commit 8d3ba4d496770cb78a87a16979f30186b016daaa
Author: Milan Crha <mcrha redhat com>
Date: Wed Dec 21 19:33:49 2011 +0100
Rewrite GAL to support restrictions and partial search results
.../e-mapi-account-listener.c | 5 +-
src/account-setup-eplugin/e-mapi-account-setup.c | 4 +
src/addressbook/e-book-backend-mapi-contacts.c | 389 +------
src/addressbook/e-book-backend-mapi-gal.c | 201 ++--
src/addressbook/e-book-backend-mapi.c | 938 ++--------------
src/addressbook/e-book-backend-mapi.h | 28 +-
src/libexchangemapi/Makefile.am | 5 +
src/libexchangemapi/e-mapi-book-utils.c | 1134 ++++++++++++++++++
src/libexchangemapi/e-mapi-book-utils.h | 67 ++
src/libexchangemapi/e-mapi-connection.c | 942 +++++++++++++---
src/libexchangemapi/e-mapi-connection.h | 50 +-
src/libexchangemapi/e-mapi-debug.c | 1200 ++++++++++----------
src/libexchangemapi/e-mapi-debug.h | 4 +-
src/libexchangemapi/e-mapi-utils.c | 119 --
src/libexchangemapi/e-mapi-utils.h | 145 ++--
15 files changed, 2967 insertions(+), 2264 deletions(-)
---
diff --git a/src/account-setup-eplugin/e-mapi-account-listener.c b/src/account-setup-eplugin/e-mapi-account-listener.c
index f223c54..85ebe54 100644
--- a/src/account-setup-eplugin/e-mapi-account-listener.c
+++ b/src/account-setup-eplugin/e-mapi-account-listener.c
@@ -843,7 +843,7 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
g_free (uri);
e_source_set_property (source, "auth", "plain/password");
- //FIXME: Offline handling
+ /* FIXME: Offline handling */
e_source_set_property(source, "user", NULL);
e_source_set_property(source, "username", url->user);
e_source_set_property(source, "profile", profile);
@@ -852,7 +852,8 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
SET_KRB_SSO(source, kerberos);
if (is_new_source) {
- e_source_set_property(source, "offline_sync", "1");
+ e_source_set_property(source, "offline_sync", "0");
+ e_source_set_property(source, "allow-partial", "true");
e_source_set_property (source, "completion", "true");
}
diff --git a/src/account-setup-eplugin/e-mapi-account-setup.c b/src/account-setup-eplugin/e-mapi-account-setup.c
index d009229..10cd1f4 100644
--- a/src/account-setup-eplugin/e-mapi-account-setup.c
+++ b/src/account-setup-eplugin/e-mapi-account-setup.c
@@ -706,6 +706,10 @@ e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
uri_text = e_source_get_uri (source);
if (uri_text && g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH)) {
+ if (uri_text && g_ascii_strncasecmp (uri_text, "mapigal://", strlen ("mapigal://")) == 0) {
+ e_plugin_util_add_check (parent, _("Allow _partial search results"), source, "allow-partial", "true", NULL);
+ }
+
return NULL;
}
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index 5ecb253..0b77f9f 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -56,76 +56,6 @@ struct _EBookBackendMAPIContactsPrivate
gboolean is_public_folder;
};
-static gboolean
-build_restriction_from_sexp_query (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- struct mapi_SRestriction **restrictions,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- const gchar *sexp_query = user_data;
-
- g_return_val_if_fail (sexp_query != NULL, FALSE);
-
- *restrictions = mapi_book_utils_sexp_to_restriction (mem_ctx, sexp_query);
-
- return TRUE;
-}
-
-static uint32_t
-string_to_bin (TALLOC_CTX *mem_ctx, const gchar *str, uint8_t **lpb)
-{
- uint32_t len, i;
-
- g_return_val_if_fail (str != NULL, 0);
- g_return_val_if_fail (lpb != NULL, 0);
-
- len = strlen (str);
- g_return_val_if_fail ((len & 1) == 0, 0);
-
- len = len / 2;
- *lpb = talloc_zero_array (mem_ctx, uint8_t, len);
-
- i = 0;
- while (*str && i < len) {
- gchar c1 = str[0], c2 = str[1];
- str += 2;
-
- g_return_val_if_fail ((c1 >= '0' && c1 <= '9') || (c1 >= 'a' && c1 <= 'f') || (c1 >= 'A' && c1 <= 'F'), 0);
- g_return_val_if_fail ((c2 >= '0' && c2 <= '9') || (c2 >= 'a' && c2 <= 'f') || (c2 >= 'A' && c2 <= 'F'), 0);
-
- #define deHex(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : (((x) >= 'a' && (x) <= 'f') ? (x) - 'a' + 10 : (x) - 'A' + 10))
- (*lpb)[i] = (deHex (c1) << 4) | (deHex (c2));
- #undef deHex
- i++;
- }
-
- return len;
-}
-
-static gint
-cmp_member_id (gconstpointer a, gconstpointer b, gpointer ht)
-{
- gchar *va, *vb;
- gint res;
-
- if (!a)
- return b ? -1 : 0;
- if (!b)
- return 1;
-
- va = e_vcard_attribute_get_value ((EVCardAttribute *) a);
- vb = e_vcard_attribute_get_value ((EVCardAttribute *) b);
-
- res = GPOINTER_TO_INT (g_hash_table_lookup (ht, va)) - GPOINTER_TO_INT (g_hash_table_lookup (ht, vb));
-
- g_free (va);
- g_free (vb);
-
- return res;
-}
-
typedef struct {
EContact *contact;
EBookBackendSqliteDB *db;
@@ -140,17 +70,10 @@ ebbm_contact_to_object (EMapiConnection *conn,
GError **perror)
{
EMapiCreateitemData *mcd = user_data;
- EMapiObject *object;
-
- #define set_value(hex, val) G_STMT_START { \
- if (!e_mapi_utils_add_property (&object->properties, hex, val, object)) \
- return FALSE; \
- } G_STMT_END
-
- #define set_con_value(hex, field_id) G_STMT_START { \
- if (e_contact_get (mcd->contact, field_id)) { \
- set_value (hex, e_contact_get (mcd->contact, field_id)); \
- } } G_STMT_END
+ const gchar *uid = NULL;
+ EContact *old_contact = NULL;
+ gboolean res;
+ GError *error = NULL;
g_return_val_if_fail (mcd != NULL, FALSE);
g_return_val_if_fail (mcd->contact != NULL, FALSE);
@@ -159,228 +82,24 @@ ebbm_contact_to_object (EMapiConnection *conn,
g_return_val_if_fail (mem_ctx != NULL, FALSE);
g_return_val_if_fail (pobject != NULL, FALSE);
- object = e_mapi_object_new (mem_ctx);
- *pobject = object;
-
- if (GPOINTER_TO_INT (e_contact_get (mcd->contact, E_CONTACT_IS_LIST))) {
- const gchar *uid = NULL;
- EContact *old_contact = NULL;
- GList *local, *l;
- struct BinaryArray_r *members, *oneoff_members;
- uint32_t u32, crc32 = 0;
- GHashTable *member_values = NULL, *member_ids = NULL;
- GError *error = NULL;
-
- uid = e_contact_get_const (mcd->contact, E_CONTACT_UID);
- if (uid)
- old_contact = e_book_backend_sqlitedb_get_contact (mcd->db, EMA_EBB_CACHE_FOLDERID, uid, NULL, NULL, &error);
-
- if (!error && old_contact) {
- member_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- member_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
- local = e_contact_get_attributes (old_contact, E_CONTACT_EMAIL);
- for (l = local; l; l = l->next) {
- EVCardAttribute *attr = l->data;
- GList *param;
-
- if (!attr)
- continue;
-
- param = e_vcard_attribute_get_param (attr, EMA_X_MEMBERVALUE);
- if (param && param->data && !param->next) {
- g_hash_table_insert (member_values, e_vcard_attribute_get_value (attr), g_strdup (param->data));
- }
-
- param = e_vcard_attribute_get_param (attr, EMA_X_MEMBERID);
- if (param && param->data && !param->next) {
- g_hash_table_insert (member_ids, e_vcard_attribute_get_value (attr), GINT_TO_POINTER (atoi (param->data)));
- }
- }
-
- g_object_unref (old_contact);
- g_list_foreach (local, (GFunc)e_vcard_attribute_free, NULL);
- g_list_free (local);
- }
-
- if (error)
- g_error_free (error);
-
- set_value (PidTagMessageClass, IPM_DISTLIST);
- u32 = 0xFFFFFFFF;
- set_value (PidLidFileUnderId, &u32);
- set_con_value (PidLidFileUnder, E_CONTACT_FILE_AS);
- set_con_value (PidLidDistributionListName, E_CONTACT_FILE_AS);
- set_con_value (PidTagDisplayName, E_CONTACT_FILE_AS);
- set_con_value (PidTagNormalizedSubject, E_CONTACT_FILE_AS);
-
- local = e_contact_get_attributes (mcd->contact, E_CONTACT_EMAIL);
- if (member_ids)
- local = g_list_sort_with_data (local, cmp_member_id, member_ids);
-
- members = talloc_zero (mem_ctx, struct BinaryArray_r);
- members->cValues = 0;
- members->lpbin = talloc_zero_array (mem_ctx, struct Binary_r, g_list_length (local));
-
- oneoff_members = talloc_zero (mem_ctx, struct BinaryArray_r);
- oneoff_members->cValues = 0;
- oneoff_members->lpbin = talloc_zero_array (mem_ctx, struct Binary_r, g_list_length (local));
-
- for (l = local; l; l = l->next) {
- EVCardAttribute *attr = (EVCardAttribute *) l->data;
- gchar *raw;
- CamelInternetAddress *addr;
-
- if (!attr)
- continue;
-
- raw = e_vcard_attribute_get_value (attr);
- if (!raw)
- continue;
-
- addr = camel_internet_address_new ();
- if (camel_address_decode (CAMEL_ADDRESS (addr), raw) > 0) {
- const gchar *nm = NULL, *eml = NULL;
-
- camel_internet_address_get (addr, 0, &nm, &eml);
- if (eml) {
- /* keep both lists in sync */
- if (member_values && g_hash_table_lookup (member_values, raw)) {
- /* stored ListMembers values when contact's value didn't change */
- members->lpbin[members->cValues].cb = string_to_bin (mem_ctx, g_hash_table_lookup (member_values, raw), &members->lpbin[members->cValues].lpb);
- members->cValues++;
- } else {
- e_mapi_util_recip_entryid_generate_smtp (mem_ctx, &members->lpbin[members->cValues], nm ? nm : "", eml);
- members->cValues++;
- }
-
- e_mapi_util_recip_entryid_generate_smtp (mem_ctx, &oneoff_members->lpbin[oneoff_members->cValues], nm ? nm : "", eml);
- oneoff_members->cValues++;
-
- crc32 = e_mapi_utils_push_crc32 (crc32, members->lpbin[members->cValues - 1].lpb, members->lpbin[members->cValues - 1].cb);
- }
- }
-
- g_object_unref (addr);
- g_free (raw);
- }
-
- if (member_values)
- g_hash_table_destroy (member_values);
- if (member_ids)
- g_hash_table_destroy (member_ids);
- g_list_foreach (local, (GFunc)e_vcard_attribute_free, NULL);
- g_list_free (local);
-
- set_value (PidLidDistributionListOneOffMembers, oneoff_members);
- set_value (PidLidDistributionListMembers, members);
- set_value (PidLidDistributionListChecksum, &crc32);
-
- return TRUE;
- }
-
- set_value (PidTagMessageClass, IPM_CONTACT);
- set_con_value (PidLidFileUnder, E_CONTACT_FILE_AS);
-
- set_con_value (PidTagDisplayName, E_CONTACT_FULL_NAME);
- set_con_value (PidTagNormalizedSubject, E_CONTACT_FILE_AS);
- set_con_value (PidLidEmail1OriginalDisplayName, E_CONTACT_EMAIL_1);
- /*set_con_value (PidLidEmail1EmailAddress, E_CONTACT_EMAIL_1);*/
-
- /*set_con_value (0x8083001e, E_CONTACT_EMAIL_1);*/
- set_con_value (PidLidEmail2EmailAddress, E_CONTACT_EMAIL_2);
-
- set_con_value (PidLidEmail3EmailAddress, E_CONTACT_EMAIL_3);
- /*set_con_value (PidLidEmail3OriginalDisplayName, E_CONTACT_EMAIL_3);*/
-
- set_con_value (PidLidHtml, E_CONTACT_HOMEPAGE_URL);
- set_con_value (PidLidFreeBusyLocation, E_CONTACT_FREEBUSY_URL);
-
- set_con_value (PidTagBusinessTelephoneNumber, E_CONTACT_PHONE_BUSINESS);
- set_con_value (PidTagHomeTelephoneNumber, E_CONTACT_PHONE_HOME);
- set_con_value (PidTagMobileTelephoneNumber, E_CONTACT_PHONE_MOBILE);
- set_con_value (PidTagHomeFaxNumber, E_CONTACT_PHONE_HOME_FAX);
- set_con_value (PidTagBusinessFaxNumber, E_CONTACT_PHONE_BUSINESS_FAX);
- set_con_value (PidTagPagerTelephoneNumber, E_CONTACT_PHONE_PAGER);
- set_con_value (PidTagAssistantTelephoneNumber, E_CONTACT_PHONE_ASSISTANT);
- set_con_value (PidTagCompanyMainTelephoneNumber, E_CONTACT_PHONE_COMPANY);
-
- set_con_value (PidTagManagerName, E_CONTACT_MANAGER);
- set_con_value (PidTagAssistant, E_CONTACT_ASSISTANT);
- set_con_value (PidTagCompanyName, E_CONTACT_ORG);
- set_con_value (PidTagDepartmentName, E_CONTACT_ORG_UNIT);
- set_con_value (PidTagProfession, E_CONTACT_ROLE);
- set_con_value (PidTagTitle, E_CONTACT_TITLE);
-
- set_con_value (PidTagOfficeLocation, E_CONTACT_OFFICE);
- set_con_value (PidTagSpouseName, E_CONTACT_SPOUSE);
+ uid = e_contact_get_const (mcd->contact, E_CONTACT_UID);
+ if (uid)
+ old_contact = e_book_backend_sqlitedb_get_contact (mcd->db, EMA_EBB_CACHE_FOLDERID, uid, NULL, NULL, &error);
- set_con_value (PidTagBody, E_CONTACT_NOTE);
- set_con_value (PidTagNickname, E_CONTACT_NICKNAME);
-
- /* BDAY AND ANNV */
- if (e_contact_get (mcd->contact, E_CONTACT_BIRTH_DATE)) {
- EContactDate *date = e_contact_get (mcd->contact, E_CONTACT_BIRTH_DATE);
- struct tm tmtime = { 0 };
- struct FILETIME t;
-
- tmtime.tm_mday = date->day;
- tmtime.tm_mon = date->month - 1;
- tmtime.tm_year = date->year - 1900;
-
- e_mapi_util_time_t_to_filetime (mktime (&tmtime) + (24 * 60 * 60), &t);
-
- set_value (PidTagBirthday, &t);
- }
-
- if (e_contact_get (mcd->contact, E_CONTACT_ANNIVERSARY)) {
- EContactDate *date = e_contact_get (mcd->contact, E_CONTACT_ANNIVERSARY);
- struct tm tmtime = { 0 };
- struct FILETIME t;
-
- tmtime.tm_mday = date->day;
- tmtime.tm_mon = date->month - 1;
- tmtime.tm_year = date->year - 1900;
-
- e_mapi_util_time_t_to_filetime (mktime (&tmtime) + (24 * 60 * 60), &t);
-
- set_value (PidTagWeddingAnniversary, &t);
+ if (error) {
+ old_contact = NULL;
+ g_clear_error (&error);
}
- /* Home and Office address */
- if (e_contact_get (mcd->contact, E_CONTACT_ADDRESS_HOME)) {
- EContactAddress *contact_addr = e_contact_get (mcd->contact, E_CONTACT_ADDRESS_HOME);
+ res = e_mapi_book_utils_contact_to_object (mcd->contact, old_contact, pobject, mem_ctx, cancellable, perror);
- set_value (PidLidHomeAddress, contact_addr->street);
- set_value (PidTagHomeAddressPostOfficeBox, contact_addr->ext);
- set_value (PidTagHomeAddressCity, contact_addr->locality);
- set_value (PidTagHomeAddressStateOrProvince, contact_addr->region);
- set_value (PidTagHomeAddressPostalCode, contact_addr->code);
- set_value (PidTagHomeAddressCountry, contact_addr->country);
- }
-
- if (e_contact_get (mcd->contact, E_CONTACT_ADDRESS_WORK)) {
- EContactAddress *contact_addr = e_contact_get (mcd->contact, E_CONTACT_ADDRESS_WORK);
+ if (old_contact)
+ g_object_unref (old_contact);
- set_value (PidLidWorkAddress, contact_addr->street);
- set_value (PidTagPostOfficeBox, contact_addr->ext);
- set_value (PidTagLocality, contact_addr->locality);
- set_value (PidTagStateOrProvince, contact_addr->region);
- set_value (PidTagPostalCode, contact_addr->code);
- set_value (PidTagCountry, contact_addr->country);
- }
-
- if (e_contact_get (mcd->contact, E_CONTACT_IM_AIM)) {
- GList *l = e_contact_get (mcd->contact, E_CONTACT_IM_AIM);
- set_value (PidLidInstantMessagingAddress, l->data);
- }
-
- #undef set_value
-
- return TRUE;
+ return res;
}
-struct FetchContactItemData
+struct TransferContactData
{
EBookBackendMAPI *ebma;
EContact *contact; /* out */
@@ -396,34 +115,15 @@ transfer_contact_cb (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror)
{
- struct FetchContactItemData *fcid = user_data;
+ struct TransferContactData *tc = user_data;
- g_return_val_if_fail (fcid != NULL, FALSE);
- g_return_val_if_fail (fcid->ebma != NULL, FALSE);
+ g_return_val_if_fail (tc != NULL, FALSE);
+ g_return_val_if_fail (tc->ebma != NULL, FALSE);
g_return_val_if_fail (object != NULL, FALSE);
- fcid->contact = mapi_book_utils_contact_from_props (conn, E_BOOK_BACKEND_MAPI_CONTACTS (fcid->ebma)->priv->fid, e_book_backend_mapi_get_book_uri (fcid->ebma), &object->properties, NULL);
-
- if (fcid->contact) {
- const mapi_id_t *pmid;
-
- pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
- if (pmid) {
- gchar *suid = e_mapi_util_mapi_id_to_string (*pmid);
-
- /* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
- e_contact_set (fcid->contact, E_CONTACT_UID, suid);
-
- if (!e_book_backend_mapi_notify_contact_update (fcid->ebma, NULL, fcid->contact, obj_index, obj_total, NULL)) {
- g_free (suid);
- return FALSE;
- }
-
- g_free (suid);
- } else {
- g_debug ("%s: No PidTagMid found", G_STRFUNC);
- }
- }
+ tc->contact = e_mapi_book_utils_contact_from_object (conn, object, e_book_backend_mapi_get_book_uri (tc->ebma));
+ if (tc->contact)
+ return e_book_backend_mapi_notify_contact_update (tc->ebma, NULL, tc->contact, obj_index, obj_total, NULL);
return TRUE;
}
@@ -477,29 +177,17 @@ transfer_contacts_cb (EMapiConnection *conn,
g_return_val_if_fail (object != NULL, FALSE);
g_return_val_if_fail (tcd->ebma != NULL, FALSE);
- contact = mapi_book_utils_contact_from_props (conn, E_BOOK_BACKEND_MAPI_CONTACTS (tcd->ebma)->priv->fid, e_book_backend_mapi_get_book_uri (tcd->ebma), &object->properties, NULL);
+ contact = e_mapi_book_utils_contact_from_object (conn, object, e_book_backend_mapi_get_book_uri (tcd->ebma));
if (contact) {
- const mapi_id_t *pmid;
-
- pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
- if (pmid) {
- gchar *suid = e_mapi_util_mapi_id_to_string (*pmid);
-
- e_contact_set (contact, E_CONTACT_UID, suid);
- g_free (suid);
-
- if (tcd->cards)
- *tcd->cards = g_slist_prepend (*tcd->cards, e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30));
-
- if (!e_book_backend_mapi_notify_contact_update (tcd->ebma, tcd->book_view, contact, obj_index, obj_total, tcd->notify_contact_data)) {
- g_object_unref (contact);
- return FALSE;
- }
+ if (tcd->cards)
+ *tcd->cards = g_slist_prepend (*tcd->cards, e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30));
+ if (!e_book_backend_mapi_notify_contact_update (tcd->ebma, tcd->book_view, contact, obj_index, obj_total, tcd->notify_contact_data)) {
g_object_unref (contact);
- } else {
- g_debug ("%s: No PidTagMid found", G_STRFUNC);
+ return FALSE;
}
+
+ g_object_unref (contact);
} else {
g_debug ("%s: [%d/%d] Failed to transform to contact", G_STRFUNC, obj_index, obj_total);
}
@@ -525,7 +213,7 @@ gather_known_uids_cb (EMapiConnection *conn,
suid = e_mapi_util_mapi_id_to_string (object_data->mid);
if (suid) {
- g_hash_table_insert (lku->uid_to_rev, suid, mapi_book_utils_timet_to_string (object_data->last_modified));
+ g_hash_table_insert (lku->uid_to_rev, suid, e_mapi_book_utils_timet_to_string (object_data->last_modified));
if (lku->latest_last_modify < object_data->last_modified)
lku->latest_last_modify = object_data->last_modified;
}
@@ -597,7 +285,8 @@ ebbmc_server_notification_cb (EMapiConnection *conn,
}
priv = ((EBookBackendMAPIContacts *) ebma)->priv;
- if (priv->fid == update_folder1 || priv->fid == update_folder2)
+ if ((priv->fid == update_folder1 || priv->fid == update_folder2) &&
+ e_book_backend_mapi_is_marked_for_offline (ebma))
e_book_backend_mapi_refresh_cache (ebma);
}
@@ -947,7 +636,7 @@ ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, co
EMapiConnection *conn;
mapi_id_t mid;
mapi_object_t obj_folder;
- struct FetchContactItemData fcid = { 0 };
+ struct TransferContactData tc = { 0 };
gboolean status;
GError *mapi_error = NULL;
@@ -996,17 +685,17 @@ ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, co
}
if (status) {
- fcid.ebma = ebma;
- fcid.contact = NULL;
+ tc.ebma = ebma;
+ tc.contact = NULL;
- e_mapi_connection_transfer_object (conn, &obj_folder, mid, transfer_contact_cb, &fcid, cancellable, &mapi_error);
+ e_mapi_connection_transfer_object (conn, &obj_folder, mid, transfer_contact_cb, &tc, cancellable, &mapi_error);
}
e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- if (fcid.contact) {
- *vcard = e_vcard_to_string (E_VCARD (fcid.contact), EVC_FORMAT_VCARD_30);
- g_object_unref (fcid.contact);
+ if (tc.contact) {
+ *vcard = e_vcard_to_string (E_VCARD (tc.contact), EVC_FORMAT_VCARD_30);
+ g_object_unref (tc.contact);
} else {
if (!mapi_error || mapi_error->code == MAPI_E_NOT_FOUND) {
g_propagate_error (error, EDB_ERROR (CONTACT_NOT_FOUND));
@@ -1076,7 +765,7 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
if (status) {
status = e_mapi_connection_list_objects (conn, &obj_folder,
- build_restriction_from_sexp_query, (gpointer) query,
+ e_mapi_book_utils_build_sexp_restriction, (gpointer) query,
gather_contact_mids_cb, &mids,
cancellable, &mapi_error);
diff --git a/src/addressbook/e-book-backend-mapi-gal.c b/src/addressbook/e-book-backend-mapi-gal.c
index da4ac39..1b1990d 100644
--- a/src/addressbook/e-book-backend-mapi-gal.c
+++ b/src/addressbook/e-book-backend-mapi-gal.c
@@ -1,3 +1,26 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Bharath Acharya <abharath novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -21,6 +44,9 @@
#include "e-book-backend-mapi-gal.h"
+/* default value for "partial-count", upper bound of objects to download during partial search */
+#define DEFAULT_PARTIAL_COUNT 50
+
G_DEFINE_TYPE (EBookBackendMAPIGAL, e_book_backend_mapi_gal, E_TYPE_BOOK_BACKEND_MAPI)
struct _EBookBackendMAPIGALPrivate
@@ -31,68 +57,37 @@ struct _EBookBackendMAPIGALPrivate
gint32 unused;
};
-static gchar *
-get_uid_from_row (struct SRow *aRow, uint32_t row_index)
-{
- gchar *suid = NULL;
- const gchar *str;
-
- g_return_val_if_fail (aRow != NULL, NULL);
-
- str = e_mapi_util_find_row_propval (aRow, PR_EMAIL_ADDRESS_UNICODE);
- if (str && *str)
- suid = g_strdup (str);
-
- if (!suid) {
- const mapi_id_t *midptr;
-
- midptr = e_mapi_util_find_row_propval (aRow, PR_MID);
-
- suid = e_mapi_util_mapi_id_to_string (midptr ? *midptr : row_index);
- }
-
- return suid;
-}
-
-struct FetchGalData
+struct TransferGalData
{
EBookBackendMAPI *ebma;
EDataBookView *book_view;
gpointer notify_contact_data;
- mapi_id_t fid; /* folder ID of contacts, for named IDs */
};
static gboolean
-fetch_gal_cb (EMapiConnection *conn,
- uint32_t row_index,
- uint32_t n_rows,
- struct SRow *aRow,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
+transfer_gal_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- struct FetchGalData *fgd = data;
+ struct TransferGalData *tg = user_data;
EContact *contact;
g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (aRow != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (tg != NULL, FALSE);
- contact = mapi_book_utils_contact_from_props (conn, fgd->fid, e_book_backend_mapi_get_book_uri (fgd->ebma), NULL, aRow);
+ contact = e_mapi_book_utils_contact_from_object (conn, object, e_book_backend_mapi_get_book_uri (tg->ebma));
if (!contact) {
- /* just ignore them */
+ /* this is GAL, just ignore them */
return TRUE;
}
- if (!e_contact_get_const (contact, E_CONTACT_UID)) {
- gchar *suid;
-
- suid = get_uid_from_row (aRow, row_index);
- e_contact_set (contact, E_CONTACT_UID, suid);
- g_free (suid);
- }
-
- if (!e_book_backend_mapi_notify_contact_update (fgd->ebma, fgd->book_view, contact, row_index, n_rows, fgd->notify_contact_data)) {
+ if (!e_book_backend_mapi_notify_contact_update (tg->ebma, tg->book_view, contact, obj_index, obj_total, tg->notify_contact_data)) {
g_object_unref (contact);
return FALSE;
}
@@ -104,9 +99,10 @@ fetch_gal_cb (EMapiConnection *conn,
static gboolean
list_gal_uids_cb (EMapiConnection *conn,
- uint32_t row_index,
- uint32_t n_rows,
- struct SRow *aRow,
+ TALLOC_CTX *mem_ctx,
+ const ListObjectsData *object_data,
+ guint32 obj_index,
+ guint32 obj_total,
gpointer user_data,
GCancellable *cancellable,
GError **perror)
@@ -115,24 +111,18 @@ list_gal_uids_cb (EMapiConnection *conn,
struct ListKnownUidsData *lku = user_data;
g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (aRow != NULL, FALSE);
+ g_return_val_if_fail (object_data != NULL, FALSE);
g_return_val_if_fail (lku != NULL, FALSE);
- uid = get_uid_from_row (aRow, row_index);
+ uid = e_mapi_util_mapi_id_to_string (object_data->mid);
if (uid) {
- const struct FILETIME *ft;
- time_t tt;
+ if (lku->latest_last_modify < object_data->last_modified)
+ lku->latest_last_modify = object_data->last_modified;
- ft = e_mapi_util_find_row_propval (aRow, PidTagLastModificationTime);
- tt = ft ? e_mapi_util_filetime_to_time_t (ft) : 1;
-
- if (lku->latest_last_modify < tt)
- lku->latest_last_modify = tt;
-
- g_hash_table_insert (lku->uid_to_rev, uid, mapi_book_utils_timet_to_string (tt));
+ g_hash_table_insert (lku->uid_to_rev, uid, e_mapi_book_utils_timet_to_string (object_data->last_modified));
}
- return !g_cancellable_is_cancelled (cancellable);
+ return TRUE;
}
static void
@@ -180,10 +170,13 @@ ebbm_gal_transfer_contacts (EBookBackendMAPI *ebma,
GError **error)
{
GError *mapi_error = NULL;
- struct FetchGalData fgd = { 0 };
+ struct TransferGalData tg = { 0 };
EMapiConnection *conn;
- gchar *last_fetch;
- gboolean fetch_successful;
+ ESource *source;
+ GSList *get_mids = NULL;
+ const GSList *iter;
+ gint partial_count = -1;
+ gboolean status;
e_book_backend_mapi_lock_connection (ebma);
@@ -194,50 +187,47 @@ ebbm_gal_transfer_contacts (EBookBackendMAPI *ebma,
return;
}
- /* GAL doesn't use restrictions yet, thus just fetches all items always */
- last_fetch = e_book_backend_mapi_cache_get (ebma, "gal-last-update");
- if (last_fetch) {
- GTimeVal last_tv = { 0 }, now = { 0 };
+ source = e_backend_get_source (E_BACKEND (ebma));
+ if (source && g_strcmp0 (e_source_get_property (source, "allow-partial"), "true") == 0) {
+ const gchar *partial_count_str = e_source_get_property (source, "partial-count");
- g_get_current_time (&now);
+ partial_count = 0;
+ if (partial_count_str)
+ partial_count = atoi (partial_count_str);
- /* refetch gal only once per week */
- if (g_time_val_from_iso8601 (last_fetch, &last_tv) && now.tv_sec - last_tv.tv_sec <= 60 * 60 * 24 * 7) {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
- g_free (last_fetch);
- e_book_backend_mapi_unlock_connection (ebma);
- return;
- }
+ if (partial_count <= 0)
+ partial_count = DEFAULT_PARTIAL_COUNT;
+ }
- g_free (last_fetch);
+ for (iter = uids; iter && (partial_count == -1 || partial_count > 0); iter = iter->next) {
+ mapi_id_t *pmid, mid;
+
+ if (e_mapi_util_mapi_id_from_string (iter->data, &mid)) {
+ pmid = g_new0 (mapi_id_t, 1);
+ *pmid = mid;
+
+ get_mids = g_slist_prepend (get_mids, pmid);
+
+ if (partial_count > 0)
+ partial_count--;
+ }
}
- fgd.ebma = ebma;
- fgd.book_view = book_view;
- fgd.notify_contact_data = notify_contact_data;
- fgd.fid = e_mapi_connection_get_default_folder_id (conn, olFolderContacts, NULL, NULL);
+ tg.ebma = ebma;
+ tg.book_view = book_view;
+ tg.notify_contact_data = notify_contact_data;
- fetch_successful = e_mapi_connection_fetch_gal (conn, NULL, NULL,
- mapi_book_utils_get_prop_list, GET_ALL_KNOWN_IDS,
- fetch_gal_cb, &fgd, NULL, &mapi_error);
+ status = e_mapi_connection_transfer_gal_objects (conn, get_mids, transfer_gal_cb, &tg, cancellable, &mapi_error);
if (mapi_error) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to fetch GAL entries"));
g_error_free (mapi_error);
- } else if (!fetch_successful) {
+ } else if (!status) {
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
- } else {
- GTimeVal now = { 0 };
-
- g_get_current_time (&now);
-
- last_fetch = g_time_val_to_iso8601 (&now);
- if (last_fetch && *last_fetch)
- e_book_backend_mapi_cache_set (ebma, "gal-last-update", last_fetch);
-
- g_free (last_fetch);
}
+ g_slist_free_full (get_mids, g_free);
+
e_book_backend_mapi_unlock_connection (ebma);
}
@@ -247,11 +237,24 @@ ebbm_gal_get_contacts_count (EBookBackendMAPI *ebma,
GCancellable *cancellable,
GError **error)
{
+ EMapiConnection *conn;
+
e_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (obj_total != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- /* just a fake value, to check by ids */
- *obj_total = -1;
+ e_book_backend_mapi_lock_connection (ebma);
+
+ conn = e_book_backend_mapi_get_connection (ebma);
+ if (!conn) {
+ e_book_backend_mapi_unlock_connection (ebma);
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ return;
+ }
+
+ if (!e_mapi_connection_count_gal_objects (conn, obj_total, cancellable, error))
+ *obj_total = -1;
+
+ e_book_backend_mapi_unlock_connection (ebma);
}
static void
@@ -278,9 +281,7 @@ ebbm_gal_list_known_uids (EBookBackendMAPI *ebma,
return;
}
- e_mapi_connection_fetch_gal (conn, NULL, NULL,
- mapi_book_utils_get_prop_list, GET_UIDS_ONLY,
- list_gal_uids_cb, lku, cancellable, &mapi_error);
+ e_mapi_connection_list_gal_objects (conn, build_rs_cb, build_rs_cb_data, list_gal_uids_cb, lku, cancellable, &mapi_error);
if (mapi_error) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to fetch GAL entries"));
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index a63fbe8..08bdc50 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -34,7 +34,6 @@
#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>
@@ -61,73 +60,14 @@ struct _EBookBackendMAPIPrivate
time_t last_update_cache;
EBookBackendSqliteDB *db;
- GHashTable *running_book_views;
guint32 last_server_contact_count;
time_t last_modify_time;
gboolean server_dirty;
-};
-
-#define ELEMENT_TYPE_MASK 0xF /* mask where the real type of the element is stored */
-
-#define ELEMENT_TYPE_SIMPLE 0x01
-#define ELEMENT_TYPE_COMPLEX 0x02
-
-#define ELEMENT_TYPE_NAMEDID 0x10
-
-static const struct field_element_mapping {
- EContactField field_id;
- uint32_t element_type;
- uint32_t mapi_id;
- gint contact_type;
- } mappings [] = {
-
- { E_CONTACT_UID, PT_UNICODE, PR_EMAIL_ADDRESS_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_REV, PT_SYSTIME, PR_LAST_MODIFICATION_TIME, ELEMENT_TYPE_SIMPLE},
-
- { E_CONTACT_FILE_AS, PT_UNICODE, PidLidFileUnder, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_FULL_NAME, PT_UNICODE, PR_DISPLAY_NAME_UNICODE, ELEMENT_TYPE_SIMPLE },
- { E_CONTACT_GIVEN_NAME, PT_UNICODE, PR_GIVEN_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_FAMILY_NAME, PT_UNICODE, PR_SURNAME_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_NICKNAME, PT_UNICODE, PR_NICKNAME_UNICODE, ELEMENT_TYPE_SIMPLE },
-
- { E_CONTACT_EMAIL_1, PT_UNICODE, PidLidEmail1OriginalDisplayName, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_EMAIL_2, PT_UNICODE, PidLidEmail2EmailAddress, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_EMAIL_3, PT_UNICODE, PidLidEmail3EmailAddress, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_IM_AIM, PT_UNICODE, PidLidInstantMessagingAddress, ELEMENT_TYPE_COMPLEX | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_PHONE_BUSINESS, PT_UNICODE, PR_OFFICE_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_HOME, PT_UNICODE, PR_HOME_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_MOBILE, PT_UNICODE, PR_MOBILE_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_HOME_FAX, PT_UNICODE, PR_HOME_FAX_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_BUSINESS_FAX, PT_UNICODE, PR_BUSINESS_FAX_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_PAGER, PT_UNICODE, PR_PAGER_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_ASSISTANT, PT_UNICODE, PR_ASSISTANT_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_PHONE_COMPANY, PT_UNICODE, PR_COMPANY_MAIN_PHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-
- { E_CONTACT_HOMEPAGE_URL, PT_UNICODE, PidLidHtml, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_FREEBUSY_URL, PT_UNICODE, PidLidFreeBusyLocation, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
-
- { E_CONTACT_ROLE, PT_UNICODE, PR_PROFESSION_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_TITLE, PT_UNICODE, PR_TITLE_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_ORG, PT_UNICODE, PR_COMPANY_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_ORG_UNIT, PT_UNICODE, PR_DEPARTMENT_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_MANAGER, PT_UNICODE, PR_MANAGER_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_ASSISTANT, PT_UNICODE, PR_ASSISTANT_UNICODE, ELEMENT_TYPE_SIMPLE},
-
- { E_CONTACT_OFFICE, PT_UNICODE, PR_OFFICE_LOCATION_UNICODE, ELEMENT_TYPE_SIMPLE},
- { E_CONTACT_SPOUSE, PT_UNICODE, PR_SPOUSE_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-
- { E_CONTACT_BIRTH_DATE, PT_SYSTIME, PR_BIRTHDAY, ELEMENT_TYPE_COMPLEX},
- { E_CONTACT_ANNIVERSARY, PT_SYSTIME, PR_WEDDING_ANNIVERSARY, ELEMENT_TYPE_COMPLEX},
-
- { E_CONTACT_NOTE, PT_UNICODE, PR_BODY_UNICODE, ELEMENT_TYPE_SIMPLE},
-
- { E_CONTACT_ADDRESS_HOME, PT_UNICODE, PidLidHomeAddress, ELEMENT_TYPE_COMPLEX | ELEMENT_TYPE_NAMEDID},
- { E_CONTACT_ADDRESS_WORK, PT_UNICODE, PidLidOtherAddress, ELEMENT_TYPE_COMPLEX | ELEMENT_TYPE_NAMEDID}
- /* { E_CONTACT_BOOK_URI, ELEMENT_TYPE_SIMPLE, "book_uri"}, */
- /* { E_CONTACT_CATEGORIES, } */
- };
+ GHashTable *running_views; /* EDataBookView => GCancellable */
+ GMutex *running_views_lock;
+};
static gboolean
pick_view_cb (EDataBookView *view, gpointer user_data)
@@ -236,7 +176,6 @@ ebbm_update_cache_cb (gpointer data)
ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (ebma);
g_return_val_if_fail (ebmac != NULL, NULL);
-
cancellable = priv->update_cache;
g_cancellable_reset (cancellable);
@@ -414,7 +353,7 @@ ebbm_connect_user (EBookBackendMAPI *ebma, GCancellable *cancellable, const gcha
ebbm_notify_connection_status (ebma, TRUE);
- if (!g_cancellable_is_cancelled (cancellable) /* && priv->marked_for_offline */) {
+ if (!g_cancellable_is_cancelled (cancellable) && priv->marked_for_offline) {
ebbm_maybe_invoke_cache_update (ebma);
}
}
@@ -535,18 +474,14 @@ ebbm_get_backend_property (EBookBackendMAPI *ebma, const gchar *prop_name, gchar
g_return_val_if_fail (prop_value != NULL, FALSE);
if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
- *prop_value = g_strdup ("net,bulk-removes,do-initial-query,contact-lists");
+ if (e_book_backend_mapi_is_marked_for_offline (ebma))
+ *prop_value = g_strdup ("net,bulk-removes,contact-lists,do-initial-query");
+ else
+ *prop_value = g_strdup ("net,bulk-removes,contact-lists");
} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
*prop_value = g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
- gint ii;
- GSList *fields = NULL;
-
- for (ii = 0; ii < G_N_ELEMENTS (mappings); ii++) {
- fields = g_slist_append (fields, (gpointer) e_contact_field_name (mappings[ii].field_id));
- }
-
- fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_BOOK_URI));
+ GSList *fields = e_mapi_book_utils_get_supported_contact_fields ();
*prop_value = e_data_book_string_slist_to_comma_string (fields);
@@ -686,6 +621,7 @@ struct BookViewThreadData
{
EBookBackendMAPI *ebma;
EDataBookView *book_view;
+ GCancellable *cancellable;
};
static gpointer
@@ -693,18 +629,20 @@ ebbm_book_view_thread (gpointer data)
{
struct BookViewThreadData *bvtd = data;
EBookBackendMAPIPrivate *priv;
+ EBookBackendMAPIClass *ebmac;
GError *error = NULL;
g_return_val_if_fail (bvtd != NULL, NULL);
g_return_val_if_fail (bvtd->ebma != NULL, NULL);
g_return_val_if_fail (bvtd->book_view != NULL, NULL);
+ ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (bvtd->ebma);
+ g_return_val_if_fail (ebmac != NULL, NULL);
+
priv = bvtd->ebma->priv;
e_data_book_view_notify_progress (bvtd->book_view, -1, _("Searching"));
- e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
-
if (!error && priv && priv->conn && (!priv->update_cache_thread || g_cancellable_is_cancelled (priv->update_cache))
&& e_book_backend_mapi_book_view_is_running (bvtd->ebma, bvtd->book_view)) {
EBookBackendMAPIClass *ebmac;
@@ -713,7 +651,61 @@ ebbm_book_view_thread (gpointer data)
if (ebmac && ebmac->op_book_view_thread)
ebmac->op_book_view_thread (bvtd->ebma, bvtd->book_view, priv->update_cache, &error);
- ebbm_maybe_invoke_cache_update (bvtd->ebma);
+ if (priv->marked_for_offline) {
+ e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
+
+ ebbm_maybe_invoke_cache_update (bvtd->ebma);
+
+ e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
+ } else if (ebmac->op_list_known_uids && ebmac->op_transfer_contacts) {
+ const gchar *sexp = e_data_book_view_get_card_query (bvtd->book_view);
+
+ /* search only if not searching for everything */
+ if (sexp && *sexp && g_ascii_strcasecmp (sexp, "(contains \"x-evolution-any-field\" \"\")") != 0) {
+ struct ListKnownUidsData lku = { 0 };
+ GHashTable *local_known_uids, *server_known_uids;
+
+ e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
+
+ local_known_uids = e_book_backend_sqlitedb_get_uids_and_rev (priv->db, EMA_EBB_CACHE_FOLDERID, &error);
+ server_known_uids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ lku.uid_to_rev = server_known_uids;
+ lku.latest_last_modify = 0;
+
+ ebmac->op_list_known_uids (bvtd->ebma, e_mapi_book_utils_build_sexp_restriction, (gpointer) sexp, &lku, bvtd->cancellable, &error);
+
+ if (!g_cancellable_is_cancelled (bvtd->cancellable)) {
+ GSList *uids = NULL;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, server_known_uids);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ const gchar *uid = key, *rev = value, *local_rev;
+
+ local_rev = g_hash_table_lookup (local_known_uids, uid);
+ if (g_strcmp0 (local_rev, rev) != 0) {
+ uids = g_slist_prepend (uids, (gpointer) uid);
+ }
+
+ g_hash_table_remove (local_known_uids, uid);
+ }
+
+ if (uids) {
+ ebbm_transfer_contacts (bvtd->ebma, uids, NULL, bvtd->cancellable, &error);
+ e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
+ }
+
+ /* has borrowed data from server_known_uids */
+ g_slist_free (uids);
+ }
+
+ g_hash_table_destroy (server_known_uids);
+ if (local_known_uids)
+ g_hash_table_destroy (local_known_uids);
+ }
+ }
}
if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@@ -727,6 +719,8 @@ ebbm_book_view_thread (gpointer data)
if (error)
g_error_free (error);
+ if (bvtd->cancellable)
+ g_object_unref (bvtd->cancellable);
g_object_unref (bvtd->book_view);
/* May unref it out of the thread, in case it's the last reference to it */
g_idle_add (unref_backend_idle_cb, bvtd->ebma);
@@ -960,8 +954,16 @@ ebbm_operation_cb (OperationBase *op, gboolean cancelled, EBookBackend *backend)
GError *err = NULL;
struct BookViewThreadData *bvtd = g_new0 (struct BookViewThreadData, 1);
+ g_mutex_lock (ebma->priv->running_views_lock);
+
bvtd->ebma = g_object_ref (ebma);
bvtd->book_view = g_object_ref (opbv->book_view);
+ bvtd->cancellable = g_hash_table_lookup (ebma->priv->running_views, bvtd->book_view);
+
+ if (bvtd->cancellable)
+ g_object_ref (bvtd->cancellable);
+
+ g_mutex_unlock (ebma->priv->running_views_lock);
g_thread_create (ebbm_book_view_thread, bvtd, FALSE, &err);
@@ -1200,7 +1202,9 @@ ebbm_op_start_book_view (EBookBackend *backend, EDataBookView *book_view)
op->base.opid = 0;
op->book_view = g_object_ref (book_view);
- g_hash_table_insert (priv->running_book_views, book_view, GINT_TO_POINTER(1));
+ g_mutex_lock (priv->running_views_lock);
+ g_hash_table_insert (priv->running_views, book_view, g_cancellable_new ());
+ g_mutex_unlock (priv->running_views_lock);
e_mapi_operation_queue_push (priv->op_queue, op);
}
@@ -1211,6 +1215,7 @@ ebbm_op_stop_book_view (EBookBackend *backend, EDataBookView *book_view)
OperationBookView *op;
EBookBackendMAPI *ebbm;
EBookBackendMAPIPrivate *priv;
+ GCancellable *cancellable;
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (backend));
@@ -1228,7 +1233,12 @@ ebbm_op_stop_book_view (EBookBackend *backend, EDataBookView *book_view)
op->base.opid = 0;
op->book_view = g_object_ref (book_view);
- g_hash_table_remove (priv->running_book_views, book_view);
+ g_mutex_lock (priv->running_views_lock);
+ cancellable = g_hash_table_lookup (priv->running_views, book_view);
+ if (cancellable)
+ g_cancellable_cancel (cancellable);
+ g_hash_table_remove (priv->running_views, book_view);
+ g_mutex_unlock (priv->running_views_lock);
e_mapi_operation_queue_push (priv->op_queue, op);
}
@@ -1268,7 +1278,8 @@ e_book_backend_mapi_init (EBookBackendMAPI *ebma)
ebma->priv = G_TYPE_INSTANCE_GET_PRIVATE (ebma, E_TYPE_BOOK_BACKEND_MAPI, EBookBackendMAPIPrivate);
ebma->priv->op_queue = e_mapi_operation_queue_new ((EMapiOperationQueueFunc) ebbm_operation_cb, ebma);
- ebma->priv->running_book_views = g_hash_table_new (g_direct_hash, g_direct_equal);
+ ebma->priv->running_views = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ ebma->priv->running_views_lock = g_mutex_new ();
ebma->priv->conn_lock = g_mutex_new ();
ebma->priv->update_cache = g_cancellable_new ();
@@ -1309,7 +1320,8 @@ ebbm_dispose (GObject *object)
FREE (priv->profile);
FREE (priv->book_uri);
- g_hash_table_destroy (priv->running_book_views);
+ g_hash_table_destroy (priv->running_views);
+ g_mutex_free (priv->running_views_lock);
g_mutex_free (priv->conn_lock);
#undef UNREF
@@ -1424,10 +1436,16 @@ e_book_backend_mapi_get_db (EBookBackendMAPI *ebma, EBookBackendSqliteDB **db)
gboolean
e_book_backend_mapi_book_view_is_running (EBookBackendMAPI *ebma, EDataBookView *book_view)
{
+ gboolean res;
+
g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
g_return_val_if_fail (ebma->priv != NULL, FALSE);
- return g_hash_table_lookup (ebma->priv->running_book_views, book_view) != NULL;
+ g_mutex_lock (ebma->priv->running_views_lock);
+ res = g_hash_table_lookup (ebma->priv->running_views, book_view) != NULL;
+ g_mutex_unlock (ebma->priv->running_views_lock);
+
+ return res;
}
gboolean
@@ -1615,344 +1633,6 @@ e_book_backend_mapi_refresh_cache (EBookBackendMAPI *ebma)
/* utility functions/macros */
-/* 'data' is one of GET_ALL_KNOWN_IDS or GET_UIDS_ONLY */
-gboolean
-mapi_book_utils_get_prop_list (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
-{
- /* this is a list of all known book MAPI tag IDs;
- if you add new add it here too, otherwise it may not be fetched */
- static uint32_t known_book_mapi_ids[] = {
- PR_ASSISTANT_TELEPHONE_NUMBER_UNICODE,
- PR_ASSISTANT_UNICODE,
- PR_BIRTHDAY,
- PR_BODY,
- PR_BODY_UNICODE,
- PR_BUSINESS_FAX_NUMBER_UNICODE,
- PR_COMPANY_MAIN_PHONE_NUMBER_UNICODE,
- PR_COMPANY_NAME_UNICODE,
- PR_COUNTRY_UNICODE,
- PR_DEPARTMENT_NAME_UNICODE,
- PR_DISPLAY_NAME_UNICODE,
- PR_EMAIL_ADDRESS_UNICODE,
- PR_SMTP_ADDRESS_UNICODE, /* used in GAL */
- PR_FID,
- PR_GIVEN_NAME_UNICODE,
- PR_HASATTACH,
- PR_HOME_ADDRESS_CITY_UNICODE,
- PR_HOME_ADDRESS_COUNTRY_UNICODE,
- PR_HOME_ADDRESS_POSTAL_CODE_UNICODE,
- PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE,
- PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE,
- PR_HOME_FAX_NUMBER_UNICODE,
- PR_HOME_TELEPHONE_NUMBER_UNICODE,
- PR_INSTANCE_NUM,
- PR_INST_ID,
- PR_LAST_MODIFICATION_TIME,
- PR_LOCALITY_UNICODE,
- PR_MANAGER_NAME_UNICODE,
- PR_MESSAGE_CLASS,
- PR_MID,
- PR_MOBILE_TELEPHONE_NUMBER_UNICODE,
- PR_NICKNAME_UNICODE,
- PR_NORMALIZED_SUBJECT_UNICODE,
- PR_OFFICE_LOCATION_UNICODE,
- PR_OFFICE_TELEPHONE_NUMBER_UNICODE,
- PR_PAGER_TELEPHONE_NUMBER_UNICODE,
- PR_POSTAL_CODE_UNICODE,
- PR_POST_OFFICE_BOX_UNICODE,
- PR_PROFESSION_UNICODE,
- PR_RULE_MSG_NAME,
- PR_RULE_MSG_PROVIDER,
- PR_SPOUSE_NAME_UNICODE,
- PR_STATE_OR_PROVINCE_UNICODE,
- PR_SUBJECT_UNICODE,
- PR_SURNAME_UNICODE,
- PR_TITLE_UNICODE,
- PR_WEDDING_ANNIVERSARY,
- PROP_TAG(PT_UNICODE, 0x801f)
- };
-
- static uint32_t uids_only_ids[] = {
- PidTagFolderId,
- PidTagMid,
- PidTagLastModificationTime,
- PidTagEmailAddress
- };
-
- /* do not make this array static, the function modifies it on run */
- ResolveNamedIDsData nids[] = {
- { PidLidDistributionListName, 0 },
- { PidLidDistributionListOneOffMembers, 0 },
- { PidLidDistributionListMembers, 0 },
- { PidLidDistributionListChecksum, 0 },
-
- { PidLidFileUnder, 0 },
-
- { PidLidEmail1OriginalDisplayName, 0 },
- { PidLidEmail2OriginalDisplayName, 0 },
- { PidLidEmail3OriginalDisplayName, 0 },
- { PidLidInstantMessagingAddress, 0 },
- { PidLidHtml, 0 },
- { PidLidFreeBusyLocation, 0 }
- };
-
- g_return_val_if_fail (props != NULL, FALSE);
-
- if (data == GET_UIDS_ONLY)
- return e_mapi_utils_add_props_to_props_array (mem_ctx, props, uids_only_ids, G_N_ELEMENTS (uids_only_ids));
-
- if (data == GET_ALL_KNOWN_IDS && !e_mapi_utils_add_props_to_props_array (mem_ctx, props, known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids)))
- return FALSE;
-
- /* called with fid = 0 from GAL */
- if (!fid)
- fid = e_mapi_connection_get_default_folder_id (conn, olFolderContacts, cancellable, NULL);
-
- return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-static gchar *
-bin_to_string (const uint8_t *lpb, uint32_t cb)
-{
- gchar *res, *p;
- uint32_t i;
-
- g_return_val_if_fail (lpb != NULL, NULL);
- g_return_val_if_fail (cb > 0, NULL);
-
- res = g_new0 (gchar, cb * 2 + 1);
- for (i = 0, p = res; i < cb; i++, p += 2) {
- sprintf (p, "%02x", lpb[i] & 0xFF);
- }
-
- return res;
-}
-
-static const gchar *
-not_null (gconstpointer ptr)
-{
- return ptr ? (const gchar *) ptr : "";
-}
-
-/* This is not setting E_CONTACT_UID */
-EContact *
-mapi_book_utils_contact_from_props (EMapiConnection *conn, mapi_id_t fid, const gchar *book_uri, struct mapi_SPropValue_array *mapi_properties, struct SRow *aRow)
-{
- EContact *contact = e_contact_new ();
- gint i;
-
- if (book_uri)
- e_contact_set (contact, E_CONTACT_BOOK_URI, book_uri);
-
- #define get_proptag(proptag) (aRow ? e_mapi_util_find_row_propval (aRow, proptag) : e_mapi_util_find_array_propval (mapi_properties, proptag))
- #define get_str_proptag(proptag) not_null (get_proptag (proptag))
- #define get_namedid(nid) (aRow ? e_mapi_util_find_row_namedid (aRow, conn, fid, nid) : e_mapi_util_find_array_namedid (mapi_properties, conn, fid, nid))
- #define get_str_namedid(nid) not_null (get_namedid (nid))
-
- if (g_str_equal (get_str_proptag (PR_MESSAGE_CLASS), IPM_DISTLIST)) {
- const struct mapi_SBinaryArray *members, *members_dlist;
- const struct FILETIME *last_modification;
- GSList *attrs = NULL, *a;
- gint i;
-
- last_modification = get_proptag (PidTagLastModificationTime);
- if (last_modification) {
- gchar *buff = NULL;
-
- buff = mapi_book_utils_timet_to_string (e_mapi_util_filetime_to_time_t (last_modification));
- if (buff)
- e_contact_set (contact, E_CONTACT_REV, buff);
-
- g_free (buff);
- }
-
- /* it's a contact list/distribution list, fetch members and return it */
- e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE));
- /* we do not support this option, same as GroupWise */
- e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (TRUE));
-
- e_contact_set (contact, E_CONTACT_FILE_AS, get_str_namedid (PidLidDistributionListName));
-
- members = get_namedid (PidLidDistributionListOneOffMembers);
- members_dlist = get_namedid (PidLidDistributionListMembers);
-
- g_return_val_if_fail (members != NULL, NULL);
- g_return_val_if_fail (members_dlist != NULL, NULL);
-
- /* these two lists should be in sync */
- g_return_val_if_fail (members_dlist->cValues == members->cValues, NULL);
-
- for (i = 0; i < members->cValues; i++) {
- struct Binary_r br;
- gchar *display_name = NULL, *email = NULL;
- gchar *str;
-
- br.lpb = members->bin[i].lpb;
- br.cb = members->bin[i].cb;
- if (e_mapi_util_recip_entryid_decode (conn, &br, &display_name, &email)) {
- EVCardAttribute *attr;
- gchar *value;
- CamelInternetAddress *addr;
-
- addr = camel_internet_address_new ();
- attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
-
- camel_internet_address_add (addr, display_name, email);
-
- value = camel_address_encode (CAMEL_ADDRESS (addr));
-
- if (value)
- e_vcard_attribute_add_value (attr, value);
-
- g_free (value);
- g_object_unref (addr);
-
- str = g_strdup_printf ("%d", i + 1);
- e_vcard_attribute_add_param_with_value (attr,
- e_vcard_attribute_param_new (EMA_X_MEMBERID),
- str);
- g_free (str);
-
- /* keep the value from ListMembers with the email, to not need to generate it on list changes;
- new values added in evolution-mapi will be always SMTP addresses anyway */
- str = bin_to_string (members_dlist->bin[i].lpb, members_dlist->bin[i].cb);
- if (str) {
- e_vcard_attribute_add_param_with_value (attr,
- e_vcard_attribute_param_new (EMA_X_MEMBERVALUE),
- str);
- g_free (str);
- }
-
- attrs = g_slist_prepend (attrs, attr);
- }
-
- g_free (display_name);
- g_free (email);
- }
-
- for (a = attrs; a; a = a->next) {
- e_vcard_add_attribute (E_VCARD (contact), a->data);
- }
-
- g_slist_free (attrs);
-
- return contact;
- }
-
- for (i = 0; i < G_N_ELEMENTS (mappings); i++) {
- gpointer value;
- gint contact_type;
-
- /* can cast value, no writing to the value; and it'll be freed not before the end of this function */
- if (mappings[i].contact_type & ELEMENT_TYPE_NAMEDID)
- value = (gpointer) get_namedid (mappings[i].mapi_id);
- else
- value = (gpointer) get_proptag (mappings[i].mapi_id);
- contact_type = mappings[i].contact_type & ELEMENT_TYPE_MASK;
- if (mappings[i].element_type == PT_UNICODE && contact_type == ELEMENT_TYPE_SIMPLE) {
- const gchar *str = value;
- if (str && *str)
- e_contact_set (contact, mappings[i].field_id, str);
- } else if (contact_type == ELEMENT_TYPE_SIMPLE) {
- if (value && mappings[i].element_type == PT_SYSTIME) {
- const struct FILETIME *t = value;
- gchar *buff = NULL;
-
- buff = mapi_book_utils_timet_to_string (e_mapi_util_filetime_to_time_t (t));
- if (buff)
- e_contact_set (contact, mappings[i].field_id, buff);
-
- g_free (buff);
- }
- } else if (contact_type == ELEMENT_TYPE_COMPLEX) {
- if (mappings[i].field_id == E_CONTACT_IM_AIM) {
- const gchar *str = value;
- if (str && *str) {
- GList *list = g_list_append (NULL, (gpointer) str);
-
- e_contact_set (contact, mappings[i].field_id, list);
-
- g_list_free (list);
- }
- } else if (mappings[i].field_id == E_CONTACT_BIRTH_DATE
- || mappings[i].field_id == E_CONTACT_ANNIVERSARY) {
- const struct FILETIME *t = value;
- time_t time;
- struct tm * tmtime;
- if (value) {
- EContactDate date = {0};
-
- time = e_mapi_util_filetime_to_time_t (t);
- tmtime = gmtime (&time);
-
- date.day = tmtime->tm_mday;
- date.month = tmtime->tm_mon + 1;
- date.year = tmtime->tm_year + 1900;
- e_contact_set (contact, mappings[i].field_id, &date);
- }
-
- } else if (mappings[i].field_id == E_CONTACT_ADDRESS_WORK
- || mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
- EContactAddress contact_addr = { 0 };
-
- /* type-casting below to not allocate memory twice; e_contact_set will copy values itself. */
- if (mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
- contact_addr.address_format = NULL;
- contact_addr.po = NULL;
- contact_addr.street = (gchar *) value;
- contact_addr.ext = (gchar *) get_str_proptag (PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE);
- contact_addr.locality = (gchar *) get_str_proptag (PR_HOME_ADDRESS_CITY_UNICODE);
- contact_addr.region = (gchar *) get_str_proptag (PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE);
- contact_addr.code = (gchar *) get_str_proptag (PR_HOME_ADDRESS_POSTAL_CODE_UNICODE);
- contact_addr.country = (gchar *) get_str_proptag (PR_HOME_ADDRESS_COUNTRY_UNICODE);
- } else {
- contact_addr.address_format = NULL;
- contact_addr.po = NULL;
- contact_addr.street = (gchar *) value;
- contact_addr.ext = (gchar *) get_str_proptag (PR_POST_OFFICE_BOX_UNICODE);
- contact_addr.locality = (gchar *) get_str_proptag (PR_LOCALITY_UNICODE);
- contact_addr.region = (gchar *) get_str_proptag (PR_STATE_OR_PROVINCE_UNICODE);
- contact_addr.code = (gchar *) get_str_proptag (PR_POSTAL_CODE_UNICODE);
- contact_addr.country = (gchar *) get_str_proptag (PR_COUNTRY_UNICODE);
- }
-
- #define is_set(x) ((x) && *(x))
- if (is_set (contact_addr.address_format) ||
- is_set (contact_addr.po) ||
- is_set (contact_addr.street) ||
- is_set (contact_addr.ext) ||
- is_set (contact_addr.locality) ||
- is_set (contact_addr.region) ||
- is_set (contact_addr.code) ||
- is_set (contact_addr.country)) {
- e_contact_set (contact, mappings[i].field_id, &contact_addr);
- }
- #undef is_set
- }
- }
- }
-
- if (!e_contact_get (contact, E_CONTACT_EMAIL_1)) {
- gconstpointer value = get_proptag (PR_SMTP_ADDRESS_UNICODE);
-
- if (value)
- e_contact_set (contact, E_CONTACT_EMAIL_1, value);
- }
-
- #undef get_proptag
- #undef get_str_proptag
- #undef get_namedid
- #undef get_str_namedid
-
- return contact;
-}
-
void
mapi_error_to_edb_error (GError **perror, const GError *mapi_error, EDataBookStatus code, const gchar *context)
{
@@ -1990,421 +1670,3 @@ mapi_error_to_edb_error (GError **perror, const GError *mapi_error, EDataBookSta
g_free (err_msg);
}
-
-gchar *
-mapi_book_utils_timet_to_string (time_t tt)
-{
- GTimeVal tv;
-
- tv.tv_sec = tt;
- tv.tv_usec = 0;
-
- 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)
-{
- 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) {
- struct EMapiSExpParserData *esp = user_data;
- gint idx = argv[0]->value.number;
-
- if (esp && 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 504312e..ce3e2ba 100644
--- a/src/addressbook/e-book-backend-mapi.h
+++ b/src/addressbook/e-book-backend-mapi.h
@@ -32,6 +32,7 @@
#include "e-mapi-connection.h"
#include "e-mapi-defs.h"
#include "e-mapi-utils.h"
+#include "e-mapi-book-utils.h"
G_BEGIN_DECLS
@@ -127,33 +128,6 @@ void mapi_error_to_edb_error (GError **perror, const GError *mapi_error, EDataBo
#define EMA_EBB_CACHE_PROFILEID "EMA_PROFILE"
#define EMA_EBB_CACHE_FOLDERID "EMA_FOLDER"
-/* vCard parameter name in contact list */
-#define EMA_X_MEMBERID "X-EMA-MEMBER-ID"
-#define EMA_X_MEMBERVALUE "X-EMA-MEMBER-VALUE"
-
-#define GET_ALL_KNOWN_IDS (GINT_TO_POINTER(1))
-#define GET_UIDS_ONLY (GINT_TO_POINTER(2))
-
-/* data is one of GET_ALL_KNOWN_IDS or GET_UIDS_ONLY */
-gboolean mapi_book_utils_get_prop_list (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
-
-/* only one of mapi_properties and aRow can be set */
-EContact *mapi_book_utils_contact_from_props (EMapiConnection *conn, mapi_id_t fid, const gchar *book_uri, struct mapi_SPropValue_array *mapi_properties, struct SRow *aRow);
-
-/* converts time_t to string, suitable for E_CONTACT_REV field value;
- 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/Makefile.am b/src/libexchangemapi/Makefile.am
index 78e8011..ddeaa82 100644
--- a/src/libexchangemapi/Makefile.am
+++ b/src/libexchangemapi/Makefile.am
@@ -5,6 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir) \
$(EVOLUTION_DATA_SERVER_CFLAGS) \
$(LIBEDATASERVER_CFLAGS) \
+ $(LIBEBOOK_CFLAGS) \
$(LIBECAL_CFLAGS) \
$(LIBMAPI_CFLAGS) \
$(CAMEL_CFLAGS)
@@ -32,6 +33,8 @@ libexchangemapi_1_0_la_SOURCES = \
e-mapi-debug.h \
e-mapi-utils.c \
e-mapi-utils.h \
+ e-mapi-book-utils.c \
+ e-mapi-book-utils.h \
e-mapi-cal-utils.c \
e-mapi-cal-utils.h \
e-mapi-cal-tz-utils.c \
@@ -47,6 +50,7 @@ libexchangemapi_1_0_la_SOURCES = \
libexchangemapi_1_0_la_LIBADD = \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(LIBEDATASERVER_LIBS) \
+ $(LIBEBOOK_LIBS) \
$(LIBECAL_LIBS) \
$(LIBMAPI_LIBS) \
$(CAMEL_LIBS)
@@ -62,6 +66,7 @@ libexchangemapiinclude_HEADERS = \
e-mapi-debug.h \
e-mapi-fast-transfer.h \
e-mapi-utils.h \
+ e-mapi-book-utils.h \
e-mapi-cal-utils.h \
e-mapi-cal-tz-utils.h \
e-mapi-cal-recur-utils.h \
diff --git a/src/libexchangemapi/e-mapi-book-utils.c b/src/libexchangemapi/e-mapi-book-utils.c
new file mode 100644
index 0000000..911b4e1
--- /dev/null
+++ b/src/libexchangemapi/e-mapi-book-utils.c
@@ -0,0 +1,1134 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <libedataserver/e-sexp.h>
+
+#include "e-mapi-book-utils.h"
+
+#define ELEMENT_TYPE_MASK 0xF /* mask where the real type of the element is stored */
+
+#define ELEMENT_TYPE_SKIP_SET 0x00
+#define ELEMENT_TYPE_SIMPLE 0x01
+#define ELEMENT_TYPE_COMPLEX 0x02
+
+static const struct field_element_mapping {
+ EContactField field_id;
+ uint32_t mapi_id;
+ gint element_type;
+} mappings [] = {
+ { E_CONTACT_UID, PidTagMid, ELEMENT_TYPE_SKIP_SET },
+ { E_CONTACT_REV, PidTagLastModificationTime, ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_FILE_AS, PidLidFileUnder, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_FULL_NAME, PidTagDisplayName, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_GIVEN_NAME, PidTagGivenName, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_FAMILY_NAME, PidTagSurname, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_NICKNAME, PidTagNickname, ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_EMAIL_1, PidLidEmail1OriginalDisplayName,ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_EMAIL_2, PidLidEmail2EmailAddress, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_EMAIL_3, PidLidEmail3EmailAddress, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_IM_AIM, PidLidInstantMessagingAddress, ELEMENT_TYPE_COMPLEX },
+
+ { E_CONTACT_PHONE_BUSINESS, PidTagBusinessTelephoneNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_HOME, PidTagHomeTelephoneNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_MOBILE, PidTagMobileTelephoneNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_HOME_FAX, PidTagHomeFaxNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_BUSINESS_FAX, PidTagBusinessFaxNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_PAGER, PidTagPagerTelephoneNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_ASSISTANT, PidTagAssistantTelephoneNumber, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_PHONE_COMPANY, PidTagCompanyMainTelephoneNumber,ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_HOMEPAGE_URL, PidLidHtml, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_FREEBUSY_URL, PidLidFreeBusyLocation, ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_ROLE, PidTagProfession, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_TITLE, PidTagTitle, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_ORG, PidTagCompanyName, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_ORG_UNIT, PidTagDepartmentName, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_MANAGER, PidTagManagerName, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_ASSISTANT, PidTagAssistant, ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_OFFICE, PidTagOfficeLocation, ELEMENT_TYPE_SIMPLE },
+ { E_CONTACT_SPOUSE, PidTagSpouseName, ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_BIRTH_DATE, PidTagBirthday, ELEMENT_TYPE_COMPLEX },
+ { E_CONTACT_ANNIVERSARY, PidTagWeddingAnniversary, ELEMENT_TYPE_COMPLEX },
+
+ { E_CONTACT_NOTE, PidTagBody, ELEMENT_TYPE_SIMPLE },
+
+ { E_CONTACT_ADDRESS_HOME, PidLidHomeAddress, ELEMENT_TYPE_COMPLEX },
+ { E_CONTACT_ADDRESS_WORK, PidLidOtherAddress, ELEMENT_TYPE_COMPLEX }
+};
+
+/* extra properties used in ELEMENT_TYPE_COMPLEX types and some other etra properties */
+static const uint32_t extra_proptags[] = {
+ PidTagHomeAddressPostOfficeBox,
+ PidTagHomeAddressCity,
+ PidTagHomeAddressStateOrProvince,
+ PidTagHomeAddressPostalCode,
+ PidTagHomeAddressCountry,
+ PidTagPostOfficeBox,
+ PidTagLocality,
+ PidTagStateOrProvince,
+ PidTagPostalCode,
+ PidTagCountry,
+ PidTagPrimarySmtpAddress,
+ PidTagFolderId
+};
+
+static gchar *
+bin_to_string (const uint8_t *lpb, uint32_t cb)
+{
+ gchar *res, *p;
+ uint32_t i;
+
+ g_return_val_if_fail (lpb != NULL, NULL);
+ g_return_val_if_fail (cb > 0, NULL);
+
+ res = g_new0 (gchar, cb * 2 + 1);
+ for (i = 0, p = res; i < cb; i++, p += 2) {
+ sprintf (p, "%02x", lpb[i] & 0xFF);
+ }
+
+ return res;
+}
+
+static const gchar *
+not_null (gconstpointer ptr)
+{
+ return ptr ? (const gchar *) ptr : "";
+}
+
+EContact *
+e_mapi_book_utils_contact_from_object (EMapiConnection *conn,
+ EMapiObject *object,
+ const gchar *book_uri)
+{
+ EContact *contact;
+ const mapi_id_t *pmid;
+ gint i;
+
+ g_return_val_if_fail (object != NULL, NULL);
+
+ contact = e_contact_new ();
+ if (book_uri)
+ e_contact_set (contact, E_CONTACT_BOOK_URI, book_uri);
+
+ #define get_proptag(proptag) e_mapi_util_find_array_propval (&object->properties, proptag)
+ #define get_str_proptag(proptag) not_null (get_proptag (proptag))
+
+ pmid = get_proptag (PidTagMid);
+ if (pmid) {
+ gchar *suid = e_mapi_util_mapi_id_to_string (*pmid);
+
+ e_contact_set (contact, E_CONTACT_UID, suid);
+
+ g_free (suid);
+ }
+
+ if (g_str_equal (get_str_proptag (PidTagMessageClass), IPM_DISTLIST)) {
+ const struct mapi_SBinaryArray *members, *members_dlist;
+ const struct FILETIME *last_modification;
+ GSList *attrs = NULL, *a;
+ gint i;
+
+ last_modification = get_proptag (PidTagLastModificationTime);
+ if (last_modification) {
+ gchar *buff = NULL;
+
+ buff = e_mapi_book_utils_timet_to_string (e_mapi_util_filetime_to_time_t (last_modification));
+ if (buff)
+ e_contact_set (contact, E_CONTACT_REV, buff);
+
+ g_free (buff);
+ }
+
+ /* it's a contact list/distribution list, fetch members and return it */
+ e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE));
+ /* we do not support this option, same as GroupWise */
+ e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (TRUE));
+
+ e_contact_set (contact, E_CONTACT_FILE_AS, get_str_proptag (PidLidDistributionListName));
+
+ members = get_proptag (PidLidDistributionListOneOffMembers);
+ members_dlist = get_proptag (PidLidDistributionListMembers);
+
+ g_return_val_if_fail (members != NULL, NULL);
+ g_return_val_if_fail (members_dlist != NULL, NULL);
+
+ /* these two lists should be in sync */
+ g_return_val_if_fail (members_dlist->cValues == members->cValues, NULL);
+
+ for (i = 0; i < members->cValues; i++) {
+ struct Binary_r br;
+ gchar *display_name = NULL, *email = NULL;
+ gchar *str;
+
+ br.lpb = members->bin[i].lpb;
+ br.cb = members->bin[i].cb;
+ if (e_mapi_util_recip_entryid_decode (conn, &br, &display_name, &email)) {
+ EVCardAttribute *attr;
+ gchar *value;
+ CamelInternetAddress *addr;
+
+ addr = camel_internet_address_new ();
+ attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
+
+ camel_internet_address_add (addr, display_name, email);
+
+ value = camel_address_encode (CAMEL_ADDRESS (addr));
+
+ if (value)
+ e_vcard_attribute_add_value (attr, value);
+
+ g_free (value);
+ g_object_unref (addr);
+
+ str = g_strdup_printf ("%d", i + 1);
+ e_vcard_attribute_add_param_with_value (attr,
+ e_vcard_attribute_param_new (EMA_X_MEMBERID),
+ str);
+ g_free (str);
+
+ /* keep the value from ListMembers with the email, to not need to generate it on list changes;
+ new values added in evolution-mapi will be always SMTP addresses anyway */
+ str = bin_to_string (members_dlist->bin[i].lpb, members_dlist->bin[i].cb);
+ if (str) {
+ e_vcard_attribute_add_param_with_value (attr,
+ e_vcard_attribute_param_new (EMA_X_MEMBERVALUE),
+ str);
+ g_free (str);
+ }
+
+ attrs = g_slist_prepend (attrs, attr);
+ }
+
+ g_free (display_name);
+ g_free (email);
+ }
+
+ for (a = attrs; a; a = a->next) {
+ e_vcard_add_attribute (E_VCARD (contact), a->data);
+ }
+
+ g_slist_free (attrs);
+
+ return contact;
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (mappings); i++) {
+ gpointer value;
+ gint element_type;
+
+ /* can cast value, no writing to the value; and it'll be freed not before the end of this function */
+ value = (gpointer) get_proptag (mappings[i].mapi_id);
+ element_type = mappings[i].element_type & ELEMENT_TYPE_MASK;
+ if (element_type == ELEMENT_TYPE_SKIP_SET) {
+ /* skip, when asked for */
+ } else if (element_type == ELEMENT_TYPE_SIMPLE) {
+ switch (mappings[i].mapi_id & 0xFFFF) {
+ case PT_UNICODE: {
+ const gchar *str = value;
+ if (str && *str)
+ e_contact_set (contact, mappings[i].field_id, str);
+ } break;
+ case PT_SYSTIME: {
+ const struct FILETIME *t = value;
+ gchar *buff = NULL;
+
+ buff = e_mapi_book_utils_timet_to_string (e_mapi_util_filetime_to_time_t (t));
+ if (buff)
+ e_contact_set (contact, mappings[i].field_id, buff);
+
+ g_free (buff);
+ } break;
+ default:
+ /* ignore everything else */
+ break;
+ }
+ } else if (element_type == ELEMENT_TYPE_COMPLEX) {
+ if (mappings[i].field_id == E_CONTACT_IM_AIM) {
+ const gchar *str = value;
+ if (str && *str) {
+ GList *list = g_list_append (NULL, (gpointer) str);
+
+ e_contact_set (contact, mappings[i].field_id, list);
+
+ g_list_free (list);
+ }
+ } else if (mappings[i].field_id == E_CONTACT_BIRTH_DATE
+ || mappings[i].field_id == E_CONTACT_ANNIVERSARY) {
+ const struct FILETIME *t = value;
+ time_t time;
+ struct tm * tmtime;
+ if (value) {
+ EContactDate date = {0};
+
+ time = e_mapi_util_filetime_to_time_t (t);
+ tmtime = gmtime (&time);
+
+ date.day = tmtime->tm_mday;
+ date.month = tmtime->tm_mon + 1;
+ date.year = tmtime->tm_year + 1900;
+ e_contact_set (contact, mappings[i].field_id, &date);
+ }
+
+ } else if (mappings[i].field_id == E_CONTACT_ADDRESS_WORK
+ || mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
+ EContactAddress contact_addr = { 0 };
+
+ /* type-casting below to not allocate memory twice; e_contact_set will copy values itself. */
+ if (mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
+ contact_addr.address_format = NULL;
+ contact_addr.po = NULL;
+ contact_addr.street = (gchar *) value;
+ contact_addr.ext = (gchar *) get_str_proptag (PidTagHomeAddressPostOfficeBox);
+ contact_addr.locality = (gchar *) get_str_proptag (PidTagHomeAddressCity);
+ contact_addr.region = (gchar *) get_str_proptag (PidTagHomeAddressStateOrProvince);
+ contact_addr.code = (gchar *) get_str_proptag (PidTagHomeAddressPostalCode);
+ contact_addr.country = (gchar *) get_str_proptag (PidTagHomeAddressCountry);
+ } else {
+ contact_addr.address_format = NULL;
+ contact_addr.po = NULL;
+ contact_addr.street = (gchar *) value;
+ contact_addr.ext = (gchar *) get_str_proptag (PidTagPostOfficeBox);
+ contact_addr.locality = (gchar *) get_str_proptag (PidTagLocality);
+ contact_addr.region = (gchar *) get_str_proptag (PidTagStateOrProvince);
+ contact_addr.code = (gchar *) get_str_proptag (PidTagPostalCode);
+ contact_addr.country = (gchar *) get_str_proptag (PidTagCountry);
+ }
+
+ #define is_set(x) ((x) && *(x))
+ if (is_set (contact_addr.address_format) ||
+ is_set (contact_addr.po) ||
+ is_set (contact_addr.street) ||
+ is_set (contact_addr.ext) ||
+ is_set (contact_addr.locality) ||
+ is_set (contact_addr.region) ||
+ is_set (contact_addr.code) ||
+ is_set (contact_addr.country)) {
+ e_contact_set (contact, mappings[i].field_id, &contact_addr);
+ }
+ #undef is_set
+ }
+ }
+ }
+
+ if (!e_contact_get (contact, E_CONTACT_EMAIL_1)) {
+ gconstpointer value = get_proptag (PidTagPrimarySmtpAddress);
+
+ if (value)
+ e_contact_set (contact, E_CONTACT_EMAIL_1, value);
+ }
+
+ #undef get_proptag
+ #undef get_str_proptag
+
+ return contact;
+}
+
+static uint32_t
+string_to_bin (TALLOC_CTX *mem_ctx, const gchar *str, uint8_t **lpb)
+{
+ uint32_t len, i;
+
+ g_return_val_if_fail (str != NULL, 0);
+ g_return_val_if_fail (lpb != NULL, 0);
+
+ len = strlen (str);
+ g_return_val_if_fail ((len & 1) == 0, 0);
+
+ len = len / 2;
+ *lpb = talloc_zero_array (mem_ctx, uint8_t, len);
+
+ i = 0;
+ while (*str && i < len) {
+ gchar c1 = str[0], c2 = str[1];
+ str += 2;
+
+ g_return_val_if_fail ((c1 >= '0' && c1 <= '9') || (c1 >= 'a' && c1 <= 'f') || (c1 >= 'A' && c1 <= 'F'), 0);
+ g_return_val_if_fail ((c2 >= '0' && c2 <= '9') || (c2 >= 'a' && c2 <= 'f') || (c2 >= 'A' && c2 <= 'F'), 0);
+
+ #define deHex(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : (((x) >= 'a' && (x) <= 'f') ? (x) - 'a' + 10 : (x) - 'A' + 10))
+ (*lpb)[i] = (deHex (c1) << 4) | (deHex (c2));
+ #undef deHex
+ i++;
+ }
+
+ return len;
+}
+
+static gint
+cmp_member_id (gconstpointer a, gconstpointer b, gpointer ht)
+{
+ gchar *va, *vb;
+ gint res;
+
+ if (!a)
+ return b ? -1 : 0;
+ if (!b)
+ return 1;
+
+ va = e_vcard_attribute_get_value ((EVCardAttribute *) a);
+ vb = e_vcard_attribute_get_value ((EVCardAttribute *) b);
+
+ res = GPOINTER_TO_INT (g_hash_table_lookup (ht, va)) - GPOINTER_TO_INT (g_hash_table_lookup (ht, vb));
+
+ g_free (va);
+ g_free (vb);
+
+ return res;
+}
+
+gboolean
+e_mapi_book_utils_contact_to_object (EContact *contact,
+ EContact *old_contact, /* can be NULL */
+ EMapiObject **pobject,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ EMapiObject *object;
+
+ #define set_value(hex, val) G_STMT_START { \
+ if (!e_mapi_utils_add_property (&object->properties, hex, val, object)) \
+ return FALSE; \
+ } G_STMT_END
+
+ #define set_con_value(hex, field_id) G_STMT_START { \
+ if (e_contact_get (contact, field_id)) { \
+ set_value (hex, e_contact_get (contact, field_id)); \
+ } } G_STMT_END
+
+ g_return_val_if_fail (contact != NULL, FALSE);
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (pobject != NULL, FALSE);
+
+ object = e_mapi_object_new (mem_ctx);
+ *pobject = object;
+
+ if (GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_IS_LIST))) {
+ GList *local, *l;
+ struct BinaryArray_r *members, *oneoff_members;
+ uint32_t u32, crc32 = 0;
+ GHashTable *member_values = NULL, *member_ids = NULL;
+ GError *error = NULL;
+
+ if (!error && old_contact) {
+ member_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ member_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ local = e_contact_get_attributes (old_contact, E_CONTACT_EMAIL);
+ for (l = local; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ GList *param;
+
+ if (!attr)
+ continue;
+
+ param = e_vcard_attribute_get_param (attr, EMA_X_MEMBERVALUE);
+ if (param && param->data && !param->next) {
+ g_hash_table_insert (member_values, e_vcard_attribute_get_value (attr), g_strdup (param->data));
+ }
+
+ param = e_vcard_attribute_get_param (attr, EMA_X_MEMBERID);
+ if (param && param->data && !param->next) {
+ g_hash_table_insert (member_ids, e_vcard_attribute_get_value (attr), GINT_TO_POINTER (atoi (param->data)));
+ }
+ }
+
+ g_list_free_full (local, (GDestroyNotify) e_vcard_attribute_free);
+ }
+
+ if (error)
+ g_error_free (error);
+
+ set_value (PidTagMessageClass, IPM_DISTLIST);
+ u32 = 0xFFFFFFFF;
+ set_value (PidLidFileUnderId, &u32);
+ set_con_value (PidLidFileUnder, E_CONTACT_FILE_AS);
+ set_con_value (PidLidDistributionListName, E_CONTACT_FILE_AS);
+ set_con_value (PidTagDisplayName, E_CONTACT_FILE_AS);
+ set_con_value (PidTagNormalizedSubject, E_CONTACT_FILE_AS);
+
+ local = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
+ if (member_ids)
+ local = g_list_sort_with_data (local, cmp_member_id, member_ids);
+
+ members = talloc_zero (mem_ctx, struct BinaryArray_r);
+ members->cValues = 0;
+ members->lpbin = talloc_zero_array (mem_ctx, struct Binary_r, g_list_length (local));
+
+ oneoff_members = talloc_zero (mem_ctx, struct BinaryArray_r);
+ oneoff_members->cValues = 0;
+ oneoff_members->lpbin = talloc_zero_array (mem_ctx, struct Binary_r, g_list_length (local));
+
+ for (l = local; l; l = l->next) {
+ EVCardAttribute *attr = (EVCardAttribute *) l->data;
+ gchar *raw;
+ CamelInternetAddress *addr;
+
+ if (!attr)
+ continue;
+
+ raw = e_vcard_attribute_get_value (attr);
+ if (!raw)
+ continue;
+
+ addr = camel_internet_address_new ();
+ if (camel_address_decode (CAMEL_ADDRESS (addr), raw) > 0) {
+ const gchar *nm = NULL, *eml = NULL;
+
+ camel_internet_address_get (addr, 0, &nm, &eml);
+ if (eml) {
+ /* keep both lists in sync */
+ if (member_values && g_hash_table_lookup (member_values, raw)) {
+ /* stored ListMembers values when contact's value didn't change */
+ members->lpbin[members->cValues].cb = string_to_bin (mem_ctx, g_hash_table_lookup (member_values, raw), &members->lpbin[members->cValues].lpb);
+ members->cValues++;
+ } else {
+ e_mapi_util_recip_entryid_generate_smtp (mem_ctx, &members->lpbin[members->cValues], nm ? nm : "", eml);
+ members->cValues++;
+ }
+
+ e_mapi_util_recip_entryid_generate_smtp (mem_ctx, &oneoff_members->lpbin[oneoff_members->cValues], nm ? nm : "", eml);
+ oneoff_members->cValues++;
+
+ crc32 = e_mapi_utils_push_crc32 (crc32, members->lpbin[members->cValues - 1].lpb, members->lpbin[members->cValues - 1].cb);
+ }
+ }
+
+ g_object_unref (addr);
+ g_free (raw);
+ }
+
+ if (member_values)
+ g_hash_table_destroy (member_values);
+ if (member_ids)
+ g_hash_table_destroy (member_ids);
+ g_list_foreach (local, (GFunc)e_vcard_attribute_free, NULL);
+ g_list_free (local);
+
+ set_value (PidLidDistributionListOneOffMembers, oneoff_members);
+ set_value (PidLidDistributionListMembers, members);
+ set_value (PidLidDistributionListChecksum, &crc32);
+
+ return TRUE;
+ }
+
+ set_value (PidTagMessageClass, IPM_CONTACT);
+ set_con_value (PidLidFileUnder, E_CONTACT_FILE_AS);
+
+ set_con_value (PidTagDisplayName, E_CONTACT_FULL_NAME);
+ set_con_value (PidTagNormalizedSubject, E_CONTACT_FILE_AS);
+ set_con_value (PidLidEmail1OriginalDisplayName, E_CONTACT_EMAIL_1);
+ /*set_con_value (PidLidEmail1EmailAddress, E_CONTACT_EMAIL_1);*/
+
+ /*set_con_value (0x8083001e, E_CONTACT_EMAIL_1);*/
+ set_con_value (PidLidEmail2EmailAddress, E_CONTACT_EMAIL_2);
+
+ set_con_value (PidLidEmail3EmailAddress, E_CONTACT_EMAIL_3);
+ /*set_con_value (PidLidEmail3OriginalDisplayName, E_CONTACT_EMAIL_3);*/
+
+ set_con_value (PidLidHtml, E_CONTACT_HOMEPAGE_URL);
+ set_con_value (PidLidFreeBusyLocation, E_CONTACT_FREEBUSY_URL);
+
+ set_con_value (PidTagBusinessTelephoneNumber, E_CONTACT_PHONE_BUSINESS);
+ set_con_value (PidTagHomeTelephoneNumber, E_CONTACT_PHONE_HOME);
+ set_con_value (PidTagMobileTelephoneNumber, E_CONTACT_PHONE_MOBILE);
+ set_con_value (PidTagHomeFaxNumber, E_CONTACT_PHONE_HOME_FAX);
+ set_con_value (PidTagBusinessFaxNumber, E_CONTACT_PHONE_BUSINESS_FAX);
+ set_con_value (PidTagPagerTelephoneNumber, E_CONTACT_PHONE_PAGER);
+ set_con_value (PidTagAssistantTelephoneNumber, E_CONTACT_PHONE_ASSISTANT);
+ set_con_value (PidTagCompanyMainTelephoneNumber, E_CONTACT_PHONE_COMPANY);
+
+ set_con_value (PidTagManagerName, E_CONTACT_MANAGER);
+ set_con_value (PidTagAssistant, E_CONTACT_ASSISTANT);
+ set_con_value (PidTagCompanyName, E_CONTACT_ORG);
+ set_con_value (PidTagDepartmentName, E_CONTACT_ORG_UNIT);
+ set_con_value (PidTagProfession, E_CONTACT_ROLE);
+ set_con_value (PidTagTitle, E_CONTACT_TITLE);
+
+ set_con_value (PidTagOfficeLocation, E_CONTACT_OFFICE);
+ set_con_value (PidTagSpouseName, E_CONTACT_SPOUSE);
+
+ set_con_value (PidTagBody, E_CONTACT_NOTE);
+ set_con_value (PidTagNickname, E_CONTACT_NICKNAME);
+
+ /* BDAY AND ANNV */
+ if (e_contact_get (contact, E_CONTACT_BIRTH_DATE)) {
+ EContactDate *date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
+ struct tm tmtime = { 0 };
+ struct FILETIME t;
+
+ tmtime.tm_mday = date->day;
+ tmtime.tm_mon = date->month - 1;
+ tmtime.tm_year = date->year - 1900;
+
+ e_mapi_util_time_t_to_filetime (mktime (&tmtime) + (24 * 60 * 60), &t);
+
+ set_value (PidTagBirthday, &t);
+ }
+
+ if (e_contact_get (contact, E_CONTACT_ANNIVERSARY)) {
+ EContactDate *date = e_contact_get (contact, E_CONTACT_ANNIVERSARY);
+ struct tm tmtime = { 0 };
+ struct FILETIME t;
+
+ tmtime.tm_mday = date->day;
+ tmtime.tm_mon = date->month - 1;
+ tmtime.tm_year = date->year - 1900;
+
+ e_mapi_util_time_t_to_filetime (mktime (&tmtime) + (24 * 60 * 60), &t);
+
+ set_value (PidTagWeddingAnniversary, &t);
+ }
+
+ /* Home and Office address */
+ if (e_contact_get (contact, E_CONTACT_ADDRESS_HOME)) {
+ EContactAddress *contact_addr = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
+
+ set_value (PidLidHomeAddress, contact_addr->street);
+ set_value (PidTagHomeAddressPostOfficeBox, contact_addr->ext);
+ set_value (PidTagHomeAddressCity, contact_addr->locality);
+ set_value (PidTagHomeAddressStateOrProvince, contact_addr->region);
+ set_value (PidTagHomeAddressPostalCode, contact_addr->code);
+ set_value (PidTagHomeAddressCountry, contact_addr->country);
+ }
+
+ if (e_contact_get (contact, E_CONTACT_ADDRESS_WORK)) {
+ EContactAddress *contact_addr = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
+
+ set_value (PidLidWorkAddress, contact_addr->street);
+ set_value (PidTagPostOfficeBox, contact_addr->ext);
+ set_value (PidTagLocality, contact_addr->locality);
+ set_value (PidTagStateOrProvince, contact_addr->region);
+ set_value (PidTagPostalCode, contact_addr->code);
+ set_value (PidTagCountry, contact_addr->country);
+ }
+
+ if (e_contact_get (contact, E_CONTACT_IM_AIM)) {
+ GList *l = e_contact_get (contact, E_CONTACT_IM_AIM);
+ set_value (PidLidInstantMessagingAddress, l->data);
+ }
+
+ #undef set_value
+
+ return TRUE;
+}
+
+gchar *
+e_mapi_book_utils_timet_to_string (time_t tt)
+{
+ GTimeVal tv;
+
+ tv.tv_sec = tt;
+ tv.tv_usec = 0;
+
+ 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)
+{
+ 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) {
+ struct EMapiSExpParserData *esp = user_data;
+ gint idx = argv[0]->value.number;
+
+ if (esp && 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) {
+ uint32_t ii, jj;
+ const gchar *emails[] = {"email_1", "email_2", "email_3", NULL};
+ 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 = 4;
+ res->res.resOr.res = talloc_zero_array (esp->mem_ctx, struct mapi_SRestriction_or, res->res.resOr.cRes + 1);
+
+ proptag = PidTagPrimarySmtpAddress;
+ 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);
+
+ for (ii = 1, jj = 0; emails[jj]; jj++) {
+ proptag = get_proptag_from_field_name (emails[jj], TRUE);
+ if (proptag == MAPI_E_RESERVED)
+ continue;
+
+ res->res.resOr.res[ii].rt = RES_CONTENT;
+ res->res.resOr.res[ii].res.resContent.fuzzy = fuzzy | FL_IGNORECASE;
+ res->res.resOr.res[ii].res.resContent.ulPropTag = proptag;
+ res->res.resOr.res[ii].res.resContent.lpProp.ulPropTag = proptag;
+ res->res.resOr.res[ii].res.resContent.lpProp.value.lpszW = talloc_strdup (esp->mem_ctx, propvalue);
+
+ ii++;
+ }
+
+ res->res.resOr.cRes = ii;
+
+ 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) {
+ uint32_t ii, jj;
+ const gchar *emails[] = { "email_1", "email_2", "email_3", NULL };
+ 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 = 4;
+ 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 = PidTagPrimarySmtpAddress;
+
+ for (ii = 1, jj = 0; emails[jj]; jj++) {
+ proptag = get_proptag_from_field_name ("email_1", TRUE);
+
+ if (proptag == MAPI_E_RESERVED)
+ continue;
+
+ res->res.resOr.res[ii].rt = RES_EXIST;
+ res->res.resOr.res[ii].res.resExist.ulPropTag = proptag;
+
+ ii++;
+ }
+
+ res->res.resOr.cRes = ii;
+
+ 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);
+}
+
+static 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;
+}
+
+gboolean
+e_mapi_book_utils_build_sexp_restriction (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct mapi_SRestriction **restrictions,
+ gpointer user_data, /* const gchar *sexp */
+ GCancellable *cancellable,
+ GError **perror)
+{
+ const gchar *sexp = user_data;
+
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (restrictions != NULL, FALSE);
+
+ if (!sexp || !*sexp)
+ *restrictions = NULL;
+ else
+ *restrictions = mapi_book_utils_sexp_to_restriction (mem_ctx, sexp);
+
+ return TRUE;
+}
+
+/* return with g_slist_free(), 'data' pointers (strings) are not newly allocated */
+GSList *
+e_mapi_book_utils_get_supported_contact_fields (void)
+{
+ gint ii;
+ GSList *fields = NULL;
+
+ for (ii = 0; ii < G_N_ELEMENTS (mappings); ii++) {
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (mappings[ii].field_id));
+ }
+
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_BOOK_URI));
+
+ return fields;
+}
+
+gboolean
+e_mapi_book_utils_get_supported_mapi_proptags (TALLOC_CTX *mem_ctx,
+ struct SPropTagArray **propTagArray)
+{
+ gint ii;
+
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (propTagArray != NULL, FALSE);
+
+ *propTagArray = set_SPropTagArray (mem_ctx, 1, PidTagObjectType);
+
+ for (ii = 0; ii < G_N_ELEMENTS (mappings); ii++) {
+ SPropTagArray_add (mem_ctx, *propTagArray, mappings[ii].mapi_id);
+ }
+
+ for (ii = 0; ii < G_N_ELEMENTS (extra_proptags); ii++) {
+ SPropTagArray_add (mem_ctx, *propTagArray, extra_proptags[ii]);
+ }
+
+ return TRUE;
+}
diff --git a/src/libexchangemapi/e-mapi-book-utils.h b/src/libexchangemapi/e-mapi-book-utils.h
new file mode 100644
index 0000000..6ec2d9c
--- /dev/null
+++ b/src/libexchangemapi/e-mapi-book-utils.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_MAPI_BOOK_UTILS_H
+#define E_MAPI_BOOK_UTILS_H
+
+#include <libebook/e-contact.h>
+
+#include <e-mapi-connection.h>
+#include <e-mapi-defs.h>
+#include <e-mapi-utils.h>
+
+/* vCard parameter name in contact list */
+#define EMA_X_MEMBERID "X-EMA-MEMBER-ID"
+#define EMA_X_MEMBERVALUE "X-EMA-MEMBER-VALUE"
+
+G_BEGIN_DECLS
+
+EContact * e_mapi_book_utils_contact_from_object (EMapiConnection *conn,
+ EMapiObject *object,
+ const gchar *book_uri);
+
+gboolean e_mapi_book_utils_contact_to_object (EContact *contact,
+ EContact *old_contact, /* can be NULL */
+ EMapiObject **pobject,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror);
+
+/* converts time_t to string, suitable for E_CONTACT_REV field value;
+ free returned pointer with g_free() */
+gchar * e_mapi_book_utils_timet_to_string (time_t tt);
+
+/* converts sexp_query into mapi_SRestriction, which is completely
+ allocated on the given mem_ctx */
+gboolean e_mapi_book_utils_build_sexp_restriction (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct mapi_SRestriction **restrictions,
+ gpointer user_data, /* const gchar *sexp */
+ GCancellable *cancellable,
+ GError **perror);
+
+GSList * e_mapi_book_utils_get_supported_contact_fields (void);
+
+gboolean e_mapi_book_utils_get_supported_mapi_proptags (TALLOC_CTX *mem_ctx,
+ struct SPropTagArray **propTagArray);
+
+G_END_DECLS
+
+#endif
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index b1d2f54..f35cf9a 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -38,15 +38,18 @@
#include "e-mapi-connection.h"
#include "e-mapi-folder.h"
#include "e-mapi-utils.h"
+#include "e-mapi-book-utils.h"
#include "e-mapi-mail-utils.h"
#include "e-mapi-fast-transfer.h"
#include "e-mapi-openchange.h"
-//#include <param.h>
/* how many bytes can be written within one property with SetProps() call;
if its size exceeds this limit, it's converted into an EMapiStreamedProp */
#define MAX_PROPERTY_WRITE_SIZE 2048
+/* how may contacts in one chunk can GAL ask to fetch */
+#define MAX_GAL_CHUNK 50
+
static void register_connection (EMapiConnection *conn);
static void unregister_connection (EMapiConnection *conn);
static gboolean mapi_profile_create (struct mapi_context *mapi_ctx, const EMapiProfileData *empd, mapi_profile_callback_t callback, gconstpointer data, GCancellable *cancellable, GError **perror, gboolean use_locking);
@@ -531,6 +534,7 @@ e_mapi_connection_new (const gchar *profile, const gchar *password, GCancellable
priv->profile = g_strdup (profile);
priv->has_public_store = FALSE;
+
UNLOCK ();
e_mapi_debug_print ("%s: %s: Connected ", G_STRLOC, G_STRFUNC);
@@ -649,84 +653,6 @@ may_skip_property (uint32_t proptag)
}
gboolean
-e_mapi_connection_fetch_gal (EMapiConnection *conn,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchGALCallback cb,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct SPropTagArray *propsTagArray;
- struct SRowSet *aRowSet;
- enum MAPISTATUS ms;
- uint32_t i, count, n_rows = 0;
- uint8_t ulFlags;
- TALLOC_CTX *mem_ctx;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (build_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- mem_ctx = talloc_new (priv->session);
-
- LOCK ();
-
- ms = GetGALTableCount (priv->session, &n_rows);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetGALTableCount", ms);
- n_rows = 0;
- }
-
- propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
- if (!build_props (conn, 0, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
- UNLOCK();
- talloc_free (mem_ctx);
- return FALSE;
- }
-
- ms = MAPI_E_SUCCESS;
- count = 0;
- ulFlags = TABLE_START;
- while (ms == MAPI_E_SUCCESS) {
- aRowSet = NULL;
- /* fetch per 100 items */
- ms = GetGALTable (priv->session, propsTagArray, &aRowSet, 100, ulFlags);
- if ((!aRowSet) || (!(aRowSet->aRow)) || ms != MAPI_E_SUCCESS) {
- break;
- }
- if (aRowSet->cRows) {
- global_unlock ();
- for (i = 0; i < aRowSet->cRows; i++, count++) {
- if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data, cancellable, perror)) {
- ms = MAPI_E_RESERVED;
- break;
- }
- }
- global_lock ();
- } else {
- talloc_free (aRowSet);
- break;
- }
-
- ulFlags = TABLE_CUR;
- talloc_free (aRowSet);
- }
-
- talloc_free (mem_ctx);
-
- UNLOCK ();
-
- if (ms != MAPI_E_SUCCESS && ms != MAPI_E_RESERVED)
- make_mapi_error (perror, "GetGALTable", ms);
-
- return ms == MAPI_E_SUCCESS;
-}
-
-gboolean
e_mapi_connection_get_public_folder (EMapiConnection *conn,
mapi_object_t *obj_store,
GCancellable *cancellable,
@@ -929,7 +855,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
spropTagArray = set_SPropTagArray (mem_ctx, 3, PidTagFolderId, PidTagLastModificationTime, PidTagContentCount);
if (brp_cb) {
- if (!brp_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, spropTagArray, brp_cb_user_data, cancellable, perror)) {
+ if (!brp_cb (conn, mem_ctx, spropTagArray, brp_cb_user_data, cancellable, perror)) {
goto cleanup;
}
} else {
@@ -941,7 +867,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
if (spropTagArray && spropTagArray->cValues) {
struct SPropValue *lpProps;
uint32_t prop_count = 0, k, ll;
- ResolveNamedIDsData *named_ids_list = NULL;
+ EResolveNamedIDsData *named_ids_list = NULL;
guint named_ids_len = 0;
lpProps = talloc_zero (mem_ctx, struct SPropValue);
@@ -957,7 +883,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
} else if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
if (!named_ids_list)
- named_ids_list = g_new0 (ResolveNamedIDsData, spropTagArray->cValues - k + 1);
+ named_ids_list = g_new0 (EResolveNamedIDsData, spropTagArray->cValues - k + 1);
named_ids_list[named_ids_len].pidlid_propid = proptag;
named_ids_list[named_ids_len].propid = MAPI_E_RESERVED;
named_ids_len++;
@@ -1130,10 +1056,10 @@ list_objects_internal_cb (EMapiConnection *conn,
GError **perror)
{
struct ListObjectsInternalData *loi_data = user_data;
- ListObjectsData lod;
+ ListObjectsData lod = { 0 };
const mapi_id_t *pmid;
const gchar *msg_class;
- const uint32_t *pmsg_flags;
+ const uint32_t *pmsg_flags, *pobj_type;
const struct FILETIME *last_modified;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
@@ -1141,12 +1067,14 @@ list_objects_internal_cb (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (srow != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- pmid = get_SPropValue_SRow_data (srow, PidTagMid);
- msg_class = get_SPropValue_SRow_data (srow, PidTagMessageClass);
- pmsg_flags = get_SPropValue_SRow_data (srow, PidTagMessageFlags);
- last_modified = get_SPropValue_SRow_data (srow, PidTagLastModificationTime);
+ pmid = e_mapi_util_find_row_propval (srow, PidTagMid);
+ pobj_type = e_mapi_util_find_row_propval (srow, PidTagObjectType);
+ msg_class = e_mapi_util_find_row_propval (srow, PidTagMessageClass);
+ pmsg_flags = e_mapi_util_find_row_propval (srow, PidTagMessageFlags);
+ last_modified = e_mapi_util_find_row_propval (srow, PidTagLastModificationTime);
lod.mid = pmid ? *pmid : 0;
+ lod.obj_type = pobj_type ? *pobj_type : 0;
lod.msg_class = msg_class;
lod.msg_flags = pmsg_flags ? *pmsg_flags : 0;
lod.last_modified = last_modified ? e_mapi_util_filetime_to_time_t (last_modified) : 0;
@@ -1156,7 +1084,7 @@ list_objects_internal_cb (EMapiConnection *conn,
static void
maybe_add_named_id_tag (uint32_t proptag,
- ResolveNamedIDsData **named_ids_list,
+ EResolveNamedIDsData **named_ids_list,
guint *named_ids_len)
{
g_return_if_fail (named_ids_list != NULL);
@@ -1164,10 +1092,10 @@ maybe_add_named_id_tag (uint32_t proptag,
if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
if (!*named_ids_list) {
- *named_ids_list = g_new0 (ResolveNamedIDsData, 1);
+ *named_ids_list = g_new0 (EResolveNamedIDsData, 1);
*named_ids_len = 0;
} else {
- *named_ids_list = g_renew (ResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
+ *named_ids_list = g_renew (EResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
}
(*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
@@ -1178,7 +1106,7 @@ maybe_add_named_id_tag (uint32_t proptag,
static void
gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
- ResolveNamedIDsData **named_ids_list,
+ EResolveNamedIDsData **named_ids_list,
guint *named_ids_len)
{
guint i;
@@ -1227,60 +1155,78 @@ gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
}
}
+/* free returned pointer with g_hash_table_destroy */
+static GHashTable *
+prepare_maybe_replace_hash (const EResolveNamedIDsData *named_ids_list,
+ guint named_ids_len)
+{
+ GHashTable *res;
+ gint ii;
+
+ if (!named_ids_list || !named_ids_len)
+ return NULL;
+
+ res = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ for (ii = 0; ii < named_ids_len; ii++) {
+ uint32_t search_tag = named_ids_list[ii].pidlid_propid;
+ uint32_t replace_with = named_ids_list[ii].propid;
+
+ g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
+
+ search_tag = (search_tag & ~0xFFFF) | PT_ERROR;
+ replace_with = (replace_with & ~0xFFFF) | PT_ERROR;
+
+ g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
+ }
+
+ return res;
+}
+
static void
maybe_replace_named_id_tag (uint32_t *pproptag,
- const ResolveNamedIDsData *named_ids_list,
- guint named_ids_len)
+ GHashTable *replace_hash)
{
- gint i;
+ gpointer key, value;
g_return_if_fail (pproptag != NULL);
- g_return_if_fail (named_ids_list != NULL);
- if ((((*pproptag) >> 16) & 0xFFFF) < 0x8000)
+ if (!replace_hash)
return;
- for (i = 0; i < named_ids_len; i++) {
- if ((*pproptag) == named_ids_list[i].pidlid_propid ||
- ((((*pproptag) & 0xFFFF) == PT_ERROR) &&
- ((*pproptag) & ~0xFFFF) == (named_ids_list[i].pidlid_propid & ~0xFFFF))) {
- (*pproptag) = ((*pproptag) & 0xFFFF) | (named_ids_list[i].propid & ~0xFFFF);
- break;
- }
- }
+ if (g_hash_table_lookup_extended (replace_hash, GUINT_TO_POINTER (*pproptag), &key, &value))
+ *pproptag = GPOINTER_TO_UINT (value);
}
static void
replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
- const ResolveNamedIDsData *named_ids_list,
- guint named_ids_len)
+ GHashTable *replace_hash)
{
guint i;
uint32_t proptag;
g_return_if_fail (restriction != NULL);
- g_return_if_fail (named_ids_list != NULL);
- #define check_proptag(x) { \
- proptag = x; \
- maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len); \
- x = proptag; \
+ #define check_proptag(x) { \
+ proptag = x; \
+ maybe_replace_named_id_tag (&proptag, replace_hash); \
+ x = proptag; \
}
switch (restriction->rt) {
case RES_AND:
for (i = 0; i < restriction->res.resAnd.cRes; i++) {
- replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
+ replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), replace_hash);
}
break;
case RES_OR:
for (i = 0; i < restriction->res.resOr.cRes; i++) {
- replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
+ replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), replace_hash);
}
break;
#ifdef HAVE_RES_NOT_SUPPORTED
case RES_NOT:
- replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, named_ids_list, named_ids_len);
+ replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, replace_hash);
break;
#endif
case RES_CONTENT:
@@ -1316,7 +1262,7 @@ change_mapi_SRestriction_named_ids (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror)
{
- ResolveNamedIDsData *named_ids_list = NULL;
+ EResolveNamedIDsData *named_ids_list = NULL;
guint named_ids_len = 0;
gboolean res = FALSE;
@@ -1332,8 +1278,14 @@ change_mapi_SRestriction_named_ids (EMapiConnection *conn,
res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
- if (res)
- replace_mapi_SRestriction_named_ids (restrictions, named_ids_list, named_ids_len);
+ if (res) {
+ GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+
+ if (replace_hash) {
+ replace_mapi_SRestriction_named_ids (restrictions, replace_hash);
+ g_hash_table_destroy (replace_hash);
+ }
+ }
g_free (named_ids_list);
@@ -1378,8 +1330,9 @@ e_mapi_connection_list_objects (EMapiConnection *conn,
goto cleanup;
}
- propTagArray = set_SPropTagArray (mem_ctx, 0x4,
+ propTagArray = set_SPropTagArray (mem_ctx, 0x5,
PidTagMid,
+ PidTagObjectType,
PidTagMessageClass,
PidTagMessageFlags,
PidTagLastModificationTime);
@@ -2474,7 +2427,7 @@ convert_mapi_props_to_props (EMapiConnection *conn,
GError **perror)
{
uint16_t ii;
- ResolveNamedIDsData *named_ids_list = NULL;
+ EResolveNamedIDsData *named_ids_list = NULL;
guint named_ids_len = 0;
gboolean res = TRUE;
@@ -2576,23 +2529,31 @@ convert_mapi_props_to_props (EMapiConnection *conn,
}
if (named_ids_list) {
+ GHashTable *replace_hash = NULL;
+
res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
- if (res && *props) {
+ if (res)
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+
+ if (replace_hash && *props) {
for (ii = 0; ii < *propslen; ii++) {
uint32_t proptag = (*props)[ii].ulPropTag;
- maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
+ maybe_replace_named_id_tag (&proptag, replace_hash);
(*props)[ii].ulPropTag = proptag;
}
}
- if (res && streams) {
+ if (replace_hash && streams) {
for (ii = 0; ii < *streamslen; ii++) {
- maybe_replace_named_id_tag (&((*streams)[ii].proptag), named_ids_list, named_ids_len);
+ maybe_replace_named_id_tag (&((*streams)[ii].proptag), replace_hash);
}
}
+
+ if (replace_hash)
+ g_hash_table_destroy (replace_hash);
}
g_free (named_ids_list);
@@ -2834,7 +2795,7 @@ add_object_recipients (EMapiConnection *conn,
struct SPropTagArray *tags;
struct SRowSet *rows = NULL;
struct PropertyTagArray_r *flagList = NULL;
- ResolveNamedIDsData *named_ids_list = NULL;
+ EResolveNamedIDsData *named_ids_list = NULL;
guint named_ids_len = 0;
const gchar **users = NULL;
EMapiRecipient *recipient;
@@ -2902,19 +2863,26 @@ add_object_recipients (EMapiConnection *conn,
}
if (named_ids_list) {
+ GHashTable *replace_hash;
+
if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
ms = MAPI_E_CALL_FAILED;
make_mapi_error (perror, "e_mapi_connection_resolve_named_props", ms);
goto cleanup;
}
- for (ii = 0; ii < tags->cValues; ii++) {
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+
+ for (ii = 0; ii < tags->cValues && replace_hash; ii++) {
uint32_t proptag = tags->aulPropTag[ii];
- maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
+ maybe_replace_named_id_tag (&proptag, replace_hash);
tags->aulPropTag[ii] = proptag;
}
+
+ if (replace_hash)
+ g_hash_table_destroy (replace_hash);
}
ms = ResolveNames (priv->session, users, tags, &rows, &flagList, MAPI_UNICODE);
@@ -3387,6 +3355,615 @@ e_mapi_connection_modify_object (EMapiConnection *conn,
return ms == MAPI_E_SUCCESS;
}
+static void
+convert_mapi_SRestriction_to_Restriction_r (struct mapi_SRestriction *restriction,
+ struct Restriction_r *rr,
+ TALLOC_CTX *mem_ctx,
+ GHashTable *replace_hash)
+{
+ guint i;
+ uint32_t proptag;
+
+ g_return_if_fail (restriction != NULL);
+ g_return_if_fail (rr != NULL);
+ g_return_if_fail (mem_ctx != NULL);
+
+ #define copy(x, y) rr->res.x = restriction->res.y
+ #define copy_prop(pprop, mprop) { \
+ rr->res.pprop = talloc_zero (mem_ctx, struct SPropValue); \
+ g_return_if_fail (rr->res.pprop != NULL); \
+ rr->res.pprop->ulPropTag = restriction->res.mprop.ulPropTag; \
+ rr->res.pprop->dwAlignPad = 0; \
+ cast_SPropValue (mem_ctx, &(restriction->res.mprop), rr->res.pprop); \
+ }
+ #define check_proptag(x) { \
+ proptag = x; \
+ maybe_replace_named_id_tag (&proptag, replace_hash); \
+ /* workaround for unresolved properties */ \
+ if (proptag == MAPI_E_RESERVED) \
+ proptag = PidTagDisplayName; \
+ x = proptag; \
+ }
+
+ rr->rt = restriction->rt;
+
+ switch (restriction->rt) {
+ case RES_AND:
+ rr->res.resAnd.lpRes = talloc_zero_array (mem_ctx, struct Restriction_r, restriction->res.resAnd.cRes);
+ g_return_if_fail (rr->res.resAnd.lpRes != NULL);
+
+ copy (resAnd.cRes, resAnd.cRes);
+ for (i = 0; i < restriction->res.resAnd.cRes; i++) {
+ convert_mapi_SRestriction_to_Restriction_r (
+ (struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]),
+ &(rr->res.resAnd.lpRes[i]),
+ mem_ctx, replace_hash);
+ }
+ break;
+ case RES_OR:
+ rr->res.resOr.lpRes = talloc_zero_array (mem_ctx, struct Restriction_r, restriction->res.resOr.cRes);
+ g_return_if_fail (rr->res.resOr.lpRes != NULL);
+
+ copy (resOr.cRes, resOr.cRes);
+ for (i = 0; i < restriction->res.resOr.cRes; i++) {
+ convert_mapi_SRestriction_to_Restriction_r (
+ (struct mapi_SRestriction *) &(restriction->res.resOr.res[i]),
+ &(rr->res.resOr.lpRes[i]),
+ mem_ctx, replace_hash);
+ }
+ break;
+ #ifdef HAVE_RES_NOT_SUPPORTED
+ case RES_NOT:
+ rr->res.resNot.lpRes = talloc_zero (mem_ctx, struct Restriction_r);
+ g_return_if_fail (r->res.resNot.lpRes != NULL);
+
+ convert_mapi_SRestriction_to_Restriction_r (
+ restriction->res.resNot.res,
+ rr->res.resNot.lpRes,
+ mem_ctx, replace_hash);
+ break;
+ #endif
+ case RES_CONTENT:
+ copy (resContent.ulFuzzyLevel, resContent.fuzzy);
+ copy (resContent.ulPropTag, resContent.ulPropTag);
+ copy_prop (resContent.lpProp, resContent.lpProp);
+
+ check_proptag (rr->res.resContent.ulPropTag);
+ check_proptag (rr->res.resContent.lpProp->ulPropTag);
+ break;
+ case RES_PROPERTY:
+ copy (resProperty.relop, resProperty.relop);
+ copy (resProperty.ulPropTag, resProperty.ulPropTag);
+ copy_prop (resProperty.lpProp, resProperty.lpProp);
+
+
+ check_proptag (rr->res.resProperty.ulPropTag);
+ check_proptag (rr->res.resProperty.lpProp->ulPropTag);
+ break;
+ case RES_COMPAREPROPS:
+ copy (resCompareProps.relop, resCompareProps.relop);
+ copy (resCompareProps.ulPropTag1, resCompareProps.ulPropTag1);
+ copy (resCompareProps.ulPropTag2, resCompareProps.ulPropTag2);
+
+ check_proptag (rr->res.resCompareProps.ulPropTag1);
+ check_proptag (rr->res.resCompareProps.ulPropTag2);
+ break;
+ case RES_BITMASK:
+ copy (resBitMask.relMBR, resBitmask.relMBR);
+ copy (resBitMask.ulPropTag, resBitmask.ulPropTag);
+ copy (resBitMask.ulMask, resBitmask.ulMask);
+
+ check_proptag (rr->res.resBitMask.ulPropTag);
+ break;
+ case RES_SIZE:
+ copy (resSize.relop, resSize.relop);
+ copy (resSize.ulPropTag, resSize.ulPropTag);
+ copy (resSize.cb, resSize.size);
+
+ check_proptag (rr->res.resSize.ulPropTag);
+ break;
+ case RES_EXIST:
+ rr->res.resExist.ulReserved1 = 0;
+ rr->res.resExist.ulReserved2 = 0;
+ copy (resExist.ulPropTag, resExist.ulPropTag);
+
+ check_proptag (rr->res.resExist.ulPropTag);
+ break;
+ }
+
+ #undef check_proptag
+ #undef copy_prop
+ #undef copy
+}
+
+static enum MAPISTATUS
+process_gal_rows_chunk (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ uint32_t rows_offset,
+ uint32_t rows_total,
+ struct SRowSet *rows,
+ struct PropertyTagArray_r *mids,
+ ForeachTableRowCB cb,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms = MAPI_E_SUCCESS;
+ uint32_t ii;
+
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (rows != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (mids != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (rows->cRows <= mids->cValues, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+
+ for (ii = 0; ii < rows->cRows; ii++) {
+ struct SRow *row = &rows->aRow[ii];
+ int64_t mid = mids->aulPropTag[ii];
+
+ /* add the temporary mid as a PidTagMid */
+ if (!e_mapi_utils_add_spropvalue (mem_ctx, &row->lpProps, &row->cValues, PidTagMid, &mid)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "e_mapi_utils_add_spropvalue", ms);
+ break;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
+ }
+
+ if (!cb (conn, mem_ctx, row, rows_offset + ii + 1, rows_total, user_data, cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
+ }
+ }
+
+ return ms;
+}
+
+static enum MAPISTATUS
+foreach_gal_tablerow (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SRowSet *first_rows,
+ struct PropertyTagArray_r *all_mids,
+ struct SPropTagArray *propTagArray,
+ ForeachTableRowCB cb,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ struct SRowSet *rows = NULL;
+ struct PropertyTagArray_r *to_query = NULL;
+ uint32_t midspos;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (first_rows != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (all_mids != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (first_rows->cRows <= all_mids->cValues, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+
+ midspos = 0;
+ ms = process_gal_rows_chunk (conn, mem_ctx, midspos, all_mids->cValues, first_rows, all_mids, cb, user_data, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "process_gal_rows_chunk", ms);
+ goto cleanup;
+ }
+
+ midspos = first_rows->cRows;
+ to_query = talloc_zero (mem_ctx, struct PropertyTagArray_r);
+ to_query->aulPropTag = talloc_zero_array (mem_ctx, uint32_t, MAX_GAL_CHUNK);
+
+ while (midspos < all_mids->cValues) {
+ uint32_t ii;
+
+ to_query->cValues = 0;
+ for (ii = midspos; to_query->cValues < MAX_GAL_CHUNK && ii < all_mids->cValues; to_query->cValues++, ii++) {
+ to_query->aulPropTag[to_query->cValues] = all_mids->aulPropTag[ii];
+ }
+
+ if (!to_query->cValues)
+ break;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
+ }
+
+ ms = nspi_QueryRows (priv->session->nspi->ctx, mem_ctx, propTagArray, to_query, to_query->cValues, &rows);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "nspi_QueryRows", ms);
+ goto cleanup;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
+ }
+
+ if (!rows || rows->cRows <= 0) {
+ /* success or finished, probably */
+ break;
+ }
+
+ ms = process_gal_rows_chunk (conn, mem_ctx, midspos, all_mids->cValues, rows, to_query, cb, user_data, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "process_gal_rows_chunk", ms);
+ goto cleanup;
+ }
+
+ midspos += rows->cRows;
+ talloc_free (rows);
+ rows = NULL;
+ }
+
+ cleanup:
+ talloc_free (to_query);
+ talloc_free (rows);
+
+ return ms;
+}
+
+gboolean
+e_mapi_connection_count_gal_objects (EMapiConnection *conn,
+ guint32 *obj_total,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ uint32_t count = 0;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session->nspi != NULL, MAPI_E_UNCONFIGURED, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session->nspi->ctx != NULL, MAPI_E_UNCONFIGURED, FALSE);
+ e_return_val_mapi_error_if_fail (obj_total != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ *obj_total = 0;
+
+ LOCK ();
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ } else {
+ ms = GetGALTableCount (priv->session, &count);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetGALTableCount", ms);
+ } else {
+ *obj_total = count;
+ }
+ }
+
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
+e_mapi_connection_list_gal_objects (EMapiConnection *conn,
+ BuildRestrictionsCB build_rs_cb,
+ gpointer build_rs_cb_data,
+ ListObjectsCB cb,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *propTagArray = NULL;
+ struct Restriction_r *use_restriction = NULL;
+ struct SRowSet *rows = NULL;
+ struct PropertyTagArray_r *pMIds = NULL;
+ struct ListObjectsInternalData loi_data;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session->nspi != NULL, MAPI_E_UNCONFIGURED, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session->nspi->ctx != NULL, MAPI_E_UNCONFIGURED, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ LOCK ();
+ mem_ctx = talloc_new (priv->session);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ propTagArray = set_SPropTagArray (mem_ctx, 4,
+ PidTagObjectType,
+ PidTagMessageClass,
+ PidTagMessageFlags,
+ PidTagLastModificationTime);
+
+ if (build_rs_cb) {
+ struct mapi_SRestriction *restrictions = NULL;
+
+ if (!build_rs_cb (conn, mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "build_restrictions", ms);
+ goto cleanup;
+ }
+
+ if (restrictions) {
+ EResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0;
+ gboolean res = FALSE;
+
+ gather_mapi_SRestriction_named_ids (restrictions, &named_ids_list, &named_ids_len);
+
+ if (named_ids_list) {
+ /* use 0 for GAL as a folder ID parameter */
+ res = e_mapi_connection_resolve_named_props (conn, 0, named_ids_list, named_ids_len, cancellable, perror);
+
+ if (res) {
+ GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+
+ use_restriction = talloc_zero (mem_ctx, struct Restriction_r);
+ convert_mapi_SRestriction_to_Restriction_r (restrictions, use_restriction, mem_ctx, replace_hash);
+
+ if (replace_hash)
+ g_hash_table_destroy (replace_hash);
+ } else {
+ ms = MAPI_E_CALL_FAILED;
+ goto cleanup;
+ }
+
+ g_free (named_ids_list);
+ } else {
+ use_restriction = talloc_zero (mem_ctx, struct Restriction_r);
+ convert_mapi_SRestriction_to_Restriction_r (restrictions, use_restriction, mem_ctx, NULL);
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+ }
+ }
+
+ ms = nspi_GetMatches (priv->session->nspi->ctx, mem_ctx, propTagArray, use_restriction, &rows, &pMIds);
+ if (ms != MAPI_E_SUCCESS || !rows) {
+ if (ms == MAPI_E_NOT_FOUND || (!rows && ms == MAPI_E_SUCCESS))
+ ms = MAPI_E_SUCCESS;
+ else if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "nspi_GetMatches", ms);
+ goto cleanup;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ loi_data.cb = cb;
+ loi_data.user_data = user_data;
+
+ ms = foreach_gal_tablerow (conn, mem_ctx, rows, pMIds, propTagArray, list_objects_internal_cb, &loi_data, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "foreach_gal_tablerow", ms);
+ goto cleanup;
+ }
+
+ cleanup:
+ talloc_free (pMIds);
+ talloc_free (rows);
+ talloc_free (propTagArray);
+ talloc_free (mem_ctx);
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+struct TransferGALObjectData
+{
+ GHashTable *reverse_replace_hash;
+ TransferObjectCB cb;
+ gpointer cb_user_data;
+};
+
+static gboolean
+e_mapi_transfer_gal_objects_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SRow *srow,
+ guint32 row_index,
+ guint32 rows_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct TransferGALObjectData *tgo = user_data;
+ EMapiObject *object;
+ uint32_t ii;
+ gboolean res;
+
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (srow != NULL, FALSE);
+ g_return_val_if_fail (tgo != NULL, FALSE);
+ g_return_val_if_fail (tgo->cb != NULL, FALSE);
+
+ object = e_mapi_object_new (mem_ctx);
+
+ res = TRUE;
+
+ for (ii = 0; ii < srow->cValues; ii++) {
+ uint32_t proptag = srow->lpProps[ii].ulPropTag;
+ gconstpointer propdata = get_SPropValue_data (&srow->lpProps[ii]);
+
+ if (!propdata || may_skip_property (srow->lpProps[ii].ulPropTag))
+ continue;
+
+ /* reverse_replace_hash has them stored in opposite,
+ the key is the name-id-proptag as stored on the server,
+ the value is a pidlid/pidname proptag */
+ maybe_replace_named_id_tag (&proptag, tgo->reverse_replace_hash);
+
+ if (!e_mapi_utils_add_property (&object->properties, proptag, propdata, object)) {
+ res = FALSE;
+ make_mapi_error (perror, "e_mapi_utils_add_property", MAPI_E_CALL_FAILED);
+ break;
+ }
+ }
+
+ if (res)
+ res = tgo->cb (conn, mem_ctx, object, row_index, rows_total, tgo->cb_user_data, cancellable, perror);
+
+ e_mapi_object_free (object);
+
+ return res;
+}
+
+static void
+fill_reverse_replace_hash (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GHashTable *reverse_replace_hash = user_data;
+
+ g_return_if_fail (reverse_replace_hash != NULL);
+
+ g_hash_table_insert (reverse_replace_hash, value, key);
+}
+
+gboolean
+e_mapi_connection_transfer_gal_objects (EMapiConnection *conn,
+ const GSList *mids,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ struct PropertyTagArray_r *ids = NULL;
+ struct SPropTagArray *propTagArray = NULL;
+ struct SRowSet rows;
+ struct TransferGALObjectData tgo;
+ GHashTable *reverse_replace_hash = NULL;
+ EResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0, ii;
+ const GSList *iter;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session->nspi != NULL, MAPI_E_UNCONFIGURED, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session->nspi->ctx != NULL, MAPI_E_UNCONFIGURED, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ LOCK ();
+ mem_ctx = talloc_new (priv->session);
+
+ for (iter = mids; iter; iter = iter->next) {
+ mapi_id_t *pmid = iter->data;
+
+ if (pmid) {
+ if (!ids) {
+ ids = talloc_zero (mem_ctx, struct PropertyTagArray_r);
+ }
+ ids->cValues++;
+ ids->aulPropTag = talloc_realloc (mem_ctx,
+ ids->aulPropTag,
+ uint32_t,
+ ids->cValues + 1);
+ ids->aulPropTag[ids->cValues - 1] = (uint32_t) (*pmid);
+ ids->aulPropTag[ids->cValues] = 0;
+ }
+ }
+
+ if (!ids) {
+ ms = MAPI_E_INVALID_PARAMETER;
+ make_mapi_error (perror, "gather valid mids", ms);
+ goto cleanup;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ if (!e_mapi_book_utils_get_supported_mapi_proptags (mem_ctx, &propTagArray) || !propTagArray) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "e_mapi_book_utils_get_supported_mapi_proptags", ms);
+ goto cleanup;
+ }
+
+ for (ii = 0; ii < propTagArray->cValues; ii++) {
+ maybe_add_named_id_tag (propTagArray->aulPropTag[ii], &named_ids_list, &named_ids_len);
+ }
+
+ if (named_ids_list) {
+ GHashTable *replace_hash;
+
+ if (!e_mapi_connection_resolve_named_props (conn, 0, named_ids_list, named_ids_len, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "e_mapi_connection_resolve_named_props", ms);
+ goto cleanup;
+ }
+
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+
+ if (replace_hash) {
+ for (ii = 0; ii < propTagArray->cValues; ii++) {
+ uint32_t proptag = propTagArray->aulPropTag[ii];
+
+ maybe_replace_named_id_tag (&proptag, replace_hash);
+
+ propTagArray->aulPropTag[ii] = proptag;
+ }
+
+ reverse_replace_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ g_hash_table_foreach (replace_hash, fill_reverse_replace_hash, reverse_replace_hash);
+ g_hash_table_destroy (replace_hash);
+ }
+ }
+
+ /* fake rows, to start reading from the first mid */
+ rows.cRows = 0;
+ rows.aRow = NULL;
+
+ tgo.cb = cb;
+ tgo.cb_user_data = cb_user_data;
+ tgo.reverse_replace_hash = reverse_replace_hash;
+
+ ms = foreach_gal_tablerow (conn, mem_ctx, &rows, ids, propTagArray, e_mapi_transfer_gal_objects_cb, &tgo, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "foreach_gal_tablerow", ms);
+ goto cleanup;
+ }
+
+ cleanup:
+ if (reverse_replace_hash)
+ g_hash_table_destroy (reverse_replace_hash);
+ talloc_free (propTagArray);
+ talloc_free (ids);
+ talloc_free (mem_ctx);
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
+e_mapi_connection_transfer_gal_object (EMapiConnection *conn,
+ mapi_id_t message_id,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ GSList *mids;
+ gboolean res;
+
+ mids = g_slist_append (NULL, &message_id);
+ res = e_mapi_connection_transfer_gal_objects (conn, mids, cb, cb_user_data, cancellable, perror);
+ g_slist_free (mids);
+
+ return res;
+}
+
mapi_id_t
e_mapi_connection_create_folder (EMapiConnection *conn,
uint32_t olFolder,
@@ -3775,11 +4352,12 @@ e_mapi_connection_move_folder (EMapiConnection *conn,
return result;
}
-/* named_ids_list contains pointers to ResolveNamedIDsData structure */
+/* named_ids_list contains pointers to EResolveNamedIDsData structure;
+ fid 0 is reserved for lookup in GAL */
gboolean
e_mapi_connection_resolve_named_props (EMapiConnection *conn,
mapi_id_t fid,
- ResolveNamedIDsData *named_ids_list,
+ EResolveNamedIDsData *named_ids_list,
guint named_ids_n_elems,
GCancellable *cancellable,
GError **perror)
@@ -3807,7 +4385,7 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
if (ids) {
for (i = 0; i < named_ids_n_elems; i++) {
- ResolveNamedIDsData *data = &named_ids_list[i];
+ EResolveNamedIDsData *data = &named_ids_list[i];
uint32_t propid;
propid = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (data->pidlid_propid)));
@@ -3834,10 +4412,17 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
nameid = mapi_nameid_new (mem_ctx);
SPropTagArray = talloc_zero (mem_ctx, struct SPropTagArray);
- /* Attempt to open the folder */
- ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
+ if (fid) {
+ /* Attempt to open the folder */
+ ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ goto cleanup;
+ }
+ } else {
+ if (!priv->session->nspi || !priv->session->nspi->ctx) {
+ ms = MAPI_E_UNCONFIGURED;
+ goto cleanup;
+ }
}
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -3853,7 +4438,7 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
}
for (i = 0; i < todo->len; i++) {
- ResolveNamedIDsData *data = todo->pdata[i];
+ EResolveNamedIDsData *data = todo->pdata[i];
if (mapi_nameid_canonical_add (nameid, data->pidlid_propid) != MAPI_E_SUCCESS)
data->propid = MAPI_E_RESERVED;
@@ -3866,7 +4451,88 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
goto cleanup;
}
- ms = mapi_nameid_GetIDsFromNames (nameid, &obj_folder, SPropTagArray);
+ if (fid) {
+ ms = mapi_nameid_GetIDsFromNames (nameid, &obj_folder, SPropTagArray);
+ } else {
+ /* lookup in GAL */
+ struct SPropTagArray *gal_tags;
+ uint32_t prop_count = nameid->count;
+ struct PropertyName_r *names = talloc_zero_array (mem_ctx, struct PropertyName_r, prop_count + 1);
+
+ g_assert (names != NULL);
+
+ SPropTagArray = talloc_zero (mem_ctx, struct SPropTagArray);
+ g_assert (SPropTagArray != NULL);
+
+ SPropTagArray->cValues = nameid->count;
+ SPropTagArray->aulPropTag = talloc_zero_array (mem_ctx, enum MAPITAGS, SPropTagArray->cValues + 1);
+ g_assert (SPropTagArray->aulPropTag != NULL);
+
+ j = 0;
+ for (i = 0; i < nameid->count; i++) {
+ guint ab[16];
+
+ SPropTagArray->aulPropTag[i] = nameid->entries[i].proptag;
+
+ if (nameid->entries[i].ulKind == MNID_ID &&
+ 16 == sscanf (nameid->entries[i].OLEGUID,
+ "%02x%02x%02x%02x-"
+ "%02x%02x-"
+ "%02x%02x-"
+ "%02x%02x-"
+ "%02x%02x%02x%02x%02x%02x",
+ &ab[0], &ab[1], &ab[2], &ab[3],
+ &ab[4], &ab[5],
+ &ab[6], &ab[7],
+ &ab[8], &ab[9],
+ &ab[10], &ab[11], &ab[12], &ab[13], &ab[14], &ab[15])) {
+ gint k;
+
+ names[j].ulReserved = 0;
+ names[j].lID = nameid->entries[i].lid;
+ names[j].lpguid = talloc_zero (mem_ctx, struct FlatUID_r);
+
+ for (k = 0; k < 16; k++) {
+ names[j].lpguid->ab[k] = (ab[k] & 0xFF);
+ }
+
+ j++;
+ } else {
+ SPropTagArray->aulPropTag[i] = (SPropTagArray->aulPropTag[i] & (~0xFFFF)) | PT_ERROR;
+ prop_count--;
+ }
+ }
+
+ if (prop_count > 0) {
+ ms = nspi_GetIDsFromNames (priv->session->nspi->ctx, mem_ctx, false, prop_count, names, &gal_tags);
+ if (ms == MAPI_E_SUCCESS && gal_tags) {
+ if (gal_tags->cValues != prop_count)
+ g_warning ("%s: Requested (%d) and returned (%d) property names don't match", G_STRFUNC, prop_count, gal_tags->cValues);
+
+ j = 0;
+ for (i = 0; i < gal_tags->cValues; i++) {
+ while (j < SPropTagArray->cValues && (SPropTagArray->aulPropTag[j] & 0xFFFF) == PT_ERROR) {
+ j++;
+ }
+
+ if (j >= SPropTagArray->cValues)
+ break;
+
+ SPropTagArray->aulPropTag[j] = gal_tags->aulPropTag[i];
+ }
+
+ while (j < SPropTagArray->cValues) {
+ SPropTagArray->aulPropTag[j] = (SPropTagArray->aulPropTag[j] & (~0xFFFF)) | PT_ERROR;
+ j++;
+ }
+ }
+ } else {
+ ms = MAPI_E_NOT_FOUND;
+ }
+
+ talloc_free (names);
+ }
+
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
goto cleanup;
@@ -3879,7 +4545,7 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
for (i = 0, j = 0; i < SPropTagArray->cValues && j < todo->len; i++) {
while (j < todo->len) {
- ResolveNamedIDsData *data = todo->pdata[j];
+ EResolveNamedIDsData *data = todo->pdata[j];
if (data && data->propid == 0) {
if ((SPropTagArray->aulPropTag[i] & 0xFFFF) == PT_ERROR)
data->propid = MAPI_E_RESERVED;
@@ -3906,7 +4572,7 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
}
for (i = 0; i < todo->len; i++) {
- ResolveNamedIDsData *data = todo->pdata[i];
+ EResolveNamedIDsData *data = todo->pdata[i];
g_hash_table_insert (ids, GUINT_TO_POINTER (data->pidlid_propid), GUINT_TO_POINTER (data->propid));
}
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 2c9b6ea..348c0a3 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -23,7 +23,7 @@
*/
#ifndef E_MAPI_CONNECTION_H
-#define E_MAPI_CONNECTION_H
+#define E_MAPI_CONNECTION_H
#include <glib.h>
#include <glib-object.h>
@@ -64,13 +64,14 @@ typedef enum {
typedef struct {
uint32_t pidlid_propid; /* PidLid or PidName legacy property named ID to resolve */
uint32_t propid; /* resolved prop ID; equals to MAPI_E_RESERVED when not found or other error */
-} ResolveNamedIDsData;
+} EResolveNamedIDsData;
typedef struct {
- mapi_id_t mid; /* message ID, from PidTagMid */
- const gchar *msg_class; /* PidTagMessageClass */
- uint32_t msg_flags; /* MAPI MSGFLAG_* bit OR, from PidTagMessageFlags */
- time_t last_modified; /* PidTagLastModificationTime as UTC */
+ mapi_id_t mid; /* message ID, from PidTagMid */
+ uint32_t obj_type; /* PidTagObjectType */
+ const gchar *msg_class; /* PidTagMessageClass */
+ uint32_t msg_flags; /* MAPI MSGFLAG_* bit OR, from PidTagMessageFlags */
+ time_t last_modified; /* PidTagLastModificationTime as UTC */
} ListObjectsData;
struct _EMapiObject;
@@ -123,15 +124,7 @@ typedef enum {
} EMapiCreateFlags;
/* callbacks return whether to continue in transfer of the next object */
-typedef gboolean (*FetchGALCallback) (EMapiConnection *conn,
- uint32_t row_index,
- uint32_t n_rows,
- struct SRow *aRow,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
typedef gboolean (*BuildReadPropsCB) (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct SPropTagArray *props,
gpointer data,
@@ -285,13 +278,30 @@ gboolean e_mapi_connection_modify_object (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
-gboolean e_mapi_connection_fetch_gal (EMapiConnection *conn,
+gboolean e_mapi_connection_count_gal_objects (EMapiConnection *conn,
+ guint32 *obj_total,
+ GCancellable *cancellable,
+ GError **perror);
+
+gboolean e_mapi_connection_list_gal_objects (EMapiConnection *conn,
BuildRestrictionsCB build_rs_cb,
gpointer build_rs_cb_data,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchGALCallback cb,
- gpointer data,
+ ListObjectsCB cb,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror);
+
+gboolean e_mapi_connection_transfer_gal_objects (EMapiConnection *conn,
+ const GSList *mids,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror);
+
+gboolean e_mapi_connection_transfer_gal_object (EMapiConnection *conn,
+ mapi_id_t message_id,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
GCancellable *cancellable,
GError **perror);
@@ -384,7 +394,7 @@ GSList * e_mapi_connection_peek_folders_list (EMapiConnection *conn);
gboolean e_mapi_connection_resolve_named_props (EMapiConnection *conn,
mapi_id_t fid,
- ResolveNamedIDsData *named_ids_list,
+ EResolveNamedIDsData *named_ids_list,
guint named_ids_n_elems,
GCancellable *cancellable,
GError **perror);
diff --git a/src/libexchangemapi/e-mapi-debug.c b/src/libexchangemapi/e-mapi-debug.c
index a715895..b9cb8ad 100644
--- a/src/libexchangemapi/e-mapi-debug.c
+++ b/src/libexchangemapi/e-mapi-debug.c
@@ -110,603 +110,618 @@ dump_bin (const uint8_t *bin, uint32_t bin_sz, gint indent)
}
static const gchar *
-get_namedid_name (EMapiConnection *conn, mapi_id_t fid, uint32_t proptag)
+get_namedid_name (uint32_t proptag)
{
- if (conn)
- proptag = e_mapi_connection_unresolve_proptag_to_nameid (conn, fid, proptag);
+ static GHashTable *names = NULL;
if (proptag == MAPI_E_RESERVED)
return NULL;
- switch (proptag) {
- #define cs(x) case x: return #x;
- cs (PidLidAddressBookProviderArrayType)
- cs (PidLidAddressBookProviderEmailList)
- cs (PidLidAddressCountryCode)
- cs (PidLidAnniversaryEventEntryId)
- cs (PidLidAutoLog)
- cs (PidLidBirthdayEventEntryId)
- cs (PidLidBirthdayLocal)
- cs (PidLidBusinessCardCardPicture)
- cs (PidLidBusinessCardDisplayDefinition)
- cs (PidLidContactCharacterSet)
- cs (PidLidContactItemData)
- cs (PidLidContactUserField1)
- cs (PidLidContactUserField2)
- cs (PidLidContactUserField3)
- cs (PidLidContactUserField4)
- cs (PidLidDepartment)
- cs (PidLidDistributionListChecksum)
- cs (PidLidDistributionListMembers)
- cs (PidLidDistributionListName)
- cs (PidLidDistributionListOneOffMembers)
- cs (PidLidDistributionListStream)
- cs (PidLidEmail1AddressType)
- cs (PidLidEmail1DisplayName)
- cs (PidLidEmail1EmailAddress)
- cs (PidLidEmail1OriginalDisplayName)
- cs (PidLidEmail1OriginalEntryId)
- cs (PidLidEmail1RichTextFormat)
- cs (PidLidEmail2AddressType)
- cs (PidLidEmail2DisplayName)
- cs (PidLidEmail2EmailAddress)
- cs (PidLidEmail2OriginalDisplayName)
- cs (PidLidEmail2OriginalEntryId)
- cs (PidLidEmail2RichTextFormat)
- cs (PidLidEmail3AddressType)
- cs (PidLidEmail3DisplayName)
- cs (PidLidEmail3EmailAddress)
- cs (PidLidEmail3OriginalDisplayName)
- cs (PidLidEmail3OriginalEntryId)
- cs (PidLidEmail3RichTextFormat)
- cs (PidLidEmailList)
- cs (PidLidFax1AddressType)
- cs (PidLidFax1EmailAddress)
- cs (PidLidFax1OriginalDisplayName)
- cs (PidLidFax1OriginalEntryId)
- cs (PidLidFax2AddressType)
- cs (PidLidFax2EmailAddress)
- cs (PidLidFax2OriginalDisplayName)
- cs (PidLidFax2OriginalEntryId)
- cs (PidLidFax3AddressType)
- cs (PidLidFax3EmailAddress)
- cs (PidLidFax3OriginalDisplayName)
- cs (PidLidFax3OriginalEntryId)
- cs (PidLidFileUnder)
- cs (PidLidFileUnderId)
- cs (PidLidFileUnderList)
- cs (PidLidFreeBusyLocation)
- cs (PidLidHasPicture)
- cs (PidLidHomeAddress)
- cs (PidLidHomeAddressCountryCode)
- cs (PidLidHtml)
- cs (PidLidInstantMessagingAddress)
- cs (PidLidOtherAddress)
- cs (PidLidOtherAddressCountryCode)
- cs (PidLidPostalAddressId)
- cs (PidLidReferredBy)
- cs (PidLidWeddingAnniversaryLocal)
- cs (PidLidWorkAddress)
- cs (PidLidWorkAddressCity)
- cs (PidLidWorkAddressCountry)
- cs (PidLidWorkAddressCountryCode)
- cs (PidLidWorkAddressPostalCode)
- cs (PidLidWorkAddressPostOfficeBox)
- cs (PidLidWorkAddressState)
- cs (PidLidYomiCompanyName)
- cs (PidLidYomiFirstName)
- cs (PidLidYomiLastName)
- cs (PidLidAllAttendeesString)
- cs (PidLidAllowExternalCheck)
- cs (PidLidAppointmentAuxiliaryFlags)
- cs (PidLidAppointmentColor)
- cs (PidLidAppointmentCounterProposal)
- cs (PidLidAppointmentDuration)
- cs (PidLidAppointmentEndDate)
- cs (PidLidAppointmentEndTime)
- cs (PidLidAppointmentEndWhole)
- cs (PidLidAppointmentLastSequence)
- cs (PidLidAppointmentNotAllowPropose)
- cs (PidLidAppointmentProposalNumber)
- cs (PidLidAppointmentProposedDuration)
- cs (PidLidAppointmentProposedEndWhole)
- cs (PidLidAppointmentProposedStartWhole)
- cs (PidLidAppointmentRecur)
- cs (PidLidAppointmentReplyName)
- cs (PidLidAppointmentReplyTime)
- cs (PidLidAppointmentSequence)
- cs (PidLidAppointmentSequenceTime)
- cs (PidLidAppointmentStartDate)
- cs (PidLidAppointmentStartTime)
- cs (PidLidAppointmentStartWhole)
- cs (PidLidAppointmentStateFlags)
- cs (PidLidAppointmentSubType)
- cs (PidLidAppointmentTimeZoneDefinitionEndDisplay)
- cs (PidLidAppointmentTimeZoneDefinitionRecur)
- cs (PidLidAppointmentTimeZoneDefinitionStartDisplay)
- cs (PidLidAppointmentUnsendableRecipients)
- cs (PidLidAppointmentUpdateTime)
- cs (PidLidAutoFillLocation)
- cs (PidLidAutoStartCheck)
- cs (PidLidBusyStatus)
- cs (PidLidCcAttendeesString)
- cs (PidLidChangeHighlight)
- cs (PidLidClipEnd)
- cs (PidLidClipStart)
- cs (PidLidCollaborateDoc)
- cs (PidLidConferencingCheck)
- cs (PidLidConferencingType)
- cs (PidLidDirectory)
- cs (PidLidExceptionReplaceTime)
- cs (PidLidFExceptionalAttendees)
- cs (PidLidFExceptionalBody)
- cs (PidLidFInvited)
- cs (PidLidForwardInstance)
- cs (PidLidForwardNotificationRecipients)
- cs (PidLidFOthersAppointment)
- cs (PidLidInboundICalStream)
- cs (PidLidIntendedBusyStatus)
- cs (PidLidLinkedTaskItems)
- cs (PidLidLocation)
- cs (PidLidMeetingWorkspaceUrl)
- cs (PidLidNetShowUrl)
- cs (PidLidOnlinePassword)
- cs (PidLidOrganizerAlias)
- cs (PidLidOriginalStoreEntryId)
- cs (PidLidOwnerName)
- cs (PidLidRecurrencePattern)
- cs (PidLidRecurrenceType)
- cs (PidLidRecurring)
- cs (PidLidResponseStatus)
- cs (PidLidSingleBodyICal)
- cs (PidLidTimeZoneDescription)
- cs (PidLidTimeZoneStruct)
- cs (PidLidToAttendeesString)
- cs (PidLidClientIntent)
- cs (PidLidServerProcessed)
- cs (PidLidServerProcessingActions)
- cs (PidLidAgingDontAgeMe)
- cs (PidLidAutoProcessState)
- cs (PidLidBilling)
- cs (PidLidClassification)
- cs (PidLidClassificationDescription)
- cs (PidLidClassificationGuid)
- cs (PidLidClassificationKeep)
- cs (PidLidClassified)
- cs (PidLidCommonEnd)
- cs (PidLidCommonStart)
- cs (PidLidCompanies)
- cs (PidLidContactLinkEntry)
- cs (PidLidContactLinkName)
- cs (PidLidContactLinkSearchKey)
- cs (PidLidContacts)
- cs (PidLidConversationActionLastAppliedTime)
- cs (PidLidConversationActionMaxDeliveryTime)
- cs (PidLidConversationActionMoveFolderEid)
- cs (PidLidConversationActionMoveStoreEid)
- cs (PidLidConversationActionVersion)
- cs (PidLidConversationProcessed)
- cs (PidLidCurrentVersion)
- cs (PidLidCurrentVersionName)
- cs (PidLidDayOfMonth)
- cs (PidLidFlagRequest)
- cs (PidLidFlagString)
- cs (PidLidICalendarDayOfWeekMask)
- cs (PidLidInfoPathFormName)
- cs (PidLidInternetAccountName)
- cs (PidLidInternetAccountStamp)
- cs (PidLidMonthOfYear)
- cs (PidLidNoEndDateFlag)
- cs (PidLidNonSendableBcc)
- cs (PidLidNonSendableCc)
- cs (PidLidNonSendableTo)
- cs (PidLidNonSendBccTrackStatus)
- cs (PidLidNonSendCcTrackStatus)
- cs (PidLidNonSendToTrackStatus)
- cs (PidLidOccurrences)
- cs (PidLidPrivate)
- cs (PidLidPromptSendUpdate)
- cs (PidLidRecurrenceDuration)
- cs (PidLidReferenceEntryId)
- cs (PidLidReminderDelta)
- cs (PidLidReminderFileParameter)
- cs (PidLidReminderOverride)
- cs (PidLidReminderPlaySound)
- cs (PidLidReminderSet)
- cs (PidLidReminderSignalTime)
- cs (PidLidReminderTime)
- cs (PidLidReminderTimeDate)
- cs (PidLidReminderTimeTime)
- cs (PidLidReminderType)
- cs (PidLidRemoteStatus)
- cs (PidLidSideEffects)
- cs (PidLidSmartNoAttach)
- cs (PidLidSpamOriginalFolder)
- cs (PidLidTaskGlobalId)
- cs (PidLidTaskMode)
- cs (PidLidToDoOrdinalDate)
- cs (PidLidToDoSubOrdinal)
- cs (PidLidToDoTitle)
- cs (PidLidUseTnef)
- cs (PidLidValidFlagStringProof)
- cs (PidLidVerbResponse)
- cs (PidLidVerbStream)
- cs (PidLidLogDocumentPosted)
- cs (PidLidLogDocumentPrinted)
- cs (PidLidLogDocumentRouted)
- cs (PidLidLogDocumentSaved)
- cs (PidLidLogDuration)
- cs (PidLidLogEnd)
- cs (PidLidLogFlags)
- cs (PidLidLogStart)
- cs (PidLidLogType)
- cs (PidLidLogTypeDesc)
- cs (PidLidAppointmentMessageClass)
- cs (PidLidAttendeeCriticalChange)
- cs (PidLidCalendarType)
- cs (PidLidCleanGlobalObjectId)
- cs (PidLidDayInterval)
- cs (PidLidDelegateMail)
- cs (PidLidEndRecurrenceDate)
- cs (PidLidEndRecurrenceTime)
- cs (PidLidGlobalObjectId)
- cs (PidLidIsException)
- cs (PidLidIsRecurring)
- cs (PidLidIsSilent)
- cs (PidLidMeetingType)
- cs (PidLidMonthInterval)
- cs (PidLidMonthOfYearMask)
- cs (PidLidOldLocation)
- cs (PidLidOldRecurrenceType)
- cs (PidLidOldWhenEndWhole)
- cs (PidLidOldWhenStartWhole)
- cs (PidLidOptionalAttendees)
- cs (PidLidOwnerCriticalChange)
- cs (PidLidRequiredAttendees)
- cs (PidLidResourceAttendees)
- cs (PidLidStartRecurrenceDate)
- cs (PidLidStartRecurrenceTime)
- cs (PidLidTimeZone)
- cs (PidLidWeekInterval)
- cs (PidLidWhere)
- cs (PidLidYearInterval)
- cs (PidLidNoteColor)
- cs (PidLidNoteHeight)
- cs (PidLidNoteWidth)
- cs (PidLidNoteX)
- cs (PidLidNoteY)
- cs (PidLidPostRssChannel)
- cs (PidLidPostRssChannelLink)
- cs (PidLidPostRssItemGuid)
- cs (PidLidPostRssItemHash)
- cs (PidLidPostRssItemLink)
- cs (PidLidPostRssItemXml)
- cs (PidLidPostRssSubscription)
- cs (PidLidSharingAnonymity)
- cs (PidLidSharingBindingEntryId)
- cs (PidLidSharingBrowseUrl)
- cs (PidLidSharingCapabilities)
- cs (PidLidSharingConfigurationUrl)
- cs (PidLidSharingDataRangeEnd)
- cs (PidLidSharingDataRangeStart)
- cs (PidLidSharingDetail)
- cs (PidLidSharingExtensionXml)
- cs (PidLidSharingFilter)
- cs (PidLidSharingFlags)
- cs (PidLidSharingFlavor)
- cs (PidLidSharingFolderEntryId)
- cs (PidLidSharingIndexEntryId)
- cs (PidLidSharingInitiatorEntryId)
- cs (PidLidSharingInitiatorName)
- cs (PidLidSharingInitiatorSmtp)
- cs (PidLidSharingInstanceGuid)
- cs (PidLidSharingLastAutoSyncTime)
- cs (PidLidSharingLastSyncTime)
- cs (PidLidSharingLocalComment)
- cs (PidLidSharingLocalLastModificationTime)
- cs (PidLidSharingLocalName)
- cs (PidLidSharingLocalPath)
- cs (PidLidSharingLocalStoreUid)
- cs (PidLidSharingLocalType)
- cs (PidLidSharingLocalUid)
- cs (PidLidSharingOriginalMessageEntryId)
- cs (PidLidSharingParentBindingEntryId)
- cs (PidLidSharingParticipants)
- cs (PidLidSharingPermissions)
- cs (PidLidSharingProviderExtension)
- cs (PidLidSharingProviderGuid)
- cs (PidLidSharingProviderName)
- cs (PidLidSharingProviderUrl)
- cs (PidLidSharingRangeEnd)
- cs (PidLidSharingRangeStart)
- cs (PidLidSharingReciprocation)
- cs (PidLidSharingRemoteByteSize)
- cs (PidLidSharingRemoteComment)
- cs (PidLidSharingRemoteCrc)
- cs (PidLidSharingRemoteLastModificationTime)
- cs (PidLidSharingRemoteMessageCount)
- cs (PidLidSharingRemoteName)
- cs (PidLidSharingRemotePass)
- cs (PidLidSharingRemotePath)
- cs (PidLidSharingRemoteStoreUid)
- cs (PidLidSharingRemoteType)
- cs (PidLidSharingRemoteUid)
- cs (PidLidSharingRemoteUser)
- cs (PidLidSharingRemoteVersion)
- cs (PidLidSharingResponseTime)
- cs (PidLidSharingResponseType)
- cs (PidLidSharingRoamLog)
- cs (PidLidSharingStart)
- cs (PidLidSharingStatus)
- cs (PidLidSharingStop)
- cs (PidLidSharingSyncFlags)
- cs (PidLidSharingSyncInterval)
- cs (PidLidSharingTimeToLive)
- cs (PidLidSharingTimeToLiveAuto)
- cs (PidLidSharingWorkingHoursDays)
- cs (PidLidSharingWorkingHoursEnd)
- cs (PidLidSharingWorkingHoursStart)
- cs (PidLidSharingWorkingHoursTimeZone)
- cs (PidLidPercentComplete)
- cs (PidLidTaskAcceptanceState)
- cs (PidLidTaskAccepted)
- cs (PidLidTaskActualEffort)
- cs (PidLidTaskAssigner)
- cs (PidLidTaskAssigners)
- cs (PidLidTaskComplete)
- cs (PidLidTaskCustomFlags)
- cs (PidLidTaskDateCompleted)
- cs (PidLidTaskDeadOccurrence)
- cs (PidLidTaskDueDate)
- cs (PidLidTaskEstimatedEffort)
- cs (PidLidTaskFCreator)
- cs (PidLidTaskFFixOffline)
- cs (PidLidTaskFRecurring)
- cs (PidLidTaskHistory)
- cs (PidLidTaskLastDelegate)
- cs (PidLidTaskLastUpdate)
- cs (PidLidTaskLastUser)
- cs (PidLidTaskMultipleRecipients)
- cs (PidLidTaskNoCompute)
- cs (PidLidTaskOrdinal)
- cs (PidLidTaskOwner)
- cs (PidLidTaskOwnership)
- cs (PidLidTaskRecurrence)
- cs (PidLidTaskResetReminder)
- cs (PidLidTaskRole)
- cs (PidLidTaskStartDate)
- cs (PidLidTaskState)
- cs (PidLidTaskStatus)
- cs (PidLidTaskStatusOnComplete)
- cs (PidLidTaskUpdates)
- cs (PidLidTaskVersion)
- cs (PidLidTeamTask)
- cs (PidLidTrustRecipientHighlights)
- cs (PidLidCategories)
- cs (PidNameInstantMessagingAddress2)
- cs (PidNameInstantMessagingAddress3)
- cs (PidNameAttachmentMacContentType)
- cs (PidNameAttachmentMacInfo)
- cs (PidNameOriginalSpamConfidenceLevel)
- cs (PidNameAudioNotes)
- cs (PidNameAutomaticSpeechRecognitionData)
- cs (PidNameOutlookProtectionRuleTimestamp)
- cs (PidNameXUnifiedMessagingPartnerAssignedId)
- cs (PidNameXUnifiedMessagingPartnerContent)
- cs (PidNameXUnifiedMessagingPartnerContext)
- cs (PidNameXUnifiedMessagingPartnerStatus)
- cs (PidNameAcceptLanguage)
- cs (PidNameApprovalAllowedDecisionMakers)
- cs (PidNameApprovalRequestor)
- cs (PidNameApproved)
- cs (PidNameAuthenticatedAs)
- cs (PidNameAuthenticatedDomain)
- cs (PidNameAuthenticatedMechanism)
- cs (PidNameAuthenticatedSource)
- cs (PidNameBcc)
- cs (PidNameCc)
- cs (PidNameContentBase)
- cs (PidNameContentClass)
- cs (PidNameContentDisposition)
- cs (PidNameContentID)
- cs (PidNameContentLanguage)
- cs (PidNameContentLocation)
- cs (PidNameContentTransferEncoding)
- cs (PidNameContentType)
- cs (PidNameControl)
- cs (PidNameCrossReference)
- cs (PidNameDisposition)
- cs (PidNameDispositionNotificationTo)
- cs (PidNameDistribution)
- cs (PidNameExpires)
- cs (PidNameExpiryDate)
- cs (PidNameFollowupTo)
- cs (PidNameFrom)
- cs (PidNameImportance)
- cs (PidNameInReplyTo)
- cs (PidNameInternetComment)
- cs (PidNameInternetKeywords)
- cs (PidNameInternetSubject)
- cs (PidNameLines)
- cs (PidNameMessageId)
- cs (PidNameMimeVersion)
- cs (PidNameNewsgroups)
- cs (PidNameNntpPostingHost)
- cs (PidNameOrganization)
- cs (PidNameOriginalRecipient)
- cs (PidNameOutlookProtectionRuleOverridden)
- cs (PidNameOutlookProtectionRuleVersion)
- cs (PidNamePath)
- cs (PidNamePostingVersion)
- cs (PidNamePriority)
- cs (PidNameReceived)
- cs (PidNameReferences)
- cs (PidNameRelayVersion)
- cs (PidNameReplyBy)
- cs (PidNameReplyTo)
- cs (PidNameReturnPath)
- cs (PidNameReturnReceiptTo)
- cs (PidNameRightsProtectMessage)
- cs (PidNameSender)
- cs (PidNameSensitivity)
- cs (PidNameSummary)
- cs (PidNameThreadIndex)
- cs (PidNameThreadTopic)
- cs (PidNameTo)
- cs (PidNameXCallId)
- cs (PidNameXFaxNumberOfPages)
- cs (PidNameXMailer)
- cs (PidNameXMessageCompleted)
- cs (PidNameXMessageFlag)
- cs (PidNameXRequireProtectedPlayOnPhone)
- cs (PidNameXSenderTelephoneNumber)
- cs (PidNameXSharingBrowseUrl)
- cs (PidNameXSharingCapabilities)
- cs (PidNameXSharingConfigUrl)
- cs (PidNameXSharingExendedCaps)
- cs (PidNameXSharingFlavor)
- cs (PidNameXSharingInstanceGuid)
- cs (PidNameXSharingLocalType)
- cs (PidNameXSharingProviderGuid)
- cs (PidNameXSharingProviderName)
- cs (PidNameXSharingProviderUrl)
- cs (PidNameXSharingRemoteName)
- cs (PidNameXSharingRemotePath)
- cs (PidNameXSharingRemoteStoreUid)
- cs (PidNameXSharingRemoteType)
- cs (PidNameXSharingRemoteUid)
- cs (PidNameXUnsent)
- cs (PidNameXVoiceMessageAttachmentOrder)
- cs (PidNameXVoiceMessageDuration)
- cs (PidNameXVoiceMessageSenderName)
- cs (PidNameApplicationName)
- cs (PidNameAuthor)
- cs (PidNameByteCount)
- cs (PidNameCalendarAttendeeRole)
- cs (PidNameCalendarBusystatus)
- cs (PidNameCalendarContact)
- cs (PidNameCalendarContactUrl)
- cs (PidNameCalendarCreated)
- cs (PidNameCalendarDescriptionUrl)
- cs (PidNameCalendarDuration)
- cs (PidNameCalendarExceptionDate)
- cs (PidNameCalendarExceptionRule)
- cs (PidNameCalendarGeoLatitude)
- cs (PidNameCalendarGeoLongitude)
- cs (PidNameCalendarInstanceType)
- cs (PidNameCalendarIsOrganizer)
- cs (PidNameCalendarLastModified)
- cs (PidNameCalendarLocationUrl)
- cs (PidNameCalendarMeetingStatus)
- cs (PidNameCalendarMethod)
- cs (PidNameCalendarProductId)
- cs (PidNameCalendarRecurrenceIdRange)
- cs (PidNameCalendarReminderOffset)
- cs (PidNameCalendarResources)
- cs (PidNameCalendarRsvp)
- cs (PidNameCalendarSequence)
- cs (PidNameCalendarTimeZone)
- cs (PidNameCalendarTimeZoneId)
- cs (PidNameCalendarTransparent)
- cs (PidNameCalendarUid)
- cs (PidNameCalendarVersion)
- cs (PidNameCategory)
- cs (PidNameCharacterCount)
- cs (PidNameComments)
- cs (PidNameCompany)
- cs (PidNameContactsAlternateRecipient)
- cs (PidNameContactsCountry)
- cs (PidNameContactsEmail1)
- cs (PidNameContactsEmail2)
- cs (PidNameContactsEmail3)
- cs (PidNameContactsFileAs)
- cs (PidNameContactsFileasId)
- cs (PidNameContactsHomeLatitude)
- cs (PidNameContactsHomeLongitude)
- cs (PidNameContactsHomeTimeZone)
- cs (PidNameContactsMapUrl)
- cs (PidNameContactsOtherCountryCode)
- cs (PidNameContactsOtherPager)
- cs (PidNameContactsOtherTimeZone)
- cs (PidNameContactsProxyAddresses)
- cs (PidNameContactsSecretaryUrl)
- cs (PidNameContactsSourceUrl)
- cs (PidNameCreateDateTimeReadOnly)
- cs (PidNameDavGetContentType)
- cs (PidNameDavId)
- cs (PidNameDavIsCollection)
- cs (PidNameDavIsStructuredDocument)
- cs (PidNameDavParentName)
- cs (PidNameDavResourceType)
- cs (PidNameDavSearchRequest)
- cs (PidNameDavSearchType)
- cs (PidNameDavUid)
- cs (PidNameDocumentParts)
- cs (PidNameEditTime)
- cs (PidNameExchangeIntendedBusyStatus)
- cs (PidNameExchangeJunkEmailMoveStamp)
- cs (PidNameExchangeModifyExceptionStructure)
- cs (PidNameExchangeNoModifyExceptions)
- cs (PidNameExchangePatternEnd)
- cs (PidNameExchangePatternStart)
- cs (PidNameExchangePublicFolderEmailAddress)
- cs (PidNameExchangeReminderInterval)
- cs (PidNameExchDatabaseSchema)
- cs (PidNameExchDataExpectedContentClass)
- cs (PidNameExchDataSchemaCollectionReference)
- cs (PidNameHeadingPairs)
- cs (PidNameHiddenCount)
- cs (PidNameHttpmailCalendar)
- cs (PidNameHttpmailCc)
- cs (PidNameHttpmailContacts)
- cs (PidNameHttpmailContentMediaType)
- cs (PidNameHttpmailFrom)
- cs (PidNameHttpmailFromEmail)
- cs (PidNameHttpmailHtmlDescription)
- cs (PidNameHttpmailOutbox)
- cs (PidNameHttpmailSendMessage)
- cs (PidNameHttpmailSubmitted)
- cs (PidNameHttpmailTo)
- cs (PidNameICalendarRecurrenceDate)
- cs (PidNameICalendarRecurrenceRule)
- cs (PidNameKeywords)
- cs (PidNameLastAuthor)
- cs (PidNameLastPrinted)
- cs (PidNameLastSaveDateTime)
- cs (PidNameLineCount)
- cs (PidNameLinksDirty)
- cs (PidNameMailSubmissionUri)
- cs (PidNameManager)
- cs (PidNameMultimediaClipCount)
- cs (PidNameNoteCount)
- cs (PidNameOMSAccountGuid)
- cs (PidNameOMSMobileModel)
- cs (PidNameOMSScheduleTime)
- cs (PidNameOMSServiceType)
- cs (PidNameOMSSourceType)
- cs (PidNamePageCount)
- cs (PidNameParagraphCount)
- cs (PidNamePhishingStamp)
- cs (PidNamePresentationFormat)
- cs (PidNameQuarantineOriginalSender)
- cs (PidNameRevisionNumber)
- cs (PidNameRightsManagementLicense)
- cs (PidNameScale)
- cs (PidNameSecurity)
- cs (PidNameSlideCount)
- cs (PidNameSubject)
- cs (PidNameTemplate)
- cs (PidNameThumbnail)
- cs (PidNameTitle)
- cs (PidNameWordCount)
- #undef cs
+ if (!names) {
+ struct _array {
+ uint32_t proptag;
+ const gchar *name;
+ } array[] = {
+ #define cs(x) { x, #x } ,
+ cs (PidLidAddressBookProviderArrayType)
+ cs (PidLidAddressBookProviderEmailList)
+ cs (PidLidAddressCountryCode)
+ cs (PidLidAnniversaryEventEntryId)
+ cs (PidLidAutoLog)
+ cs (PidLidBirthdayEventEntryId)
+ cs (PidLidBirthdayLocal)
+ cs (PidLidBusinessCardCardPicture)
+ cs (PidLidBusinessCardDisplayDefinition)
+ cs (PidLidContactCharacterSet)
+ cs (PidLidContactItemData)
+ cs (PidLidContactUserField1)
+ cs (PidLidContactUserField2)
+ cs (PidLidContactUserField3)
+ cs (PidLidContactUserField4)
+ cs (PidLidDepartment)
+ cs (PidLidDistributionListChecksum)
+ cs (PidLidDistributionListMembers)
+ cs (PidLidDistributionListName)
+ cs (PidLidDistributionListOneOffMembers)
+ cs (PidLidDistributionListStream)
+ cs (PidLidEmail1AddressType)
+ cs (PidLidEmail1DisplayName)
+ cs (PidLidEmail1EmailAddress)
+ cs (PidLidEmail1OriginalDisplayName)
+ cs (PidLidEmail1OriginalEntryId)
+ cs (PidLidEmail1RichTextFormat)
+ cs (PidLidEmail2AddressType)
+ cs (PidLidEmail2DisplayName)
+ cs (PidLidEmail2EmailAddress)
+ cs (PidLidEmail2OriginalDisplayName)
+ cs (PidLidEmail2OriginalEntryId)
+ cs (PidLidEmail2RichTextFormat)
+ cs (PidLidEmail3AddressType)
+ cs (PidLidEmail3DisplayName)
+ cs (PidLidEmail3EmailAddress)
+ cs (PidLidEmail3OriginalDisplayName)
+ cs (PidLidEmail3OriginalEntryId)
+ cs (PidLidEmail3RichTextFormat)
+ cs (PidLidEmailList)
+ cs (PidLidFax1AddressType)
+ cs (PidLidFax1EmailAddress)
+ cs (PidLidFax1OriginalDisplayName)
+ cs (PidLidFax1OriginalEntryId)
+ cs (PidLidFax2AddressType)
+ cs (PidLidFax2EmailAddress)
+ cs (PidLidFax2OriginalDisplayName)
+ cs (PidLidFax2OriginalEntryId)
+ cs (PidLidFax3AddressType)
+ cs (PidLidFax3EmailAddress)
+ cs (PidLidFax3OriginalDisplayName)
+ cs (PidLidFax3OriginalEntryId)
+ cs (PidLidFileUnder)
+ cs (PidLidFileUnderId)
+ cs (PidLidFileUnderList)
+ cs (PidLidFreeBusyLocation)
+ cs (PidLidHasPicture)
+ cs (PidLidHomeAddress)
+ cs (PidLidHomeAddressCountryCode)
+ cs (PidLidHtml)
+ cs (PidLidInstantMessagingAddress)
+ cs (PidLidOtherAddress)
+ cs (PidLidOtherAddressCountryCode)
+ cs (PidLidPostalAddressId)
+ cs (PidLidReferredBy)
+ cs (PidLidWeddingAnniversaryLocal)
+ cs (PidLidWorkAddress)
+ cs (PidLidWorkAddressCity)
+ cs (PidLidWorkAddressCountry)
+ cs (PidLidWorkAddressCountryCode)
+ cs (PidLidWorkAddressPostalCode)
+ cs (PidLidWorkAddressPostOfficeBox)
+ cs (PidLidWorkAddressState)
+ cs (PidLidYomiCompanyName)
+ cs (PidLidYomiFirstName)
+ cs (PidLidYomiLastName)
+ cs (PidLidAllAttendeesString)
+ cs (PidLidAllowExternalCheck)
+ cs (PidLidAppointmentAuxiliaryFlags)
+ cs (PidLidAppointmentColor)
+ cs (PidLidAppointmentCounterProposal)
+ cs (PidLidAppointmentDuration)
+ cs (PidLidAppointmentEndDate)
+ cs (PidLidAppointmentEndTime)
+ cs (PidLidAppointmentEndWhole)
+ cs (PidLidAppointmentLastSequence)
+ cs (PidLidAppointmentNotAllowPropose)
+ cs (PidLidAppointmentProposalNumber)
+ cs (PidLidAppointmentProposedDuration)
+ cs (PidLidAppointmentProposedEndWhole)
+ cs (PidLidAppointmentProposedStartWhole)
+ cs (PidLidAppointmentRecur)
+ cs (PidLidAppointmentReplyName)
+ cs (PidLidAppointmentReplyTime)
+ cs (PidLidAppointmentSequence)
+ cs (PidLidAppointmentSequenceTime)
+ cs (PidLidAppointmentStartDate)
+ cs (PidLidAppointmentStartTime)
+ cs (PidLidAppointmentStartWhole)
+ cs (PidLidAppointmentStateFlags)
+ cs (PidLidAppointmentSubType)
+ cs (PidLidAppointmentTimeZoneDefinitionEndDisplay)
+ cs (PidLidAppointmentTimeZoneDefinitionRecur)
+ cs (PidLidAppointmentTimeZoneDefinitionStartDisplay)
+ cs (PidLidAppointmentUnsendableRecipients)
+ cs (PidLidAppointmentUpdateTime)
+ cs (PidLidAutoFillLocation)
+ cs (PidLidAutoStartCheck)
+ cs (PidLidBusyStatus)
+ cs (PidLidCcAttendeesString)
+ cs (PidLidChangeHighlight)
+ cs (PidLidClipEnd)
+ cs (PidLidClipStart)
+ cs (PidLidCollaborateDoc)
+ cs (PidLidConferencingCheck)
+ cs (PidLidConferencingType)
+ cs (PidLidDirectory)
+ cs (PidLidExceptionReplaceTime)
+ cs (PidLidFExceptionalAttendees)
+ cs (PidLidFExceptionalBody)
+ cs (PidLidFInvited)
+ cs (PidLidForwardInstance)
+ cs (PidLidForwardNotificationRecipients)
+ cs (PidLidFOthersAppointment)
+ cs (PidLidInboundICalStream)
+ cs (PidLidIntendedBusyStatus)
+ cs (PidLidLinkedTaskItems)
+ cs (PidLidLocation)
+ cs (PidLidMeetingWorkspaceUrl)
+ cs (PidLidNetShowUrl)
+ cs (PidLidOnlinePassword)
+ cs (PidLidOrganizerAlias)
+ cs (PidLidOriginalStoreEntryId)
+ cs (PidLidOwnerName)
+ cs (PidLidRecurrencePattern)
+ cs (PidLidRecurrenceType)
+ cs (PidLidRecurring)
+ cs (PidLidResponseStatus)
+ cs (PidLidSingleBodyICal)
+ cs (PidLidTimeZoneDescription)
+ cs (PidLidTimeZoneStruct)
+ cs (PidLidToAttendeesString)
+ cs (PidLidClientIntent)
+ cs (PidLidServerProcessed)
+ cs (PidLidServerProcessingActions)
+ cs (PidLidAgingDontAgeMe)
+ cs (PidLidAutoProcessState)
+ cs (PidLidBilling)
+ cs (PidLidClassification)
+ cs (PidLidClassificationDescription)
+ cs (PidLidClassificationGuid)
+ cs (PidLidClassificationKeep)
+ cs (PidLidClassified)
+ cs (PidLidCommonEnd)
+ cs (PidLidCommonStart)
+ cs (PidLidCompanies)
+ cs (PidLidContactLinkEntry)
+ cs (PidLidContactLinkName)
+ cs (PidLidContactLinkSearchKey)
+ cs (PidLidContacts)
+ cs (PidLidConversationActionLastAppliedTime)
+ cs (PidLidConversationActionMaxDeliveryTime)
+ cs (PidLidConversationActionMoveFolderEid)
+ cs (PidLidConversationActionMoveStoreEid)
+ cs (PidLidConversationActionVersion)
+ cs (PidLidConversationProcessed)
+ cs (PidLidCurrentVersion)
+ cs (PidLidCurrentVersionName)
+ cs (PidLidDayOfMonth)
+ cs (PidLidFlagRequest)
+ cs (PidLidFlagString)
+ cs (PidLidICalendarDayOfWeekMask)
+ cs (PidLidInfoPathFormName)
+ cs (PidLidInternetAccountName)
+ cs (PidLidInternetAccountStamp)
+ cs (PidLidMonthOfYear)
+ cs (PidLidNoEndDateFlag)
+ cs (PidLidNonSendableBcc)
+ cs (PidLidNonSendableCc)
+ cs (PidLidNonSendableTo)
+ cs (PidLidNonSendBccTrackStatus)
+ cs (PidLidNonSendCcTrackStatus)
+ cs (PidLidNonSendToTrackStatus)
+ cs (PidLidOccurrences)
+ cs (PidLidPrivate)
+ cs (PidLidPromptSendUpdate)
+ cs (PidLidRecurrenceDuration)
+ cs (PidLidReferenceEntryId)
+ cs (PidLidReminderDelta)
+ cs (PidLidReminderFileParameter)
+ cs (PidLidReminderOverride)
+ cs (PidLidReminderPlaySound)
+ cs (PidLidReminderSet)
+ cs (PidLidReminderSignalTime)
+ cs (PidLidReminderTime)
+ cs (PidLidReminderTimeDate)
+ cs (PidLidReminderTimeTime)
+ cs (PidLidReminderType)
+ cs (PidLidRemoteStatus)
+ cs (PidLidSideEffects)
+ cs (PidLidSmartNoAttach)
+ cs (PidLidSpamOriginalFolder)
+ cs (PidLidTaskGlobalId)
+ cs (PidLidTaskMode)
+ cs (PidLidToDoOrdinalDate)
+ cs (PidLidToDoSubOrdinal)
+ cs (PidLidToDoTitle)
+ cs (PidLidUseTnef)
+ cs (PidLidValidFlagStringProof)
+ cs (PidLidVerbResponse)
+ cs (PidLidVerbStream)
+ cs (PidLidLogDocumentPosted)
+ cs (PidLidLogDocumentPrinted)
+ cs (PidLidLogDocumentRouted)
+ cs (PidLidLogDocumentSaved)
+ cs (PidLidLogDuration)
+ cs (PidLidLogEnd)
+ cs (PidLidLogFlags)
+ cs (PidLidLogStart)
+ cs (PidLidLogType)
+ cs (PidLidLogTypeDesc)
+ cs (PidLidAppointmentMessageClass)
+ cs (PidLidAttendeeCriticalChange)
+ cs (PidLidCalendarType)
+ cs (PidLidCleanGlobalObjectId)
+ cs (PidLidDayInterval)
+ cs (PidLidDelegateMail)
+ cs (PidLidEndRecurrenceDate)
+ cs (PidLidEndRecurrenceTime)
+ cs (PidLidGlobalObjectId)
+ cs (PidLidIsException)
+ cs (PidLidIsRecurring)
+ cs (PidLidIsSilent)
+ cs (PidLidMeetingType)
+ cs (PidLidMonthInterval)
+ cs (PidLidMonthOfYearMask)
+ cs (PidLidOldLocation)
+ cs (PidLidOldRecurrenceType)
+ cs (PidLidOldWhenEndWhole)
+ cs (PidLidOldWhenStartWhole)
+ cs (PidLidOptionalAttendees)
+ cs (PidLidOwnerCriticalChange)
+ cs (PidLidRequiredAttendees)
+ cs (PidLidResourceAttendees)
+ cs (PidLidStartRecurrenceDate)
+ cs (PidLidStartRecurrenceTime)
+ cs (PidLidTimeZone)
+ cs (PidLidWeekInterval)
+ cs (PidLidWhere)
+ cs (PidLidYearInterval)
+ cs (PidLidNoteColor)
+ cs (PidLidNoteHeight)
+ cs (PidLidNoteWidth)
+ cs (PidLidNoteX)
+ cs (PidLidNoteY)
+ cs (PidLidPostRssChannel)
+ cs (PidLidPostRssChannelLink)
+ cs (PidLidPostRssItemGuid)
+ cs (PidLidPostRssItemHash)
+ cs (PidLidPostRssItemLink)
+ cs (PidLidPostRssItemXml)
+ cs (PidLidPostRssSubscription)
+ cs (PidLidSharingAnonymity)
+ cs (PidLidSharingBindingEntryId)
+ cs (PidLidSharingBrowseUrl)
+ cs (PidLidSharingCapabilities)
+ cs (PidLidSharingConfigurationUrl)
+ cs (PidLidSharingDataRangeEnd)
+ cs (PidLidSharingDataRangeStart)
+ cs (PidLidSharingDetail)
+ cs (PidLidSharingExtensionXml)
+ cs (PidLidSharingFilter)
+ cs (PidLidSharingFlags)
+ cs (PidLidSharingFlavor)
+ cs (PidLidSharingFolderEntryId)
+ cs (PidLidSharingIndexEntryId)
+ cs (PidLidSharingInitiatorEntryId)
+ cs (PidLidSharingInitiatorName)
+ cs (PidLidSharingInitiatorSmtp)
+ cs (PidLidSharingInstanceGuid)
+ cs (PidLidSharingLastAutoSyncTime)
+ cs (PidLidSharingLastSyncTime)
+ cs (PidLidSharingLocalComment)
+ cs (PidLidSharingLocalLastModificationTime)
+ cs (PidLidSharingLocalName)
+ cs (PidLidSharingLocalPath)
+ cs (PidLidSharingLocalStoreUid)
+ cs (PidLidSharingLocalType)
+ cs (PidLidSharingLocalUid)
+ cs (PidLidSharingOriginalMessageEntryId)
+ cs (PidLidSharingParentBindingEntryId)
+ cs (PidLidSharingParticipants)
+ cs (PidLidSharingPermissions)
+ cs (PidLidSharingProviderExtension)
+ cs (PidLidSharingProviderGuid)
+ cs (PidLidSharingProviderName)
+ cs (PidLidSharingProviderUrl)
+ cs (PidLidSharingRangeEnd)
+ cs (PidLidSharingRangeStart)
+ cs (PidLidSharingReciprocation)
+ cs (PidLidSharingRemoteByteSize)
+ cs (PidLidSharingRemoteComment)
+ cs (PidLidSharingRemoteCrc)
+ cs (PidLidSharingRemoteLastModificationTime)
+ cs (PidLidSharingRemoteMessageCount)
+ cs (PidLidSharingRemoteName)
+ cs (PidLidSharingRemotePass)
+ cs (PidLidSharingRemotePath)
+ cs (PidLidSharingRemoteStoreUid)
+ cs (PidLidSharingRemoteType)
+ cs (PidLidSharingRemoteUid)
+ cs (PidLidSharingRemoteUser)
+ cs (PidLidSharingRemoteVersion)
+ cs (PidLidSharingResponseTime)
+ cs (PidLidSharingResponseType)
+ cs (PidLidSharingRoamLog)
+ cs (PidLidSharingStart)
+ cs (PidLidSharingStatus)
+ cs (PidLidSharingStop)
+ cs (PidLidSharingSyncFlags)
+ cs (PidLidSharingSyncInterval)
+ cs (PidLidSharingTimeToLive)
+ cs (PidLidSharingTimeToLiveAuto)
+ cs (PidLidSharingWorkingHoursDays)
+ cs (PidLidSharingWorkingHoursEnd)
+ cs (PidLidSharingWorkingHoursStart)
+ cs (PidLidSharingWorkingHoursTimeZone)
+ cs (PidLidPercentComplete)
+ cs (PidLidTaskAcceptanceState)
+ cs (PidLidTaskAccepted)
+ cs (PidLidTaskActualEffort)
+ cs (PidLidTaskAssigner)
+ cs (PidLidTaskAssigners)
+ cs (PidLidTaskComplete)
+ cs (PidLidTaskCustomFlags)
+ cs (PidLidTaskDateCompleted)
+ cs (PidLidTaskDeadOccurrence)
+ cs (PidLidTaskDueDate)
+ cs (PidLidTaskEstimatedEffort)
+ cs (PidLidTaskFCreator)
+ cs (PidLidTaskFFixOffline)
+ cs (PidLidTaskFRecurring)
+ cs (PidLidTaskHistory)
+ cs (PidLidTaskLastDelegate)
+ cs (PidLidTaskLastUpdate)
+ cs (PidLidTaskLastUser)
+ cs (PidLidTaskMultipleRecipients)
+ cs (PidLidTaskNoCompute)
+ cs (PidLidTaskOrdinal)
+ cs (PidLidTaskOwner)
+ cs (PidLidTaskOwnership)
+ cs (PidLidTaskRecurrence)
+ cs (PidLidTaskResetReminder)
+ cs (PidLidTaskRole)
+ cs (PidLidTaskStartDate)
+ cs (PidLidTaskState)
+ cs (PidLidTaskStatus)
+ cs (PidLidTaskStatusOnComplete)
+ cs (PidLidTaskUpdates)
+ cs (PidLidTaskVersion)
+ cs (PidLidTeamTask)
+ cs (PidLidTrustRecipientHighlights)
+ cs (PidLidCategories)
+ cs (PidNameInstantMessagingAddress2)
+ cs (PidNameInstantMessagingAddress3)
+ cs (PidNameAttachmentMacContentType)
+ cs (PidNameAttachmentMacInfo)
+ cs (PidNameOriginalSpamConfidenceLevel)
+ cs (PidNameAudioNotes)
+ cs (PidNameAutomaticSpeechRecognitionData)
+ cs (PidNameOutlookProtectionRuleTimestamp)
+ cs (PidNameXUnifiedMessagingPartnerAssignedId)
+ cs (PidNameXUnifiedMessagingPartnerContent)
+ cs (PidNameXUnifiedMessagingPartnerContext)
+ cs (PidNameXUnifiedMessagingPartnerStatus)
+ cs (PidNameAcceptLanguage)
+ cs (PidNameApprovalAllowedDecisionMakers)
+ cs (PidNameApprovalRequestor)
+ cs (PidNameApproved)
+ cs (PidNameAuthenticatedAs)
+ cs (PidNameAuthenticatedDomain)
+ cs (PidNameAuthenticatedMechanism)
+ cs (PidNameAuthenticatedSource)
+ cs (PidNameBcc)
+ cs (PidNameCc)
+ cs (PidNameContentBase)
+ cs (PidNameContentClass)
+ cs (PidNameContentDisposition)
+ cs (PidNameContentID)
+ cs (PidNameContentLanguage)
+ cs (PidNameContentLocation)
+ cs (PidNameContentTransferEncoding)
+ cs (PidNameContentType)
+ cs (PidNameControl)
+ cs (PidNameCrossReference)
+ cs (PidNameDisposition)
+ cs (PidNameDispositionNotificationTo)
+ cs (PidNameDistribution)
+ cs (PidNameExpires)
+ cs (PidNameExpiryDate)
+ cs (PidNameFollowupTo)
+ cs (PidNameFrom)
+ cs (PidNameImportance)
+ cs (PidNameInReplyTo)
+ cs (PidNameInternetComment)
+ cs (PidNameInternetKeywords)
+ cs (PidNameInternetSubject)
+ cs (PidNameLines)
+ cs (PidNameMessageId)
+ cs (PidNameMimeVersion)
+ cs (PidNameNewsgroups)
+ cs (PidNameNntpPostingHost)
+ cs (PidNameOrganization)
+ cs (PidNameOriginalRecipient)
+ cs (PidNameOutlookProtectionRuleOverridden)
+ cs (PidNameOutlookProtectionRuleVersion)
+ cs (PidNamePath)
+ cs (PidNamePostingVersion)
+ cs (PidNamePriority)
+ cs (PidNameReceived)
+ cs (PidNameReferences)
+ cs (PidNameRelayVersion)
+ cs (PidNameReplyBy)
+ cs (PidNameReplyTo)
+ cs (PidNameReturnPath)
+ cs (PidNameReturnReceiptTo)
+ cs (PidNameRightsProtectMessage)
+ cs (PidNameSender)
+ cs (PidNameSensitivity)
+ cs (PidNameSummary)
+ cs (PidNameThreadIndex)
+ cs (PidNameThreadTopic)
+ cs (PidNameTo)
+ cs (PidNameXCallId)
+ cs (PidNameXFaxNumberOfPages)
+ cs (PidNameXMailer)
+ cs (PidNameXMessageCompleted)
+ cs (PidNameXMessageFlag)
+ cs (PidNameXRequireProtectedPlayOnPhone)
+ cs (PidNameXSenderTelephoneNumber)
+ cs (PidNameXSharingBrowseUrl)
+ cs (PidNameXSharingCapabilities)
+ cs (PidNameXSharingConfigUrl)
+ cs (PidNameXSharingExendedCaps)
+ cs (PidNameXSharingFlavor)
+ cs (PidNameXSharingInstanceGuid)
+ cs (PidNameXSharingLocalType)
+ cs (PidNameXSharingProviderGuid)
+ cs (PidNameXSharingProviderName)
+ cs (PidNameXSharingProviderUrl)
+ cs (PidNameXSharingRemoteName)
+ cs (PidNameXSharingRemotePath)
+ cs (PidNameXSharingRemoteStoreUid)
+ cs (PidNameXSharingRemoteType)
+ cs (PidNameXSharingRemoteUid)
+ cs (PidNameXUnsent)
+ cs (PidNameXVoiceMessageAttachmentOrder)
+ cs (PidNameXVoiceMessageDuration)
+ cs (PidNameXVoiceMessageSenderName)
+ cs (PidNameApplicationName)
+ cs (PidNameAuthor)
+ cs (PidNameByteCount)
+ cs (PidNameCalendarAttendeeRole)
+ cs (PidNameCalendarBusystatus)
+ cs (PidNameCalendarContact)
+ cs (PidNameCalendarContactUrl)
+ cs (PidNameCalendarCreated)
+ cs (PidNameCalendarDescriptionUrl)
+ cs (PidNameCalendarDuration)
+ cs (PidNameCalendarExceptionDate)
+ cs (PidNameCalendarExceptionRule)
+ cs (PidNameCalendarGeoLatitude)
+ cs (PidNameCalendarGeoLongitude)
+ cs (PidNameCalendarInstanceType)
+ cs (PidNameCalendarIsOrganizer)
+ cs (PidNameCalendarLastModified)
+ cs (PidNameCalendarLocationUrl)
+ cs (PidNameCalendarMeetingStatus)
+ cs (PidNameCalendarMethod)
+ cs (PidNameCalendarProductId)
+ cs (PidNameCalendarRecurrenceIdRange)
+ cs (PidNameCalendarReminderOffset)
+ cs (PidNameCalendarResources)
+ cs (PidNameCalendarRsvp)
+ cs (PidNameCalendarSequence)
+ cs (PidNameCalendarTimeZone)
+ cs (PidNameCalendarTimeZoneId)
+ cs (PidNameCalendarTransparent)
+ cs (PidNameCalendarUid)
+ cs (PidNameCalendarVersion)
+ cs (PidNameCategory)
+ cs (PidNameCharacterCount)
+ cs (PidNameComments)
+ cs (PidNameCompany)
+ cs (PidNameContactsAlternateRecipient)
+ cs (PidNameContactsCountry)
+ cs (PidNameContactsEmail1)
+ cs (PidNameContactsEmail2)
+ cs (PidNameContactsEmail3)
+ cs (PidNameContactsFileAs)
+ cs (PidNameContactsFileasId)
+ cs (PidNameContactsHomeLatitude)
+ cs (PidNameContactsHomeLongitude)
+ cs (PidNameContactsHomeTimeZone)
+ cs (PidNameContactsMapUrl)
+ cs (PidNameContactsOtherCountryCode)
+ cs (PidNameContactsOtherPager)
+ cs (PidNameContactsOtherTimeZone)
+ cs (PidNameContactsProxyAddresses)
+ cs (PidNameContactsSecretaryUrl)
+ cs (PidNameContactsSourceUrl)
+ cs (PidNameCreateDateTimeReadOnly)
+ cs (PidNameDavGetContentType)
+ cs (PidNameDavId)
+ cs (PidNameDavIsCollection)
+ cs (PidNameDavIsStructuredDocument)
+ cs (PidNameDavParentName)
+ cs (PidNameDavResourceType)
+ cs (PidNameDavSearchRequest)
+ cs (PidNameDavSearchType)
+ cs (PidNameDavUid)
+ cs (PidNameDocumentParts)
+ cs (PidNameEditTime)
+ cs (PidNameExchangeIntendedBusyStatus)
+ cs (PidNameExchangeJunkEmailMoveStamp)
+ cs (PidNameExchangeModifyExceptionStructure)
+ cs (PidNameExchangeNoModifyExceptions)
+ cs (PidNameExchangePatternEnd)
+ cs (PidNameExchangePatternStart)
+ cs (PidNameExchangePublicFolderEmailAddress)
+ cs (PidNameExchangeReminderInterval)
+ cs (PidNameExchDatabaseSchema)
+ cs (PidNameExchDataExpectedContentClass)
+ cs (PidNameExchDataSchemaCollectionReference)
+ cs (PidNameHeadingPairs)
+ cs (PidNameHiddenCount)
+ cs (PidNameHttpmailCalendar)
+ cs (PidNameHttpmailCc)
+ cs (PidNameHttpmailContacts)
+ cs (PidNameHttpmailContentMediaType)
+ cs (PidNameHttpmailFrom)
+ cs (PidNameHttpmailFromEmail)
+ cs (PidNameHttpmailHtmlDescription)
+ cs (PidNameHttpmailOutbox)
+ cs (PidNameHttpmailSendMessage)
+ cs (PidNameHttpmailSubmitted)
+ cs (PidNameHttpmailTo)
+ cs (PidNameICalendarRecurrenceDate)
+ cs (PidNameICalendarRecurrenceRule)
+ cs (PidNameKeywords)
+ cs (PidNameLastAuthor)
+ cs (PidNameLastPrinted)
+ cs (PidNameLastSaveDateTime)
+ cs (PidNameLineCount)
+ cs (PidNameLinksDirty)
+ cs (PidNameMailSubmissionUri)
+ cs (PidNameManager)
+ cs (PidNameMultimediaClipCount)
+ cs (PidNameNoteCount)
+ cs (PidNameOMSAccountGuid)
+ cs (PidNameOMSMobileModel)
+ cs (PidNameOMSScheduleTime)
+ cs (PidNameOMSServiceType)
+ cs (PidNameOMSSourceType)
+ cs (PidNamePageCount)
+ cs (PidNameParagraphCount)
+ cs (PidNamePhishingStamp)
+ cs (PidNamePresentationFormat)
+ cs (PidNameQuarantineOriginalSender)
+ cs (PidNameRevisionNumber)
+ cs (PidNameRightsManagementLicense)
+ cs (PidNameScale)
+ cs (PidNameSecurity)
+ cs (PidNameSlideCount)
+ cs (PidNameSubject)
+ cs (PidNameTemplate)
+ cs (PidNameThumbnail)
+ cs (PidNameTitle)
+ cs (PidNameWordCount)
+ #undef cs
+ { 0, NULL }
+ };
+ gint ii;
+
+ names = g_hash_table_new (g_direct_hash, g_direct_equal);
+ for (ii = 0; array[ii].proptag; ii++) {
+ gpointer name = (gpointer) array[ii].name;
+
+ g_hash_table_insert (names, GUINT_TO_POINTER (array[ii].proptag), name);
+ g_hash_table_insert (names, GUINT_TO_POINTER ((array[ii].proptag & ~0xFFFF) | PT_ERROR), name);
+ }
}
- return NULL;
+ return g_hash_table_lookup (names, GUINT_TO_POINTER (proptag));
}
void
-e_mapi_debug_dump_properties (EMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *properties, gint indent)
+e_mapi_debug_dump_properties (struct mapi_SPropValue_array *properties,
+ gint indent)
{
gint i = 0;
@@ -714,12 +729,13 @@ e_mapi_debug_dump_properties (EMapiConnection *conn, mapi_id_t fid, struct mapi_
for (i = 0; i < properties->cValues; i++) {
struct mapi_SPropValue *lpProp = &properties->lpProps[i];
- const gchar *tmp = get_proptag_name (lpProp->ulPropTag);
+ const gchar *tmp;
gchar t_str[26];
gint j = 0;
+ tmp = get_proptag_name (lpProp->ulPropTag);
if (!tmp || !*tmp)
- tmp = get_namedid_name (conn, fid, lpProp->ulPropTag);
+ tmp = get_namedid_name (lpProp->ulPropTag);
if (tmp && *tmp)
g_print ("%*s%s ", indent, "", tmp);
@@ -862,18 +878,18 @@ e_mapi_debug_dump_object (EMapiObject *object, gboolean with_properties, gint in
return;
if (with_properties)
- e_mapi_debug_dump_properties (NULL, 0, &object->properties, indent + 3);
+ e_mapi_debug_dump_properties (&object->properties, indent + 3);
for (index = 0, recipient = object->recipients; recipient; index++, recipient = recipient->next) {
g_print ("%*sRecipient[%d]:\n", indent + 2, "", index);
if (with_properties)
- e_mapi_debug_dump_properties (NULL, 0, &recipient->properties, indent + 5);
+ e_mapi_debug_dump_properties (&recipient->properties, indent + 5);
}
for (index = 0, attachment = object->attachments; attachment; index++, attachment = attachment->next) {
g_print ("%*sAttachment[%d]:\n", indent + 2, "", index);
if (with_properties)
- e_mapi_debug_dump_properties (NULL, 0, &attachment->properties, indent + 3);
+ e_mapi_debug_dump_properties (&attachment->properties, indent + 3);
if (attachment->embedded_object) {
g_print ("%*sEmbedded object:\n", indent + 3, "");
e_mapi_debug_dump_object (attachment->embedded_object, with_properties, indent + 5);
diff --git a/src/libexchangemapi/e-mapi-debug.h b/src/libexchangemapi/e-mapi-debug.h
index b3479ca..3056aff 100644
--- a/src/libexchangemapi/e-mapi-debug.h
+++ b/src/libexchangemapi/e-mapi-debug.h
@@ -30,9 +30,7 @@ G_BEGIN_DECLS
gboolean e_mapi_debug_is_enabled (void);
void e_mapi_debug_print (const gchar *format, ...);
-void e_mapi_debug_dump_properties (EMapiConnection *conn,
- mapi_id_t fid,
- struct mapi_SPropValue_array *properties,
+void e_mapi_debug_dump_properties (struct mapi_SPropValue_array *properties,
gint indent);
void e_mapi_debug_dump_object (EMapiObject *object,
gboolean with_properties,
diff --git a/src/libexchangemapi/e-mapi-utils.c b/src/libexchangemapi/e-mapi-utils.c
index dbda865..ed99c18 100644
--- a/src/libexchangemapi/e-mapi-utils.c
+++ b/src/libexchangemapi/e-mapi-utils.c
@@ -146,25 +146,6 @@ e_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag)
return (find_SPropValue_data(aRow, proptag));
}
-gconstpointer
-e_mapi_util_find_row_namedid (struct SRow *aRow, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
- uint32_t proptag;
- gconstpointer res = NULL;
-
- g_return_val_if_fail (aRow != NULL, NULL);
- g_return_val_if_fail (conn != NULL, NULL);
-
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
- if (proptag != MAPI_E_RESERVED)
- res = e_mapi_util_find_row_propval (aRow, proptag);
-
- if (!res)
- res = e_mapi_util_find_row_propval (aRow, namedid);
-
- return res;
-}
-
/*
* Retrieve the property value for a given mapi_SPropValue_array and property tag.
*
@@ -205,25 +186,6 @@ e_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties, uint32
return (find_mapi_SPropValue_data(properties, proptag));
}
-gconstpointer
-e_mapi_util_find_array_namedid (struct mapi_SPropValue_array *properties, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
- uint32_t proptag;
- gconstpointer res = NULL;
-
- g_return_val_if_fail (properties != NULL, NULL);
- g_return_val_if_fail (conn != NULL, NULL);
-
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
- if (proptag != MAPI_E_RESERVED)
- res = e_mapi_util_find_array_propval (properties, proptag);
-
- if (!res)
- res = e_mapi_util_find_array_propval (properties, namedid);
-
- return res;
-}
-
uint32_t
e_mapi_util_find_array_proptag (struct mapi_SPropValue_array *properties, uint32_t proptag)
{
@@ -753,60 +715,6 @@ e_mapi_util_profile_name (struct mapi_context *mapi_ctx, const EMapiProfileData
}
/**
- * Adds prop_ids to props array. props should be created within the given mem_ctx.
- **/
-gboolean
-e_mapi_utils_add_props_to_props_array (TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- const uint32_t *prop_ids,
- guint prop_ids_n_elems)
-{
- guint i;
-
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (props != NULL, FALSE);
- g_return_val_if_fail (prop_ids != NULL, FALSE);
- g_return_val_if_fail (prop_ids_n_elems > 0, FALSE);
-
- for (i = 0; i < prop_ids_n_elems; i++) {
- SPropTagArray_add (mem_ctx, props, prop_ids[i]);
- }
-
- return TRUE;
-}
-
-/* Beware, the named_ids_list array is modified */
-gboolean
-e_mapi_utils_add_named_ids_to_props_array (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- ResolveNamedIDsData *named_ids_list,
- guint named_ids_n_elems,
- GCancellable *cancellable,
- GError **perror)
-{
- guint i;
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (props != NULL, FALSE);
- g_return_val_if_fail (fid > 0, FALSE);
- g_return_val_if_fail (named_ids_list != NULL, FALSE);
- g_return_val_if_fail (named_ids_n_elems > 0, FALSE);
-
- if (!e_mapi_connection_resolve_named_props (conn, fid, named_ids_list, named_ids_n_elems, cancellable, perror))
- return FALSE;
-
- for (i = 0; i < named_ids_n_elems; i++) {
- if (named_ids_list[i].propid != MAPI_E_RESERVED)
- SPropTagArray_add (mem_ctx, props, named_ids_list[i].propid);
- }
-
- return TRUE;
-}
-
-/**
* Adds a new SPropValue at the end of values_array, allocating its memory in the mem_ctx.
* *n_values holds number of items stored in the array, and will be increased by one.
**/
@@ -826,33 +734,6 @@ e_mapi_utils_add_spropvalue (TALLOC_CTX *mem_ctx,
return TRUE;
}
-/* similar as e_mapi_utils_add_spropvalue, just here is not used prop_tag, but named id */
-gboolean
-e_mapi_utils_add_spropvalue_namedid (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values_array,
- uint32_t *n_values,
- uint32_t named_id,
- gconstpointer prop_value,
- GCancellable *cancellable,
- GError **perror)
-{
- uint32_t prop_tag;
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (fid != 0, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (values_array != NULL, FALSE);
- g_return_val_if_fail (n_values != NULL, FALSE);
-
- prop_tag = e_mapi_connection_resolve_named_prop (conn, fid, named_id, cancellable, perror);
- if (prop_tag == MAPI_E_RESERVED)
- return FALSE;
-
- return e_mapi_utils_add_spropvalue (mem_ctx, values_array, n_values, prop_tag, prop_value);
-}
-
gboolean
e_mapi_utils_add_property (struct mapi_SPropValue_array *properties,
uint32_t proptag,
diff --git a/src/libexchangemapi/e-mapi-utils.h b/src/libexchangemapi/e-mapi-utils.h
index 25f6a39..7dc02ed 100644
--- a/src/libexchangemapi/e-mapi-utils.h
+++ b/src/libexchangemapi/e-mapi-utils.h
@@ -28,81 +28,76 @@
#include "e-mapi-debug.h"
#include "e-mapi-connection.h"
-gchar * e_mapi_util_mapi_id_to_string (mapi_id_t id);
-gboolean e_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id);
-
-gconstpointer e_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t proptag);
-gconstpointer e_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag);
-gconstpointer e_mapi_util_find_row_namedid (struct SRow *aRow, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
-gconstpointer e_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties, uint32_t proptag);
-gconstpointer e_mapi_util_find_array_namedid (struct mapi_SPropValue_array *properties, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
-uint32_t e_mapi_util_find_array_proptag (struct mapi_SPropValue_array *properties, uint32_t proptag);
-
-enum MAPISTATUS e_mapi_util_find_array_datetime_propval (struct timeval *tv, struct mapi_SPropValue_array *properties, uint32_t proptag);
-
-void e_mapi_util_recip_entryid_generate_smtp (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *display_name, const gchar *email);
-void e_mapi_util_recip_entryid_generate_ex (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *exchange_dn);
-gboolean e_mapi_util_recip_entryid_decode (EMapiConnection *conn, const struct Binary_r *entyrid, gchar **display_name, gchar **email);
-
-void e_mapi_util_profiledata_from_settings (EMapiProfileData *empd, CamelMapiSettings *settings);
-gchar * e_mapi_util_profile_name (struct mapi_context *mapi_ctx,
- const EMapiProfileData *empd,
- gboolean migrate);
-gboolean e_mapi_util_trigger_krb_auth (const EMapiProfileData *empd, GError **error);
-
-gboolean e_mapi_utils_add_props_to_props_array (TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- const uint32_t *prop_ids,
- guint prop_ids_n_elems);
-gboolean e_mapi_utils_add_named_ids_to_props_array (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- ResolveNamedIDsData *named_ids_list,
- guint named_ids_n_elems,
- GCancellable *cancellable,
- GError **perror);
-
-gboolean e_mapi_utils_add_spropvalue (TALLOC_CTX *mem_ctx,
- struct SPropValue **values_array,
- uint32_t *n_values,
- uint32_t prop_tag,
- gconstpointer prop_value);
-gboolean e_mapi_utils_add_spropvalue_namedid (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values_array,
- uint32_t *n_values,
- uint32_t named_id,
- gconstpointer prop_value,
- GCancellable *cancellable,
- GError **perror);
-gboolean e_mapi_utils_add_property (struct mapi_SPropValue_array *properties,
- uint32_t proptag,
- gconstpointer propvalue,
- TALLOC_CTX *mem_ctx);
-gboolean e_mapi_utils_ensure_utf8_string (uint32_t proptag,
- const uint32_t *cpid,
- const guint8 *buf_data,
- guint32 buf_len,
- gchar **out_utf8);
-
-uint32_t e_mapi_utils_push_crc32 (uint32_t crc32, uint8_t *bytes, uint32_t n_bytes);
-
-struct Binary_r *e_mapi_util_copy_binary_r (const struct Binary_r *bin);
-void e_mapi_util_free_binary_r (struct Binary_r *bin);
-
-time_t e_mapi_util_filetime_to_time_t (const struct FILETIME *filetime);
-void e_mapi_util_time_t_to_filetime (const time_t tt, struct FILETIME *filetime);
-
-gboolean e_mapi_utils_propagate_cancelled_error (const GError *mapi_error,
- GError **error);
-
-void e_mapi_utils_global_lock (void);
-void e_mapi_utils_global_unlock (void);
-gboolean e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx,
- GError **perror);
-void e_mapi_utils_destroy_mapi_context (struct mapi_context *mapi_ctx);
+gchar * e_mapi_util_mapi_id_to_string (mapi_id_t id);
+gboolean e_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id);
+
+gconstpointer e_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t proptag);
+gconstpointer e_mapi_util_find_row_propval (struct SRow *aRow,
+ uint32_t proptag);
+gconstpointer e_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties,
+ uint32_t proptag);
+uint32_t e_mapi_util_find_array_proptag (struct mapi_SPropValue_array *properties,
+ uint32_t proptag);
+
+enum MAPISTATUS e_mapi_util_find_array_datetime_propval (struct timeval *tv,
+ struct mapi_SPropValue_array *properties,
+ uint32_t proptag);
+
+void e_mapi_util_recip_entryid_generate_smtp (TALLOC_CTX *mem_ctx,
+ struct Binary_r *entryid,
+ const gchar *display_name,
+ const gchar *email);
+void e_mapi_util_recip_entryid_generate_ex (TALLOC_CTX *mem_ctx,
+ struct Binary_r *entryid,
+ const gchar *exchange_dn);
+gboolean e_mapi_util_recip_entryid_decode (EMapiConnection *conn,
+ const struct Binary_r *entyrid,
+ gchar **display_name,
+ gchar **email);
+
+void e_mapi_util_profiledata_from_settings (EMapiProfileData *empd,
+ CamelMapiSettings *settings);
+gchar * e_mapi_util_profile_name (struct mapi_context *mapi_ctx,
+ const EMapiProfileData *empd,
+ gboolean migrate);
+gboolean e_mapi_util_trigger_krb_auth (const EMapiProfileData *empd,
+ GError **error);
+
+gboolean e_mapi_utils_add_spropvalue (TALLOC_CTX *mem_ctx,
+ struct SPropValue **values_array,
+ uint32_t *n_values,
+ uint32_t prop_tag,
+ gconstpointer prop_value);
+gboolean e_mapi_utils_add_property (struct mapi_SPropValue_array *properties,
+ uint32_t proptag,
+ gconstpointer propvalue,
+ TALLOC_CTX *mem_ctx);
+gboolean e_mapi_utils_ensure_utf8_string (uint32_t proptag,
+ const uint32_t *cpid,
+ const guint8 *buf_data,
+ guint32 buf_len,
+ gchar **out_utf8);
+
+uint32_t e_mapi_utils_push_crc32 (uint32_t crc32,
+ uint8_t *bytes,
+ uint32_t n_bytes);
+
+struct
+Binary_r * e_mapi_util_copy_binary_r (const struct Binary_r *bin);
+void e_mapi_util_free_binary_r (struct Binary_r *bin);
+
+time_t e_mapi_util_filetime_to_time_t (const struct FILETIME *filetime);
+void e_mapi_util_time_t_to_filetime (const time_t tt,
+ struct FILETIME *filetime);
+
+gboolean e_mapi_utils_propagate_cancelled_error (const GError *mapi_error,
+ GError **error);
+
+void e_mapi_utils_global_lock (void);
+void e_mapi_utils_global_unlock (void);
+gboolean e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx,
+ GError **perror);
+void e_mapi_utils_destroy_mapi_context (struct mapi_context *mapi_ctx);
gboolean e_mapi_utils_build_last_modify_restriction (EMapiConnection *conn,
TALLOC_CTX *mem_ctx,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]