~ubuntu-branches/ubuntu/karmic/evolution-mapi/karmic

« back to all changes in this revision

Viewing changes to src/addressbook/e-book-backend-mapi.c

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2009-02-06 01:15:32 UTC
  • Revision ID: james.westby@ubuntu.com-20090206011532-eat2f3r2koynqpkd
Tags: upstream-0.25.91
ImportĀ upstreamĀ versionĀ 0.25.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/*
 
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.
 
7
 *
 
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.
 
12
 *
 
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/>  
 
15
 *
 
16
 *
 
17
 * Authors:
 
18
 *    Srinivasa Ragavan <sragavan@novell.com>
 
19
 *
 
20
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>  
 
26
#endif
 
27
 
 
28
#include <stdlib.h>
 
29
#include <fcntl.h>
 
30
#include <string.h>
 
31
#include <glib.h>
 
32
#include <glib/gstdio.h>
 
33
 
 
34
#include <sys/time.h>
 
35
/*
 
36
** #include <glib/gi18n-lib.h>
 
37
*/
 
38
 
 
39
#include <libedataserver/e-sexp.h>
 
40
#include "libedataserver/e-flag.h"
 
41
#include <libebook/e-contact.h>
 
42
 
 
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"
 
49
 
 
50
 
 
51
static EBookBackendClass *e_book_backend_mapi_parent_class;
 
52
static gboolean enable_debug = TRUE;
 
53
 
 
54
struct _EBookBackendMAPIPrivate
 
55
{
 
56
        char *profile;
 
57
        mapi_id_t fid;
 
58
        int mode;
 
59
        gboolean marked_for_offline;
 
60
        gboolean is_cache_ready;
 
61
        gboolean is_summary_ready;
 
62
        gboolean is_writable;
 
63
        char *uri;
 
64
        char *book_name;
 
65
        
 
66
        GMutex *lock;
 
67
        char *summary_file_name;
 
68
        EBookBackendSummary *summary;
 
69
        EBookBackendCache *cache;
 
70
 
 
71
};
 
72
 
 
73
#define LOCK() g_mutex_lock (priv->lock)
 
74
#define UNLOCK() g_mutex_unlock (priv->lock)
 
75
 
 
76
#define ELEMENT_TYPE_SIMPLE 0x01
 
77
#define ELEMENT_TYPE_COMPLEX 0x02 /* fields which require explicit functions to set values into EContact and EGwItem */
 
78
 
 
79
#define SUMMARY_FLUSH_TIMEOUT 5000
 
80
#define ELEMENT_TYPE_SIMPLE 0x01
 
81
#define ELEMENT_TYPE_COMPLEX 0x02
 
82
 
 
83
static EContact * emapidump_contact(struct mapi_SPropValue_array *properties);
 
84
 
 
85
static const struct field_element_mapping {
 
86
                EContactField field_id;
 
87
                int element_type;
 
88
                int mapi_id;
 
89
                int contact_type;
 
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);
 
94
 
 
95
        } mappings [] = { 
 
96
 
 
97
        { E_CONTACT_UID, PT_STRING8, 0, ELEMENT_TYPE_SIMPLE},
 
98
        { E_CONTACT_REV, PT_SYSTIME, PR_LAST_MODIFICATION_TIME, ELEMENT_TYPE_SIMPLE},
 
99
                
 
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 },
 
105
 
 
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},   
 
110
                
 
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},
 
119
 
 
120
        { E_CONTACT_HOMEPAGE_URL, PT_STRING8, 0x802b001e, ELEMENT_TYPE_SIMPLE},
 
121
        { E_CONTACT_FREEBUSY_URL, PT_STRING8, 0x80d8001e, ELEMENT_TYPE_SIMPLE},
 
122
 
 
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},
 
129
                
 
130
        { E_CONTACT_OFFICE, PT_STRING8, PR_OFFICE_LOCATION, ELEMENT_TYPE_SIMPLE},
 
131
        { E_CONTACT_SPOUSE, PT_STRING8, PR_SPOUSE_NAME, ELEMENT_TYPE_SIMPLE},
 
132
                
 
133
        { E_CONTACT_BIRTH_DATE,  PT_SYSTIME, PR_BIRTHDAY, ELEMENT_TYPE_COMPLEX},
 
134
        { E_CONTACT_ANNIVERSARY, PT_SYSTIME, PR_WEDDING_ANNIVERSARY, ELEMENT_TYPE_COMPLEX},
 
135
                  
 
136
        { E_CONTACT_NOTE, PT_STRING8, PR_BODY, ELEMENT_TYPE_SIMPLE},
 
137
                
 
138
 
 
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, },              
 
144
        };
 
145
 
 
146
static int maplen = G_N_ELEMENTS(mappings);
 
147
 
 
148
static EDataBookView *
 
149
find_book_view (EBookBackendMAPI *ebmapi)
 
150
{
 
151
        EList *views = e_book_backend_get_book_views (E_BOOK_BACKEND (ebmapi));
 
152
        EIterator *iter;
 
153
        EDataBookView *rv = NULL;
 
154
 
 
155
        if (!views)
 
156
                return NULL;
 
157
 
 
158
        iter = e_list_get_iterator (views);
 
159
 
 
160
        if (!iter) {
 
161
                g_object_unref (views);
 
162
                return NULL;
 
163
        }
 
164
 
 
165
        if (e_iterator_is_valid (iter)) {
 
166
                /* just always use the first book view */
 
167
                EDataBookView *v = (EDataBookView*)e_iterator_get(iter);
 
168
                if (v)
 
169
                        rv = v;
 
170
        }
 
171
 
 
172
        g_object_unref (iter);
 
173
        g_object_unref (views);
 
174
        
 
175
        return rv;
 
176
}
 
177
 
 
178
static gboolean
 
179
build_restriction_emails_contains (struct mapi_SRestriction *res, 
 
180
                                   const char *query)
 
181
{
 
182
        char *email=NULL, *tmp, *tmp1;
 
183
 
 
184
        /* This currently supports "email foo@bar.soo" */
 
185
        tmp = strdup (query);
 
186
        
 
187
        tmp = strstr (tmp, "email");
 
188
        if (tmp ) {
 
189
                tmp = strchr (tmp, '\"');
 
190
                if (tmp && ++tmp) {
 
191
                        tmp = strchr (tmp, '\"');
 
192
                        if (tmp && ++tmp) {
 
193
                                tmp1 = tmp;
 
194
                                tmp1 = strchr (tmp1, '\"');
 
195
                                if (tmp1) {
 
196
                                        *tmp1 = 0;
 
197
                                        email = tmp;
 
198
                                }
 
199
                        }
 
200
                }
 
201
        }
 
202
        
 
203
 
 
204
        if (email==NULL || !strchr (email, '@'))
 
205
                return FALSE;
 
206
 
 
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;
 
212
 
 
213
        return TRUE;
 
214
}
 
215
 
 
216
static gboolean
 
217
build_multiple_restriction_emails_contains (struct mapi_SRestriction *res, 
 
218
                                            struct mapi_SRestriction_or *or_res, 
 
219
                                            const char *query)
 
220
{
 
221
        char *email=NULL, *tmp, *tmp1;
 
222
        //Number of restriction to apply
 
223
        unsigned int res_count = 6;
 
224
 
 
225
        /* This currently supports "email foo@bar.soo" */
 
226
        tmp = strdup (query);
 
227
        
 
228
        tmp = strstr (tmp, "email");
 
229
        if (tmp ) {
 
230
                tmp = strchr (tmp, '\"');
 
231
                if (tmp && ++tmp) {
 
232
                        tmp = strchr (tmp, '\"');
 
233
                        if (tmp && ++tmp) {
 
234
                                tmp1 = tmp;
 
235
                                tmp1 = strchr (tmp1, '\"');
 
236
                                if (tmp1) {
 
237
                                        *tmp1 = 0;
 
238
                                        email = tmp;
 
239
                                }
 
240
                        }
 
241
                }
 
242
        }
 
243
 
 
244
        if (email==NULL || !strchr (email, '@'))
 
245
                return FALSE;
 
246
 
 
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;
 
251
 
 
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;
 
256
 
 
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;
 
261
 
 
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;
 
266
 
 
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;
 
271
 
 
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;
 
276
 
 
277
        res = g_new0 (struct mapi_SRestriction, 1);
 
278
 
 
279
        res->rt = RES_OR;
 
280
        res->res.resOr.cRes = res_count;
 
281
        res->res.resOr.res = or_res;
 
282
 
 
283
        return TRUE;
 
284
}
 
285
 
 
286
static char *
 
287
get_filename_from_uri (const char *uri, const char *file)
 
288
{
 
289
        char *mangled_uri, *filename;
 
290
        int i;
 
291
 
 
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]) {
 
296
                case ':' :
 
297
                case '/' :
 
298
                        mangled_uri[i] = '_';
 
299
                }
 
300
        }
 
301
 
 
302
        /* generate the file name */
 
303
        filename = g_build_filename (g_get_home_dir (), ".evolution/cache/addressbook",
 
304
                                     mangled_uri, file, NULL);
 
305
 
 
306
        /* free memory */
 
307
        g_free (mangled_uri);
 
308
 
 
309
        return filename;
 
310
}
 
311
 
 
312
static GNOME_Evolution_Addressbook_CallStatus
 
313
e_book_backend_mapi_load_source (EBookBackend *backend,
 
314
                                 ESource      *source,
 
315
                                 gboolean     only_if_exists)
 
316
{
 
317
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
318
        const gchar *offline, *tmp;
 
319
        char **tokens;
 
320
        char *uri = NULL;
 
321
        if (enable_debug)
 
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;
 
326
 
 
327
 
 
328
 
 
329
        /* Either we are in Online mode or this is marked for offline */
 
330
        
 
331
        priv->uri = g_strdup (e_source_get_uri (source));
 
332
 
 
333
        tokens = g_strsplit (priv->uri, ";", 2);
 
334
        if (tokens[0])
 
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;
 
340
        }
 
341
        g_strfreev (tokens);
 
342
 
 
343
        if (priv->mode ==  GNOME_Evolution_Addressbook_MODE_LOCAL &&
 
344
            !priv->marked_for_offline ) {
 
345
                return GNOME_Evolution_Addressbook_OfflineUnavailable;
 
346
        }
 
347
        
 
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;
 
356
                }
 
357
 
 
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;
 
363
                }
 
364
                //FIXME: We may have to do a time based reload. Or deltas should upload.
 
365
        } else {
 
366
                priv->summary = e_book_backend_summary_new (NULL,SUMMARY_FLUSH_TIMEOUT);
 
367
        }
 
368
 
 
369
        g_free (uri);
 
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);
 
376
                if (!priv->cache) {
 
377
                        printf("Unfortunately the cache is not yet created\n");
 
378
                        return GNOME_Evolution_Addressbook_OfflineUnavailable;
 
379
                }
 
380
        } else {
 
381
                e_book_backend_notify_connection_status (backend, TRUE);
 
382
        }
 
383
        
 
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);
 
386
 
 
387
        tmp = e_source_get_property (source, "folder-id");
 
388
        printf("Folder is %s %016llX\n", tmp, priv->fid);
 
389
 
 
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;
 
393
        }
 
394
 
 
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);
 
398
 
 
399
 
 
400
        if (enable_debug)
 
401
                printf("For profile %s and folder %s - %016llX\n", priv->profile, tmp, priv->fid);
 
402
 
 
403
        return GNOME_Evolution_Addressbook_Success;
 
404
}
 
405
 
 
406
static char *
 
407
e_book_backend_mapi_get_static_capabilities (EBookBackend *backend)
 
408
{
 
409
        if(enable_debug)
 
410
                printf("mapi get_static_capabilities\n");
 
411
        //FIXME: Implement this.
 
412
        
 
413
        return g_strdup ("net,bulk-removes,do-initial-query,contact-lists");
 
414
}
 
415
 
 
416
gboolean
 
417
mapi_book_build_name_id (struct mapi_nameid *nameid, gpointer data)
 
418
{
 
419
//      EContact *contact = data;
 
420
        
 
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);
 
424
 
 
425
        mapi_nameid_lid_add(nameid, 0x8093, PSETID_Address);
 
426
        mapi_nameid_lid_add(nameid, 0x80A3, PSETID_Address);
 
427
        
 
428
        mapi_nameid_string_add(nameid, "urn:schemas:contacts:fileas", PS_PUBLIC_STRINGS);
 
429
 
 
430
        mapi_nameid_lid_add(nameid, 0x802B, PSETID_Address);
 
431
        mapi_nameid_lid_add(nameid, 0x8062, PSETID_Address);
 
432
 
 
433
        mapi_nameid_lid_add(nameid, 0x801A, PSETID_Address);    
 
434
        mapi_nameid_lid_add(nameid, 0x801B, PSETID_Address);
 
435
 
 
436
        mapi_nameid_lid_add(nameid, 0x3A4F, PS_MAPI);
 
437
 
 
438
        mapi_nameid_lid_add(nameid, 0x8094, PSETID_Address);
 
439
        mapi_nameid_lid_add(nameid, 0x80A4, PSETID_Address);
 
440
 
 
441
        return TRUE;
 
442
}
 
443
 
 
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));
 
445
 
 
446
int
 
447
mapi_book_build_props (struct SPropValue ** value, struct SPropTagArray * SPropTagArray, gpointer data)
 
448
{
 
449
        EContact *contact = data;       
 
450
        struct SPropValue *props;
 
451
        int i=0;
 
452
 
 
453
        for (i=0; i<13; i++)
 
454
                printf("hex %x\n", SPropTagArray->aulPropTag[i]);
 
455
        i=0;
 
456
        props = g_new (struct SPropValue, 50); //FIXME: Correct value tbd
 
457
        set_str_value ( E_CONTACT_FILE_AS, SPropTagArray->aulPropTag[0]);
 
458
 
 
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]);
 
465
 
 
466
        
 
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]);
 
470
        
 
471
        set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[4]);
 
472
//      set_str_value ( E_CONTACT_EMAIL_3, SPropTagArray->aulPropTag[12]);
 
473
        
 
474
        set_str_value (E_CONTACT_HOMEPAGE_URL, SPropTagArray->aulPropTag[6]);
 
475
        set_str_value (E_CONTACT_FREEBUSY_URL, 0x812C001E);
 
476
        
 
477
 
 
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);
 
486
 
 
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);
 
493
 
 
494
        set_str_value (E_CONTACT_OFFICE, PR_OFFICE_LOCATION);
 
495
        set_str_value (E_CONTACT_SPOUSE, PR_SPOUSE_NAME);
 
496
 
 
497
        set_str_value (E_CONTACT_NOTE, PR_BODY);
 
498
 
 
499
        //BDAY AND ANNV
 
500
        if (e_contact_get (contact, E_CONTACT_BIRTH_DATE)) {
 
501
                EContactDate *date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
 
502
                struct tm tmtime;
 
503
                time_t lt;
 
504
                NTTIME nt;
 
505
                struct FILETIME t;
 
506
                
 
507
                tmtime.tm_mday = date->day - 1;
 
508
                tmtime.tm_mon = date->month - 1;
 
509
                tmtime.tm_year = date->year - 1900;
 
510
 
 
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);
 
517
        }
 
518
 
 
519
        if (e_contact_get (contact, E_CONTACT_ANNIVERSARY)) {
 
520
                EContactDate *date = e_contact_get (contact, E_CONTACT_ANNIVERSARY);
 
521
                struct tm tmtime;
 
522
                time_t lt;
 
523
                NTTIME nt;
 
524
                struct FILETIME t;
 
525
                
 
526
                tmtime.tm_mday = date->day - 1;
 
527
                tmtime.tm_mon = date->month - 1;
 
528
                tmtime.tm_year = date->year - 1900;
 
529
 
 
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);
 
536
        }       
 
537
        //Home and Office address
 
538
        if (e_contact_get (contact, E_CONTACT_ADDRESS_HOME)) {
 
539
                EContactAddress *contact_addr;
 
540
 
 
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);                           
 
548
        }
 
549
 
 
550
        if (e_contact_get (contact, E_CONTACT_ADDRESS_WORK)) {
 
551
                EContactAddress *contact_addr;
 
552
 
 
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);                                
 
560
        }
 
561
 
 
562
        
 
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);
 
567
        }
 
568
 
 
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]);
 
573
        }
 
574
        
 
575
        *value =props;
 
576
        printf("Sending %d \n", i);
 
577
        return i;
 
578
}
 
579
 
 
580
static void
 
581
e_book_backend_mapi_create_contact (EBookBackend *backend,
 
582
                                          EDataBook *book,
 
583
                                          guint32 opid,
 
584
                                          const char *vcard )
 
585
{
 
586
        EContact *contact;
 
587
        char *id;
 
588
        mapi_id_t status;
 
589
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
590
 
 
591
        if(enable_debug)
 
592
                printf("mapi create_contact \n");
 
593
        
 
594
        switch (priv->mode) {
 
595
 
 
596
        case GNOME_Evolution_Addressbook_MODE_LOCAL :
 
597
                e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
 
598
                return;
 
599
           
 
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);
 
603
                if (!status) {
 
604
                        e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
 
605
                        return;
 
606
                }
 
607
                id = exchange_mapi_util_mapi_ids_to_uid (priv->fid, status); 
 
608
        
 
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);
 
612
                
 
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);
 
617
 
 
618
                if (priv->marked_for_offline && priv->is_summary_ready)
 
619
                        e_book_backend_summary_add_contact (priv->summary, contact);
 
620
 
 
621
                e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_Success, contact);
 
622
                return;                 
 
623
        }
 
624
        
 
625
        return;
 
626
}
 
627
 
 
628
static void
 
629
e_book_backend_mapi_remove_contacts (EBookBackend *backend,
 
630
                                           EDataBook    *book,
 
631
                                           guint32 opid,
 
632
                                           GList *id_list)
 
633
{
 
634
        GSList *list=NULL; 
 
635
        GList *tmp = id_list;
 
636
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
637
        mapi_id_t fid, mid;
 
638
                        
 
639
        if(enable_debug)
 
640
                printf("mapi: remove_contacts\n");
 
641
 
 
642
        switch (priv->mode) {
 
643
 
 
644
        case GNOME_Evolution_Addressbook_MODE_LOCAL :
 
645
                e_data_book_respond_remove_contacts (book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
 
646
                return;
 
647
 
 
648
        case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
649
                
 
650
                while (tmp) {
 
651
                        struct id_list *data = g_new (struct id_list, 1);
 
652
                        exchange_mapi_util_mapi_ids_from_uid (tmp->data, &fid, &mid);
 
653
                        data->id = mid;
 
654
                        list = g_slist_prepend (list, (gpointer) data);
 
655
                        tmp = tmp->next;
 
656
                }
 
657
 
 
658
                exchange_mapi_remove_items (olFolderContacts, priv->fid, list);
 
659
                if (priv->marked_for_offline && priv->is_cache_ready) {
 
660
                        tmp = id_list;
 
661
                        while (tmp) {
 
662
                                e_book_backend_cache_remove_contact (priv->cache, tmp->data);
 
663
                                tmp = tmp->next;
 
664
                        }
 
665
                }
 
666
 
 
667
                if (priv->marked_for_offline && priv->is_summary_ready) {
 
668
                        tmp = id_list;
 
669
                        while (tmp) {
 
670
                                e_book_backend_summary_remove_contact (priv->summary, tmp->data);               
 
671
                                tmp = tmp->next;
 
672
                        }
 
673
                }
 
674
                
 
675
                g_slist_free (list);
 
676
                e_data_book_respond_remove_contacts (book, opid,
 
677
                                                             GNOME_Evolution_Addressbook_Success, id_list);
 
678
                return;
 
679
        default:
 
680
                break;
 
681
        }
 
682
}
 
683
 
 
684
static void
 
685
e_book_backend_mapi_modify_contact (EBookBackend *backend,
 
686
                                          EDataBook    *book,
 
687
                                          guint32       opid,
 
688
                                          const char   *vcard)
 
689
{
 
690
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
691
        EContact *contact;
 
692
        mapi_id_t fid, mid;
 
693
        gboolean status;
 
694
        char *tmp;
 
695
        
 
696
        if(enable_debug)
 
697
                printf("mapi: modify_contacts\n");
 
698
 
 
699
        switch (priv->mode) {
 
700
 
 
701
        case GNOME_Evolution_Addressbook_MODE_LOCAL :
 
702
                e_data_book_respond_modify(book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
 
703
                return;
 
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);
 
709
                
 
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);
 
712
                if (!status) {
 
713
                        e_data_book_respond_modify(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
 
714
                        return;
 
715
                }
 
716
                
 
717
                e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
 
718
 
 
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));
 
722
 
 
723
                if (priv->marked_for_offline && priv->is_summary_ready)
 
724
                                e_book_backend_summary_remove_contact (priv->summary, tmp);
 
725
                
 
726
                if (priv->marked_for_offline && priv->is_cache_ready)
 
727
                        e_book_backend_cache_add_contact (priv->cache, contact);
 
728
 
 
729
                if (priv->marked_for_offline && priv->is_summary_ready)
 
730
                        e_book_backend_summary_add_contact (priv->summary, contact);
 
731
                
 
732
                
 
733
                e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_Success, contact);
 
734
 
 
735
 
 
736
        }
 
737
}
 
738
 
 
739
static gboolean
 
740
create_contact_item (FetchItemsCallbackData *item_data, gpointer data)
 
741
{
 
742
        EContact *contact;
 
743
        char *suid;
 
744
        
 
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);
 
748
        if (contact) {
 
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);
 
751
                data = contact;
 
752
        }
 
753
 
 
754
        g_free (suid);
 
755
 
 
756
        return TRUE;
 
757
}
 
758
 
 
759
static void
 
760
e_book_backend_mapi_get_contact (EBookBackend *backend,
 
761
                                       EDataBook    *book,
 
762
                                       guint32       opid,
 
763
                                       const char   *id)
 
764
{
 
765
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
766
        EContact *contact = NULL;
 
767
        char *vcard;
 
768
        
 
769
        if (enable_debug)
 
770
                printf("mapi: get_contact %s\n", id);
 
771
 
 
772
        switch (priv->mode) {
 
773
        
 
774
        case GNOME_Evolution_Addressbook_MODE_LOCAL:
 
775
                contact = e_book_backend_cache_get_contact (priv->cache,
 
776
                                                            id);
 
777
                if (contact) {
 
778
                        vcard =  e_vcard_to_string (E_VCARD (contact), 
 
779
                                                     EVC_FORMAT_VCARD_30);
 
780
                        e_data_book_respond_get_contact (book,
 
781
                                                         opid,
 
782
                                                         GNOME_Evolution_Addressbook_Success,
 
783
                                                         vcard);
 
784
                        g_free (vcard);
 
785
                        g_object_unref (contact);
 
786
                        return;
 
787
                }
 
788
                else {
 
789
                        e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");                  
 
790
                        return;
 
791
                }
 
792
                
 
793
        case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
794
 
 
795
                if (priv->marked_for_offline && e_book_backend_cache_is_populated (priv->cache)) {
 
796
                        contact = e_book_backend_cache_get_contact (priv->cache,
 
797
                                                                    id);
 
798
                        if (contact) {
 
799
                                vcard =  e_vcard_to_string (E_VCARD (contact), 
 
800
                                                             EVC_FORMAT_VCARD_30);
 
801
                                e_data_book_respond_get_contact (book,
 
802
                                                                 opid,
 
803
                                                                 GNOME_Evolution_Addressbook_Success,
 
804
                                                                 vcard);
 
805
                                g_free (vcard);
 
806
                                g_object_unref (contact);
 
807
                                return;
 
808
                        }
 
809
                        else {
 
810
                                e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");                  
 
811
                                return;
 
812
                        }
 
813
 
 
814
                } else {
 
815
                        mapi_id_t fid, mid;
 
816
                        
 
817
                        exchange_mapi_util_mapi_ids_from_uid (id, &fid, &mid);
 
818
                        exchange_mapi_connection_fetch_item (priv->fid, mid, 
 
819
                                                        NULL, 0, 
 
820
                                                        NULL, NULL, 
 
821
                                                        create_contact_item, contact, 
 
822
                                                        MAPI_OPTIONS_FETCH_ALL);
 
823
 
 
824
                        if (contact) {
 
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,
 
829
                                                                 opid,
 
830
                                                                 GNOME_Evolution_Addressbook_Success,
 
831
                                                                 vcard);
 
832
                                g_free (vcard);
 
833
                                g_object_unref (contact);
 
834
                                return;
 
835
                        
 
836
                        } else {
 
837
                                e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");                  
 
838
                                return;                         
 
839
                        }
 
840
                }
 
841
 
 
842
        default:
 
843
                break;
 
844
        }
 
845
 
 
846
        return;
 
847
        
 
848
}
 
849
 
 
850
static gboolean
 
851
create_contact_list_cb (FetchItemsCallbackData *item_data, gpointer data)
 
852
{
 
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;
 
856
 
 
857
        GList *list = * (GList **) data;
 
858
        EContact *contact;
 
859
        char *suid;
 
860
        
 
861
        contact = emapidump_contact (array);
 
862
        suid = exchange_mapi_util_mapi_ids_to_uid (fid, mid);
 
863
        
 
864
        if (contact) {
 
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;
 
875
        }
 
876
 
 
877
        g_free (suid);
 
878
        return TRUE;
 
879
}
 
880
 
 
881
static const uint32_t GetPropsList[] = {
 
882
        PR_FID,
 
883
        PR_MID,
 
884
        PR_INST_ID,
 
885
        PR_INSTANCE_NUM,
 
886
        PR_SUBJECT,
 
887
        PR_MESSAGE_CLASS,
 
888
        PR_HASATTACH,
 
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,
 
892
        PR_RULE_MSG_NAME
 
893
};
 
894
static const uint16_t n_GetPropsList = G_N_ELEMENTS (GetPropsList);
 
895
 
 
896
gboolean
 
897
mapi_book_build_name_id_for_getprops (struct mapi_nameid *nameid, gpointer data)
 
898
{
 
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);
 
904
 
 
905
        return TRUE;
 
906
}
 
907
 
 
908
static void
 
909
e_book_backend_mapi_get_contact_list (EBookBackend *backend,
 
910
                                            EDataBook    *book,
 
911
                                            guint32       opid,
 
912
                                            const char   *query )
 
913
{
 
914
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
915
 
 
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) {
 
920
                        GList *contacts;
 
921
                        GList *vcard_strings = NULL;
 
922
                        GList *l;
 
923
 
 
924
                        contacts = e_book_backend_cache_get_contacts (priv->cache, query);
 
925
 
 
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);
 
931
                        }
 
932
 
 
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);
 
936
                        return;
 
937
                }
 
938
                e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_RepositoryOffline,
 
939
                                                      NULL);
 
940
                return;
 
941
                
 
942
        case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
943
                printf("Mode : Remote\n");
 
944
                if (priv->marked_for_offline && priv->cache) {
 
945
                        GList *contacts;
 
946
                        GList *vcard_strings = NULL;
 
947
                        GList *l;
 
948
 
 
949
                        contacts = e_book_backend_cache_get_contacts (priv->cache, query);
 
950
 
 
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);
 
956
                        }
 
957
 
 
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);
 
961
                        return ;
 
962
                }
 
963
                else {
 
964
                        struct mapi_SRestriction res;
 
965
                        GList *vcard_str = NULL;
 
966
 
 
967
                        printf("Not marked for cache\n");
 
968
 
 
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);
 
972
                                return ;                                
 
973
                        }
 
974
 
 
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);
 
981
                                return ;
 
982
                        }
 
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);
 
985
                        return ;
 
986
                        
 
987
                }
 
988
        }       
 
989
}
 
990
 
 
991
typedef struct {
 
992
        EBookBackendMAPI *bg;
 
993
        GThread *thread;
 
994
        EFlag *running;
 
995
} BESearchClosure;
 
996
 
 
997
static void
 
998
closure_destroy (BESearchClosure *closure)
 
999
{
 
1000
        e_flag_free (closure->running);
 
1001
        g_free (closure);
 
1002
}
 
1003
 
 
1004
static BESearchClosure*
 
1005
init_closure (EDataBookView *book_view, EBookBackendMAPI *bg)
 
1006
{
 
1007
        BESearchClosure *closure = g_new (BESearchClosure, 1);
 
1008
 
 
1009
        closure->bg = bg;
 
1010
        closure->thread = NULL;
 
1011
        closure->running = e_flag_new ();
 
1012
 
 
1013
        g_object_set_data_full (G_OBJECT (book_view), "closure",
 
1014
                                closure, (GDestroyNotify)closure_destroy);
 
1015
 
 
1016
        return closure;
 
1017
}
 
1018
 
 
1019
static BESearchClosure*
 
1020
get_closure (EDataBookView *book_view)
 
1021
{
 
1022
        return g_object_get_data (G_OBJECT (book_view), "closure");
 
1023
}
 
1024
 
 
1025
//FIXME: Be more clever in dumping contacts. Can we have a callback mechanism for each types?
 
1026
static EContact *
 
1027
emapidump_contact(struct mapi_SPropValue_array *properties)
 
1028
{
 
1029
        EContact *contact = e_contact_new ();
 
1030
        int i;
 
1031
        
 
1032
//      exchange_mapi_debug_property_dump (properties);
 
1033
        for (i=1; i<maplen; i++) {
 
1034
                gpointer value;
 
1035
 
 
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) {
 
1039
                        if (value)
 
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;
 
1044
                                time_t time;
 
1045
                                NTTIME nt;
 
1046
                                char buff[129];
 
1047
 
 
1048
                                nt = t->dwHighDateTime;
 
1049
                                nt = nt << 32;
 
1050
                                nt |= t->dwLowDateTime;
 
1051
                                time = nt_time_to_unix (nt);
 
1052
                                e_contact_set (contact, mappings[i].field_id, ctime_r (&time, buff));
 
1053
                        } else
 
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);
 
1058
 
 
1059
                                e_contact_set (contact, mappings[i].field_id, list);
 
1060
 
 
1061
                                g_list_free (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;
 
1065
                                time_t time;
 
1066
                                NTTIME nt;
 
1067
                                struct tm * tmtime;
 
1068
                                if (value) {
 
1069
                                        EContactDate date = {0};
 
1070
                                        nt = t->dwHighDateTime;
 
1071
                                        nt = nt << 32;
 
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);
 
1080
                                }
 
1081
                                
 
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 };
 
1085
 
 
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);
 
1096
                                } else {
 
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);
 
1105
                                }
 
1106
                                e_contact_set (contact, mappings[i].field_id, &contact_addr);
 
1107
                        }
 
1108
                }
 
1109
        }
 
1110
        
 
1111
        return contact;
 
1112
}
 
1113
 
 
1114
static void
 
1115
get_contacts_from_cache (EBookBackendMAPI *ebmapi, 
 
1116
                         const char *query,
 
1117
                         GPtrArray *ids,
 
1118
                         EDataBookView *book_view, 
 
1119
                         BESearchClosure *closure)
 
1120
{
 
1121
        int i;
 
1122
 
 
1123
        if (enable_debug)
 
1124
                printf ("\nread contacts from cache for the ids found in summary\n");
 
1125
        for (i = 0; i < ids->len; i ++) {
 
1126
                char *uid;
 
1127
                EContact *contact; 
 
1128
 
 
1129
                if (!e_flag_is_set (closure->running))
 
1130
                        break;
 
1131
 
 
1132
                uid = g_ptr_array_index (ids, i);
 
1133
                contact = e_book_backend_cache_get_contact (ebmapi->priv->cache, uid);
 
1134
                if (contact) {
 
1135
                        e_data_book_view_notify_update (book_view, contact);
 
1136
                        g_object_unref (contact);
 
1137
                }
 
1138
        }
 
1139
        if (e_flag_is_set (closure->running))
 
1140
                e_data_book_view_notify_complete (book_view, 
 
1141
                                                  GNOME_Evolution_Addressbook_Success);
 
1142
}
 
1143
 
 
1144
static gboolean
 
1145
create_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
 
1146
{
 
1147
        EDataBookView *book_view = data;
 
1148
        BESearchClosure *closure = get_closure (book_view);
 
1149
        EBookBackendMAPI *be = closure->bg;
 
1150
        EContact *contact;
 
1151
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
 
1152
        char *suid;
 
1153
        
 
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");
 
1156
                return FALSE;
 
1157
        }
 
1158
        
 
1159
        contact = emapidump_contact (item_data->properties);
 
1160
        suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
 
1161
        
 
1162
        if (contact) {
 
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);
 
1168
        }
 
1169
 
 
1170
        g_free (suid);
 
1171
        return TRUE;
 
1172
}
 
1173
 
 
1174
static void
 
1175
book_view_thread (gpointer data)
 
1176
{
 
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;
 
1188
        
 
1189
        if (enable_debug)
 
1190
                printf("mapi: book view\n");
 
1191
        
 
1192
        bonobo_object_ref (book_view);
 
1193
        e_flag_set (closure->running);
 
1194
                                                
 
1195
        e_data_book_view_notify_status_message (book_view, "Searching...");
 
1196
        query = e_data_book_view_get_card_query (book_view);
 
1197
                                                
 
1198
        switch (priv->mode) {
 
1199
 
 
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);
 
1205
                        return;
 
1206
                }
 
1207
                if (!priv->cache) {
 
1208
                        printf("The cache is not yet built\n");
 
1209
                        e_data_book_view_notify_complete (book_view, 
 
1210
                                        GNOME_Evolution_Addressbook_Success);
 
1211
                        return;
 
1212
                }
 
1213
 
 
1214
                if (priv->is_summary_ready && 
 
1215
                    e_book_backend_summary_is_summary_query (priv->summary, query)) {
 
1216
                        if (enable_debug)
 
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);
 
1222
                        }
 
1223
                        bonobo_object_unref (book_view);
 
1224
                        return;
 
1225
                }
 
1226
 
 
1227
                /* fall back to cache */
 
1228
                if (enable_debug)
 
1229
                        printf ("summary not found or a summary query  reading the contacts from cache %s\n", query);
 
1230
                
 
1231
                contacts = e_book_backend_cache_get_contacts (priv->cache, 
 
1232
                                                              query);
 
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);
 
1238
                                break;
 
1239
                        }                       
 
1240
                        e_data_book_view_notify_update (book_view, 
 
1241
                                                        E_CONTACT(contacts->data));
 
1242
                        g_object_unref (contacts->data);
 
1243
                }
 
1244
                if (e_flag_is_set (closure->running))
 
1245
                        e_data_book_view_notify_complete (book_view, 
 
1246
                                                          GNOME_Evolution_Addressbook_Success);
 
1247
                if (temp_list)
 
1248
                         g_list_free (temp_list);
 
1249
                bonobo_object_unref (book_view);
 
1250
                return;
 
1251
                
 
1252
        case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
1253
 
 
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);
 
1259
                        return;
 
1260
                }
 
1261
                
 
1262
 
 
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)) {
 
1266
                                if (enable_debug)
 
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);
 
1272
                                }
 
1273
                                bonobo_object_unref (book_view);
 
1274
                                return;
 
1275
                        }
 
1276
                        
 
1277
                        printf("Summary seems to be not there or not a summary query, lets fetch from cache directly\n");
 
1278
                        
 
1279
                        /* We are already cached. Lets return from there. */
 
1280
                        contacts = e_book_backend_cache_get_contacts (priv->cache, 
 
1281
                                                                      query);
 
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);
 
1287
                                        break;
 
1288
                                }                                                       
 
1289
                                e_data_book_view_notify_update (book_view, 
 
1290
                                                                E_CONTACT(contacts->data));
 
1291
                                g_object_unref (contacts->data);
 
1292
                        }
 
1293
                        if (e_flag_is_set (closure->running))
 
1294
                                e_data_book_view_notify_complete (book_view, 
 
1295
                                                                  GNOME_Evolution_Addressbook_Success);
 
1296
                        if (temp_list)
 
1297
                                 g_list_free (temp_list);
 
1298
                        bonobo_object_unref (book_view);
 
1299
                        return;
 
1300
                }
 
1301
                
 
1302
                if (e_book_backend_summary_is_summary_query (priv->summary, query)) {
 
1303
                        or_res = g_new (struct mapi_SRestriction_or, res_count);
 
1304
        
 
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);
 
1308
                                return ;
 
1309
                        } 
 
1310
 
 
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);
 
1321
                                        
 
1322
                                if (or_res)
 
1323
                                        g_free(or_res);
 
1324
        
 
1325
                                return;
 
1326
                        }
 
1327
                } else {
 
1328
                        if (!exchange_mapi_connection_fetch_items (priv->fid, NULL, NULL,
 
1329
                                                        NULL, 0, 
 
1330
                                                        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);
 
1337
                                return;
 
1338
                        }
 
1339
                }
 
1340
 
 
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);
 
1345
 
 
1346
                
 
1347
 
 
1348
        default:
 
1349
                break;
 
1350
        }
 
1351
 
 
1352
        if (or_res)
 
1353
                g_free(or_res);
 
1354
 
 
1355
        return;
 
1356
}
 
1357
 
 
1358
static void
 
1359
e_book_backend_mapi_start_book_view (EBookBackend  *backend,
 
1360
                                           EDataBookView *book_view)
 
1361
{
 
1362
        BESearchClosure *closure = init_closure (book_view, E_BOOK_BACKEND_MAPI (backend));
 
1363
 
 
1364
        if (enable_debug)
 
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);
 
1368
        
 
1369
        /* at this point we know the book view thread is actually running */    
 
1370
}
 
1371
 
 
1372
static void
 
1373
e_book_backend_mapi_stop_book_view (EBookBackend  *backend,
 
1374
                                          EDataBookView *book_view)
 
1375
{
 
1376
        if(enable_debug)
 
1377
                printf("mapi: stop book view\n");       
 
1378
        /* FIXME : provide implmentation */
 
1379
}
 
1380
 
 
1381
static void
 
1382
e_book_backend_mapi_get_changes (EBookBackend *backend,
 
1383
                                       EDataBook    *book,
 
1384
                                       guint32       opid,
 
1385
                                       const char *change_id  )
 
1386
{
 
1387
        if(enable_debug)
 
1388
                printf("mapi: get changes\n");  
 
1389
        /* FIXME : provide implmentation */
 
1390
}
 
1391
 
 
1392
static gboolean 
 
1393
cache_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
 
1394
{
 
1395
        EBookBackendMAPI *be = data;
 
1396
        EContact *contact;
 
1397
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
 
1398
        char *suid;
 
1399
 
 
1400
        contact = emapidump_contact (item_data->properties);
 
1401
        suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
 
1402
        
 
1403
        if (contact) {
 
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);
 
1410
        }
 
1411
 
 
1412
        g_free (suid);
 
1413
        return TRUE;    
 
1414
}
 
1415
 
 
1416
static gpointer
 
1417
build_cache (EBookBackendMAPI *ebmapi)
 
1418
{
 
1419
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) ebmapi)->priv;
 
1420
        char *tmp;
 
1421
        
 
1422
        //FIXME: What if book view is NULL? Can it be? Check that.
 
1423
        if (!priv->cache) {
 
1424
                printf("Caching for the first time\n");
 
1425
                priv->cache = e_book_backend_cache_new (priv->uri);
 
1426
        }
 
1427
 
 
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);
 
1432
        }
 
1433
        
 
1434
        e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
 
1435
        
 
1436
        if (!exchange_mapi_connection_fetch_items (priv->fid, NULL, NULL,
 
1437
                                                NULL, 0, 
 
1438
                                                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));
 
1443
                return NULL;
 
1444
        }
 
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);
 
1448
        g_free (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;
 
1453
        return NULL;            
 
1454
}
 
1455
 
 
1456
static gpointer
 
1457
update_cache (EBookBackendMAPI *ebmapi)
 
1458
{
 
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.
 
1462
        time_t t=0;
 
1463
//      struct mapi_SRestriction res;
 
1464
        
 
1465
        if (tmp)
 
1466
                t = atoi (tmp);
 
1467
 
 
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;
 
1473
 
 
1474
#if 0
 
1475
        printf("time updated was %d\n", t);
 
1476
        /* Assume the cache and summary are already there */
 
1477
        
 
1478
        e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
 
1479
        
 
1480
        if (!exchange_mapi_connection_fetch_items ( priv->fid, &res, NULL,
 
1481
                                                NULL, 0, 
 
1482
                                                NULL, 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));
 
1487
                return NULL;
 
1488
        }
 
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;
 
1493
#endif
 
1494
        
 
1495
        return NULL;
 
1496
}
 
1497
 
 
1498
static void
 
1499
e_book_backend_mapi_authenticate_user (EBookBackend *backend,
 
1500
                                            EDataBook    *book,
 
1501
                                            guint32       opid,
 
1502
                                            const char *user,
 
1503
                                            const char *passwd,
 
1504
                                            const char *auth_method)
 
1505
{
 
1506
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
1507
        
 
1508
        if (enable_debug) {
 
1509
                printf ("mapi: authenticate user\n");
 
1510
        }       
 
1511
 
 
1512
        
 
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); 
 
1518
                return;
 
1519
                
 
1520
        case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
1521
                
 
1522
                if (!exchange_mapi_connection_new (priv->profile, NULL))
 
1523
                        return e_data_book_respond_authenticate_user (book, opid,GNOME_Evolution_Addressbook_OtherError);
 
1524
 
 
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);
 
1533
                } 
 
1534
                e_book_backend_set_is_writable (backend, TRUE);
 
1535
                e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success);
 
1536
                return;
 
1537
                
 
1538
        default :
 
1539
                break;
 
1540
        }       
 
1541
}
 
1542
 
 
1543
static void
 
1544
e_book_backend_mapi_get_required_fields (EBookBackend *backend,
 
1545
                                               EDataBook    *book,
 
1546
                                               guint32       opid)
 
1547
{
 
1548
        GList *fields = NULL;
 
1549
 
 
1550
        if (enable_debug)
 
1551
                printf ("mapi get_required_fields...\n");
 
1552
  
 
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,
 
1556
                                                  fields);
 
1557
        g_list_free (fields);   
 
1558
}
 
1559
 
 
1560
static void
 
1561
e_book_backend_mapi_get_supported_fields (EBookBackend *backend,
 
1562
                                               EDataBook    *book,
 
1563
                                               guint32       opid)
 
1564
{
 
1565
        GList *fields = NULL;
 
1566
        int i;
 
1567
 
 
1568
        if (enable_debug)
 
1569
                printf ("mapi get_supported_fields...\n");
 
1570
 
 
1571
        for (i=0; i<maplen; i++)
 
1572
        {
 
1573
                fields = g_list_append (fields, (char *)e_contact_field_name (mappings[i].field_id));
 
1574
        }
 
1575
        fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_BOOK_URI)));
 
1576
 
 
1577
        e_data_book_respond_get_supported_fields (book, opid,
 
1578
                                                  GNOME_Evolution_Addressbook_Success,
 
1579
                                                  fields);
 
1580
        g_list_free (fields);
 
1581
        
 
1582
}
 
1583
 
 
1584
static void 
 
1585
e_book_backend_mapi_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid)
 
1586
{
 
1587
        GList *auth_methods = NULL;
 
1588
        char *auth_method;
 
1589
        
 
1590
        if (enable_debug)
 
1591
                printf ("mapi get_supported_auth_methods...\n");
 
1592
 
 
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,
 
1596
                                                        opid,
 
1597
                                                        GNOME_Evolution_Addressbook_Success,
 
1598
                                                        auth_methods);  
 
1599
        g_free (auth_method);
 
1600
        g_list_free (auth_methods);     
 
1601
}
 
1602
 
 
1603
 
 
1604
static GNOME_Evolution_Addressbook_CallStatus
 
1605
e_book_backend_mapi_cancel_operation (EBookBackend *backend, EDataBook *book)
 
1606
{
 
1607
        if (enable_debug)
 
1608
                printf ("mapi cancel_operation...\n");
 
1609
        return GNOME_Evolution_Addressbook_CouldNotCancel;      
 
1610
}
 
1611
 
 
1612
 
 
1613
static void
 
1614
e_book_backend_mapi_remove (EBookBackend *backend,
 
1615
                                  EDataBook    *book,
 
1616
                                  guint32      opid)
 
1617
{
 
1618
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
1619
        char *cache_uri = NULL;
 
1620
        gboolean status;
 
1621
 
 
1622
        if(enable_debug)
 
1623
                printf("mapi: remove\n");
 
1624
        
 
1625
        switch (priv->mode) {
 
1626
        
 
1627
        case GNOME_Evolution_Addressbook_MODE_LOCAL:
 
1628
                e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_OfflineUnavailable);
 
1629
                return;
 
1630
                
 
1631
        case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
1632
 
 
1633
                status = exchange_mapi_remove_folder (olFolderContacts, priv->fid);
 
1634
                if (!status) {
 
1635
                        e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_OtherError);
 
1636
                        return;                 
 
1637
                }
 
1638
                
 
1639
                if (priv->marked_for_offline && priv->is_summary_ready) {
 
1640
                        g_object_unref (priv->summary);
 
1641
                        priv->summary = NULL;
 
1642
                }
 
1643
 
 
1644
                if (e_book_backend_cache_exists (priv->uri)) {
 
1645
 
 
1646
                        g_object_unref (priv->cache);
 
1647
                        priv->cache= NULL;
 
1648
                        
 
1649
                }
 
1650
 
 
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);
 
1655
                }
 
1656
                g_free (cache_uri);
 
1657
                
 
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);
 
1661
                }
 
1662
                g_free (cache_uri);
 
1663
                                
 
1664
                e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_Success);
 
1665
                return;
 
1666
 
 
1667
 
 
1668
        default:
 
1669
                break;
 
1670
        }
 
1671
 
 
1672
        return;
 
1673
        
 
1674
        /* FIXME : provide implmentation */
 
1675
}
 
1676
 
 
1677
static void 
 
1678
e_book_backend_mapi_set_mode (EBookBackend *backend, int mode)
 
1679
{
 
1680
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) backend)->priv;
 
1681
 
 
1682
        if(enable_debug)
 
1683
                printf("mapi: set_mode \n");
 
1684
        
 
1685
        priv->mode = mode;
 
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.*/
 
1691
                }
 
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.
 
1696
                }
 
1697
        }       
 
1698
}
 
1699
 
 
1700
static void
 
1701
e_book_backend_mapi_dispose (GObject *object)
 
1702
{
 
1703
        /* FIXME : provide implmentation */
 
1704
        EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) object)->priv;
 
1705
        
 
1706
        if (priv->profile) {
 
1707
                g_free (priv->profile);
 
1708
                priv->profile = NULL;
 
1709
        }
 
1710
        if (priv->uri) {
 
1711
                g_free (priv->uri);
 
1712
                priv->uri = NULL;
 
1713
        }
 
1714
        
 
1715
}
 
1716
 
 
1717
 
 
1718
 
 
1719
static void e_book_backend_mapi_class_init (EBookBackendMAPIClass *klass)
 
1720
{
 
1721
        GObjectClass  *object_class = G_OBJECT_CLASS (klass);
 
1722
        EBookBackendClass *parent_class;
 
1723
        
 
1724
        
 
1725
        e_book_backend_mapi_parent_class = g_type_class_peek_parent (klass);
 
1726
        
 
1727
        parent_class = E_BOOK_BACKEND_CLASS (klass);
 
1728
        
 
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;
 
1748
        
 
1749
}
 
1750
 
 
1751
EBookBackend *e_book_backend_mapi_new (void)
 
1752
{
 
1753
        EBookBackendMAPI *backend;
 
1754
        
 
1755
        
 
1756
        backend = g_object_new (E_TYPE_BOOK_BACKEND_MAPI, NULL);
 
1757
        return E_BOOK_BACKEND (backend);
 
1758
}
 
1759
 
 
1760
 
 
1761
static void     e_book_backend_mapi_init (EBookBackendMAPI *backend)
 
1762
{
 
1763
        EBookBackendMAPIPrivate *priv;
 
1764
  
 
1765
        priv= g_new0 (EBookBackendMAPIPrivate, 1);
 
1766
        /* Priv Struct init */
 
1767
        backend->priv = priv;
 
1768
 
 
1769
        priv->marked_for_offline = FALSE;
 
1770
        priv->uri = NULL;
 
1771
        priv->cache = NULL;
 
1772
        priv->is_summary_ready = FALSE;
 
1773
        priv->is_cache_ready = FALSE;
 
1774
        
 
1775
        if (g_getenv ("MAPI_DEBUG"))
 
1776
                enable_debug = TRUE;
 
1777
        else
 
1778
                enable_debug = FALSE;
 
1779
        
 
1780
        
 
1781
}
 
1782
 
 
1783
 
 
1784
GType   e_book_backend_mapi_get_type (void)
 
1785
{
 
1786
        static GType type = 0;
 
1787
        
 
1788
        if (! type) {
 
1789
                GTypeInfo info = {
 
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
 
1799
                };
 
1800
                
 
1801
                type = g_type_register_static (E_TYPE_BOOK_BACKEND, "EBookBackendMAPI", &info, 0);
 
1802
        }
 
1803
        
 
1804
        return type;
 
1805
}