[evolution-mapi] Bug #586096 - Contact list doesn't work at all
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug #586096 - Contact list doesn't work at all
- Date: Tue, 20 Apr 2010 17:09:16 +0000 (UTC)
commit 446afb4f6cf77b1aaa47c42b46902dc957d0573d
Author: Milan Crha <mcrha redhat com>
Date: Tue Apr 20 19:07:58 2010 +0200
Bug #586096 - Contact list doesn't work at all
Reading only, it requires changes on OpenChange side to work properly.
src/addressbook/e-book-backend-mapi.c | 397 +++++++++++++++++++++---
src/libexchangemapi/exchange-mapi-connection.c | 27 ++-
src/libexchangemapi/exchange-mapi-defs.h | 1 +
src/libexchangemapi/exchange-mapi-utils.c | 331 ++++++++++++++++++--
src/libexchangemapi/exchange-mapi-utils.h | 5 +-
5 files changed, 670 insertions(+), 91 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index 2f2453d..2dca7da 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -39,6 +39,7 @@
#include <libedataserver/e-sexp.h>
#include "libedataserver/e-flag.h"
#include <libebook/e-contact.h>
+#include <camel/camel.h>
#include <libedata-book/e-book-backend-sexp.h>
#include <libedata-book/e-data-book.h>
@@ -47,6 +48,10 @@
#include <libedata-book/e-book-backend-summary.h>
#include "e-book-backend-mapi.h"
+/* vCard parameter name in contact list */
+#define EMA_X_MEMBERID "X-EMA-MEMBER-ID"
+#define EMA_X_MEMBERVALUE "X-EMA-MEMBER-VALUE"
+
G_DEFINE_TYPE (EBookBackendMAPI, e_book_backend_mapi, E_TYPE_BOOK_BACKEND)
static gboolean enable_debug = TRUE;
@@ -145,7 +150,7 @@ static uint32_t known_book_mapi_ids[] = {
#define ELEMENT_TYPE_SIMPLE 0x01
#define ELEMENT_TYPE_COMPLEX 0x02
-static EContact * emapidump_contact(struct mapi_SPropValue_array *properties);
+static EContact * emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *properties);
static const struct field_element_mapping {
EContactField field_id;
@@ -429,6 +434,7 @@ e_book_backend_mapi_load_source (EBookBackend *backend,
//FIXME: We may have to do a time based reload. Or deltas should upload.
} else {
priv->summary = e_book_backend_summary_new (NULL,SUMMARY_FLUSH_TIMEOUT);
+ priv->cache = e_book_backend_cache_new (priv->uri);
}
g_free (uri);
@@ -477,11 +483,85 @@ e_book_backend_mapi_get_static_capabilities (EBookBackend *backend)
return g_strdup ("net,bulk-removes,do-initial-query,contact-lists");
}
+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 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
mapi_book_build_name_id (struct mapi_nameid *nameid, gpointer data)
{
// EContact *contact = data;
+ mapi_nameid_lid_add (nameid, 0x8053, PSETID_Address); /* PidLidDistributionListName */
+ mapi_nameid_lid_add (nameid, 0x8054, PSETID_Address); /* PidLidDistributionListOneOffMembers */
+ mapi_nameid_lid_add (nameid, 0x8055, PSETID_Address); /* PidLidDistributionListMembers */
+
mapi_nameid_lid_add(nameid, 0x8005, PSETID_Address);
mapi_nameid_lid_add(nameid, 0x8084, PSETID_Address);
mapi_nameid_lid_add(nameid, 0x8083, PSETID_Address);
@@ -505,36 +585,159 @@ mapi_book_build_name_id (struct mapi_nameid *nameid, gpointer data)
return TRUE;
}
-#define set_str_value(field_id, hex) if (e_contact_get (contact, field_id)) set_SPropValue_proptag (&props[i++], hex, e_contact_get (contact, field_id));
+#define set_str_value(field_id, hex) if (e_contact_get (mcd->contact, field_id)) set_SPropValue_proptag (&props[i++], hex, e_contact_get (mcd->contact, field_id));
+
+typedef struct {
+ EContact *contact;
+ EBookBackendCache *cache;
+ TALLOC_CTX *mem_ctx;
+} MapiCreateitemData;
gint
mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropTagArray, gpointer data)
{
- EContact *contact = data;
+ MapiCreateitemData *mcd = data;
struct SPropValue *props;
- gint i=0;
+ gint i;
- for (i=0; i<13; i++)
- printf("hex %x\n", SPropTagArray->aulPropTag[i]);
- i=0;
+ g_return_val_if_fail (mcd != NULL, 0);
+ g_return_val_if_fail (mcd->contact != NULL, 0);
+ g_return_val_if_fail (mcd->mem_ctx != NULL, 0);
+
+ if (GPOINTER_TO_INT (e_contact_get (mcd->contact, E_CONTACT_IS_LIST))) {
+ EContact *old_contact;
+ GList *local, *l;
+ struct BinaryArray_r *members, *oneoff_members;
+ uint32_t list_size = 0;
+ GHashTable *member_values = NULL, *member_ids = NULL;
+
+ old_contact = e_book_backend_cache_get_contact (mcd->cache, e_contact_get (mcd->contact, E_CONTACT_UID));
+ if (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);
+ }
+
+ i = 0;
+ props = g_new0 (struct SPropValue, 6);
+
+ set_SPropValue_proptag (&props[i++], PR_MESSAGE_CLASS, IPM_DISTLIST);
+ set_str_value (E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[3]);
+ set_str_value (E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[0]); /* PidLidDistributionListName */
+
+ local = g_list_sort_with_data (e_contact_get_attributes (mcd->contact, E_CONTACT_EMAIL), cmp_member_id, member_ids);
+
+ members = talloc_zero (mcd->mem_ctx, struct BinaryArray_r);
+ members->cValues = 0;
+ members->lpbin = talloc_zero_array (mcd->mem_ctx, struct Binary_r, g_list_length (local));
+
+ oneoff_members = talloc_zero (mcd->mem_ctx, struct BinaryArray_r);
+ oneoff_members->cValues = 0;
+ oneoff_members->lpbin = talloc_zero_array (mcd->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 (mcd->mem_ctx, g_hash_table_lookup (member_values, raw), &members->lpbin[members->cValues].lpb);
+ members->cValues++;
+ } else {
+ exchange_mapi_util_entryid_generate_oneoff (mcd->mem_ctx, &members->lpbin[members->cValues], nm ? nm : "", eml);
+ members->cValues++;
+ }
+
+ exchange_mapi_util_entryid_generate_oneoff (mcd->mem_ctx, &oneoff_members->lpbin[oneoff_members->cValues], nm ? nm : "", eml);
+ oneoff_members->cValues++;
+
+ list_size += MAX (oneoff_members->lpbin[oneoff_members->cValues - 1].cb, members->lpbin[members->cValues - 1].cb);
+ }
+ }
+
+ camel_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);
+
+ /* PidLidDistributionListOneOffMembers */
+ set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[1], oneoff_members);
+ /* PidLidDistributionListMembers */
+ set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[2], members);
+
+ /* list_size shouldn't exceed 15000 bytes */
+ if (list_size > 15000) {
+ g_free (props);
+ props = NULL;
+ i = 0;
+ }
+
+ *value = props;
+ return i;
+ }
+
+ i = 0;
props = g_new0 (struct SPropValue, 50); //FIXME: Correct value tbd
- set_str_value ( E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[0]);
+ set_str_value ( E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[3]);
set_str_value (E_CONTACT_FULL_NAME, PR_DISPLAY_NAME_UNICODE);
set_SPropValue_proptag(&props[i++], PR_MESSAGE_CLASS, (gconstpointer )IPM_CONTACT);
set_str_value (E_CONTACT_FILE_AS, PR_NORMALIZED_SUBJECT_UNICODE);
- set_str_value (E_CONTACT_EMAIL_1, SPropTagArray->aulPropTag[1]);
-// set_str_value (E_CONTACT_EMAIL_1, SPropTagArray->aulPropTag[2]);
- set_str_value (E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[5]);
+ set_str_value (E_CONTACT_EMAIL_1, SPropTagArray->aulPropTag[4]);
+// set_str_value (E_CONTACT_EMAIL_1, SPropTagArray->aulPropTag[5]);
+ set_str_value (E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[8]);
// set_str_value ( E_CONTACT_EMAIL_1, 0x8083001e);
- set_str_value ( E_CONTACT_EMAIL_2, SPropTagArray->aulPropTag[3]);
-// set_str_value ( E_CONTACT_EMAIL_2, SPropTagArray->aulPropTag[11]);
+ set_str_value ( E_CONTACT_EMAIL_2, SPropTagArray->aulPropTag[6]);
+// set_str_value ( E_CONTACT_EMAIL_2, SPropTagArray->aulPropTag[14]);
- set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[4]);
-// set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[12]);
+ set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[7]);
+// set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[15]);
- set_str_value (E_CONTACT_HOMEPAGE_URL, SPropTagArray->aulPropTag[6]);
+ set_str_value (E_CONTACT_HOMEPAGE_URL, SPropTagArray->aulPropTag[9]);
set_str_value (E_CONTACT_FREEBUSY_URL, PROP_TAG(PT_UNICODE, 0x812c));
set_str_value ( E_CONTACT_PHONE_BUSINESS, PR_OFFICE_TELEPHONE_NUMBER_UNICODE);
@@ -559,8 +762,8 @@ mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropT
set_str_value (E_CONTACT_NOTE, PR_BODY_UNICODE);
//BDAY AND ANNV
- if (e_contact_get (contact, E_CONTACT_BIRTH_DATE)) {
- EContactDate *date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
+ if (e_contact_get (mcd->contact, E_CONTACT_BIRTH_DATE)) {
+ EContactDate *date = e_contact_get (mcd->contact, E_CONTACT_BIRTH_DATE);
struct tm tmtime;
time_t lt;
NTTIME nt;
@@ -578,8 +781,8 @@ mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropT
set_SPropValue_proptag (&props[i++], PR_BIRTHDAY, &t);
}
- if (e_contact_get (contact, E_CONTACT_ANNIVERSARY)) {
- EContactDate *date = e_contact_get (contact, E_CONTACT_ANNIVERSARY);
+ if (e_contact_get (mcd->contact, E_CONTACT_ANNIVERSARY)) {
+ EContactDate *date = e_contact_get (mcd->contact, E_CONTACT_ANNIVERSARY);
struct tm tmtime;
time_t lt;
NTTIME nt;
@@ -597,11 +800,11 @@ mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropT
set_SPropValue_proptag (&props[i++], PR_WEDDING_ANNIVERSARY, &t);
}
//Home and Office address
- if (e_contact_get (contact, E_CONTACT_ADDRESS_HOME)) {
+ if (e_contact_get (mcd->contact, E_CONTACT_ADDRESS_HOME)) {
EContactAddress *contact_addr;
- contact_addr = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
- set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[8], contact_addr->street);
+ contact_addr = e_contact_get (mcd->contact, E_CONTACT_ADDRESS_HOME);
+ set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[11], contact_addr->street);
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE, contact_addr->ext);
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_CITY_UNICODE, contact_addr->locality);
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE, contact_addr->region);
@@ -609,11 +812,11 @@ mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropT
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_COUNTRY_UNICODE, contact_addr->country);
}
- if (e_contact_get (contact, E_CONTACT_ADDRESS_WORK)) {
+ if (e_contact_get (mcd->contact, E_CONTACT_ADDRESS_WORK)) {
EContactAddress *contact_addr;
- contact_addr = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
- set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[9], contact_addr->street);
+ contact_addr = e_contact_get (mcd->contact, E_CONTACT_ADDRESS_WORK);
+ set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[12], contact_addr->street);
set_SPropValue_proptag (&props[i++], PR_POST_OFFICE_BOX_UNICODE, contact_addr->ext);
set_SPropValue_proptag (&props[i++], PR_LOCALITY_UNICODE, contact_addr->locality);
set_SPropValue_proptag (&props[i++], PR_STATE_OR_PROVINCE_UNICODE, contact_addr->region);
@@ -621,16 +824,16 @@ mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropT
set_SPropValue_proptag (&props[i++], PR_COUNTRY_UNICODE, contact_addr->country);
}
-// set_str_value (E_CONTACT_NICKNAME, SPropTagArray->aulPropTag[10]);
- if (e_contact_get (contact, E_CONTACT_IM_AIM)) {
- GList *l = e_contact_get (contact, E_CONTACT_IM_AIM);
- set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[7], l->data);
+// set_str_value (E_CONTACT_NICKNAME, SPropTagArray->aulPropTag[12]);
+ if (e_contact_get (mcd->contact, E_CONTACT_IM_AIM)) {
+ GList *l = e_contact_get (mcd->contact, E_CONTACT_IM_AIM);
+ set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[10], l->data);
}
- if (e_contact_get (contact, E_CONTACT_NICKNAME)) {
- gchar *nick = e_contact_get (contact, E_CONTACT_NICKNAME);
-// set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[10], nick);
- printf("nickname %s %x\n", nick, SPropTagArray->aulPropTag[10]);
+ if (e_contact_get (mcd->contact, E_CONTACT_NICKNAME)) {
+ gchar *nick = e_contact_get (mcd->contact, E_CONTACT_NICKNAME);
+// set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[13], nick);
+ printf("nickname %s %x\n", nick, SPropTagArray->aulPropTag[13]);
}
*value =props;
@@ -647,6 +850,7 @@ e_book_backend_mapi_create_contact (EBookBackend *backend,
EContact *contact;
gchar *id;
mapi_id_t status;
+ MapiCreateitemData mcd;
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
if (enable_debug)
@@ -660,7 +864,11 @@ e_book_backend_mapi_create_contact (EBookBackend *backend,
case GNOME_Evolution_Addressbook_MODE_REMOTE :
contact = e_contact_new_from_vcard(vcard);
- status = exchange_mapi_connection_create_item (priv->conn, olFolderContacts, priv->fid, mapi_book_build_name_id, contact, mapi_book_build_props, contact, NULL, NULL, NULL, 0);
+ mcd.contact = contact;
+ mcd.cache = priv->cache;
+ mcd.mem_ctx = talloc_init ("ExchangeMAPI_MCD");
+ status = exchange_mapi_connection_create_item (priv->conn, olFolderContacts, priv->fid, mapi_book_build_name_id, contact, mapi_book_build_props, &mcd, NULL, NULL, NULL, 0);
+ talloc_free (mcd.mem_ctx);
if (!status) {
e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
return;
@@ -749,6 +957,7 @@ e_book_backend_mapi_modify_contact (EBookBackend *backend,
const gchar *vcard)
{
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
+ MapiCreateitemData mcd;
EContact *contact;
mapi_id_t fid, mid;
gboolean status;
@@ -768,7 +977,11 @@ e_book_backend_mapi_modify_contact (EBookBackend *backend,
exchange_mapi_util_mapi_ids_from_uid (tmp, &fid, &mid);
printf("modify id %s\n", tmp);
- status = exchange_mapi_connection_modify_item (priv->conn, olFolderContacts, priv->fid, mid, mapi_book_build_name_id, contact, mapi_book_build_props, contact, NULL, NULL, NULL, 0);
+ mcd.contact = contact;
+ mcd.cache = priv->cache;
+ mcd.mem_ctx = talloc_init ("ExchangeMAPI_MCD");
+ status = exchange_mapi_connection_modify_item (priv->conn, olFolderContacts, priv->fid, mid, mapi_book_build_name_id, contact, mapi_book_build_props, &mcd, NULL, NULL, NULL, 0);
+ talloc_free (mcd.mem_ctx);
printf("getting %d\n", status);
if (!status) {
e_data_book_respond_modify(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
@@ -800,9 +1013,8 @@ create_contact_item (FetchItemsCallbackData *item_data, gpointer data)
{
EContact *contact;
gchar *suid;
- GSList *recipients = item_data->recipients;
- contact = emapidump_contact (item_data->properties);
+ contact = emapidump_contact (item_data->conn, item_data->fid, item_data->properties);
suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
printf("got contact %s\n", suid);
if (contact) {
@@ -811,8 +1023,6 @@ create_contact_item (FetchItemsCallbackData *item_data, gpointer data)
data = contact;
}
- exchange_mapi_util_free_recipient_list (&recipients);
-
g_free (suid);
return TRUE;
@@ -879,7 +1089,7 @@ e_book_backend_mapi_get_contact (EBookBackend *backend,
exchange_mapi_util_mapi_ids_from_uid (id, &fid, &mid);
exchange_mapi_connection_fetch_item (priv->conn, priv->fid, mid,
known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids),
- NULL, NULL,
+ mapi_book_build_name_id_for_getprops, NULL,
create_contact_item, contact,
MAPI_OPTIONS_FETCH_ALL);
@@ -920,7 +1130,7 @@ create_contact_list_cb (FetchItemsCallbackData *item_data, gpointer data)
EContact *contact;
gchar *suid;
- contact = emapidump_contact (array);
+ contact = emapidump_contact (item_data->conn, fid, array);
suid = exchange_mapi_util_mapi_ids_to_uid (fid, mid);
if (contact) {
@@ -958,9 +1168,15 @@ static const uint16_t n_GetPropsList = G_N_ELEMENTS (GetPropsList);
gboolean
mapi_book_build_name_id_for_getprops (struct mapi_nameid *nameid, gpointer data)
{
+ /* Fix indexes in emapidump_contact when adding/removing from here */
+
+ mapi_nameid_lid_add (nameid, 0x8053, PSETID_Address); /* PidLidDistributionListName */
+ mapi_nameid_lid_add (nameid, 0x8054, PSETID_Address); /* PidLidDistributionListOneOffMembers */
+ mapi_nameid_lid_add (nameid, 0x8055, PSETID_Address); /* PidLidDistributionListMembers */
+
mapi_nameid_lid_add(nameid, 0x8084, PSETID_Address); /* PT_UNICODE - EmailOriginalDisplayName */
-// mapi_nameid_lid_add(nameid, 0x8020, PSETID_Address);
-// mapi_nameid_lid_add(nameid, 0x8021, PSETID_Address);
+ /*mapi_nameid_lid_add(nameid, 0x8020, PSETID_Address);
+ mapi_nameid_lid_add(nameid, 0x8021, PSETID_Address);*/
mapi_nameid_lid_add(nameid, 0x8094, PSETID_Address);
mapi_nameid_lid_add(nameid, 0x80a4, PSETID_Address);
@@ -1086,11 +1302,90 @@ get_closure (EDataBookView *book_view)
//FIXME: Be more clever in dumping contacts. Can we have a callback mechanism for each types?
static EContact *
-emapidump_contact(struct mapi_SPropValue_array *properties)
+emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *properties)
{
EContact *contact = e_contact_new ();
gint i;
+ if (g_str_equal (exchange_mapi_util_find_array_propval (properties, PR_MESSAGE_CLASS), IPM_DISTLIST)) {
+ const struct mapi_SBinaryArray *members, *members_dlist;
+ GSList *attrs = NULL, *a;
+
+ /* 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));
+
+ /* PidLidDistributionListName */
+ e_contact_set (contact, E_CONTACT_FILE_AS, exchange_mapi_util_find_array_propval (properties, properties->lpProps[0].ulPropTag));
+ /* PidLidDistributionListOneOffMembers */
+ members = exchange_mapi_util_find_array_propval (properties, properties->lpProps[1].ulPropTag);
+ /* PidLidDistributionListMembers */
+ members_dlist = exchange_mapi_util_find_array_propval (properties, properties->lpProps[2].ulPropTag);
+
+ g_return_val_if_fail (members != NULL, NULL);
+ g_return_val_if_fail (members_dlist != NULL, NULL);
+
+ /* these two list 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 (exchange_mapi_util_entryid_decode_oneoff (&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);
+ camel_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;
+ }
+
// exchange_mapi_debug_property_dump (properties);
for (i=1; i<maplen; i++) {
gpointer value;
@@ -1218,13 +1513,15 @@ create_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
return FALSE;
}
- contact = emapidump_contact (item_data->properties);
+ contact = emapidump_contact (item_data->conn, item_data->fid, item_data->properties);
suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
if (contact) {
/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
e_contact_set (contact, E_CONTACT_UID, suid);
e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
+ if (priv->cache)
+ e_book_backend_cache_add_contact (priv->cache, contact);
e_data_book_view_notify_update (book_view, contact);
g_object_unref(contact);
}
@@ -1388,7 +1685,7 @@ book_view_thread (gpointer data)
} else {
if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, NULL, NULL,
known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids),
- NULL, NULL,
+ mapi_book_build_name_id_for_getprops, NULL,
create_contact_cb, book_view,
MAPI_OPTIONS_FETCH_ALL)) {
if (e_flag_is_set (closure->running))
@@ -1457,7 +1754,7 @@ cache_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
gchar *suid;
- contact = emapidump_contact (item_data->properties);
+ contact = emapidump_contact (item_data->conn, item_data->fid, item_data->properties);
suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
if (contact) {
@@ -1495,7 +1792,7 @@ build_cache (EBookBackendMAPI *ebmapi)
if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, NULL, NULL,
known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids),
- NULL, NULL,
+ mapi_book_build_name_id_for_getprops, NULL,
cache_contact_cb, ebmapi,
MAPI_OPTIONS_FETCH_ALL)) {
printf("Error during caching addressbook\n");
@@ -1540,7 +1837,7 @@ update_cache (EBookBackendMAPI *ebmapi)
if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, &res, NULL,
known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids),
- NULL, NULL,
+ mapi_book_build_name_id_for_getprops, NULL,
cache_contact_cb, ebmapi,
MAPI_OPTIONS_FETCH_ALL)) {
printf("Error during caching addressbook\n");
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index b02e79f..2d35adc 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -1048,7 +1048,7 @@ set_recipient_properties (TALLOC_CTX *mem_ctx, struct SRow *aRow, ExchangeMAPIRe
/* FIXME: Setting PR_ENTRYID property seems to create problems for now. We should take
* another look at this after the CreateOneoffEntryId API is provided by LibMAPI. */
#if 0
- struct Binary_r *oneoff_eid;
+ struct Binary_r oneoff_eid;
struct SPropValue sprop;
const gchar *dn = NULL, *email = NULL;
@@ -1056,7 +1056,7 @@ set_recipient_properties (TALLOC_CTX *mem_ctx, struct SRow *aRow, ExchangeMAPIRe
dn = (dn) ? dn : "";
email = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_SMTP_ADDRESS_UNICODE);
email = (email) ? email : "";
- oneoff_eid = exchange_mapi_util_entryid_generate_oneoff (mem_ctx, dn, email, FALSE);
+ exchange_mapi_util_entryid_generate_oneoff (mem_ctx, &oneoff_eid, dn, email);
set_SPropValue_proptag (&sprop, PR_ENTRYID, (gconstpointer )(oneoff_eid));
SRow_addprop (aRow, sprop);
#endif
@@ -1458,13 +1458,26 @@ exchange_mapi_connection_fetch_items (ExchangeMapiConnection *conn, mapi_id_t
for (k = 1; k < GetPropsTagArray->cValues; k++)
SPropTagArray_add (mem_ctx, tags, GetPropsTagArray->aulPropTag[k]);
retval = GetProps (&obj_message, tags, &lpProps, &prop_count);
+
MAPIFreeBuffer (tags);
properties_array.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue,
prop_count + 1);
properties_array.cValues = prop_count;
- for (k=0; k < prop_count; k++)
- cast_mapi_SPropValue(&properties_array.lpProps[k], &lpProps[k]);
-
+ for (k=0; k < prop_count; k++) {
+ if ((lpProps[k].ulPropTag & 0xFFFF) == PT_MV_BINARY) {
+ uint32_t ci;
+
+ properties_array.lpProps[k].ulPropTag = lpProps[k].ulPropTag;
+ properties_array.lpProps[k].value.MVbin.cValues = lpProps[k].value.MVbin.cValues;
+ properties_array.lpProps[k].value.MVbin.bin = (struct SBinary_short *) talloc_array (mem_ctx, struct Binary_r, properties_array.lpProps[k].value.MVbin.cValues);
+ for (ci = 0; ci < properties_array.lpProps[k].value.MVbin.cValues; ci++) {
+ properties_array.lpProps[k].value.MVbin.bin[ci].cb = lpProps[k].value.MVbin.lpbin[ci].cb;
+ properties_array.lpProps[k].value.MVbin.bin[ci].lpb = lpProps[k].value.MVbin.lpbin[ci].lpb;
+ }
+ } else {
+ cast_mapi_SPropValue (&properties_array.lpProps[k], &lpProps[k]);
+ }
+ }
} else
retval = GetPropsAll (&obj_message, &properties_array);
relax:
@@ -3155,9 +3168,9 @@ exchange_mapi_connection_ex_to_smtp (ExchangeMapiConnection *conn, const gchar *
SPropTagArray = set_SPropTagArray(mem_ctx, 0x1,
PR_SMTP_ADDRESS_UNICODE);
- retval = ResolveNames (priv->session, (const gchar **)str_array, SPropTagArray, &SRowSet, &flaglist, 0);
+ retval = ResolveNames (priv->session, (const gchar **)str_array, SPropTagArray, &SRowSet, &flaglist, MAPI_UNICODE);
if (retval != MAPI_E_SUCCESS)
- retval = ResolveNames (priv->session, (const gchar **)str_array, SPropTagArray, &SRowSet, &flaglist, MAPI_UNICODE);
+ retval = ResolveNames (priv->session, (const gchar **)str_array, SPropTagArray, &SRowSet, &flaglist, 0);
if (retval == MAPI_E_SUCCESS && SRowSet && SRowSet->cRows == 1) {
smtp_addr = (const gchar *) exchange_mapi_util_find_row_propval (SRowSet->aRow, PR_SMTP_ADDRESS_UNICODE);
diff --git a/src/libexchangemapi/exchange-mapi-defs.h b/src/libexchangemapi/exchange-mapi-defs.h
index 53ed08c..751505d 100644
--- a/src/libexchangemapi/exchange-mapi-defs.h
+++ b/src/libexchangemapi/exchange-mapi-defs.h
@@ -245,6 +245,7 @@ typedef enum {
#endif
#define IPM_CONTACT "IPM.Contact"
+#define IPM_DISTLIST "IPM.DistList"
#define IPM_APPOINTMENT "IPM.Appointment"
#define IPM_SCHEDULE_MEETING_PREFIX "IPM.Schedule.Meeting."
#define IPM_SCHEDULE_MEETING_REQUEST "IPM.Schedule.Meeting.Request"
diff --git a/src/libexchangemapi/exchange-mapi-utils.c b/src/libexchangemapi/exchange-mapi-utils.c
index 0a69b41..8d264bf 100644
--- a/src/libexchangemapi/exchange-mapi-utils.c
+++ b/src/libexchangemapi/exchange-mapi-utils.c
@@ -320,6 +320,65 @@ exchange_mapi_util_free_stream_list (GSList **stream_list)
*stream_list = NULL;
}
+static void
+dump_bin (const uint8_t *bin, uint32_t bin_sz, const gchar *line_prefix)
+{
+ gint k, l, last;
+
+ if (!bin) {
+ g_print ("NULL");
+ return;
+ }
+
+ g_print ("%s", line_prefix);
+
+ last = 0;
+ for (k = 0; k < bin_sz; k++) {
+ if ((k > 0 && (k % 16) == 0)) {
+ g_print (" ");
+ for (l = last; l < k; l++) {
+ uint8_t u8 = bin[l];
+
+ if ((l % 8) == 0)
+ g_print (" ");
+ if (u8 <= 32 || u8 >= 128)
+ g_print (".");
+ else
+ g_print ("%c", u8);
+ }
+
+ last = l;
+ g_print ("\n%s", line_prefix);
+ } else if (k > 0 && (k % 8) == 0) {
+ g_print (" ");
+ }
+ g_print (" %02X", bin[k]);
+ }
+
+ if (last < k) {
+ l = k;
+
+ while ((l % 16) != 0) {
+ g_print (" ");
+ if (l > 0 && (l % 8) == 0)
+ g_print (" ");
+ l++;
+ }
+
+ g_print (" ");
+ for (l = last; l < k; l++) {
+ uint8_t u8 = bin[l];
+
+ if ((l % 8) == 0)
+ g_print (" ");
+ if (u8 <= 32 || u8 >= 128)
+ g_print (".");
+ else
+ g_print ("%c", u8);
+ }
+ }
+}
+
void
exchange_mapi_debug_property_dump (struct mapi_SPropValue_array *properties)
{
@@ -336,6 +395,12 @@ exchange_mapi_debug_property_dump (struct mapi_SPropValue_array *properties)
else
g_print("\n0x%08X \t", lpProp->ulPropTag);
switch (lpProp->ulPropTag & 0xFFFF) {
+ case PT_UNSPECIFIED:
+ g_print (" PT_UNSPECIFIED");
+ break;
+ case PT_NULL:
+ g_print (" PT_NULL");
+ break;
case PT_BOOLEAN:
g_print(" (bool) - %d", (bool) lpProp->value.b);
break;
@@ -345,9 +410,17 @@ exchange_mapi_debug_property_dump (struct mapi_SPropValue_array *properties)
case PT_LONG:
g_print(" (long) - %u", lpProp->value.l);
break;
+ case PT_FLOAT:
+ g_print (" PT_FLOAT");
+ break;
case PT_DOUBLE:
g_print (" (double) - %lf", (double)lpProp->value.dbl);
break;
+ case PT_CURRENCY:
+ g_print (" PT_CURRENCY");
+ break;
+ case PT_APPTIME:
+ g_print (" PT_APPTIME");
case PT_I8:
g_print (" (gint) - 0x%016" G_GINT64_MODIFIER "X", lpProp->value.d);
break;
@@ -371,19 +444,78 @@ exchange_mapi_debug_property_dump (struct mapi_SPropValue_array *properties)
if (lpProp)
g_print(" (unicodestring) - %s", lpProp->value.lpszW ? lpProp->value.lpszW : lpProp->value.lpszA ? lpProp->value.lpszA : "null");
break;
+ case PT_OBJECT:
+ g_print (" PT_OBJECT");
+ break;
+ case PT_CLSID:
+ g_print (" PT_CLSID");
+ break;
+ case PT_SVREID:
+ g_print (" PT_SVREID");
+ break;
+ case PT_SRESTRICT:
+ g_print (" PT_SRESTRICT");
+ break;
+ case PT_ACTIONS:
+ g_print (" PT_ACTIONS");
+ break;
case PT_BINARY:
- g_print(" (struct SBinary_short *) - %p Binary data follows: \n", &lpProp->value.bin);
- for (j = 0; j < lpProp->value.bin.cb; j++)
- g_print("0x%02X ", lpProp->value.bin.lpb[j]);
+ g_print(" (struct SBinary_short *) - %p Binary data follows (size %d): \n", &lpProp->value.bin, lpProp->value.bin.cb);
+ dump_bin (lpProp->value.bin.lpb, lpProp->value.bin.cb, " ");
break;
case PT_MV_STRING8:
- g_print(" (struct mapi_SLPSTRArray *) - %p", &lpProp->value.MVszA);
+ g_print(" (struct mapi_SLPSTRArray *) (%d items)", lpProp->value.MVszA.cValues);
+ for (j = 0; j < lpProp->value.MVszA.cValues; j++) {
+ g_print ("\n item[%d] = '%s'", j, lpProp->value.MVszA.strings[j].lppszA ? lpProp->value.MVszA.strings[j].lppszA : "[NULL]");
+ }
+ break;
+ case PT_MV_SHORT:
+ g_print (" PT_MV_SHORT");
+ break;
+ case PT_MV_LONG:
+ g_print (" PT_MV_LONG");
+ break;
+ case PT_MV_FLOAT:
+ g_print (" PT_MV_FLOAT");
+ break;
+ case PT_MV_DOUBLE:
+ g_print (" PT_MV_DOUBLE");
+ break;
+ case PT_MV_CURRENCY:
+ g_print (" PT_MV_CURRENCY");
+ break;
+ case PT_MV_APPTIME:
+ g_print (" PT_MV_APPTIME");
+ break;
+ case PT_MV_I8:
+ g_print (" PT_MV_I8");
+ break;
+ case PT_MV_UNICODE:
+ g_print (" PT_MV_UNICODE (%d items)", lpProp->value.MVszW.cValues);
+ for (j = 0; j < lpProp->value.MVszW.cValues; j++) {
+ g_print ("\n item[%d] = '%s'", j, lpProp->value.MVszW.strings[j].lppszW ? lpProp->value.MVszW.strings[j].lppszW : "[NULL]");
+ }
+ break;
+ case PT_MV_SYSTIME:
+ g_print (" PT_MV_SYSTIME");
+ break;
+ case PT_MV_CLSID:
+ g_print (" PT_MV_CLSID");
+ break;
+ case PT_MV_BINARY:
+ g_print (" PT_MV_BINARY (%d items)", lpProp->value.MVbin.cValues);
+ for (j = 0; j < lpProp->value.MVbin.cValues; j++) {
+ g_print ("\n item[%d] (size %d)\n", j, lpProp->value.MVbin.bin[j].cb);
+ dump_bin (lpProp->value.MVbin.bin[j].lpb, lpProp->value.MVbin.bin[j].cb, " ");
+ }
+ g_print ("\n---");
break;
default:
- g_print(" - NONE NULL");
+ g_print (" - Unknown type 0x%04X", lpProp->ulPropTag & 0xFFFF);
}
}
}
+ g_print ("\n");
}
/* Attention: Devs at work;-) */
@@ -418,6 +550,66 @@ exchange_mapi_util_bin_append_uint32 (TALLOC_CTX *mem_ctx, struct Binary_r *bin,
*ptr++ = ((val >> 24) & 0xFF);
}
+/* returns how many bytes read, 0 means an error */
+static uint32_t
+bin_decode_uint16 (const uint8_t *ptr, uint32_t ptr_cb, uint16_t *res)
+{
+ g_return_val_if_fail (res != NULL, 0);
+ g_return_val_if_fail (ptr != NULL, 0);
+
+ if (ptr_cb < 2)
+ return 0;
+
+ *res = ((ptr[0] & 0xFF) ) |
+ ((ptr[1] & 0xFF) << 8);
+
+ return 2;
+}
+
+/* returns how many bytes read, 0 means an error */
+static uint32_t
+bin_decode_uint32 (const uint8_t *ptr, uint32_t ptr_cb, uint32_t *res)
+{
+ g_return_val_if_fail (res != NULL, 0);
+ g_return_val_if_fail (ptr != NULL, 0);
+
+ if (ptr_cb < 4)
+ return 0;
+
+ *res = ((ptr[0] & 0xFF) ) |
+ ((ptr[1] & 0xFF) << 8) |
+ ((ptr[2] & 0xFF) << 16) |
+ ((ptr[3] & 0xFF) << 24);
+
+ return 4;
+}
+
+static uint32_t
+bin_decode_string (const uint8_t *ptr, uint32_t sz, gchar **str, gboolean is_unicode)
+{
+ uint32_t len;
+
+ g_return_val_if_fail (ptr != NULL, 0);
+ g_return_val_if_fail (str != NULL, 0);
+
+ for (len = 0; len < sz; len += (is_unicode ? 2 : 1)) {
+ if (ptr[len] == 0x00 && (!is_unicode || (len + 1 < sz && ptr[len + 1] == 0x00)))
+ break;
+ }
+
+ if (len >= sz || ptr[len] != 0x00 || (is_unicode && len + 1 >= sz && ptr[len + 1] != 0x00))
+ return 0;
+
+ if (is_unicode) {
+ *str = g_utf16_to_utf8 ((const gunichar2 *) ptr, len / 2, NULL, NULL, NULL);
+ } else {
+ *str = g_malloc0 (sizeof(gchar) * (1 + len));
+ strncpy (*str, (const gchar *) ptr, len - 1);
+ }
+
+ return len + 1 + (is_unicode ? 1 : 0);
+}
+
static void
exchange_mapi_util_bin_append_string (TALLOC_CTX *mem_ctx, struct Binary_r *bin, const gchar *val)
{
@@ -433,12 +625,6 @@ exchange_mapi_util_bin_append_string (TALLOC_CTX *mem_ctx, struct Binary_r *bin,
}
static void
-exchange_mapi_util_bin_append_unicode (TALLOC_CTX *mem_ctx, struct Binary_r *bin, const gchar *val)
-{
- /* WRITE ME */
-}
-
-static void
exchange_mapi_util_bin_append_val (TALLOC_CTX *mem_ctx, struct Binary_r *bin, const uint8_t *val, gsize len)
{
uint8_t *ptr = NULL;
@@ -451,6 +637,20 @@ exchange_mapi_util_bin_append_val (TALLOC_CTX *mem_ctx, struct Binary_r *bin, co
memcpy (ptr, val, len);
}
+static void
+exchange_mapi_util_bin_append_unicode (TALLOC_CTX *mem_ctx, struct Binary_r *bin, const gchar *val)
+{
+ gunichar2 *utf16;
+ glong written = 0;
+
+ utf16 = g_utf8_to_utf16 (val, -1, NULL, &written, NULL);
+ g_return_if_fail (utf16 != NULL);
+
+ exchange_mapi_util_bin_append_val (mem_ctx, bin, (uint8_t *)utf16, (written + 1) * 2);
+
+ g_free (utf16);
+}
+
static const uint8_t MAPI_ONE_OFF_UID[] = {
0x81, 0x2b, 0x1f, 0xa4, 0xbe, 0xa3, 0x10, 0x19,
0x9d, 0x6e, 0x00, 0xdd, 0x01, 0x0f, 0x54, 0x02
@@ -462,10 +662,9 @@ static const uint8_t MAPI_ONE_OFF_UID[] = {
/**
* e2k_entryid_generate_oneoff:
+ * @entryid: entry ID to be filled
* @display_name: the display name of the user
* @email: the email address
- * @unicode: %TRUE to generate a Unicode ENTRYID (in which case
- * @display_name should be UTF-8), %FALSE for an ASCII ENTRYID.
*
* Constructs a "one-off" ENTRYID value that can be used as a MAPI
* recipient (eg, for a message forwarding server-side rule),
@@ -473,32 +672,100 @@ static const uint8_t MAPI_ONE_OFF_UID[] = {
*
* Return value: the recipient ENTRYID
**/
-struct Binary_r *
-exchange_mapi_util_entryid_generate_oneoff (TALLOC_CTX *mem_ctx, const gchar *display_name, const gchar *email, gboolean unicode)
+void
+exchange_mapi_util_entryid_generate_oneoff (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *display_name, const gchar *email)
{
- struct Binary_r *entryid;
-
- entryid = talloc_zero (mem_ctx, struct Binary_r);
+ g_return_if_fail (entryid != NULL);
exchange_mapi_util_bin_append_uint32 (mem_ctx, entryid, 0);
exchange_mapi_util_bin_append_val (mem_ctx, entryid, MAPI_ONE_OFF_UID, sizeof(MAPI_ONE_OFF_UID));
exchange_mapi_util_bin_append_uint16 (mem_ctx, entryid, 0);
- exchange_mapi_util_bin_append_uint16 (mem_ctx, entryid,
- MAPI_ONE_OFF_NO_RICH_INFO |
- MAPI_ONE_OFF_MYSTERY_FLAG |
- (unicode ? MAPI_ONE_OFF_UNICODE : 0));
-
- if (unicode) {
- exchange_mapi_util_bin_append_unicode (mem_ctx, entryid, display_name);
- exchange_mapi_util_bin_append_unicode (mem_ctx, entryid, "SMTP");
- exchange_mapi_util_bin_append_unicode (mem_ctx, entryid, email);
- } else {
- exchange_mapi_util_bin_append_string (mem_ctx, entryid, display_name);
- exchange_mapi_util_bin_append_string (mem_ctx, entryid, "SMTP");
- exchange_mapi_util_bin_append_string (mem_ctx, entryid, email);
+ exchange_mapi_util_bin_append_uint16 (mem_ctx, entryid, MAPI_ONE_OFF_NO_RICH_INFO | MAPI_ONE_OFF_MYSTERY_FLAG | MAPI_ONE_OFF_UNICODE);
+ exchange_mapi_util_bin_append_unicode (mem_ctx, entryid, display_name);
+ exchange_mapi_util_bin_append_unicode (mem_ctx, entryid, "SMTP");
+ exchange_mapi_util_bin_append_unicode (mem_ctx, entryid, email);
+}
+
+gboolean
+exchange_mapi_util_entryid_decode_oneoff (const struct Binary_r *entryid, gchar **display_name, gchar **email)
+{
+ uint32_t u32, sz, r;
+ uint16_t u16, flags;
+ uint8_t *ptr;
+ gchar *smtp;
+
+ g_return_val_if_fail (entryid != NULL, FALSE);
+ g_return_val_if_fail (entryid->lpb != NULL, FALSE);
+ g_return_val_if_fail (display_name != NULL, FALSE);
+ g_return_val_if_fail (email != NULL, FALSE);
+
+ *display_name = NULL;
+ *email = NULL;
+
+ ptr = entryid->lpb;
+ sz = entryid->cb;
+
+ u32 = 1;
+ r = bin_decode_uint32 (ptr, sz, &u32);
+ if (!r || u32 != 0)
+ return FALSE;
+
+ ptr += r;
+ sz -= r;
+
+ for (r = 0; r < G_N_ELEMENTS (MAPI_ONE_OFF_UID) && r < sz; r++) {
+ if (ptr[r] != MAPI_ONE_OFF_UID[r])
+ return FALSE;
}
- return entryid;
+ if (r != G_N_ELEMENTS (MAPI_ONE_OFF_UID))
+ return FALSE;
+
+ ptr += r;
+ sz -= r;
+
+ u16 = 1;
+ r = bin_decode_uint16 (ptr, sz, &u16);
+ if (!r || u16 != 0)
+ return FALSE;
+ ptr += r;
+ sz -= r;
+
+ flags = 0;
+ r = bin_decode_uint16 (ptr, sz, &flags);
+ if (!r)
+ return FALSE;
+ ptr += r;
+ sz -= r;
+
+ r = bin_decode_string (ptr, sz, display_name, (flags & MAPI_ONE_OFF_UNICODE) != 0);
+ if (!r || !*display_name)
+ return FALSE;
+ ptr += r;
+ sz -= r;
+
+ smtp = NULL;
+ r = bin_decode_string (ptr, sz, &smtp, (flags & MAPI_ONE_OFF_UNICODE) != 0);
+ if (!r || !smtp || !g_str_equal (smtp, "SMTP")) {
+ g_free (smtp);
+ g_free (*display_name);
+ *display_name = NULL;
+
+ return FALSE;
+ }
+ g_free (smtp);
+ ptr += r;
+ sz -= r;
+
+ r = bin_decode_string (ptr, sz, email, (flags & MAPI_ONE_OFF_UNICODE) != 0);
+ if (!r || !*email) {
+ g_free (*display_name);
+ *display_name = NULL;
+
+ return FALSE;
+ }
+
+ return TRUE;
}
static const uint8_t MAPI_LOCAL_UID[] = {
diff --git a/src/libexchangemapi/exchange-mapi-utils.h b/src/libexchangemapi/exchange-mapi-utils.h
index 48cbad8..d13cff1 100644
--- a/src/libexchangemapi/exchange-mapi-utils.h
+++ b/src/libexchangemapi/exchange-mapi-utils.h
@@ -59,8 +59,9 @@ exchange_mapi_util_free_stream_list (GSList **stream_list);
void
exchange_mapi_debug_property_dump (struct mapi_SPropValue_array *properties);
-struct Binary_r *
-exchange_mapi_util_entryid_generate_oneoff (TALLOC_CTX *mem_ctx, const gchar *display_name, const gchar *email, gboolean unicode);
+void exchange_mapi_util_entryid_generate_oneoff (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *display_name, const gchar *email);
+gboolean exchange_mapi_util_entryid_decode_oneoff (const struct Binary_r *entyrid, gchar **display_name, gchar **email);
+
struct Binary_r *
exchange_mapi_util_entryid_generate_local (TALLOC_CTX *mem_ctx, const gchar *exchange_dn);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]