1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3
* This program is free software; you can redistribute it and/or
4
* modify it under the terms of the GNU Lesser General Public
5
* License as published by the Free Software Foundation; either
6
* version 2 of the License, or (at your option) version 3.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public
14
* License along with the program; if not, see <http://www.gnu.org/licenses/>
18
* Srinivasa Ragavan <sragavan@novell.com>
20
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
32
#include <glib/gstdio.h>
36
** #include <glib/gi18n-lib.h>
39
#include <libedataserver/e-sexp.h>
40
#include "libedataserver/e-flag.h"
41
#include <libebook/e-contact.h>
43
#include <libedata-book/e-book-backend-sexp.h>
44
#include <libedata-book/e-data-book.h>
45
#include <libedata-book/e-data-book-view.h>
46
#include <libedata-book/e-book-backend-cache.h>
47
#include <libedata-book/e-book-backend-summary.h>
48
#include "e-book-backend-mapi.h"
51
static EBookBackendClass *e_book_backend_mapi_parent_class;
52
static gboolean enable_debug = TRUE;
54
struct _EBookBackendMAPIPrivate
59
gboolean marked_for_offline;
60
gboolean is_cache_ready;
61
gboolean is_summary_ready;
67
char *summary_file_name;
68
EBookBackendSummary *summary;
69
EBookBackendCache *cache;
73
#define LOCK() g_mutex_lock (priv->lock)
74
#define UNLOCK() g_mutex_unlock (priv->lock)
76
#define ELEMENT_TYPE_SIMPLE 0x01
77
#define ELEMENT_TYPE_COMPLEX 0x02 /* fields which require explicit functions to set values into EContact and EGwItem */
79
#define SUMMARY_FLUSH_TIMEOUT 5000
80
#define ELEMENT_TYPE_SIMPLE 0x01
81
#define ELEMENT_TYPE_COMPLEX 0x02
83
static EContact * emapidump_contact(struct mapi_SPropValue_array *properties);
85
static const struct field_element_mapping {
86
EContactField field_id;
90
// char *element_name;
91
// void (*populate_contact_func)(EContact *contact, gpointer data);
92
// void (*set_value_in_gw_item) (EGwItem *item, gpointer data);
93
// void (*set_changes) (EGwItem *new_item, EGwItem *old_item);
97
{ E_CONTACT_UID, PT_STRING8, 0, ELEMENT_TYPE_SIMPLE},
98
{ E_CONTACT_REV, PT_SYSTIME, PR_LAST_MODIFICATION_TIME, ELEMENT_TYPE_SIMPLE},
100
{ E_CONTACT_FILE_AS, PT_STRING8, PR_EMS_AB_MANAGER_T, ELEMENT_TYPE_SIMPLE},
101
{ E_CONTACT_FULL_NAME, PT_STRING8, PR_DISPLAY_NAME, ELEMENT_TYPE_SIMPLE },
102
{ E_CONTACT_GIVEN_NAME, PT_STRING8, PR_GIVEN_NAME, ELEMENT_TYPE_SIMPLE},
103
{ E_CONTACT_FAMILY_NAME, PT_STRING8, PR_SURNAME , ELEMENT_TYPE_SIMPLE},
104
{ E_CONTACT_NICKNAME, PT_STRING8, PR_NICKNAME, ELEMENT_TYPE_SIMPLE },
106
{ E_CONTACT_EMAIL_1, PT_STRING8, PROP_TAG(PT_UNICODE, 0x8084), ELEMENT_TYPE_SIMPLE},
107
{ E_CONTACT_EMAIL_2, PT_STRING8, PROP_TAG(PT_UNICODE, 0x8094), ELEMENT_TYPE_SIMPLE},
108
{ E_CONTACT_EMAIL_3, PT_STRING8, PROP_TAG(PT_UNICODE, 0x80a4), ELEMENT_TYPE_SIMPLE},
109
{ E_CONTACT_IM_AIM, PT_STRING8, PROP_TAG(PT_UNICODE, 0x8062), ELEMENT_TYPE_COMPLEX},
111
{ E_CONTACT_PHONE_BUSINESS, PT_STRING8, PR_OFFICE_TELEPHONE_NUMBER, ELEMENT_TYPE_SIMPLE},
112
{ E_CONTACT_PHONE_HOME, PT_STRING8, PR_HOME_TELEPHONE_NUMBER, ELEMENT_TYPE_SIMPLE},
113
{ E_CONTACT_PHONE_MOBILE, PT_STRING8, PR_MOBILE_TELEPHONE_NUMBER, ELEMENT_TYPE_SIMPLE},
114
{ E_CONTACT_PHONE_HOME_FAX, PT_STRING8, PR_HOME_FAX_NUMBER ,ELEMENT_TYPE_SIMPLE},
115
{ E_CONTACT_PHONE_BUSINESS_FAX, PT_STRING8, PR_BUSINESS_FAX_NUMBER,ELEMENT_TYPE_SIMPLE},
116
{ E_CONTACT_PHONE_PAGER, PT_STRING8, PR_PAGER_TELEPHONE_NUMBER,ELEMENT_TYPE_SIMPLE},
117
{ E_CONTACT_PHONE_ASSISTANT, PT_STRING8, PR_ASSISTANT_TELEPHONE_NUMBER ,ELEMENT_TYPE_SIMPLE},
118
{ E_CONTACT_PHONE_COMPANY, PT_STRING8, PR_COMPANY_MAIN_PHONE_NUMBER ,ELEMENT_TYPE_SIMPLE},
120
{ E_CONTACT_HOMEPAGE_URL, PT_STRING8, 0x802b001e, ELEMENT_TYPE_SIMPLE},
121
{ E_CONTACT_FREEBUSY_URL, PT_STRING8, 0x80d8001e, ELEMENT_TYPE_SIMPLE},
123
{ E_CONTACT_ROLE, PT_STRING8, PR_PROFESSION, ELEMENT_TYPE_SIMPLE},
124
{ E_CONTACT_TITLE, PT_STRING8, PR_TITLE, ELEMENT_TYPE_SIMPLE},
125
{ E_CONTACT_ORG, PT_STRING8, PR_COMPANY_NAME, ELEMENT_TYPE_SIMPLE},
126
{ E_CONTACT_ORG_UNIT, PT_STRING8, PR_DEPARTMENT_NAME,ELEMENT_TYPE_SIMPLE},
127
{ E_CONTACT_MANAGER, PT_STRING8, PR_MANAGER_NAME, ELEMENT_TYPE_SIMPLE},
128
{ E_CONTACT_ASSISTANT, PT_STRING8, PR_ASSISTANT, ELEMENT_TYPE_SIMPLE},
130
{ E_CONTACT_OFFICE, PT_STRING8, PR_OFFICE_LOCATION, ELEMENT_TYPE_SIMPLE},
131
{ E_CONTACT_SPOUSE, PT_STRING8, PR_SPOUSE_NAME, ELEMENT_TYPE_SIMPLE},
133
{ E_CONTACT_BIRTH_DATE, PT_SYSTIME, PR_BIRTHDAY, ELEMENT_TYPE_COMPLEX},
134
{ E_CONTACT_ANNIVERSARY, PT_SYSTIME, PR_WEDDING_ANNIVERSARY, ELEMENT_TYPE_COMPLEX},
136
{ E_CONTACT_NOTE, PT_STRING8, PR_BODY, ELEMENT_TYPE_SIMPLE},
139
{ E_CONTACT_ADDRESS_HOME, PT_STRING8, 0x801a001e, ELEMENT_TYPE_COMPLEX},
140
{ E_CONTACT_ADDRESS_WORK, PT_STRING8, 0x801c001e, ELEMENT_TYPE_COMPLEX},
141
// { E_CONTACT_BOOK_URI, ELEMENT_TYPE_SIMPLE, "book_uri"}
142
// { E_CONTACT_EMAIL, PT_STRING8, 0x8084001e},
143
// { E_CONTACT_CATEGORIES, },
146
static int maplen = G_N_ELEMENTS(mappings);
148
static EDataBookView *
149
find_book_view (EBookBackendMAPI *ebmapi)
151
EList *views = e_book_backend_get_book_views (E_BOOK_BACKEND (ebmapi));
153
EDataBookView *rv = NULL;
158
iter = e_list_get_iterator (views);
161
g_object_unref (views);
165
if (e_iterator_is_valid (iter)) {
166
/* just always use the first book view */
167
EDataBookView *v = (EDataBookView*)e_iterator_get(iter);
172
g_object_unref (iter);
173
g_object_unref (views);
179
build_restriction_emails_contains (struct mapi_SRestriction *res,
182
char *email=NULL, *tmp, *tmp1;
184
/* This currently supports "email foo@bar.soo" */
185
tmp = strdup (query);
187
tmp = strstr (tmp, "email");
189
tmp = strchr (tmp, '\"');
191
tmp = strchr (tmp, '\"');
194
tmp1 = strchr (tmp1, '\"');
204
if (email==NULL || !strchr (email, '@'))
207
res->rt = RES_PROPERTY;
208
res->res.resProperty.relop = RES_PROPERTY;
209
res->res.resProperty.ulPropTag = 0x801f001e; /* EMAIL */
210
res->res.resProperty.lpProp.ulPropTag = 0x801f001e; /* EMAIL*/
211
res->res.resProperty.lpProp.value.lpszA = email;
217
build_multiple_restriction_emails_contains (struct mapi_SRestriction *res,
218
struct mapi_SRestriction_or *or_res,
221
char *email=NULL, *tmp, *tmp1;
222
//Number of restriction to apply
223
unsigned int res_count = 6;
225
/* This currently supports "email foo@bar.soo" */
226
tmp = strdup (query);
228
tmp = strstr (tmp, "email");
230
tmp = strchr (tmp, '\"');
232
tmp = strchr (tmp, '\"');
235
tmp1 = strchr (tmp1, '\"');
244
if (email==NULL || !strchr (email, '@'))
247
or_res[0].rt = RES_CONTENT;
248
or_res[0].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
249
or_res[0].res.resContent.ulPropTag = PR_EMS_AB_MANAGER_T;
250
or_res[0].res.resContent.lpProp.value.lpszA = email;
252
or_res[1].rt = RES_CONTENT;
253
or_res[1].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
254
or_res[1].res.resContent.ulPropTag = PR_DISPLAY_NAME;
255
or_res[1].res.resContent.lpProp.value.lpszA = email;
257
or_res[2].rt = RES_CONTENT;
258
or_res[2].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
259
or_res[2].res.resContent.ulPropTag = PR_GIVEN_NAME;
260
or_res[2].res.resContent.lpProp.value.lpszA = email;
262
or_res[3].rt = RES_CONTENT;
263
or_res[3].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
264
or_res[3].res.resContent.ulPropTag = 0x8084001e;
265
or_res[3].res.resContent.lpProp.value.lpszA = email;
267
or_res[4].rt = RES_CONTENT;
268
or_res[4].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
269
or_res[4].res.resContent.ulPropTag = 0x8094001e;
270
or_res[4].res.resContent.lpProp.value.lpszA = email;
272
or_res[5].rt = RES_CONTENT;
273
or_res[5].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
274
or_res[5].res.resContent.ulPropTag = 0x80a4001e;
275
or_res[5].res.resContent.lpProp.value.lpszA = email;
277
res = g_new0 (struct mapi_SRestriction, 1);
280
res->res.resOr.cRes = res_count;
281
res->res.resOr.res = or_res;
287
get_filename_from_uri (const char *uri, const char *file)
289
char *mangled_uri, *filename;
292
/* mangle the URI to not contain invalid characters */
293
mangled_uri = g_strdup (uri);
294
for (i = 0; i < strlen (mangled_uri); i++) {
295
switch (mangled_uri[i]) {
298
mangled_uri[i] = '_';
302
/* generate the file name */
303
filename = g_build_filename (g_get_home_dir (), ".evolution/cache/addressbook",
304
mangled_uri, file, NULL);
307
g_free (mangled_uri);
312
static GNOME_Evolution_Addressbook_CallStatus
313
e_book_backend_mapi_load_source (EBookBackend *backend,
315
gboolean only_if_exists)
317
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
318
const gchar *offline, *tmp;
322
printf("MAPI load source\n");
323
offline = e_source_get_property (source, "offline_sync");
324
if (offline && g_str_equal (offline, "1"))
325
priv->marked_for_offline = TRUE;
329
/* Either we are in Online mode or this is marked for offline */
331
priv->uri = g_strdup (e_source_get_uri (source));
333
tokens = g_strsplit (priv->uri, ";", 2);
335
uri = g_strdup (tokens [0]);
336
priv->book_name = g_strdup (tokens[1]);
337
if (priv->book_name == NULL) {
338
g_warning ("Bookname is null for %s\n", uri);
339
return GNOME_Evolution_Addressbook_OtherError;
343
if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL &&
344
!priv->marked_for_offline ) {
345
return GNOME_Evolution_Addressbook_OfflineUnavailable;
348
if (priv->marked_for_offline) {
349
priv->summary_file_name = get_filename_from_uri (priv->uri, "cache.summary");
350
if (g_file_test (priv->summary_file_name, G_FILE_TEST_EXISTS)) {
351
printf("Loading the summary\n");
352
priv->summary = e_book_backend_summary_new (priv->summary_file_name,
353
SUMMARY_FLUSH_TIMEOUT);
354
e_book_backend_summary_load (priv->summary);
355
priv->is_summary_ready = TRUE;
358
/* Load the cache as well.*/
359
if (e_book_backend_cache_exists (priv->uri)) {
360
printf("Loading the cache\n");
361
priv->cache = e_book_backend_cache_new (priv->uri);
362
priv->is_cache_ready = TRUE;
364
//FIXME: We may have to do a time based reload. Or deltas should upload.
366
priv->summary = e_book_backend_summary_new (NULL,SUMMARY_FLUSH_TIMEOUT);
370
e_book_backend_set_is_loaded (E_BOOK_BACKEND (backend), TRUE);
371
e_book_backend_set_is_writable (backend, TRUE);
372
if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL) {
373
e_book_backend_set_is_writable (backend, FALSE);
374
e_book_backend_notify_writable (backend, FALSE);
375
e_book_backend_notify_connection_status (backend, FALSE);
377
printf("Unfortunately the cache is not yet created\n");
378
return GNOME_Evolution_Addressbook_OfflineUnavailable;
381
e_book_backend_notify_connection_status (backend, TRUE);
384
priv->profile = g_strdup (e_source_get_property (source, "profile"));
385
exchange_mapi_util_mapi_id_from_string (e_source_get_property (source, "folder-id"), &priv->fid);
387
tmp = e_source_get_property (source, "folder-id");
388
printf("Folder is %s %016llX\n", tmp, priv->fid);
390
/* Once aunthentication in address book works this can be removed */
391
if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL) {
392
return GNOME_Evolution_Addressbook_Success;
395
// writable property will be set in authenticate_user callback
396
e_book_backend_set_is_loaded (E_BOOK_BACKEND (backend), TRUE);
397
e_book_backend_notify_connection_status (E_BOOK_BACKEND (backend), TRUE);
401
printf("For profile %s and folder %s - %016llX\n", priv->profile, tmp, priv->fid);
403
return GNOME_Evolution_Addressbook_Success;
407
e_book_backend_mapi_get_static_capabilities (EBookBackend *backend)
410
printf("mapi get_static_capabilities\n");
411
//FIXME: Implement this.
413
return g_strdup ("net,bulk-removes,do-initial-query,contact-lists");
417
mapi_book_build_name_id (struct mapi_nameid *nameid, gpointer data)
419
// EContact *contact = data;
421
mapi_nameid_lid_add(nameid, 0x8005, PSETID_Address);
422
mapi_nameid_lid_add(nameid, 0x8084, PSETID_Address);
423
mapi_nameid_lid_add(nameid, 0x8083, PSETID_Address);
425
mapi_nameid_lid_add(nameid, 0x8093, PSETID_Address);
426
mapi_nameid_lid_add(nameid, 0x80A3, PSETID_Address);
428
mapi_nameid_string_add(nameid, "urn:schemas:contacts:fileas", PS_PUBLIC_STRINGS);
430
mapi_nameid_lid_add(nameid, 0x802B, PSETID_Address);
431
mapi_nameid_lid_add(nameid, 0x8062, PSETID_Address);
433
mapi_nameid_lid_add(nameid, 0x801A, PSETID_Address);
434
mapi_nameid_lid_add(nameid, 0x801B, PSETID_Address);
436
mapi_nameid_lid_add(nameid, 0x3A4F, PS_MAPI);
438
mapi_nameid_lid_add(nameid, 0x8094, PSETID_Address);
439
mapi_nameid_lid_add(nameid, 0x80A4, PSETID_Address);
444
#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));
447
mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropTagArray, gpointer data)
449
EContact *contact = data;
450
struct SPropValue *props;
454
printf("hex %x\n", SPropTagArray->aulPropTag[i]);
456
props = g_new (struct SPropValue, 50); //FIXME: Correct value tbd
457
set_str_value ( E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[0]);
459
set_str_value (E_CONTACT_FULL_NAME, PR_DISPLAY_NAME);
460
set_SPropValue_proptag(&props[i++], PR_MESSAGE_CLASS, (const void *)IPM_CONTACT);
461
set_str_value (E_CONTACT_FILE_AS, PR_NORMALIZED_SUBJECT);
462
set_str_value (E_CONTACT_EMAIL_1, SPropTagArray->aulPropTag[1]);
463
// set_str_value (E_CONTACT_EMAIL_1, SPropTagArray->aulPropTag[2]);
464
set_str_value (E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[5]);
467
// set_str_value ( E_CONTACT_EMAIL_1, 0x8083001e);
468
set_str_value ( E_CONTACT_EMAIL_2, SPropTagArray->aulPropTag[3]);
469
// set_str_value ( E_CONTACT_EMAIL_2, SPropTagArray->aulPropTag[11]);
471
set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[4]);
472
// set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[12]);
474
set_str_value (E_CONTACT_HOMEPAGE_URL, SPropTagArray->aulPropTag[6]);
475
set_str_value (E_CONTACT_FREEBUSY_URL, 0x812C001E);
478
set_str_value ( E_CONTACT_PHONE_BUSINESS, PR_OFFICE_TELEPHONE_NUMBER);
479
set_str_value ( E_CONTACT_PHONE_HOME, PR_HOME_TELEPHONE_NUMBER);
480
set_str_value ( E_CONTACT_PHONE_MOBILE, PR_MOBILE_TELEPHONE_NUMBER);
481
set_str_value ( E_CONTACT_PHONE_HOME_FAX, PR_HOME_FAX_NUMBER);
482
set_str_value ( E_CONTACT_PHONE_BUSINESS_FAX, PR_BUSINESS_FAX_NUMBER);
483
set_str_value ( E_CONTACT_PHONE_PAGER, PR_PAGER_TELEPHONE_NUMBER);
484
set_str_value ( E_CONTACT_PHONE_ASSISTANT, PR_ASSISTANT_TELEPHONE_NUMBER);
485
set_str_value ( E_CONTACT_PHONE_COMPANY, PR_COMPANY_MAIN_PHONE_NUMBER);
487
set_str_value (E_CONTACT_MANAGER, PR_MANAGER_NAME);
488
set_str_value (E_CONTACT_ASSISTANT, PR_ASSISTANT);
489
set_str_value (E_CONTACT_ORG, PR_COMPANY_NAME);
490
set_str_value (E_CONTACT_ORG_UNIT, PR_DEPARTMENT_NAME);
491
set_str_value (E_CONTACT_ROLE, PR_PROFESSION);
492
set_str_value (E_CONTACT_TITLE, PR_TITLE);
494
set_str_value (E_CONTACT_OFFICE, PR_OFFICE_LOCATION);
495
set_str_value (E_CONTACT_SPOUSE, PR_SPOUSE_NAME);
497
set_str_value (E_CONTACT_NOTE, PR_BODY);
500
if (e_contact_get (contact, E_CONTACT_BIRTH_DATE)) {
501
EContactDate *date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
507
tmtime.tm_mday = date->day - 1;
508
tmtime.tm_mon = date->month - 1;
509
tmtime.tm_year = date->year - 1900;
511
lt = mktime (&tmtime);
512
unix_to_nt_time (&nt, lt);
513
t.dwLowDateTime = (nt << 32) >> 32;
514
t.dwHighDateTime = (nt >> 32);
515
printf("sending bday\n");
516
set_SPropValue_proptag (&props[i++], PR_BIRTHDAY, &t);
519
if (e_contact_get (contact, E_CONTACT_ANNIVERSARY)) {
520
EContactDate *date = e_contact_get (contact, E_CONTACT_ANNIVERSARY);
526
tmtime.tm_mday = date->day - 1;
527
tmtime.tm_mon = date->month - 1;
528
tmtime.tm_year = date->year - 1900;
530
lt = mktime (&tmtime);
531
unix_to_nt_time (&nt, lt);
532
t.dwLowDateTime = (nt << 32) >> 32;
533
t.dwHighDateTime = (nt >> 32);
534
printf("sending wed\n");
535
set_SPropValue_proptag (&props[i++], PR_WEDDING_ANNIVERSARY, &t);
537
//Home and Office address
538
if (e_contact_get (contact, E_CONTACT_ADDRESS_HOME)) {
539
EContactAddress *contact_addr;
541
contact_addr = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
542
set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[8], contact_addr->street);
543
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_POST_OFFICE_BOX, contact_addr->ext);
544
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_CITY, contact_addr->locality);
545
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_STATE_OR_PROVINCE, contact_addr->region);
546
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_POSTAL_CODE, contact_addr->code);
547
set_SPropValue_proptag (&props[i++], PR_HOME_ADDRESS_COUNTRY, contact_addr->country);
550
if (e_contact_get (contact, E_CONTACT_ADDRESS_WORK)) {
551
EContactAddress *contact_addr;
553
contact_addr = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
554
set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[9], contact_addr->street);
555
set_SPropValue_proptag (&props[i++], PR_POST_OFFICE_BOX, contact_addr->ext);
556
set_SPropValue_proptag (&props[i++], PR_LOCALITY, contact_addr->locality);
557
set_SPropValue_proptag (&props[i++], PR_STATE_OR_PROVINCE, contact_addr->region);
558
set_SPropValue_proptag (&props[i++], PR_POSTAL_CODE, contact_addr->code);
559
set_SPropValue_proptag (&props[i++], PR_COUNTRY, contact_addr->country);
563
// set_str_value (E_CONTACT_NICKNAME, SPropTagArray->aulPropTag[10]);
564
if (e_contact_get (contact, E_CONTACT_IM_AIM)) {
565
GList *l = e_contact_get (contact, E_CONTACT_IM_AIM);
566
set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[7], l->data);
569
if (e_contact_get (contact, E_CONTACT_NICKNAME)) {
570
char *nick = e_contact_get (contact, E_CONTACT_NICKNAME);
571
// set_SPropValue_proptag (&props[i++], SPropTagArray->aulPropTag[10], nick);
572
printf("nickname %s %x\n", nick, SPropTagArray->aulPropTag[10]);
576
printf("Sending %d \n", i);
581
e_book_backend_mapi_create_contact (EBookBackend *backend,
589
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
592
printf("mapi create_contact \n");
594
switch (priv->mode) {
596
case GNOME_Evolution_Addressbook_MODE_LOCAL :
597
e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
600
case GNOME_Evolution_Addressbook_MODE_REMOTE :
601
contact = e_contact_new_from_vcard(vcard);
602
status = exchange_mapi_create_item (olFolderContacts, priv->fid, mapi_book_build_name_id, contact, mapi_book_build_props, contact, NULL, NULL, NULL, 0);
604
e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
607
id = exchange_mapi_util_mapi_ids_to_uid (priv->fid, status);
609
/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
610
e_contact_set (contact, E_CONTACT_UID, id);
611
e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
613
//somehow get the mid.
614
//add to summary and cache.
615
if (priv->marked_for_offline && priv->is_cache_ready)
616
e_book_backend_cache_add_contact (priv->cache, contact);
618
if (priv->marked_for_offline && priv->is_summary_ready)
619
e_book_backend_summary_add_contact (priv->summary, contact);
621
e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_Success, contact);
629
e_book_backend_mapi_remove_contacts (EBookBackend *backend,
635
GList *tmp = id_list;
636
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
640
printf("mapi: remove_contacts\n");
642
switch (priv->mode) {
644
case GNOME_Evolution_Addressbook_MODE_LOCAL :
645
e_data_book_respond_remove_contacts (book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
648
case GNOME_Evolution_Addressbook_MODE_REMOTE:
651
struct id_list *data = g_new (struct id_list, 1);
652
exchange_mapi_util_mapi_ids_from_uid (tmp->data, &fid, &mid);
654
list = g_slist_prepend (list, (gpointer) data);
658
exchange_mapi_remove_items (olFolderContacts, priv->fid, list);
659
if (priv->marked_for_offline && priv->is_cache_ready) {
662
e_book_backend_cache_remove_contact (priv->cache, tmp->data);
667
if (priv->marked_for_offline && priv->is_summary_ready) {
670
e_book_backend_summary_remove_contact (priv->summary, tmp->data);
676
e_data_book_respond_remove_contacts (book, opid,
677
GNOME_Evolution_Addressbook_Success, id_list);
685
e_book_backend_mapi_modify_contact (EBookBackend *backend,
690
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
697
printf("mapi: modify_contacts\n");
699
switch (priv->mode) {
701
case GNOME_Evolution_Addressbook_MODE_LOCAL :
702
e_data_book_respond_modify(book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
704
case GNOME_Evolution_Addressbook_MODE_REMOTE :
705
contact = e_contact_new_from_vcard(vcard);
706
tmp = e_contact_get (contact, E_CONTACT_UID);
707
exchange_mapi_util_mapi_ids_from_uid (tmp, &fid, &mid);
708
printf("modify id %s\n", tmp);
710
status = exchange_mapi_modify_item (olFolderContacts, priv->fid, mid, mapi_book_build_name_id, contact, mapi_book_build_props, contact, NULL, NULL, NULL, 0);
711
printf("getting %d\n", status);
713
e_data_book_respond_modify(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
717
e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
719
//FIXME: Write it cleanly
720
if (priv->marked_for_offline && priv->is_cache_ready)
721
printf("delete cache %d\n", e_book_backend_cache_remove_contact (priv->cache, tmp));
723
if (priv->marked_for_offline && priv->is_summary_ready)
724
e_book_backend_summary_remove_contact (priv->summary, tmp);
726
if (priv->marked_for_offline && priv->is_cache_ready)
727
e_book_backend_cache_add_contact (priv->cache, contact);
729
if (priv->marked_for_offline && priv->is_summary_ready)
730
e_book_backend_summary_add_contact (priv->summary, contact);
733
e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_Success, contact);
740
create_contact_item (FetchItemsCallbackData *item_data, gpointer data)
745
contact = emapidump_contact (item_data->properties);
746
suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
747
printf("got contact %s\n", suid);
749
/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
750
e_contact_set (contact, E_CONTACT_UID, suid);
760
e_book_backend_mapi_get_contact (EBookBackend *backend,
765
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
766
EContact *contact = NULL;
770
printf("mapi: get_contact %s\n", id);
772
switch (priv->mode) {
774
case GNOME_Evolution_Addressbook_MODE_LOCAL:
775
contact = e_book_backend_cache_get_contact (priv->cache,
778
vcard = e_vcard_to_string (E_VCARD (contact),
779
EVC_FORMAT_VCARD_30);
780
e_data_book_respond_get_contact (book,
782
GNOME_Evolution_Addressbook_Success,
785
g_object_unref (contact);
789
e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");
793
case GNOME_Evolution_Addressbook_MODE_REMOTE:
795
if (priv->marked_for_offline && e_book_backend_cache_is_populated (priv->cache)) {
796
contact = e_book_backend_cache_get_contact (priv->cache,
799
vcard = e_vcard_to_string (E_VCARD (contact),
800
EVC_FORMAT_VCARD_30);
801
e_data_book_respond_get_contact (book,
803
GNOME_Evolution_Addressbook_Success,
806
g_object_unref (contact);
810
e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");
817
exchange_mapi_util_mapi_ids_from_uid (id, &fid, &mid);
818
exchange_mapi_connection_fetch_item (priv->fid, mid,
821
create_contact_item, contact,
822
MAPI_OPTIONS_FETCH_ALL);
825
e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
826
vcard = e_vcard_to_string (E_VCARD (contact),
827
EVC_FORMAT_VCARD_30);
828
e_data_book_respond_get_contact (book,
830
GNOME_Evolution_Addressbook_Success,
833
g_object_unref (contact);
837
e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");
851
create_contact_list_cb (FetchItemsCallbackData *item_data, gpointer data)
853
struct mapi_SPropValue_array *array = item_data->properties;
854
const mapi_id_t fid = item_data->fid;
855
const mapi_id_t mid = item_data->mid;
857
GList *list = * (GList **) data;
861
contact = emapidump_contact (array);
862
suid = exchange_mapi_util_mapi_ids_to_uid (fid, mid);
865
/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
866
printf("Contact added %s\n", suid);
867
e_contact_set (contact, E_CONTACT_UID, suid);
868
// e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
869
//FIXME: Should we set this? How can we get this first?
870
list = g_list_prepend (list, e_vcard_to_string (E_VCARD (contact),
871
EVC_FORMAT_VCARD_30));
872
g_object_unref (contact);
873
if (* (GList **)data == NULL)
874
* (GList **)data = list;
881
static const uint32_t GetPropsList[] = {
889
/* FIXME: is this tag fit to check if a recipient table exists or not ? */
890
// PR_DISCLOSURE_OF_RECIPIENTS,
891
PR_RULE_MSG_PROVIDER,
894
static const uint16_t n_GetPropsList = G_N_ELEMENTS (GetPropsList);
897
mapi_book_build_name_id_for_getprops (struct mapi_nameid *nameid, gpointer data)
899
mapi_nameid_lid_add(nameid, 0x8084, PSETID_Address); /* PT_STRING8 - EmailOriginalDisplayName */
900
// mapi_nameid_lid_add(nameid, 0x8020, PSETID_Address);
901
// mapi_nameid_lid_add(nameid, 0x8021, PSETID_Address);
902
mapi_nameid_lid_add(nameid, 0x8094, PSETID_Address);
903
mapi_nameid_lid_add(nameid, 0x80a4, PSETID_Address);
909
e_book_backend_mapi_get_contact_list (EBookBackend *backend,
914
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
916
printf("mapi: get contact list %s\n", query);
917
switch (priv->mode) {
918
case GNOME_Evolution_Addressbook_MODE_LOCAL:
919
if (priv->marked_for_offline && priv->cache) {
921
GList *vcard_strings = NULL;
924
contacts = e_book_backend_cache_get_contacts (priv->cache, query);
926
for (l = contacts; l; l = g_list_next (l)) {
927
EContact *contact = l->data;
928
vcard_strings = g_list_prepend (vcard_strings, e_vcard_to_string (E_VCARD (contact),
929
EVC_FORMAT_VCARD_30));
930
g_object_unref (contact);
933
g_list_free (contacts);
934
printf("get_contact_list in %s returning %d contacts\n", priv->uri, g_list_length (vcard_strings));
935
e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_Success, vcard_strings);
938
e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_RepositoryOffline,
942
case GNOME_Evolution_Addressbook_MODE_REMOTE:
943
printf("Mode : Remote\n");
944
if (priv->marked_for_offline && priv->cache) {
946
GList *vcard_strings = NULL;
949
contacts = e_book_backend_cache_get_contacts (priv->cache, query);
951
for (l = contacts; l ;l = g_list_next (l)) {
952
EContact *contact = l->data;
953
vcard_strings = g_list_prepend (vcard_strings, e_vcard_to_string (E_VCARD (contact),
954
EVC_FORMAT_VCARD_30));
955
g_object_unref (contact);
958
g_list_free (contacts);
959
printf("get_contact_list in %s returning %d contacts\n", priv->uri, g_list_length (vcard_strings));
960
e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_Success, vcard_strings);
964
struct mapi_SRestriction res;
965
GList *vcard_str = NULL;
967
printf("Not marked for cache\n");
969
/* Unfortunately MAPI Doesn't support searching well, we do allow only online search for emails rest all are returned as error. */
970
if (!build_restriction_emails_contains (&res, query)) {
971
e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
975
if (!exchange_mapi_connection_fetch_items (priv->fid, &res, NULL,
976
GetPropsList, n_GetPropsList,
977
mapi_book_build_name_id_for_getprops, NULL,
978
create_contact_list_cb, &vcard_str,
979
MAPI_OPTIONS_FETCH_ALL)) {
980
e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
983
printf("get_contact_list in %s returning %d contacts\n", priv->uri, g_list_length (vcard_str));
984
e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_Success, vcard_str);
992
EBookBackendMAPI *bg;
998
closure_destroy (BESearchClosure *closure)
1000
e_flag_free (closure->running);
1004
static BESearchClosure*
1005
init_closure (EDataBookView *book_view, EBookBackendMAPI *bg)
1007
BESearchClosure *closure = g_new (BESearchClosure, 1);
1010
closure->thread = NULL;
1011
closure->running = e_flag_new ();
1013
g_object_set_data_full (G_OBJECT (book_view), "closure",
1014
closure, (GDestroyNotify)closure_destroy);
1019
static BESearchClosure*
1020
get_closure (EDataBookView *book_view)
1022
return g_object_get_data (G_OBJECT (book_view), "closure");
1025
//FIXME: Be more clever in dumping contacts. Can we have a callback mechanism for each types?
1027
emapidump_contact(struct mapi_SPropValue_array *properties)
1029
EContact *contact = e_contact_new ();
1032
// exchange_mapi_debug_property_dump (properties);
1033
for (i=1; i<maplen; i++) {
1036
/* can cast it, no writing to the value; and it'll be freed not before the end of this function */
1037
value = (gpointer) find_mapi_SPropValue_data (properties, mappings[i].mapi_id);
1038
if (mappings[i].element_type == PT_STRING8 && mappings[i].contact_type == ELEMENT_TYPE_SIMPLE) {
1040
e_contact_set (contact, mappings[i].field_id, value);
1041
} else if (mappings[i].contact_type == ELEMENT_TYPE_SIMPLE) {
1042
if (value && mappings[i].element_type == PT_SYSTIME) {
1043
struct FILETIME *t = value;
1048
nt = t->dwHighDateTime;
1050
nt |= t->dwLowDateTime;
1051
time = nt_time_to_unix (nt);
1052
e_contact_set (contact, mappings[i].field_id, ctime_r (&time, buff));
1054
printf("Nothing is printed\n");
1055
} else if (mappings[i].contact_type == ELEMENT_TYPE_COMPLEX) {
1056
if (mappings[i].field_id == E_CONTACT_IM_AIM) {
1057
GList *list = g_list_append (NULL, value);
1059
e_contact_set (contact, mappings[i].field_id, list);
1062
} else if (mappings[i].field_id == E_CONTACT_BIRTH_DATE
1063
|| mappings[i].field_id == E_CONTACT_ANNIVERSARY) {
1064
struct FILETIME *t = value;
1069
EContactDate date = {0};
1070
nt = t->dwHighDateTime;
1072
nt |= t->dwLowDateTime;
1073
time = nt_time_to_unix (nt);
1074
tmtime = gmtime (&time);
1075
//FIXME: Move to new libmapi api to get string dates.
1076
date.day = tmtime->tm_mday + 1;
1077
date.month = tmtime->tm_mon + 1;
1078
date.year = tmtime->tm_year + 1900;
1079
e_contact_set (contact, mappings[i].field_id, &date);
1082
} else if (mappings[i].field_id == E_CONTACT_ADDRESS_WORK
1083
|| mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
1084
EContactAddress contact_addr = { 0 };
1086
/* type-casting below to not allocate memory twice; e_contact_set will copy values itself. */
1087
if (mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
1088
contact_addr.address_format = NULL;
1089
contact_addr.po = NULL;
1090
contact_addr.street = (char *)value;
1091
contact_addr.ext = (char *)find_mapi_SPropValue_data (properties, PR_HOME_ADDRESS_POST_OFFICE_BOX);
1092
contact_addr.locality = (char *)find_mapi_SPropValue_data (properties, PR_HOME_ADDRESS_CITY);
1093
contact_addr.region = (char *)find_mapi_SPropValue_data (properties, PR_HOME_ADDRESS_STATE_OR_PROVINCE);
1094
contact_addr.code = (char *)find_mapi_SPropValue_data (properties, PR_HOME_ADDRESS_POSTAL_CODE);
1095
contact_addr.country = (char *)find_mapi_SPropValue_data (properties, PR_HOME_ADDRESS_COUNTRY);
1097
contact_addr.address_format = NULL;
1098
contact_addr.po = NULL;
1099
contact_addr.street = (char *)value;
1100
contact_addr.ext = (char *)find_mapi_SPropValue_data (properties, PR_POST_OFFICE_BOX);
1101
contact_addr.locality = (char *)find_mapi_SPropValue_data (properties, PR_LOCALITY);
1102
contact_addr.region = (char *)find_mapi_SPropValue_data (properties, PR_STATE_OR_PROVINCE);
1103
contact_addr.code = (char *)find_mapi_SPropValue_data (properties, PR_POSTAL_CODE);
1104
contact_addr.country = (char *)find_mapi_SPropValue_data (properties, PR_COUNTRY);
1106
e_contact_set (contact, mappings[i].field_id, &contact_addr);
1115
get_contacts_from_cache (EBookBackendMAPI *ebmapi,
1118
EDataBookView *book_view,
1119
BESearchClosure *closure)
1124
printf ("\nread contacts from cache for the ids found in summary\n");
1125
for (i = 0; i < ids->len; i ++) {
1129
if (!e_flag_is_set (closure->running))
1132
uid = g_ptr_array_index (ids, i);
1133
contact = e_book_backend_cache_get_contact (ebmapi->priv->cache, uid);
1135
e_data_book_view_notify_update (book_view, contact);
1136
g_object_unref (contact);
1139
if (e_flag_is_set (closure->running))
1140
e_data_book_view_notify_complete (book_view,
1141
GNOME_Evolution_Addressbook_Success);
1145
create_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
1147
EDataBookView *book_view = data;
1148
BESearchClosure *closure = get_closure (book_view);
1149
EBookBackendMAPI *be = closure->bg;
1151
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
1154
if (!e_flag_is_set (closure->running)) {
1155
printf("Might be that the operation is cancelled. Lets ask our parent also to do.\n");
1159
contact = emapidump_contact (item_data->properties);
1160
suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
1163
/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
1164
e_contact_set (contact, E_CONTACT_UID, suid);
1165
e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
1166
e_data_book_view_notify_update (book_view, contact);
1167
g_object_unref(contact);
1175
book_view_thread (gpointer data)
1177
struct mapi_SRestriction res;
1178
struct mapi_SRestriction_or *or_res = NULL;
1179
EDataBookView *book_view = data;
1180
BESearchClosure *closure = get_closure (book_view);
1181
EBookBackendMAPI *backend = closure->bg;
1182
EBookBackendMAPIPrivate *priv = backend->priv;
1183
const char *query = NULL;
1184
GPtrArray *ids = NULL;
1185
GList *contacts = NULL, *temp_list = NULL;
1186
//Number of multiple restriction to apply
1187
unsigned int res_count = 6;
1190
printf("mapi: book view\n");
1192
bonobo_object_ref (book_view);
1193
e_flag_set (closure->running);
1195
e_data_book_view_notify_status_message (book_view, "Searching...");
1196
query = e_data_book_view_get_card_query (book_view);
1198
switch (priv->mode) {
1200
case GNOME_Evolution_Addressbook_MODE_LOCAL:
1201
if (!priv->marked_for_offline) {
1202
e_data_book_view_notify_complete (book_view,
1203
GNOME_Evolution_Addressbook_OfflineUnavailable);
1204
bonobo_object_unref (book_view);
1208
printf("The cache is not yet built\n");
1209
e_data_book_view_notify_complete (book_view,
1210
GNOME_Evolution_Addressbook_Success);
1214
if (priv->is_summary_ready &&
1215
e_book_backend_summary_is_summary_query (priv->summary, query)) {
1217
printf ("reading the contacts from summary \n");
1218
ids = e_book_backend_summary_search (priv->summary, query);
1219
if (ids && ids->len > 0) {
1220
get_contacts_from_cache (backend, query, ids, book_view, closure);
1221
g_ptr_array_free (ids, TRUE);
1223
bonobo_object_unref (book_view);
1227
/* fall back to cache */
1229
printf ("summary not found or a summary query reading the contacts from cache %s\n", query);
1231
contacts = e_book_backend_cache_get_contacts (priv->cache,
1233
temp_list = contacts;
1234
for (; contacts != NULL; contacts = g_list_next(contacts)) {
1235
if (!e_flag_is_set (closure->running)) {
1236
for (;contacts != NULL; contacts = g_list_next (contacts))
1237
g_object_unref (contacts->data);
1240
e_data_book_view_notify_update (book_view,
1241
E_CONTACT(contacts->data));
1242
g_object_unref (contacts->data);
1244
if (e_flag_is_set (closure->running))
1245
e_data_book_view_notify_complete (book_view,
1246
GNOME_Evolution_Addressbook_Success);
1248
g_list_free (temp_list);
1249
bonobo_object_unref (book_view);
1252
case GNOME_Evolution_Addressbook_MODE_REMOTE:
1254
if (!exchange_mapi_connection_exists ()) {
1255
e_book_backend_notify_auth_required (E_BOOK_BACKEND (backend));
1256
e_data_book_view_notify_complete (book_view,
1257
GNOME_Evolution_Addressbook_AuthenticationRequired);
1258
bonobo_object_unref (book_view);
1263
if (priv->marked_for_offline && priv->cache && priv->is_cache_ready) {
1264
if (priv->is_summary_ready &&
1265
e_book_backend_summary_is_summary_query (priv->summary, query)) {
1267
printf ("reading the contacts from summary \n");
1268
ids = e_book_backend_summary_search (priv->summary, query);
1269
if (ids && ids->len > 0) {
1270
get_contacts_from_cache (backend, query, ids, book_view, closure);
1271
g_ptr_array_free (ids, TRUE);
1273
bonobo_object_unref (book_view);
1277
printf("Summary seems to be not there or not a summary query, lets fetch from cache directly\n");
1279
/* We are already cached. Lets return from there. */
1280
contacts = e_book_backend_cache_get_contacts (priv->cache,
1282
temp_list = contacts;
1283
for (; contacts != NULL; contacts = g_list_next(contacts)) {
1284
if (!e_flag_is_set (closure->running)) {
1285
for (;contacts != NULL; contacts = g_list_next (contacts))
1286
g_object_unref (contacts->data);
1289
e_data_book_view_notify_update (book_view,
1290
E_CONTACT(contacts->data));
1291
g_object_unref (contacts->data);
1293
if (e_flag_is_set (closure->running))
1294
e_data_book_view_notify_complete (book_view,
1295
GNOME_Evolution_Addressbook_Success);
1297
g_list_free (temp_list);
1298
bonobo_object_unref (book_view);
1302
if (e_book_backend_summary_is_summary_query (priv->summary, query)) {
1303
or_res = g_new (struct mapi_SRestriction_or, res_count);
1305
if (!build_multiple_restriction_emails_contains (&res, or_res, query)) {
1306
e_data_book_view_notify_complete (book_view,
1307
GNOME_Evolution_Addressbook_OtherError);
1311
//FIXME: We need to fetch only the query from the server live and not everything.
1312
if (!exchange_mapi_connection_fetch_items (priv->fid, &res, NULL,
1313
GetPropsList, n_GetPropsList,
1314
mapi_book_build_name_id_for_getprops, NULL,
1315
create_contact_cb, book_view,
1316
MAPI_OPTIONS_FETCH_ALL)) {
1317
if (e_flag_is_set (closure->running))
1318
e_data_book_view_notify_complete (book_view,
1319
GNOME_Evolution_Addressbook_OtherError);
1320
bonobo_object_unref (book_view);
1328
if (!exchange_mapi_connection_fetch_items (priv->fid, NULL, NULL,
1331
create_contact_cb, book_view,
1332
MAPI_OPTIONS_FETCH_ALL)) {
1333
if (e_flag_is_set (closure->running))
1334
e_data_book_view_notify_complete (book_view,
1335
GNOME_Evolution_Addressbook_OtherError);
1336
bonobo_object_unref (book_view);
1341
if (e_flag_is_set (closure->running))
1342
e_data_book_view_notify_complete (book_view,
1343
GNOME_Evolution_Addressbook_Success);
1344
bonobo_object_unref (book_view);
1359
e_book_backend_mapi_start_book_view (EBookBackend *backend,
1360
EDataBookView *book_view)
1362
BESearchClosure *closure = init_closure (book_view, E_BOOK_BACKEND_MAPI (backend));
1365
printf ("mapi: start_book_view...\n");
1366
closure->thread = g_thread_create ((GThreadFunc) book_view_thread, book_view, FALSE, NULL);
1367
e_flag_wait (closure->running);
1369
/* at this point we know the book view thread is actually running */
1373
e_book_backend_mapi_stop_book_view (EBookBackend *backend,
1374
EDataBookView *book_view)
1377
printf("mapi: stop book view\n");
1378
/* FIXME : provide implmentation */
1382
e_book_backend_mapi_get_changes (EBookBackend *backend,
1385
const char *change_id )
1388
printf("mapi: get changes\n");
1389
/* FIXME : provide implmentation */
1393
cache_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
1395
EBookBackendMAPI *be = data;
1397
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
1400
contact = emapidump_contact (item_data->properties);
1401
suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
1404
/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
1405
e_contact_set (contact, E_CONTACT_UID, suid);
1406
e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
1407
e_book_backend_cache_add_contact (priv->cache, contact);
1408
e_book_backend_summary_add_contact (priv->summary, contact);
1409
g_object_unref(contact);
1417
build_cache (EBookBackendMAPI *ebmapi)
1419
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) ebmapi)->priv;
1422
//FIXME: What if book view is NULL? Can it be? Check that.
1424
printf("Caching for the first time\n");
1425
priv->cache = e_book_backend_cache_new (priv->uri);
1428
if (!priv->summary) {
1429
priv->summary = e_book_backend_summary_new (priv->summary_file_name,
1430
SUMMARY_FLUSH_TIMEOUT);
1431
printf("Summary file name is %s\n", priv->summary_file_name);
1434
e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
1436
if (!exchange_mapi_connection_fetch_items (priv->fid, NULL, NULL,
1439
cache_contact_cb, ebmapi,
1440
MAPI_OPTIONS_FETCH_ALL)) {
1441
printf("Error during caching addressbook\n");
1442
e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache));
1445
tmp = g_strdup_printf("%d", (int)time (NULL));
1446
e_book_backend_cache_set_time (priv->cache, tmp);
1447
printf("setting time %s\n", tmp);
1449
e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache));
1450
e_book_backend_summary_save (priv->summary);
1451
priv->is_cache_ready = TRUE;
1452
priv->is_summary_ready = TRUE;
1457
update_cache (EBookBackendMAPI *ebmapi)
1459
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) ebmapi)->priv;
1460
char *tmp = e_book_backend_cache_get_time (priv->cache);
1461
//FIXME: What if book view is NULL? Can it be? Check that.
1463
// struct mapi_SRestriction res;
1468
// res.rt = RES_PROPERTY;
1469
// res.res.resProperty.relop = RES_PROPERTY;
1470
// res.res.resProperty.ulPropTag = PR_LAST_MODIFICATION_TIME;
1471
// res.res.resProperty.lpProp.ulPropTag = PR_LAST_MODIFICATION_TIME;
1472
// res.res.resProperty.lpProp.value.lpszA = email;
1475
printf("time updated was %d\n", t);
1476
/* Assume the cache and summary are already there */
1478
e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
1480
if (!exchange_mapi_connection_fetch_items ( priv->fid, &res, NULL,
1483
cache_contact_cb, ebmapi,
1484
MAPI_OPTIONS_FETCH_ALL)) {
1485
printf("Error during caching addressbook\n");
1486
e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache));
1489
e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache));
1490
e_book_backend_summary_save (priv->summary);
1491
priv->is_cache_ready = TRUE;
1492
priv->is_summary_ready = TRUE;
1499
e_book_backend_mapi_authenticate_user (EBookBackend *backend,
1504
const char *auth_method)
1506
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
1509
printf ("mapi: authenticate user\n");
1513
switch (priv->mode) {
1514
case GNOME_Evolution_Addressbook_MODE_LOCAL:
1515
e_book_backend_notify_writable (backend, FALSE);
1516
e_book_backend_notify_connection_status (backend, FALSE);
1517
e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success);
1520
case GNOME_Evolution_Addressbook_MODE_REMOTE:
1522
if (!exchange_mapi_connection_new (priv->profile, NULL))
1523
return e_data_book_respond_authenticate_user (book, opid,GNOME_Evolution_Addressbook_OtherError);
1525
if (priv->cache && priv->is_cache_ready) {
1526
printf("FIXME: Should check for an update in the cache\n");
1527
// g_thread_create ((GThreadFunc) update_cache,
1528
// backend, FALSE, backend);
1529
} else if (priv->marked_for_offline && !priv->is_cache_ready) {
1530
/* Means we dont have a cache. Lets build that first */
1531
printf("Preparing to build cache\n");
1532
g_thread_create ((GThreadFunc) build_cache, backend, FALSE, NULL);
1534
e_book_backend_set_is_writable (backend, TRUE);
1535
e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success);
1544
e_book_backend_mapi_get_required_fields (EBookBackend *backend,
1548
GList *fields = NULL;
1551
printf ("mapi get_required_fields...\n");
1553
fields = g_list_append (fields, (char *)e_contact_field_name (E_CONTACT_FILE_AS));
1554
e_data_book_respond_get_supported_fields (book, opid,
1555
GNOME_Evolution_Addressbook_Success,
1557
g_list_free (fields);
1561
e_book_backend_mapi_get_supported_fields (EBookBackend *backend,
1565
GList *fields = NULL;
1569
printf ("mapi get_supported_fields...\n");
1571
for (i=0; i<maplen; i++)
1573
fields = g_list_append (fields, (char *)e_contact_field_name (mappings[i].field_id));
1575
fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_BOOK_URI)));
1577
e_data_book_respond_get_supported_fields (book, opid,
1578
GNOME_Evolution_Addressbook_Success,
1580
g_list_free (fields);
1585
e_book_backend_mapi_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid)
1587
GList *auth_methods = NULL;
1591
printf ("mapi get_supported_auth_methods...\n");
1593
auth_method = g_strdup_printf ("plain/password");
1594
auth_methods = g_list_append (auth_methods, auth_method);
1595
e_data_book_respond_get_supported_auth_methods (book,
1597
GNOME_Evolution_Addressbook_Success,
1599
g_free (auth_method);
1600
g_list_free (auth_methods);
1604
static GNOME_Evolution_Addressbook_CallStatus
1605
e_book_backend_mapi_cancel_operation (EBookBackend *backend, EDataBook *book)
1608
printf ("mapi cancel_operation...\n");
1609
return GNOME_Evolution_Addressbook_CouldNotCancel;
1614
e_book_backend_mapi_remove (EBookBackend *backend,
1618
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
1619
char *cache_uri = NULL;
1623
printf("mapi: remove\n");
1625
switch (priv->mode) {
1627
case GNOME_Evolution_Addressbook_MODE_LOCAL:
1628
e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_OfflineUnavailable);
1631
case GNOME_Evolution_Addressbook_MODE_REMOTE:
1633
status = exchange_mapi_remove_folder (olFolderContacts, priv->fid);
1635
e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_OtherError);
1639
if (priv->marked_for_offline && priv->is_summary_ready) {
1640
g_object_unref (priv->summary);
1641
priv->summary = NULL;
1644
if (e_book_backend_cache_exists (priv->uri)) {
1646
g_object_unref (priv->cache);
1651
/* Remove the summary and cache independent of whether they are loaded or not. */
1652
cache_uri = get_filename_from_uri (priv->uri, "cache.summary");
1653
if (g_file_test (cache_uri, G_FILE_TEST_EXISTS)) {
1654
g_unlink (cache_uri);
1658
cache_uri = get_filename_from_uri (priv->uri, "cache.xml");
1659
if (g_file_test (cache_uri, G_FILE_TEST_EXISTS)) {
1660
g_unlink (cache_uri);
1664
e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_Success);
1674
/* FIXME : provide implmentation */
1678
e_book_backend_mapi_set_mode (EBookBackend *backend, int mode)
1680
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
1683
printf("mapi: set_mode \n");
1686
if (e_book_backend_is_loaded (backend)) {
1687
if (mode == GNOME_Evolution_Addressbook_MODE_LOCAL) {
1688
e_book_backend_notify_writable (backend, FALSE);
1689
e_book_backend_notify_connection_status (backend, FALSE);
1690
/* FIXME: Uninitialize mapi here. may be.*/
1692
else if (mode == GNOME_Evolution_Addressbook_MODE_REMOTE) {
1693
e_book_backend_notify_writable (backend, TRUE);
1694
e_book_backend_notify_connection_status (backend, TRUE);
1695
e_book_backend_notify_auth_required (backend); //FIXME: WTH is this required.
1701
e_book_backend_mapi_dispose (GObject *object)
1703
/* FIXME : provide implmentation */
1704
EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) object)->priv;
1706
if (priv->profile) {
1707
g_free (priv->profile);
1708
priv->profile = NULL;
1719
static void e_book_backend_mapi_class_init (EBookBackendMAPIClass *klass)
1721
GObjectClass *object_class = G_OBJECT_CLASS (klass);
1722
EBookBackendClass *parent_class;
1725
e_book_backend_mapi_parent_class = g_type_class_peek_parent (klass);
1727
parent_class = E_BOOK_BACKEND_CLASS (klass);
1729
/* Set the virtual methods. */
1730
parent_class->load_source = e_book_backend_mapi_load_source;
1731
parent_class->get_static_capabilities = e_book_backend_mapi_get_static_capabilities;
1732
parent_class->create_contact = e_book_backend_mapi_create_contact;
1733
parent_class->remove_contacts = e_book_backend_mapi_remove_contacts;
1734
parent_class->modify_contact = e_book_backend_mapi_modify_contact;
1735
parent_class->get_contact = e_book_backend_mapi_get_contact;
1736
parent_class->get_contact_list = e_book_backend_mapi_get_contact_list;
1737
parent_class->start_book_view = e_book_backend_mapi_start_book_view;
1738
parent_class->stop_book_view = e_book_backend_mapi_stop_book_view;
1739
parent_class->get_changes = e_book_backend_mapi_get_changes;
1740
parent_class->authenticate_user = e_book_backend_mapi_authenticate_user;
1741
parent_class->get_required_fields = e_book_backend_mapi_get_required_fields;
1742
parent_class->get_supported_fields = e_book_backend_mapi_get_supported_fields;
1743
parent_class->get_supported_auth_methods = e_book_backend_mapi_get_supported_auth_methods;
1744
parent_class->cancel_operation = e_book_backend_mapi_cancel_operation;
1745
parent_class->remove = e_book_backend_mapi_remove;
1746
parent_class->set_mode = e_book_backend_mapi_set_mode;
1747
object_class->dispose = e_book_backend_mapi_dispose;
1751
EBookBackend *e_book_backend_mapi_new (void)
1753
EBookBackendMAPI *backend;
1756
backend = g_object_new (E_TYPE_BOOK_BACKEND_MAPI, NULL);
1757
return E_BOOK_BACKEND (backend);
1761
static void e_book_backend_mapi_init (EBookBackendMAPI *backend)
1763
EBookBackendMAPIPrivate *priv;
1765
priv= g_new0 (EBookBackendMAPIPrivate, 1);
1766
/* Priv Struct init */
1767
backend->priv = priv;
1769
priv->marked_for_offline = FALSE;
1772
priv->is_summary_ready = FALSE;
1773
priv->is_cache_ready = FALSE;
1775
if (g_getenv ("MAPI_DEBUG"))
1776
enable_debug = TRUE;
1778
enable_debug = FALSE;
1784
GType e_book_backend_mapi_get_type (void)
1786
static GType type = 0;
1790
sizeof (EBookBackendMAPIClass),
1791
NULL, /* base_class_init */
1792
NULL, /* base_class_finalize */
1793
(GClassInitFunc) e_book_backend_mapi_class_init,
1794
NULL, /* class_finalize */
1795
NULL, /* class_data */
1796
sizeof (EBookBackendMAPI),
1797
0, /* n_preallocs */
1798
(GInstanceInitFunc) e_book_backend_mapi_init
1801
type = g_type_register_static (E_TYPE_BOOK_BACKEND, "EBookBackendMAPI", &info, 0);