1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* e-book-backend-groupwise.c - Groupwise contact backend.
5 * Copyright (C) 2005 Novell, Inc.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
21 * Authors: Sivaiah Nallagatla <snallagatla@novell.com>
28 #include <sys/types.h>
37 #include <glib/gstdio.h>
38 #include <glib/gi18n-lib.h>
40 #include "libedataserver/e-sexp.h"
41 #include "libedataserver/e-data-server-util.h"
42 #include "libedataserver/e-db3-utils.h"
43 #include "libedataserver/e-flag.h"
44 #include "libedataserver/e-url.h"
45 #include "libebook/e-contact.h"
46 #include "libedata-book/e-book-backend-sexp.h"
47 #include "libedata-book/e-data-book.h"
48 #include "libedata-book/e-data-book-view.h"
49 #include "libedata-book/e-book-backend-db-cache.h"
50 #include "libedata-book/e-book-backend-summary.h"
51 #include "e-book-backend-groupwise.h"
53 #include "e-gw-connection.h"
54 #include "e-gw-item.h"
55 #include "e-gw-filter.h"
57 static EBookBackendClass *e_book_backend_groupwise_parent_class;
59 struct _EBookBackendGroupwisePrivate {
65 char *summary_file_name;
66 gboolean only_if_exists;
67 GHashTable *categories_by_id;
68 GHashTable *categories_by_name;
70 gboolean is_cache_ready;
71 gboolean is_summary_ready;
72 gboolean marked_for_offline;
76 EBookBackendSummary *summary;
77 GMutex *update_cache_mutex;
85 static GStaticMutex global_env_lock = G_STATIC_MUTEX_INIT;
91 #define ELEMENT_TYPE_SIMPLE 0x01
92 #define ELEMENT_TYPE_COMPLEX 0x02 /* fields which require explicit functions to set values into EContact and EGwItem */
93 #define SUMMARY_FLUSH_TIMEOUT 5000
95 static gboolean enable_debug = FALSE;
97 static void populate_emails (EContact *contact, gpointer data);
98 static void set_emails_in_gw_item (EGwItem *item, gpointer data);
99 static void set_emails_changes (EGwItem *new_item, EGwItem *old_item);
100 static void populate_full_name (EContact *contact, gpointer data);
101 static void set_full_name_in_gw_item (EGwItem *item, gpointer data);
102 static void set_full_name_changes (EGwItem *new_item, EGwItem *old_item);
103 static void populate_contact_members (EContact *contact, gpointer data);
104 static void set_categories_changes (EGwItem *new_item, EGwItem *old_item);
105 static void populate_birth_date (EContact *contact, gpointer data);
106 static void set_birth_date_in_gw_item (EGwItem *item, gpointer data);
107 static void set_birth_date_changes (EGwItem *new_item, EGwItem *old_item);
108 static void populate_address (EContact *contact, gpointer data);
109 static void set_address_in_gw_item (EGwItem *item, gpointer data);
110 static void set_address_changes (EGwItem *new_item, EGwItem *old_item);
111 static void populate_ims (EContact *contact, gpointer data);
112 static void set_ims_in_gw_item (EGwItem *item, gpointer data);
113 static void set_im_changes (EGwItem *new_item, EGwItem *old_item);
114 static void fill_contact_from_gw_item (EContact *contact, EGwItem *item, GHashTable *categories_by_ids);
116 static const struct field_element_mapping {
117 EContactField field_id;
120 void (*populate_contact_func)(EContact *contact, gpointer data);
121 void (*set_value_in_gw_item) (EGwItem *item, gpointer data);
122 void (*set_changes) (EGwItem *new_item, EGwItem *old_item);
126 { E_CONTACT_UID, ELEMENT_TYPE_SIMPLE, "id"},
127 { E_CONTACT_FILE_AS, ELEMENT_TYPE_SIMPLE, "name" },
128 { E_CONTACT_FULL_NAME, ELEMENT_TYPE_COMPLEX, "full_name", populate_full_name, set_full_name_in_gw_item, set_full_name_changes},
129 { E_CONTACT_BIRTH_DATE, ELEMENT_TYPE_COMPLEX, "birthday", populate_birth_date, set_birth_date_in_gw_item, set_birth_date_changes },
130 { E_CONTACT_HOMEPAGE_URL, ELEMENT_TYPE_SIMPLE, "website"},
131 { E_CONTACT_NOTE, ELEMENT_TYPE_SIMPLE, "comment"},
132 { E_CONTACT_PHONE_PRIMARY, ELEMENT_TYPE_SIMPLE , "default_phone"},
133 { E_CONTACT_PHONE_BUSINESS, ELEMENT_TYPE_SIMPLE, "phone_Office"},
134 { E_CONTACT_PHONE_HOME, ELEMENT_TYPE_SIMPLE, "phone_Home"},
135 { E_CONTACT_PHONE_MOBILE, ELEMENT_TYPE_SIMPLE, "phone_Mobile"},
136 { E_CONTACT_PHONE_BUSINESS_FAX, ELEMENT_TYPE_SIMPLE, "phone_Fax" },
137 { E_CONTACT_PHONE_PAGER, ELEMENT_TYPE_SIMPLE, "phone_Pager"},
138 { E_CONTACT_ORG, ELEMENT_TYPE_SIMPLE, "organization"},
139 { E_CONTACT_ORG_UNIT, ELEMENT_TYPE_SIMPLE, "department"},
140 { E_CONTACT_TITLE, ELEMENT_TYPE_SIMPLE, "title"},
141 { E_CONTACT_EMAIL, ELEMENT_TYPE_COMPLEX, "members", populate_contact_members, NULL, NULL},
142 { E_CONTACT_ADDRESS_HOME, ELEMENT_TYPE_COMPLEX, "Home", populate_address, set_address_in_gw_item, set_address_changes },
143 { E_CONTACT_IM_AIM, ELEMENT_TYPE_COMPLEX, "ims", populate_ims, set_ims_in_gw_item, set_im_changes },
144 { E_CONTACT_CATEGORIES, ELEMENT_TYPE_COMPLEX, "categories", NULL, NULL, set_categories_changes},
145 { E_CONTACT_EMAIL_1, ELEMENT_TYPE_COMPLEX, "email", populate_emails, set_emails_in_gw_item, set_emails_changes },
146 { E_CONTACT_REV, ELEMENT_TYPE_SIMPLE, "modified_time"},
147 { E_CONTACT_BOOK_URI, ELEMENT_TYPE_SIMPLE, "book_uri"}
151 free_attr_list (GList *attr_list)
155 for (l = attr_list; l; l = g_list_next (l)) {
156 EVCardAttribute *attr = l->data;
157 e_vcard_attribute_free (attr);
160 g_list_free (attr_list);
164 populate_ims (EContact *contact, gpointer data)
167 GList *aim_list = NULL;
168 GList *icq_list = NULL;
169 GList *yahoo_list = NULL;
170 GList *gadugadu_list = NULL;
171 GList *msn_list = NULL;
172 GList *jabber_list = NULL;
173 GList *groupwise_list = NULL;
177 item = E_GW_ITEM (data);
178 im_list = e_gw_item_get_im_list (item);
180 for (; im_list != NULL; im_list = g_list_next (im_list)) {
181 EVCardAttribute *attr;
182 GList **im_attr_list = NULL;
183 int im_field_id = -1;
185 address = (IMAddress *) (im_list->data);
186 if (address->service == NULL) {
190 if (g_str_equal (address->service, "icq")) {
191 im_field_id = E_CONTACT_IM_ICQ;
192 im_attr_list = &icq_list;
194 else if (g_str_equal (address->service, "aim")) {
195 im_field_id = E_CONTACT_IM_AIM;
196 im_attr_list = &aim_list;
198 else if ( g_str_equal (address->service, "msn")) {
199 im_field_id = E_CONTACT_IM_MSN;
200 im_attr_list = &msn_list;
202 else if (g_str_equal (address->service, "yahoo")) {
203 im_field_id = E_CONTACT_IM_YAHOO;
204 im_attr_list = &yahoo_list;
206 else if (g_str_equal (address->service, "gadu-gadu")) {
207 im_field_id = E_CONTACT_IM_GADUGADU;
208 im_attr_list = &gadugadu_list;
210 else if (g_str_equal (address->service, "jabber")) {
211 im_field_id = E_CONTACT_IM_JABBER;
212 im_attr_list = &jabber_list;
215 else if (g_str_equal (address->service, "nov")) {
216 im_field_id = E_CONTACT_IM_GROUPWISE;
217 im_attr_list = &groupwise_list;
219 if (im_field_id == -1)
222 attr = e_vcard_attribute_new ("", e_contact_vcard_attribute(im_field_id));
223 e_vcard_attribute_add_param_with_value (attr, e_vcard_attribute_param_new (EVC_TYPE), "WORK");
224 e_vcard_attribute_add_value (attr, address->address);
225 *im_attr_list = g_list_append (*im_attr_list, attr);
228 e_contact_set_attributes (contact, E_CONTACT_IM_AIM, aim_list);
229 e_contact_set_attributes (contact, E_CONTACT_IM_JABBER, jabber_list);
230 e_contact_set_attributes (contact, E_CONTACT_IM_ICQ, icq_list);
231 e_contact_set_attributes (contact, E_CONTACT_IM_YAHOO, yahoo_list);
232 e_contact_set_attributes (contact, E_CONTACT_IM_GADUGADU, gadugadu_list);
233 e_contact_set_attributes (contact, E_CONTACT_IM_MSN, msn_list);
234 e_contact_set_attributes (contact, E_CONTACT_IM_GROUPWISE, groupwise_list);
236 free_attr_list (aim_list);
237 free_attr_list (jabber_list);
238 free_attr_list (icq_list);
239 free_attr_list (yahoo_list);
240 free_attr_list (gadugadu_list);
241 free_attr_list (msn_list);
242 free_attr_list (groupwise_list);
246 append_ims_to_list (GList **im_list, EContact *contact, char *service_name, EContactField field_id)
250 list = e_contact_get (contact, field_id);
251 for (; list != NULL; list = g_list_next (list)) {
252 address = g_new0 (IMAddress , 1);
253 address->service = g_strdup (service_name);
254 address->address = list->data;
255 *im_list = g_list_append (*im_list, address);
262 set_ims_in_gw_item (EGwItem *item, gpointer data)
265 GList *im_list = NULL;
267 contact = E_CONTACT (data);
269 append_ims_to_list (&im_list, contact, "aim", E_CONTACT_IM_AIM);
270 append_ims_to_list (&im_list, contact, "yahoo", E_CONTACT_IM_YAHOO);
271 append_ims_to_list (&im_list, contact, "gadu-gadu", E_CONTACT_IM_GADUGADU);
272 append_ims_to_list (&im_list, contact, "icq", E_CONTACT_IM_ICQ);
273 append_ims_to_list (&im_list, contact, "msn", E_CONTACT_IM_MSN);
274 append_ims_to_list (&im_list, contact, "jabber", E_CONTACT_IM_JABBER);
275 append_ims_to_list (&im_list, contact, "nov", E_CONTACT_IM_GROUPWISE);
277 e_gw_item_set_im_list (item, im_list);
281 set_im_changes (EGwItem *new_item, EGwItem *old_item)
285 GList *added_ims = NULL;
288 gboolean ims_matched;
289 IMAddress *im1, *im2;
291 old_ims = e_gw_item_get_im_list (old_item);
292 new_ims = e_gw_item_get_im_list (new_item);
294 if (old_ims && new_ims) {
296 old_ims_copy = g_list_copy (old_ims);
297 for ( ; new_ims != NULL; new_ims = g_list_next (new_ims)) {
302 for(; temp != NULL; temp = g_list_next (temp)) {
304 if (g_str_equal (im1->service, im2->service) && g_str_equal (im1->address, im2->address)) {
306 old_ims_copy = g_list_remove (old_ims_copy, im2);
312 added_ims = g_list_append (added_ims, im1);
315 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "ims", added_ims);
316 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "ims", old_ims_copy);
318 } else if (!new_ims && old_ims) {
319 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "ims", g_list_copy (old_ims));
320 } else if (new_ims && !old_ims) {
321 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "ims", g_list_copy (new_ims));
327 copy_postal_address_to_contact_address ( EContactAddress *contact_addr, PostalAddress *address)
329 contact_addr->address_format = NULL;
330 contact_addr->po = NULL;
331 contact_addr->street = g_strdup (address->street_address);
332 contact_addr->ext = g_strdup (address->location);
333 contact_addr->locality = g_strdup (address->city);
334 contact_addr->region = g_strdup (address->state);
335 contact_addr->code = g_strdup (address->postal_code);
336 contact_addr->country = g_strdup (address->country);
340 copy_contact_address_to_postal_address (PostalAddress *address, EContactAddress *contact_addr)
342 /* ugh, contact addr has null terminated strings instead of NULLs*/
343 address->street_address = (contact_addr->street && *contact_addr->street) ? g_strdup (contact_addr->street): NULL;
344 address->location = (contact_addr->ext && *contact_addr->ext) ? g_strdup (contact_addr->ext) : NULL;
345 address->city = (contact_addr->locality && *contact_addr->locality) ? g_strdup (contact_addr->locality) : NULL;
346 address->state = (contact_addr->region && *contact_addr->region) ? g_strdup (contact_addr->region) : NULL;
347 address->postal_code = (contact_addr->code && *contact_addr->code ) ? g_strdup (contact_addr->code) : NULL;
348 address->country = (contact_addr->country && *(contact_addr->country)) ? g_strdup (contact_addr->country) : NULL;
352 populate_address (EContact *contact, gpointer data)
354 PostalAddress *address;
356 EContactAddress *contact_addr;
358 item = E_GW_ITEM (data);
360 address = e_gw_item_get_address (item, "Home");
364 contact_addr = g_new0(EContactAddress, 1);
365 copy_postal_address_to_contact_address (contact_addr, address);
366 e_contact_set (contact, E_CONTACT_ADDRESS_HOME, contact_addr);
367 e_contact_address_free (contact_addr);
370 address = e_gw_item_get_address (item, "Office");
372 contact_addr = g_new0(EContactAddress, 1);
373 copy_postal_address_to_contact_address (contact_addr, address);
374 e_contact_set (contact, E_CONTACT_ADDRESS_WORK, contact_addr);
375 e_contact_address_free (contact_addr);
380 set_address_in_gw_item (EGwItem *item, gpointer data)
383 EContactAddress *contact_address;
384 PostalAddress *address;
386 contact = E_CONTACT (data);
388 contact_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
389 if (contact_address) {
390 address = g_new0(PostalAddress, 1);
391 copy_contact_address_to_postal_address (address, contact_address);
392 e_gw_item_set_address (item, "Home", address);
393 e_contact_address_free (contact_address);
396 contact_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
397 if (contact_address) {
398 address = g_new0(PostalAddress, 1);
399 copy_contact_address_to_postal_address (address, contact_address);
400 e_gw_item_set_address (item, "Office", address);
401 e_contact_address_free (contact_address);
405 static PostalAddress *
406 copy_postal_address (PostalAddress *address)
408 PostalAddress *address_copy;
410 address_copy = g_new0(PostalAddress, 1);
412 address_copy->street_address = g_strdup (address->street_address);
413 address_copy->location = g_strdup (address->location);
414 address_copy->city = g_strdup (address->city);
415 address_copy->state = g_strdup (address->state);
416 address_copy->postal_code = g_strdup (address->postal_code);
417 address_copy->country = g_strdup (address->country);
422 set_postal_address_change (EGwItem *new_item, EGwItem *old_item, char *address_type)
424 PostalAddress *old_postal_address;
425 PostalAddress *new_postal_address;
426 PostalAddress *update_postal_address, *delete_postal_address;
428 update_postal_address = g_new0(PostalAddress, 1);
429 delete_postal_address = g_new0 (PostalAddress, 1);
431 new_postal_address = e_gw_item_get_address (new_item, address_type);
432 old_postal_address = e_gw_item_get_address (old_item, address_type);
433 if (new_postal_address && old_postal_address) {
434 s1 = new_postal_address->street_address;
435 s2 = old_postal_address->street_address;
437 delete_postal_address->street_address = g_strdup(s2);
439 update_postal_address->street_address = g_strdup(s1);
441 s1 = new_postal_address->location;
442 s2 = old_postal_address->location;
444 delete_postal_address->location = g_strdup(s2);
446 update_postal_address->location = g_strdup(s1);
448 s1 = new_postal_address->city;
449 s2 = old_postal_address->city;
451 delete_postal_address->city = g_strdup(s2);
453 update_postal_address->city = g_strdup(s1);
455 s1 = new_postal_address->state;
456 s2 = old_postal_address->state;
458 delete_postal_address->state = g_strdup(s2);
460 update_postal_address->state = g_strdup(s1);
461 s1 = new_postal_address->postal_code;
462 s2 = old_postal_address->postal_code;
464 delete_postal_address->postal_code = g_strdup(s2);
466 update_postal_address->postal_code = g_strdup(s1);
468 s1 = new_postal_address->country;
469 s2 = old_postal_address->country;
471 delete_postal_address->country = g_strdup(s2);
473 update_postal_address->country = g_strdup(s1);
475 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_UPDATE, address_type, update_postal_address);
476 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, address_type, delete_postal_address);
478 } else if (!new_postal_address && old_postal_address) {
479 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, address_type, copy_postal_address(old_postal_address));
480 } else if (new_postal_address && !old_postal_address) {
481 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, address_type, copy_postal_address(new_postal_address));
486 set_address_changes (EGwItem *new_item , EGwItem *old_item)
488 set_postal_address_change (new_item, old_item, "Home");
489 set_postal_address_change (new_item, old_item, "Office");
493 populate_birth_date (EContact *contact, gpointer data)
499 item = E_GW_ITEM (data);
500 value = e_gw_item_get_field_value (item, "birthday");
502 date = e_contact_date_from_string (value);
503 e_contact_set (contact, E_CONTACT_BIRTH_DATE, date);
504 e_contact_date_free (date);
509 set_birth_date_in_gw_item (EGwItem *item, gpointer data)
514 contact = E_CONTACT (data);
515 date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
517 date_string = e_contact_date_to_string (date);
518 e_gw_item_set_field_value (item, "birthday", date_string);
519 e_contact_date_free (date);
520 g_free (date_string);
526 set_birth_date_changes (EGwItem *new_item, EGwItem *old_item)
531 new_birthday = e_gw_item_get_field_value (new_item, "birthday");
532 old_birthday = e_gw_item_get_field_value (old_item, "birthday");
534 if (new_birthday && old_birthday) {
535 if (!g_str_equal (new_birthday, old_birthday))
536 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_UPDATE, "birthday", new_birthday);
538 else if (!new_birthday && old_birthday) {
539 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "birthday", old_birthday);
541 else if (new_birthday && !old_birthday) {
542 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "birthday", new_birthday);
546 static const int email_fields[3] = {
554 populate_emails (EContact *contact, gpointer data)
560 item = E_GW_ITEM (data);
561 email_list = e_gw_item_get_email_list(item);
563 for (i =0 ; i < 3 && email_list; i++, email_list = g_list_next (email_list)) {
564 if (email_list->data)
565 e_contact_set (contact, email_fields[i], email_list->data);
571 set_emails_in_gw_item (EGwItem *item, gpointer data)
578 contact = E_CONTACT (data);
580 for (i =0 ; i < 3; i++) {
581 email = e_contact_get (contact, email_fields[i]);
583 email_list = g_list_append (email_list, g_strdup (email));
585 e_gw_item_set_email_list (item, email_list);
589 compare_string_lists ( GList *old_list, GList *new_list, GList **additions, GList **deletions)
591 GList *temp, *old_list_copy;
592 gboolean strings_matched;
593 char *string1, *string2;
595 if (old_list && new_list) {
596 old_list_copy = g_list_copy (old_list);
597 for ( ; new_list != NULL; new_list = g_list_next (new_list)) {
599 string1 = new_list->data;
601 strings_matched = FALSE;
602 for(; temp != NULL; temp = g_list_next (temp)) {
603 string2 = temp->data;
604 if ( g_str_equal (string1, string2)) {
605 strings_matched = TRUE;
606 old_list_copy = g_list_remove (old_list_copy, string2);
610 if (!strings_matched)
611 *additions = g_list_append (*additions, string1);
613 *deletions = old_list_copy;
615 else if (!new_list && old_list)
616 *deletions = g_list_copy (old_list);
617 else if (new_list && !old_list)
618 *additions = g_list_copy (new_list);
622 set_emails_changes (EGwItem *new_item, EGwItem *old_item)
624 GList *old_email_list;
625 GList *new_email_list;
626 GList *added_emails = NULL, *deleted_emails = NULL;
628 old_email_list = e_gw_item_get_email_list (old_item);
629 new_email_list = e_gw_item_get_email_list (new_item);
630 compare_string_lists (old_email_list, new_email_list, &added_emails, &deleted_emails);
632 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "email", added_emails);
634 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "email", deleted_emails);
638 populate_full_name (EContact *contact, gpointer data)
641 FullName *full_name ;
642 char *full_name_string;
644 item = E_GW_ITEM(data);
645 full_name = e_gw_item_get_full_name (item);
647 full_name_string = g_strconcat ( (full_name->first_name == NULL) ? "\0" : full_name->first_name, " ",
648 (full_name->middle_name == NULL) ? "\0" : full_name->middle_name, " ",
649 full_name->last_name == NULL ? "\0" : full_name->last_name, " ",
650 (full_name->name_suffix == NULL ) ? "\0" : full_name->name_suffix, NULL);
651 full_name_string = g_strstrip (full_name_string);
652 if (!g_str_equal (full_name_string, "\0"))
653 e_contact_set (contact, E_CONTACT_FULL_NAME, full_name_string);
654 g_free (full_name_string);
659 set_full_name_in_gw_item (EGwItem *item, gpointer data)
663 EContactName *contact_name;
666 contact = E_CONTACT (data);
668 name = e_contact_get (contact, E_CONTACT_FULL_NAME);
671 contact_name = e_contact_name_from_string (name);
672 full_name = g_new0 (FullName, 1);
673 if (contact_name && full_name) {
674 full_name->name_prefix = g_strdup (contact_name->prefixes);
675 full_name->first_name = g_strdup (contact_name->given);
676 full_name->middle_name = g_strdup (contact_name->additional);
677 full_name->last_name = g_strdup (contact_name->family);
678 full_name->name_suffix = g_strdup (contact_name->suffixes);
679 e_contact_name_free (contact_name);
681 e_gw_item_set_full_name (item, full_name);
686 copy_full_name (FullName *full_name)
688 FullName *full_name_copy = g_new0(FullName, 1);
689 full_name_copy->name_prefix = g_strdup (full_name->name_prefix);
690 full_name_copy->first_name = g_strdup (full_name->first_name);
691 full_name_copy->middle_name = g_strdup (full_name->middle_name);
692 full_name_copy->last_name = g_strdup (full_name->last_name);
693 full_name_copy->name_suffix = g_strdup (full_name->name_suffix);
694 return full_name_copy;
698 set_full_name_changes (EGwItem *new_item, EGwItem *old_item)
700 FullName *old_full_name;
701 FullName *new_full_name;
702 FullName *update_full_name, *delete_full_name;
704 update_full_name = g_new0(FullName, 1);
705 delete_full_name = g_new0 (FullName, 1);
707 old_full_name = e_gw_item_get_full_name (old_item);
708 new_full_name = e_gw_item_get_full_name (new_item);
710 if (old_full_name && new_full_name) {
711 s1 = new_full_name->name_prefix;
712 s2 = old_full_name->name_prefix;
714 delete_full_name->name_prefix = g_strdup(s2);
716 update_full_name->name_prefix = g_strdup(s1);
717 s1 = new_full_name->first_name;
718 s2 = old_full_name->first_name;
720 delete_full_name->first_name = g_strdup(s2);
722 update_full_name->first_name = g_strdup(s1);
723 s1 = new_full_name->middle_name;
724 s2 = old_full_name->middle_name;
726 delete_full_name->middle_name = g_strdup(s2);
728 update_full_name->middle_name = g_strdup(s1);
730 s1 = new_full_name->last_name;
731 s2 = old_full_name->last_name;
733 delete_full_name->last_name = g_strdup(s2);
735 update_full_name->last_name = g_strdup(s1);
736 s1 = new_full_name->name_suffix;
737 s2 = old_full_name->name_suffix;
739 delete_full_name->name_suffix = g_strdup(s2);
741 update_full_name->name_suffix = g_strdup(s1);
742 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_UPDATE,"full_name", update_full_name);
743 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE,"full_name", delete_full_name);
745 } else if (!new_full_name && old_full_name) {
746 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "full_name", copy_full_name(old_full_name));
747 } else if (new_full_name && !old_full_name) {
748 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "full_name", copy_full_name(new_full_name));
753 populate_contact_members (EContact *contact, gpointer data)
758 item = E_GW_ITEM(data);
759 member_list = e_gw_item_get_member_list (item);
761 for (; member_list != NULL; member_list = g_list_next (member_list)) {
762 EVCardAttribute *attr;
763 EGroupMember *member;
764 member = (EGroupMember *) member_list->data;
766 attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
767 e_vcard_attribute_add_param_with_value (attr,
768 e_vcard_attribute_param_new (EVC_X_DEST_CONTACT_UID),
770 e_vcard_attribute_add_param_with_value (attr,
771 e_vcard_attribute_param_new (EVC_X_DEST_EMAIL),
774 e_vcard_attribute_add_param_with_value (attr,
775 e_vcard_attribute_param_new (EVC_X_DEST_NAME),
777 e_vcard_attribute_add_value (attr, member->email);
778 e_vcard_add_attribute (E_VCARD (contact), attr);
783 set_members_in_gw_item (EGwItem *item, EContact *contact, EBookBackendGroupwise *egwb)
785 GList *members, *temp, *items, *p, *emails_without_ids;
786 GList *group_members;
796 EGroupMember *member;
798 members = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
800 filter = e_gw_filter_new ();
801 group_members = NULL;
802 emails_without_ids = NULL;
804 for ( ;temp != NULL; temp = g_list_next (temp)) {
805 EVCardAttribute *attr = temp->data;
808 for (p = e_vcard_attribute_get_params (attr); p; p = p->next) {
809 EVCardAttributeParam *param = p->data;
810 const char *param_name = e_vcard_attribute_param_get_name (param);
812 if (!g_ascii_strcasecmp (param_name,
813 EVC_X_DEST_CONTACT_UID)) {
814 GList *v = e_vcard_attribute_param_get_values (param);
815 id = v ? v->data : NULL;
817 EGwItem *gw_item = NULL;
818 e_gw_connection_get_item (egwb->priv->cnc, egwb->priv->container_id,id, "name email", &gw_item);
820 /* The item corresponding to this id is not found. This happens in case of
821 * importing, in imported file the stored id is corresponding to the address
822 * book from which the contact list was exported.
827 g_object_unref (gw_item);
829 } else if (!g_ascii_strcasecmp (param_name,
831 GList *v = e_vcard_attribute_param_get_values (param);
832 email = v ? v->data : NULL;
836 member = g_new0 (EGroupMember , 1);
837 member->id = g_strdup (id);
838 group_members = g_list_append (group_members, member);
840 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, "emailList/@primary", email);
841 emails_without_ids = g_list_append (emails_without_ids, g_strdup (email));
845 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, count);
849 status = e_gw_connection_get_items (egwb->priv->cnc, egwb->priv->container_id, "name email default members", filter, &items);
851 for (; items != NULL; items = g_list_next (items )) {
855 temp_item = E_GW_ITEM (items->data);
856 emails = e_gw_item_get_email_list (temp_item);
857 if (emails_without_ids && (ptr = g_list_find_custom (emails_without_ids, emails->data, (GCompareFunc)strcasecmp ))) {
858 emails_without_ids = g_list_remove_link (emails_without_ids, ptr);
860 id = g_strdup (e_gw_item_get_id (temp_item));
861 member = g_new0 (EGroupMember , 1);
863 group_members = g_list_append (group_members, member);
865 g_object_unref (temp_item);
869 /* In groupwise there is no way to put arbitrary members into a group. There's no
870 * mechanism for a group to contain members that are not already present in a system
871 * or personal addressbook as a contact, and so they cant be saved and will be lost.
872 * In order to save them we first need to create groupwise based contacts for these
873 * arbitrary contacts and then add them as members to the group.
876 temp = emails_without_ids ;
877 for (; temp != NULL; temp = g_list_next (temp)) {
878 EContact *new_contact = e_contact_new ();
879 EGwItem *new_item = e_gw_item_new_empty ();
882 e_contact_set (new_contact,E_CONTACT_FULL_NAME, e_contact_name_from_string (strdup (temp->data)));
883 e_contact_set (new_contact, E_CONTACT_EMAIL_1, strdup (temp->data));
884 e_contact_set (new_contact, E_CONTACT_IS_LIST, FALSE);
885 e_gw_item_set_item_type (new_item, E_GW_ITEM_TYPE_CONTACT);
886 e_gw_item_set_container_id (new_item, g_strdup(egwb->priv->container_id));
887 full_name = g_new0 (FullName, 1);
888 full_name->name_prefix = NULL;
889 full_name->first_name = g_strdup(temp->data);
890 full_name->middle_name = NULL;
891 full_name->last_name = NULL;
892 full_name->name_suffix = NULL;
893 e_gw_item_set_full_name (new_item, full_name);
895 for (i=0; i < G_N_ELEMENTS (mappings); i++) {
896 element_type = mappings[i].element_type;
897 if (element_type == ELEMENT_TYPE_SIMPLE) {
898 value = e_contact_get (new_contact, mappings[i].field_id);
900 e_gw_item_set_field_value (new_item, mappings[i].element_name, value);
904 else if (element_type == ELEMENT_TYPE_COMPLEX) {
905 if (mappings[i].field_id == E_CONTACT_CATEGORIES) {
908 else if (mappings[i].field_id == E_CONTACT_EMAIL) {
909 if (e_contact_get (contact, E_CONTACT_IS_LIST))
912 else if (mappings[i].field_id == E_CONTACT_FULL_NAME) {
916 mappings[i].set_value_in_gw_item (new_item, new_contact);
922 status = e_gw_connection_create_item (egwb->priv->cnc, new_item, &id);
923 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
924 status = e_gw_connection_create_item (egwb->priv->cnc, new_item, &id);
926 if (status == E_GW_CONNECTION_STATUS_OK && id) {
927 e_contact_set (new_contact, E_CONTACT_UID, id);
928 e_book_backend_db_cache_add_contact (egwb->priv->file_db, new_contact);
929 e_book_backend_summary_add_contact (egwb->priv->summary, new_contact);
930 member = g_new0 (EGroupMember, 1);
931 member->id = g_strdup (id);
932 group_members = g_list_append (group_members, member);
935 g_object_unref (new_item);
936 g_object_unref (new_contact);
939 g_list_foreach (members, (GFunc) e_vcard_attribute_free, NULL);
940 g_list_free (members);
941 g_list_foreach (emails_without_ids, (GFunc) g_free, NULL);
942 g_list_free (emails_without_ids);
944 e_gw_item_set_member_list (item, group_members);
948 set_member_changes (EGwItem *new_item, EGwItem *old_item, EBookBackendGroupwise *egwb)
950 GList *old_members, *new_members ;
951 GList *old_ids, *new_ids, *additions, *deletions;
953 old_ids = new_ids = additions = deletions = NULL;
954 old_members = e_gw_item_get_member_list (old_item);
955 new_members = e_gw_item_get_member_list (new_item);
957 for ( ;old_members != NULL; old_members = g_list_next (old_members)) {
958 EGroupMember *member;
959 member = (EGroupMember *)old_members->data;
960 old_ids = g_list_append (old_ids, member->id);
962 for ( ;new_members != NULL; new_members = g_list_next (new_members)) {
963 EGroupMember *member;
964 member = (EGroupMember *)new_members->data;
965 new_ids = g_list_append (new_ids, member->id);
968 compare_string_lists (old_ids, new_ids, &additions, &deletions);
970 e_gw_connection_add_members (egwb->priv->cnc, e_gw_item_get_id (old_item), additions);
972 e_gw_connection_remove_members (egwb->priv->cnc, e_gw_item_get_id (old_item), deletions);
974 g_list_free (new_ids);
975 g_list_free (old_ids);
976 g_list_free (additions);
977 g_list_free (deletions);
981 set_organization_in_gw_item (EGwItem *item, EContact *contact, EBookBackendGroupwise *egwb)
983 char *organization_name;
984 EGwItem *org_item, *temp_item;
990 organization_name = e_contact_get (contact, E_CONTACT_ORG);
991 if (organization_name == NULL || strlen (organization_name) == 0)
994 filter = e_gw_filter_new ();
995 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, "name", organization_name);
997 status = e_gw_connection_get_items (egwb->priv->cnc, egwb->priv->container_id, NULL, filter, &items);
998 g_object_unref (filter);
1001 for (; items != NULL; items = g_list_next (items )) {
1002 temp_item = E_GW_ITEM (items->data);
1003 if (e_gw_item_get_item_type (temp_item) == E_GW_ITEM_TYPE_ORGANISATION) {
1004 id = g_strdup (e_gw_item_get_id (temp_item));
1005 for (;items != NULL; items = g_list_next (items))
1006 g_object_unref (items->data);
1009 g_object_unref (temp_item);
1011 g_list_free (items);
1014 org_item = e_gw_item_new_empty ();
1015 e_gw_item_set_container_id (org_item, egwb->priv->container_id);
1016 e_gw_item_set_field_value (org_item, "name", organization_name);
1017 e_gw_item_set_item_type (org_item, E_GW_ITEM_TYPE_ORGANISATION);
1018 status = e_gw_connection_create_item (egwb->priv->cnc, org_item, &id);
1019 if ((status == E_GW_CONNECTION_STATUS_OK) && id) {
1020 EContact *contact = e_contact_new ();
1021 fill_contact_from_gw_item (contact, org_item, egwb->priv->categories_by_id);
1022 e_contact_set (contact, E_CONTACT_UID, id);
1023 e_contact_set (contact, E_CONTACT_FULL_NAME, organization_name);
1024 /* book uri is always set outside fill_contact_from_gw_item() */
1025 e_contact_set (contact, E_CONTACT_BOOK_URI, egwb->priv->original_uri);
1026 e_book_backend_db_cache_add_contact (egwb->priv->file_db, contact);
1027 e_book_backend_summary_add_contact (egwb->priv->summary, contact);
1028 g_object_unref (contact);
1030 g_object_unref (org_item);
1031 if (status != E_GW_CONNECTION_STATUS_OK)
1036 e_gw_item_set_field_value (item, "organization_id", id);
1037 e_gw_item_set_field_value (item , "organization", organization_name);
1041 set_organization_changes_in_gw_item (EGwItem *new_item, EGwItem *old_item)
1048 old_value = e_gw_item_get_field_value (old_item, "organization");
1049 new_value = e_gw_item_get_field_value (new_item, "organization");
1050 old_org_id = e_gw_item_get_field_value (old_item, "organization_id");
1051 new_org_id = e_gw_item_get_field_value (new_item, "organization_id");
1052 if (new_value && old_value) {
1053 if (!g_str_equal (new_value, old_value)) {
1054 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_UPDATE, "organization", new_value);
1055 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_UPDATE, "organization_id", new_org_id);
1057 } else if (!new_value && old_value) {
1058 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE,"organization", old_value);
1059 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "organization_id", old_org_id);
1060 } else if (new_value && !old_value) {
1061 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "organization", new_value);
1062 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "organization_id", new_org_id);
1067 set_categories_in_gw_item (EGwItem *item, EContact *contact, EBookBackendGroupwise *egwb)
1069 GHashTable *categories_by_name;
1070 GList *category_names, *category_ids;
1074 categories_by_name = egwb->priv->categories_by_name;
1075 category_names = e_contact_get (contact, E_CONTACT_CATEGORY_LIST);
1076 category_ids = NULL;
1078 for (; category_names != NULL; category_names = g_list_next (category_names)) {
1079 if (!category_names->data || strlen(category_names->data) == 0 )
1081 id = g_hash_table_lookup (categories_by_name, category_names->data);
1083 category_ids = g_list_append (category_ids, g_strdup (id));
1085 EGwItem *category_item;
1087 category_item = e_gw_item_new_empty();
1088 e_gw_item_set_item_type (category_item, E_GW_ITEM_TYPE_CATEGORY);
1089 e_gw_item_set_category_name (category_item, category_names->data);
1090 status = e_gw_connection_create_item (egwb->priv->cnc, category_item, &id);
1091 if (status == E_GW_CONNECTION_STATUS_OK && id != NULL) {
1092 char **components = g_strsplit (id, "@", -1);
1093 char *temp_id = components[0];
1095 g_hash_table_insert (categories_by_name, g_strdup (category_names->data), g_strdup(temp_id));
1096 g_hash_table_insert (egwb->priv->categories_by_id, g_strdup(temp_id), g_strdup (category_names->data));
1097 category_ids = g_list_append (category_ids, g_strdup(temp_id));
1099 g_strfreev(components);
1101 g_object_unref (category_item);
1104 e_gw_item_set_categories (item, category_ids);
1108 set_categories_changes (EGwItem *new_item, EGwItem *old_item)
1110 GList *old_category_list;
1111 GList *new_category_list;
1112 GList *temp, *old_categories_copy, *added_categories = NULL;
1113 gboolean categories_matched;
1114 char *category1, *category2;
1116 old_category_list = e_gw_item_get_categories (old_item);
1117 new_category_list = e_gw_item_get_categories (new_item);
1119 if (old_category_list && new_category_list) {
1120 old_categories_copy = g_list_copy (old_category_list);
1122 for ( ; new_category_list != NULL; new_category_list = g_list_next (new_category_list)) {
1123 category1 = new_category_list->data;
1124 temp = old_category_list;
1125 categories_matched = FALSE;
1127 for(; temp != NULL; temp = g_list_next (temp)) {
1128 category2 = temp->data;
1129 if ( g_str_equal (category1, category2)) {
1130 categories_matched = TRUE;
1131 old_categories_copy = g_list_remove (old_categories_copy, category2);
1135 if (!categories_matched)
1136 added_categories = g_list_append (added_categories, category1);
1139 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "categories", added_categories);
1140 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "categories", old_categories_copy);
1141 } else if (!new_category_list && old_category_list) {
1142 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "categories", old_category_list);
1143 } else if (new_category_list && !old_category_list) {
1144 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "categories", new_category_list);
1149 fill_contact_from_gw_item (EContact *contact, EGwItem *item, GHashTable *categories_by_ids)
1154 gboolean is_contact_list;
1156 is_contact_list = e_gw_item_get_item_type (item) == E_GW_ITEM_TYPE_GROUP ? TRUE: FALSE;
1157 e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (is_contact_list));
1158 if (is_contact_list)
1159 e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (TRUE));
1161 for ( i = 0; i < G_N_ELEMENTS (mappings); i++) {
1162 element_type = mappings[i].element_type;
1164 if(element_type == ELEMENT_TYPE_SIMPLE) {
1165 if (mappings[i].field_id != E_CONTACT_BOOK_URI) {
1166 value = e_gw_item_get_field_value (item, mappings[i].element_name);
1168 e_contact_set (contact, mappings[i].field_id, value);
1170 } else if (element_type == ELEMENT_TYPE_COMPLEX) {
1171 if (mappings[i].field_id == E_CONTACT_CATEGORIES) {
1172 GList *category_ids, *category_names;
1175 category_names = NULL;
1176 category_ids = e_gw_item_get_categories (item);
1177 for (; category_ids; category_ids = g_list_next (category_ids)) {
1178 name = g_hash_table_lookup (categories_by_ids, category_ids->data);
1180 category_names = g_list_append (category_names, name);
1182 if (category_names) {
1183 e_contact_set (contact, E_CONTACT_CATEGORY_LIST, category_names);
1184 g_list_free (category_names);
1188 mappings[i].populate_contact_func(contact, item);
1194 e_book_backend_groupwise_create_contact (EBookBackend *backend,
1200 EBookBackendGroupwise *egwb;
1209 printf("\ne_book_backend_groupwise_create_contact...\n");
1211 egwb = E_BOOK_BACKEND_GROUPWISE (backend);
1213 switch (egwb->priv->mode) {
1215 case GNOME_Evolution_Addressbook_MODE_LOCAL :
1216 e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
1219 case GNOME_Evolution_Addressbook_MODE_REMOTE :
1221 if (egwb->priv->cnc == NULL) {
1222 e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_AuthenticationRequired, NULL);
1225 if (!egwb->priv->is_writable) {
1226 e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_PermissionDenied, NULL);
1229 contact = e_contact_new_from_vcard(vcard);
1230 item = e_gw_item_new_empty ();
1231 e_gw_item_set_item_type (item, e_contact_get (contact, E_CONTACT_IS_LIST) ? E_GW_ITEM_TYPE_GROUP :E_GW_ITEM_TYPE_CONTACT);
1232 e_gw_item_set_container_id (item, g_strdup(egwb->priv->container_id));
1234 for (i = 0; i < G_N_ELEMENTS (mappings); i++) {
1235 element_type = mappings[i].element_type;
1236 if (element_type == ELEMENT_TYPE_SIMPLE) {
1237 value = e_contact_get(contact, mappings[i].field_id);
1238 if (mappings[i].field_id == E_CONTACT_ORG) {
1239 set_organization_in_gw_item (item, contact, egwb);
1243 e_gw_item_set_field_value (item, mappings[i].element_name, value);
1244 } else if (element_type == ELEMENT_TYPE_COMPLEX) {
1245 if (mappings[i].field_id == E_CONTACT_CATEGORIES) {
1246 set_categories_in_gw_item (item, contact, egwb);
1248 else if (mappings[i].field_id == E_CONTACT_EMAIL) {
1249 if (e_contact_get (contact, E_CONTACT_IS_LIST))
1250 set_members_in_gw_item (item, contact, egwb);
1253 mappings[i].set_value_in_gw_item (item, contact);
1258 status = e_gw_connection_create_item (egwb->priv->cnc, item, &id);
1259 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
1260 status = e_gw_connection_create_item (egwb->priv->cnc, item, &id);
1262 /* Make sure server has returned an id for the created contact */
1263 if (status == E_GW_CONNECTION_STATUS_OK && id) {
1264 e_contact_set (contact, E_CONTACT_UID, id);
1266 e_book_backend_db_cache_add_contact (egwb->priv->file_db, contact);
1267 egwb->priv->file_db->sync(egwb->priv->file_db, 0);
1268 e_book_backend_summary_add_contact (egwb->priv->summary, contact);
1269 e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_Success, contact);
1273 e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
1275 g_object_unref (item);
1283 e_book_backend_groupwise_remove_contacts (EBookBackend *backend,
1289 EBookBackendGroupwise *ebgw;
1290 GList *deleted_ids = NULL;
1293 printf ("\ne_book_backend_groupwise_remove_contacts...\n");
1295 ebgw = E_BOOK_BACKEND_GROUPWISE (backend);
1297 switch (ebgw->priv->mode) {
1299 case GNOME_Evolution_Addressbook_MODE_LOCAL :
1300 e_data_book_respond_remove_contacts (book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
1303 case GNOME_Evolution_Addressbook_MODE_REMOTE :
1304 if (ebgw->priv->cnc == NULL) {
1305 e_data_book_respond_remove_contacts (book, opid, GNOME_Evolution_Addressbook_AuthenticationRequired, NULL);
1309 if (!ebgw->priv->is_writable) {
1310 e_data_book_respond_remove_contacts (book, opid, GNOME_Evolution_Addressbook_PermissionDenied, NULL);
1314 for ( ; id_list != NULL; id_list = g_list_next (id_list)) {
1315 id = (char*) id_list->data;
1316 e_gw_connection_remove_item (ebgw->priv->cnc, ebgw->priv->container_id, id);
1317 deleted_ids = g_list_append (deleted_ids, id);
1318 e_book_backend_db_cache_remove_contact (ebgw->priv->file_db, id);
1319 e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
1321 ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
1322 e_data_book_respond_remove_contacts (book, opid,
1323 GNOME_Evolution_Addressbook_Success, deleted_ids);
1331 set_changes_in_gw_item (EGwItem *new_item, EGwItem *old_item)
1338 g_return_if_fail (E_IS_GW_ITEM(new_item));
1339 g_return_if_fail (E_IS_GW_ITEM(old_item));
1341 for ( i = 0; i < G_N_ELEMENTS (mappings); i++) {
1342 element_type = mappings[i].element_type;
1343 if (element_type == ELEMENT_TYPE_SIMPLE) {
1344 if (mappings[i].field_id == E_CONTACT_ORG) {
1345 set_organization_changes_in_gw_item (new_item, old_item);
1349 new_value = e_gw_item_get_field_value (new_item, mappings[i].element_name);
1350 old_value = e_gw_item_get_field_value (old_item, mappings[i].element_name);
1351 if (new_value && old_value) {
1352 if (!g_str_equal (new_value, old_value))
1353 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_UPDATE, mappings[i].element_name, new_value);
1354 } else if (!new_value && old_value) {
1355 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, mappings[i].element_name, old_value);
1356 } else if (new_value && !old_value) {
1357 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, mappings[i].element_name, new_value);
1360 } else if (element_type == ELEMENT_TYPE_COMPLEX) {
1361 if (mappings[i].field_id != E_CONTACT_EMAIL)
1362 mappings[i].set_changes(new_item, old_item);
1368 e_book_backend_groupwise_modify_contact (EBookBackend *backend,
1374 EBookBackendGroupwise *egwb;
1381 char *new_org, *old_org;
1385 printf ("\ne_book_backend_groupwise_modify_contact...\n");
1386 egwb = E_BOOK_BACKEND_GROUPWISE (backend);
1388 switch (egwb->priv->mode) {
1390 case GNOME_Evolution_Addressbook_MODE_LOCAL :
1391 e_data_book_respond_modify(book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
1393 case GNOME_Evolution_Addressbook_MODE_REMOTE :
1395 if (egwb->priv->cnc == NULL) {
1396 e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_AuthenticationRequired, NULL);
1399 if (!egwb->priv->is_writable) {
1400 e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_PermissionDenied, NULL);
1403 contact = e_contact_new_from_vcard(vcard);
1404 new_item = e_gw_item_new_empty ();
1406 for (i = 0; i < G_N_ELEMENTS (mappings); i++) {
1407 element_type = mappings[i].element_type;
1408 if (element_type == ELEMENT_TYPE_SIMPLE) {
1409 value = e_contact_get(contact, mappings[i].field_id);
1410 if (value && *value)
1411 e_gw_item_set_field_value (new_item, mappings[i].element_name, value);
1412 } else if (element_type == ELEMENT_TYPE_COMPLEX) {
1413 if (mappings[i].field_id == E_CONTACT_CATEGORIES)
1414 set_categories_in_gw_item (new_item, contact, egwb);
1415 else if (mappings[i].field_id == E_CONTACT_EMAIL) {
1416 if (e_contact_get (contact, E_CONTACT_IS_LIST))
1417 set_members_in_gw_item (new_item, contact, egwb);
1420 mappings[i].set_value_in_gw_item (new_item, contact);
1424 id = e_contact_get (contact, E_CONTACT_UID);
1426 status = e_gw_connection_get_item (egwb->priv->cnc, egwb->priv->container_id, id, NULL, &old_item);
1428 if (old_item == NULL) {
1429 e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, NULL);
1433 if (status != E_GW_CONNECTION_STATUS_OK) {
1434 e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
1438 if (e_contact_get (contact, E_CONTACT_IS_LIST))
1439 set_member_changes (new_item, old_item, egwb);
1440 new_org = e_gw_item_get_field_value (new_item, "organization");
1441 old_org = e_gw_item_get_field_value (old_item, "organization");
1442 if (new_org && *new_org) {
1444 if ((old_org == NULL) || (old_org && strcmp (new_org, old_org)) != 0)
1445 set_organization_in_gw_item (new_item, contact, egwb);
1448 set_changes_in_gw_item (new_item, old_item);
1450 e_gw_item_set_item_type (new_item, e_gw_item_get_item_type (old_item));
1451 status = e_gw_connection_modify_item (egwb->priv->cnc, id, new_item);
1452 if (status == E_GW_CONNECTION_STATUS_OK) {
1453 e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_Success, contact);
1454 e_book_backend_db_cache_remove_contact (egwb->priv->file_db, id);
1455 e_book_backend_summary_remove_contact (egwb->priv->summary, id);
1456 e_book_backend_db_cache_add_contact (egwb->priv->file_db, contact);
1457 egwb->priv->file_db->sync(egwb->priv->file_db, 0);
1458 e_book_backend_summary_add_contact (egwb->priv->summary, contact);
1461 e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
1462 g_object_unref (new_item);
1463 g_object_ref (old_item);
1464 g_object_unref (contact);
1472 e_book_backend_groupwise_get_contact (EBookBackend *backend,
1477 EBookBackendGroupwise *gwb;
1484 printf ("\ne_book_backend_groupwise_get_contact...\n");
1486 gwb = E_BOOK_BACKEND_GROUPWISE (backend);
1488 switch (gwb->priv->mode) {
1490 case GNOME_Evolution_Addressbook_MODE_LOCAL :
1491 contact = e_book_backend_db_cache_get_contact (gwb->priv->file_db, id);
1492 vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
1494 e_data_book_respond_get_contact(book, opid, GNOME_Evolution_Addressbook_Success, vcard);
1496 g_object_unref (contact);
1499 e_data_book_respond_get_contact(book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");
1503 case GNOME_Evolution_Addressbook_MODE_REMOTE :
1504 if (gwb->priv->cnc == NULL) {
1505 e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
1508 status = e_gw_connection_get_item (gwb->priv->cnc, gwb->priv->container_id, id,
1509 "name email default members", &item);
1510 if (status == E_GW_CONNECTION_STATUS_OK) {
1512 contact = e_contact_new ();
1513 fill_contact_from_gw_item (contact, item, gwb->priv->categories_by_id);
1514 e_contact_set (contact, E_CONTACT_BOOK_URI, gwb->priv->original_uri);
1515 vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
1516 e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_Success, vcard);
1518 g_object_unref (contact);
1519 g_object_unref (item);
1523 e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_ContactNotFound, "");
1532 gboolean is_filter_valid;
1533 gboolean is_personal_book;
1534 int auto_completion;
1535 char *search_string;
1536 } EBookBackendGroupwiseSExpData;
1538 static ESExpResult *
1539 func_and(ESExp *f, int argc, ESExpResult **argv, void *data)
1543 EBookBackendGroupwiseSExpData *sexp_data;
1545 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1546 filter = E_GW_FILTER (sexp_data->filter);
1548 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_AND, argc);
1549 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1550 r->value.bool = FALSE;
1555 static ESExpResult *
1556 func_or(ESExp *f, int argc, ESExpResult **argv, void *data)
1560 EBookBackendGroupwiseSExpData *sexp_data;
1562 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1563 filter = E_GW_FILTER (sexp_data->filter);
1565 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, argc);
1566 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1567 r->value.bool = FALSE;
1572 static ESExpResult *
1573 func_not(ESExp *f, int argc, ESExpResult **argv, void *data)
1576 EBookBackendGroupwiseSExpData *sexp_data;
1578 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1579 sexp_data->is_filter_valid = FALSE;
1580 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1581 r->value.bool = FALSE;
1586 static ESExpResult *
1587 func_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
1591 EBookBackendGroupwiseSExpData *sexp_data;
1593 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1594 filter = E_GW_FILTER (sexp_data->filter);
1597 && argv[0]->type == ESEXP_RES_STRING
1598 && argv[1]->type == ESEXP_RES_STRING) {
1599 char *propname = argv[0]->value.string;
1600 char *str = argv[1]->value.string;
1601 char *gw_field_name;
1603 if (g_str_equal (propname, "x-evolution-any-field")) {
1604 if (!sexp_data->is_personal_book && str && strlen(str) == 0) {
1605 /* ignore the NULL query */
1606 sexp_data->is_filter_valid = FALSE;
1607 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1608 r->value.bool = FALSE;
1612 gw_field_name = NULL;
1613 if (g_str_equal (propname, "full_name"))
1614 gw_field_name = "fullName";
1615 else if (g_str_equal (propname, "email"))
1616 gw_field_name = "emailList/email";
1617 else if (g_str_equal (propname, "file_as") || g_str_equal (propname, "nickname"))
1618 gw_field_name = "name";
1620 if (gw_field_name) {
1621 if (g_str_equal (gw_field_name, "fullName")) {
1622 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_CONTAINS, "fullName/firstName", str);
1623 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_CONTAINS, "fullName/lastName", str);
1624 if (sexp_data->is_personal_book) {
1625 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_CONTAINS, "fullName/displayName", str);
1626 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 3);
1629 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 2);
1633 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_CONTAINS, gw_field_name, str);
1637 sexp_data->is_filter_valid = FALSE;
1641 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1642 r->value.bool = FALSE;
1647 static ESExpResult *
1648 func_is(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
1652 EBookBackendGroupwiseSExpData *sexp_data;
1654 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1655 filter = E_GW_FILTER (sexp_data->filter);
1658 && argv[0]->type == ESEXP_RES_STRING
1659 && argv[1]->type == ESEXP_RES_STRING) {
1660 char *propname = argv[0]->value.string;
1661 char *str = argv[1]->value.string;
1662 char *gw_field_name;
1664 gw_field_name = NULL;
1665 if (g_str_equal (propname, "full_name"))
1666 gw_field_name = "fullName";
1667 else if (g_str_equal (propname, "email"))
1668 gw_field_name = "emailList/email";
1669 else if (g_str_equal (propname, "file_as") || g_str_equal (propname, "nickname"))
1670 gw_field_name = "name";
1672 if (gw_field_name) {
1673 if (g_str_equal (gw_field_name, "fullName")) {
1674 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, "fullName/firstName", str);
1675 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, "fullName/lastName", str);
1676 if (sexp_data->is_personal_book) {
1677 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, "fullName/displayName", str);
1678 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 3);
1681 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 2);
1685 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, gw_field_name, str);
1689 sexp_data->is_filter_valid = FALSE;
1693 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1694 r->value.bool = FALSE;
1699 #define BEGINS_WITH_NAME (1 << 0)
1700 #define BEGINS_WITH_EMAIL (1 << 1)
1701 #define BEGINS_WITH_FILE_AS (1 << 2)
1702 #define BEGINS_WITH_NICK_NAME (1 << 3)
1703 #define AUTO_COMPLETION_QUERY 15
1705 static ESExpResult *
1706 func_beginswith(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
1710 EBookBackendGroupwiseSExpData *sexp_data;
1712 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1713 filter = E_GW_FILTER (sexp_data->filter);
1716 && argv[0]->type == ESEXP_RES_STRING
1717 && argv[1]->type == ESEXP_RES_STRING) {
1718 char *propname = argv[0]->value.string;
1719 char *str = argv[1]->value.string;
1720 char *gw_field_name;
1722 if (!sexp_data->is_personal_book && str && strlen(str) == 0) {
1723 /* ignore the NULL query */
1724 sexp_data->is_filter_valid = FALSE;
1725 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1726 r->value.bool = FALSE;
1730 gw_field_name = NULL;
1731 if (g_str_equal (propname, "full_name")) {
1732 gw_field_name = "fullName";
1733 sexp_data->auto_completion |= BEGINS_WITH_NAME;
1734 sexp_data->search_string = g_strdup (str);
1736 else if (g_str_equal (propname, "email")) {
1737 gw_field_name = "emailList/email";
1738 sexp_data->auto_completion |= BEGINS_WITH_EMAIL;
1740 else if (g_str_equal (propname, "file_as")) {
1741 gw_field_name = "name";
1742 sexp_data->auto_completion |= BEGINS_WITH_FILE_AS;
1743 } else if (g_str_equal (propname, "nickname")) {
1744 gw_field_name = "name";
1745 sexp_data->auto_completion |= BEGINS_WITH_NICK_NAME;
1748 if (gw_field_name) {
1750 if (g_str_equal (gw_field_name, "fullName")) {
1751 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_BEGINS, "fullName/firstName", str);
1752 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_BEGINS, "fullName/lastName", str);
1753 if (sexp_data->is_personal_book) {
1754 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_BEGINS, "fullName/displayName", str);
1755 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 3);
1758 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 2);
1762 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_BEGINS, gw_field_name, str);
1766 sexp_data->is_filter_valid = FALSE;
1770 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1771 r->value.bool = FALSE;
1776 static ESExpResult *
1777 func_endswith(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
1779 EBookBackendGroupwiseSExpData *sexp_data;
1782 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1783 sexp_data->is_filter_valid = FALSE;
1785 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1787 r->value.bool = FALSE;
1792 static ESExpResult *
1793 func_exists(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
1797 EBookBackendGroupwiseSExpData *sexp_data;
1799 sexp_data = (EBookBackendGroupwiseSExpData *) data;
1800 filter = E_GW_FILTER (sexp_data->filter);
1803 && argv[0]->type == ESEXP_RES_STRING) {
1804 char *propname = argv[0]->value.string;
1805 char *str = argv[1]->value.string;
1806 char *gw_field_name;
1808 gw_field_name = NULL;
1809 if (g_str_equal (propname, "full_name"))
1810 gw_field_name = "fullName";
1811 else if (g_str_equal (propname, "email"))
1812 gw_field_name = "emailList/email";
1813 else if (g_str_equal (propname, "file_as") || g_str_equal (propname, "nickname"))
1814 gw_field_name = "name";
1816 if (gw_field_name) {
1818 if (g_str_equal (gw_field_name, "fullName")) {
1819 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EXISTS, "fullName/firstName", str);
1820 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EXISTS, "fullName/lastName", str);
1821 if (sexp_data->is_personal_book) {
1822 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EXISTS, "fullName/displayName", str);
1823 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 3);
1826 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 2);
1830 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EXISTS, gw_field_name, str);
1834 sexp_data->is_filter_valid = FALSE;
1838 r = e_sexp_result_new(f, ESEXP_RES_BOOL);
1839 r->value.bool = FALSE;
1844 /* 'builtin' functions */
1845 static const struct {
1848 int type; /* set to 1 if a function can perform shortcut evaluation, or
1849 doesn't execute everything, 0 otherwise */
1851 { "and", func_and, 0 },
1852 { "or", func_or, 0 },
1853 { "not", func_not, 0 },
1854 { "contains", func_contains, 0 },
1855 { "is", func_is, 0 },
1856 { "beginswith", func_beginswith, 0 },
1857 { "endswith", func_endswith, 0 },
1858 { "exists", func_exists, 0 },
1862 e_book_backend_groupwise_build_gw_filter (EBookBackendGroupwise *ebgw, const char *query, gpointer is_auto_completion, char ** search_string)
1866 EBookBackendGroupwiseSExpData *sexp_data;
1870 sexp = e_sexp_new();
1871 filter = e_gw_filter_new ();
1873 sexp_data = g_new0 (EBookBackendGroupwiseSExpData, 1);
1874 sexp_data->filter = filter;
1875 sexp_data->is_filter_valid = TRUE;
1876 sexp_data->is_personal_book = e_book_backend_is_writable ( E_BOOK_BACKEND (ebgw));
1877 sexp_data->auto_completion = 0;
1878 sexp_data->search_string = NULL;
1880 for(i=0;i<sizeof(symbols)/sizeof(symbols[0]);i++) {
1881 if (symbols[i].type == 1) {
1882 e_sexp_add_ifunction(sexp, 0, symbols[i].name,
1883 (ESExpIFunc *)symbols[i].func, sexp_data);
1885 e_sexp_add_function(sexp, 0, symbols[i].name,
1886 symbols[i].func, sexp_data);
1890 e_sexp_input_text(sexp, query, strlen(query));
1892 r = e_sexp_eval(sexp);
1893 e_sexp_result_free(sexp, r);
1894 e_sexp_unref (sexp);
1896 if (sexp_data->is_filter_valid) {
1897 if (sexp_data->auto_completion == AUTO_COMPLETION_QUERY)
1898 *(gboolean *)is_auto_completion = TRUE;
1900 *search_string = sexp_data->search_string;
1905 g_object_unref (filter);
1912 e_book_backend_groupwise_get_contact_list (EBookBackend *backend,
1919 GList *gw_items, *contacts = NULL, *temp;
1921 EBookBackendGroupwise *egwb;
1922 gboolean match_needed;
1923 EBookBackendSExp *card_sexp = NULL;
1924 EGwFilter *filter = NULL;
1926 gboolean is_auto_completion;
1928 egwb = E_BOOK_BACKEND_GROUPWISE (backend);
1933 printf ("\ne_book_backend_groupwise_get_contact_list...\n");
1935 switch (egwb->priv->mode) {
1937 case GNOME_Evolution_Addressbook_MODE_LOCAL :
1939 if (!egwb->priv->file_db) {
1940 e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_RepositoryOffline, NULL);
1944 if (egwb->priv->is_summary_ready &&
1945 e_book_backend_summary_is_summary_query (egwb->priv->summary, query)) {
1947 ids = e_book_backend_summary_search (egwb->priv->summary, query);
1948 for (i = 0; i < ids->len; i ++) {
1949 char *uid = g_ptr_array_index (ids, i);
1952 e_book_backend_db_cache_get_contact (egwb->priv->file_db, uid);
1953 contacts = g_list_append (contacts, contact);
1955 g_ptr_array_free (ids, TRUE);
1958 contacts = e_book_backend_db_cache_get_contacts (egwb->priv->file_db, query);
1961 for (; contacts != NULL; contacts = g_list_next(contacts)) {
1962 vcard_list = g_list_append (vcard_list,
1963 e_vcard_to_string (E_VCARD (contacts->data),
1964 EVC_FORMAT_VCARD_30));
1965 g_object_unref (contacts->data);
1967 e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_Success,
1973 case GNOME_Evolution_Addressbook_MODE_REMOTE:
1975 if (egwb->priv->cnc == NULL) {
1976 e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_AuthenticationRequired, NULL);
1980 match_needed = TRUE;
1981 card_sexp = e_book_backend_sexp_new (query);
1983 e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_InvalidQuery,
1987 status = E_GW_CONNECTION_STATUS_OK;
1988 if (egwb->priv->is_cache_ready ) {
1989 if (egwb->priv->is_summary_ready &&
1990 e_book_backend_summary_is_summary_query (egwb->priv->summary, query)) {
1991 ids = e_book_backend_summary_search (egwb->priv->summary, query);
1993 if (!egwb->priv->is_writable) {
1995 for (i = 0; i < ids->len; i ++) {
1996 char *uid = g_ptr_array_index (ids, i);
1997 contact = e_book_backend_db_cache_get_contact (egwb->priv->file_db, uid);
1998 vcard_list = g_list_append (vcard_list,
1999 e_vcard_to_string (E_VCARD (contact),
2000 EVC_FORMAT_VCARD_30));
2001 g_object_unref (contact);
2003 g_ptr_array_free (ids, TRUE);
2008 ids = e_book_backend_db_cache_search (egwb->priv->file_db, query);
2012 status = e_gw_connection_get_items_from_ids (egwb->priv->cnc,
2013 egwb->priv->container_id,
2014 "name email default members",
2016 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
2017 status = e_gw_connection_get_items_from_ids (egwb->priv->cnc,
2018 egwb->priv->container_id,
2019 "name email default members",
2021 g_ptr_array_free (ids, TRUE);
2023 match_needed = FALSE;
2025 if (strcmp (query, "(contains \"x-evolution-any-field\" \"\")") != 0)
2026 filter = e_book_backend_groupwise_build_gw_filter (egwb,
2028 &is_auto_completion,
2031 match_needed = FALSE;
2032 status = e_gw_connection_get_items (egwb->priv->cnc,
2033 egwb->priv->container_id,
2034 "name email default members",
2036 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
2037 status = e_gw_connection_get_items (egwb->priv->cnc,
2038 egwb->priv->container_id,
2039 "name email default members",
2043 if (status != E_GW_CONNECTION_STATUS_OK) {
2044 e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_OtherError,
2048 for (; gw_items != NULL; gw_items = g_list_next(gw_items)) {
2049 contact = e_contact_new ();
2050 fill_contact_from_gw_item (contact, E_GW_ITEM (gw_items->data), egwb->priv->categories_by_id);
2051 e_contact_set (contact, E_CONTACT_BOOK_URI, egwb->priv->original_uri);
2052 if (match_needed && e_book_backend_sexp_match_contact (card_sexp, contact))
2053 vcard_list = g_list_append (vcard_list,
2054 e_vcard_to_string (E_VCARD (contact),
2055 EVC_FORMAT_VCARD_30));
2057 vcard_list = g_list_append (vcard_list,
2058 e_vcard_to_string (E_VCARD (contact),
2059 EVC_FORMAT_VCARD_30));
2060 g_object_unref (contact);
2061 g_object_unref (gw_items->data);
2064 g_list_free (gw_items);
2065 e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_Success,
2068 g_object_unref (filter);
2077 EBookBackendGroupwise *bg;
2080 } GroupwiseBackendSearchClosure;
2083 closure_destroy (GroupwiseBackendSearchClosure *closure)
2085 e_flag_free (closure->running);
2089 static GroupwiseBackendSearchClosure*
2090 init_closure (EDataBookView *book_view, EBookBackendGroupwise *bg)
2092 GroupwiseBackendSearchClosure *closure = g_new (GroupwiseBackendSearchClosure, 1);
2095 closure->thread = NULL;
2096 closure->running = e_flag_new ();
2098 g_object_set_data_full (G_OBJECT (book_view), "EBookBackendGroupwise.BookView::closure",
2099 closure, (GDestroyNotify)closure_destroy);
2104 static GroupwiseBackendSearchClosure*
2105 get_closure (EDataBookView *book_view)
2107 return g_object_get_data (G_OBJECT (book_view), "EBookBackendGroupwise.BookView::closure");
2111 get_contacts_from_cache (EBookBackendGroupwise *ebgw,
2114 EDataBookView *book_view,
2115 GroupwiseBackendSearchClosure *closure)
2120 printf ("\nread contacts from cache for the ids found in summary\n");
2121 for (i = 0; i < ids->len; i ++) {
2125 if (!e_flag_is_set (closure->running))
2128 uid = g_ptr_array_index (ids, i);
2129 contact = e_book_backend_db_cache_get_contact (ebgw->priv->file_db, uid);
2131 e_data_book_view_notify_update (book_view, contact);
2132 g_object_unref (contact);
2135 if (e_flag_is_set (closure->running))
2136 e_data_book_view_notify_complete (book_view,
2137 GNOME_Evolution_Addressbook_Success);
2141 book_view_thread (gpointer data)
2143 int status, count = 0;
2144 GList *gw_items, *temp_list, *contacts;
2146 EBookBackendGroupwise *gwb;
2147 const char *query = NULL;
2148 EGwFilter *filter = NULL;
2149 GPtrArray *ids = NULL;
2150 EDataBookView *book_view = data;
2151 GroupwiseBackendSearchClosure *closure = get_closure (book_view);
2153 gboolean is_auto_completion = FALSE;
2154 char *search_string = NULL;
2155 GTimeVal start, end;
2162 printf ("start book view for %s \n", gwb->priv->book_name);
2163 bonobo_object_ref (book_view);
2164 e_flag_set (closure->running);
2166 query = e_data_book_view_get_card_query (book_view);
2168 printf ("get view for query %s \n", query);
2169 switch (gwb->priv->mode) {
2171 case GNOME_Evolution_Addressbook_MODE_LOCAL :
2172 if (!gwb->priv->file_db) {
2173 e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success);
2177 if (gwb->priv->is_summary_ready &&
2178 e_book_backend_summary_is_summary_query (gwb->priv->summary, query)) {
2180 printf ("reading the uids from summary \n");
2181 ids = e_book_backend_summary_search (gwb->priv->summary, query);
2182 if (ids && ids->len > 0) {
2183 get_contacts_from_cache (gwb, query, ids, book_view, closure);
2184 g_ptr_array_free (ids, TRUE);
2186 bonobo_object_unref (book_view);
2190 /* fall back to cache */
2192 printf ("summary not found, reading the uids from cache\n");
2193 contacts = e_book_backend_db_cache_get_contacts (gwb->priv->file_db, query);
2194 temp_list = contacts;
2195 for (; contacts != NULL; contacts = g_list_next(contacts)) {
2196 if (!e_flag_is_set (closure->running)) {
2197 for (;contacts != NULL; contacts = g_list_next (contacts))
2198 g_object_unref (contacts->data);
2201 e_data_book_view_notify_update (book_view, E_CONTACT(contacts->data));
2202 g_object_unref (contacts->data);
2204 if (e_flag_is_set (closure->running))
2205 e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success);
2207 g_list_free (temp_list);
2208 bonobo_object_unref (book_view);
2211 case GNOME_Evolution_Addressbook_MODE_REMOTE :
2213 if (gwb->priv->cnc == NULL) {
2214 e_data_book_view_notify_complete (book_view,
2215 GNOME_Evolution_Addressbook_AuthenticationRequired);
2216 bonobo_object_unref (book_view);
2221 g_get_current_time(&start);
2223 filter = e_book_backend_groupwise_build_gw_filter (gwb, query, &is_auto_completion, &search_string);
2224 view = "name email default members";
2225 if (is_auto_completion)
2226 view = "name email";
2228 if (search_string) {
2229 /* groupwise server supports only name, rebuild the filter */
2230 filter = e_gw_filter_new ();
2231 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_BEGINS,
2232 "fullName/lastName", search_string);
2233 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_BEGINS,
2234 "fullName/firstName", search_string);
2235 e_gw_filter_group_conditions (filter, E_GW_FILTER_OP_OR, 2);
2236 g_free (search_string);
2239 if (!gwb->priv->is_writable && !filter) {
2240 e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success);
2241 bonobo_object_unref (book_view);
2245 status = E_GW_CONNECTION_STATUS_OK;
2247 /* Check if the data is found on summary */
2248 if (gwb->priv->is_summary_ready &&
2249 e_book_backend_summary_is_summary_query (gwb->priv->summary, query)) {
2251 printf("reading the uids from summary file\n");
2252 ids = e_book_backend_summary_search (gwb->priv->summary, query);
2256 * Search for contact in cache, if not found, read from server
2259 if (ids && ids->len > 0) {
2261 printf ("number of matches found in summary %d\n", ids->len);
2262 /* read from summary */
2263 if (gwb->priv->is_cache_ready && !gwb->priv->is_writable) {
2264 /* read from cache, only for system address book, as we refresh
2265 * only system address book, periodically.
2268 printf ("reading contacts from cache for the uids in summary \n");
2269 if (!is_auto_completion)
2270 e_data_book_view_notify_status_message (book_view,
2272 get_contacts_from_cache (gwb, query, ids, book_view, closure);
2273 g_ptr_array_free (ids, TRUE);
2274 bonobo_object_unref (book_view);
2276 g_get_current_time(&end);
2277 diff = end.tv_sec * 1000 + end.tv_usec/1000;
2278 diff -= start.tv_sec * 1000 + start.tv_usec/1000;
2279 printf("reading contacts from cache took %ld.%03ld seconds\n",
2280 diff/1000,diff%1000);
2285 /* read from server for the ids */
2286 /* either autocompletion or search query and cache not ready */
2288 printf ("reading contacts from server for the uids in summary \n");
2289 if (!is_auto_completion)
2290 e_data_book_view_notify_status_message (book_view,
2292 status = e_gw_connection_get_items_from_ids (gwb->priv->cnc,
2293 gwb->priv->container_id,
2294 view, ids, &gw_items);
2295 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
2296 status = e_gw_connection_get_items_from_ids (gwb->priv->cnc,
2297 gwb->priv->container_id,
2298 view, ids, &gw_items);
2299 if (enable_debug && status == E_GW_CONNECTION_STATUS_OK)
2300 printf ("read contacts from server \n");
2302 g_ptr_array_free (ids, TRUE);
2305 /* no summary information found, read from server */
2307 printf ("summary not found, reading the contacts from server\n");
2308 if (!is_auto_completion) {
2310 e_data_book_view_notify_status_message (book_view, _("Searching..."));
2312 e_data_book_view_notify_status_message (book_view, _("Loading..."));
2314 status = e_gw_connection_get_items (gwb->priv->cnc,
2315 gwb->priv->container_id,
2316 view, filter, &gw_items);
2317 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
2318 status = e_gw_connection_get_items (gwb->priv->cnc,
2319 gwb->priv->container_id,
2320 view, filter, &gw_items);
2323 if (status != E_GW_CONNECTION_STATUS_OK) {
2324 e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_OtherError);
2325 bonobo_object_unref (book_view);
2329 temp_list = gw_items;
2330 for (; gw_items != NULL; gw_items = g_list_next(gw_items)) {
2332 if (!e_flag_is_set (closure->running)) {
2333 for (;gw_items != NULL; gw_items = g_list_next (gw_items))
2334 g_object_unref (gw_items->data);
2339 contact = e_contact_new ();
2340 fill_contact_from_gw_item (contact,
2341 E_GW_ITEM (gw_items->data),
2342 gwb->priv->categories_by_id);
2343 e_contact_set (contact, E_CONTACT_BOOK_URI, gwb->priv->original_uri);
2344 if (e_contact_get_const (contact, E_CONTACT_UID))
2345 e_data_book_view_notify_update (book_view, contact);
2347 g_critical ("Id missing for item %s\n", (char *)e_contact_get_const (contact, E_CONTACT_FILE_AS));
2348 g_object_unref(contact);
2349 g_object_unref (gw_items->data);
2352 g_list_free (temp_list);
2353 if (e_flag_is_set (closure->running))
2354 e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success);
2356 g_object_unref (filter);
2357 bonobo_object_unref (book_view);
2360 g_get_current_time(&end);
2361 diff = end.tv_sec * 1000 + end.tv_usec/1000;
2362 diff -= start.tv_sec * 1000 + start.tv_usec/1000;
2363 printf("reading %d contacts from server took %ld.%03ld seconds\n",
2364 count, diff/1000,diff%1000);
2375 e_book_backend_groupwise_start_book_view (EBookBackend *backend,
2376 EDataBookView *book_view)
2378 GroupwiseBackendSearchClosure *closure = init_closure (book_view, E_BOOK_BACKEND_GROUPWISE (backend));
2381 printf ("\ne_book_backend_groupwise_start_book_view...\n");
2382 closure->thread = g_thread_create (book_view_thread, book_view, FALSE, NULL);
2383 e_flag_wait (closure->running);
2385 /* at this point we know the book view thread is actually running */
2389 e_book_backend_groupwise_stop_book_view (EBookBackend *backend,
2390 EDataBookView *book_view)
2392 GroupwiseBackendSearchClosure *closure = get_closure (book_view);
2395 printf ("\ne_book_backend_groupwise_stop_book_view...\n");
2396 e_flag_clear (closure->running);
2400 e_book_backend_groupwise_get_changes (EBookBackend *backend,
2403 const char *change_id )
2406 printf ("\ne_book_backend_groupwise_get_changes...\n");
2408 /* FIXME : provide implmentation */
2413 book_view_notify_status (EDataBookView *view, const char *status)
2417 e_data_book_view_notify_status_message (view, status);
2420 static EDataBookView *
2421 find_book_view (EBookBackendGroupwise *ebgw)
2423 EList *views = e_book_backend_get_book_views (E_BOOK_BACKEND (ebgw));
2425 EDataBookView *rv = NULL;
2430 iter = e_list_get_iterator (views);
2433 g_object_unref (views);
2437 if (e_iterator_is_valid (iter)) {
2438 /* just always use the first book view */
2439 EDataBookView *v = (EDataBookView*)e_iterator_get(iter);
2444 g_object_unref (iter);
2445 g_object_unref (views);
2451 get_sequence_from_cache (DB *db,
2452 gdouble *cache_first_sequence,
2453 gdouble *cache_last_sequence,
2454 gdouble *cache_last_po_rebuild_time)
2456 DBT uid_dbt, vcard_dbt;
2459 string_to_dbt ("firstSequence", &uid_dbt);
2460 memset (&vcard_dbt, 0, sizeof(vcard_dbt));
2461 vcard_dbt.flags = DB_DBT_MALLOC;
2463 db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
2464 if (db_error != 0) {
2465 g_warning ("db->get failed with %d", db_error);
2468 *cache_first_sequence = strtod (g_strdup (vcard_dbt.data), NULL);
2469 g_free (vcard_dbt.data);
2472 string_to_dbt ("lastSequence", &uid_dbt);
2473 memset (&vcard_dbt, 0, sizeof(vcard_dbt));
2474 vcard_dbt.flags = DB_DBT_MALLOC;
2476 db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
2477 if (db_error != 0) {
2478 g_warning ("db->get failed with %d", db_error);
2481 *cache_last_sequence = strtod (g_strdup (vcard_dbt.data), NULL);
2482 g_free (vcard_dbt.data);
2485 string_to_dbt ("lastTimePORebuild", &uid_dbt);
2486 memset (&vcard_dbt, 0, sizeof(vcard_dbt));
2487 vcard_dbt.flags = DB_DBT_MALLOC;
2489 db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
2490 if (db_error != 0) {
2491 g_warning ("db->get failed with %d", db_error);
2494 *cache_last_po_rebuild_time = strtod (g_strdup (vcard_dbt.data), NULL);
2495 g_free (vcard_dbt.data);
2499 printf("Read sequences from cache\n");
2500 printf("firstSequence:%lf, lastSequence:%lf, lastPoRebuildTime:%lf\n", *cache_first_sequence, *cache_last_sequence, *cache_last_po_rebuild_time);
2505 add_sequence_to_cache (DB *db,
2506 gdouble first_sequence,
2507 gdouble last_sequence,
2508 gdouble last_po_rebuild_time)
2511 DBT uid_dbt, vcard_dbt;
2515 printf("Adding sequences to cache\n");
2516 printf("firstSequence:%lf, lastSequence:%lf, lastPoRebuildTime:%lf\n", first_sequence, last_sequence, last_po_rebuild_time);
2519 string_to_dbt ("firstSequence",&uid_dbt );
2520 tmp = g_strdup_printf("%lf", first_sequence);
2521 string_to_dbt (tmp, &vcard_dbt);
2523 db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
2527 if (db_error != 0) {
2528 g_warning ("db->put failed with %d", db_error);
2531 string_to_dbt ("lastSequence",&uid_dbt );
2532 tmp = g_strdup_printf("%lf", last_sequence);
2533 string_to_dbt (tmp, &vcard_dbt);
2535 db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
2539 if (db_error != 0) {
2540 g_warning ("db->put failed with %d", db_error);
2543 string_to_dbt ("lastTimePORebuild",&uid_dbt );
2544 tmp = g_strdup_printf("%lf", last_po_rebuild_time);
2545 string_to_dbt (tmp, &vcard_dbt);
2547 db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
2551 if (db_error != 0) {
2552 g_warning ("db->put failed with %d", db_error);
2556 #define CURSOR_ITEM_LIMIT 100
2559 build_cache (EBookBackendGroupwise *ebgw)
2561 int status, contact_num = 0;
2562 GList *gw_items = NULL;
2564 EDataBookView *book_view;
2565 EBookBackendGroupwisePrivate *priv = ebgw->priv;
2568 status = e_gw_connection_get_items (ebgw->priv->cnc, ebgw->priv->container_id, "name email default members", NULL, &gw_items);
2569 if (status != E_GW_CONNECTION_STATUS_OK)
2573 for (; gw_items != NULL; gw_items = g_list_next(gw_items)) {
2575 contact = e_contact_new ();
2576 fill_contact_from_gw_item (contact, E_GW_ITEM (gw_items->data), ebgw->priv->categories_by_id);
2577 e_book_backend_cache_add_contact (ebgw->priv->cache, contact);
2579 status_msg = g_strdup_printf (_("Downloading contacts (%d)... "),
2581 book_view_notify_status (book_view, status_msg);
2582 g_free (status_msg);
2584 g_object_unref(contact);
2585 g_object_unref (gw_items->data);
2589 e_book_backend_cache_set_populated (priv->cache);
2590 priv->is_cache_ready=TRUE;
2592 g_list_free (gw_items);
2598 /*FIXME using cursors for address book seems to be crashing server
2599 till it gets fixed we will use get items. cursor implementation is below */
2602 build_cache (EBookBackendGroupwise *ebgw)
2605 GList *gw_items = NULL, *l;
2607 int cursor, contact_num = 0;
2608 gboolean done = FALSE;
2609 EBookBackendGroupwisePrivate *priv = ebgw->priv;
2610 const char *position = E_GW_CURSOR_POSITION_START;
2611 EDataBookView *book_view;
2612 GroupwiseBackendSearchClosure *closure;
2614 GTimeVal start, end;
2615 GTimeVal tstart, tend;
2622 g_get_current_time(&start);
2623 printf("Building the cache for %s \n", ebgw->priv->book_name);
2626 status = e_gw_connection_create_cursor (priv->cnc, priv->container_id,
2627 "name email default members", NULL, &cursor);
2628 if (status != E_GW_CONNECTION_STATUS_OK) {
2630 printf("No connection with the server \n");
2634 book_view = find_book_view (ebgw);
2636 closure = get_closure (book_view);
2637 bonobo_object_ref (book_view);
2639 e_flag_set (closure->running);
2645 g_get_current_time(&tstart);
2646 status = e_gw_connection_read_cursor (priv->cnc, priv->container_id,
2647 cursor, TRUE, CURSOR_ITEM_LIMIT,
2648 position, &gw_items);
2650 g_get_current_time(&tend);
2651 diff = tend.tv_sec * 1000 + tend.tv_usec/1000;
2652 diff -= tstart.tv_sec * 1000 + tstart.tv_usec/1000;
2653 printf("e_gw_connection_read_cursor took %ld.%03ld seconds for %d contacts\n", diff / 1000, diff % 1000, CURSOR_ITEM_LIMIT);
2656 for (l = gw_items; l != NULL; l = g_list_next (l)) {
2659 contact = e_contact_new ();
2660 fill_contact_from_gw_item (contact, E_GW_ITEM (l->data),
2661 ebgw->priv->categories_by_id);
2662 e_contact_set (contact, E_CONTACT_BOOK_URI, priv->original_uri);
2663 e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
2664 e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
2666 /* Since we get contacts incrementally, 100 at a time, we can not
2667 * calculate the percentage of cache update.
2668 * Also we should be using "percent" in notify_progress() instead of
2669 * forming the message like this.
2672 status_msg = g_strdup_printf (_("Downloading contacts (%d)... "),
2674 book_view_notify_status (book_view, status_msg);
2675 g_free (status_msg);
2678 g_object_unref(contact);
2679 g_object_unref (l->data);
2683 e_book_backend_db_cache_set_populated (ebgw->priv->file_db);
2685 priv->is_cache_ready=TRUE;
2686 priv->is_summary_ready = TRUE;
2689 g_list_free (gw_items);
2691 position = E_GW_CURSOR_POSITION_CURRENT;
2694 ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
2697 e_data_book_view_notify_complete (book_view,
2698 GNOME_Evolution_Addressbook_Success);
2699 bonobo_object_unref (book_view);
2702 e_gw_connection_destroy_cursor (priv->cnc, priv->container_id, cursor);
2705 g_get_current_time(&end);
2706 diff = end.tv_sec * 1000 + end.tv_usec/1000;
2707 diff -= start.tv_sec * 1000 + start.tv_usec/1000;
2708 printf("completed building cache for %s in %ld.%03ld seconds for %d contacts\n",
2709 priv->book_name, diff / 1000, diff % 1000, contact_num);
2715 build_summary (EBookBackendGroupwise *ebgw)
2717 gchar *query_string;
2718 GList *contacts, *temp_list = NULL;
2719 GTimeVal start, end;
2723 g_get_current_time(&start);
2724 printf ("summary file not found or not up-to-date, building summary for %s\n",
2725 ebgw->priv->book_name);
2728 /* build summary from cache */
2729 query_string = g_strdup_printf ("(or (beginswith \"file_as\" \"\") "
2730 " (beginswith \"full_name\" \"\") "
2731 " (beginswith \"email\" \"\") "
2732 " (beginswith \"nickname\" \"\"))");
2733 contacts = e_book_backend_db_cache_get_contacts (ebgw->priv->file_db, query_string);
2734 g_free (query_string);
2735 temp_list = contacts;
2736 for (; contacts != NULL; contacts = g_list_next(contacts)) {
2737 e_book_backend_summary_add_contact (ebgw->priv->summary, contacts->data);
2738 g_object_unref (contacts->data);
2741 g_list_free (temp_list);
2742 ebgw->priv->is_summary_ready = TRUE;
2745 g_get_current_time(&end);
2746 diff = end.tv_sec * 1000 + end.tv_usec/1000;
2747 diff -= start.tv_sec * 1000 + start.tv_usec/1000;
2748 printf("building summary for %s took %ld.%03ld seconds \n",
2749 ebgw->priv->book_name, diff / 1000, diff % 1000);
2754 update_cache (EBookBackendGroupwise *ebgw)
2756 int status, contact_num = 0;
2757 GList *gw_items = NULL;
2761 char cache_time_string[25], *status_msg;
2762 const struct tm *tm;
2764 char *cache_file_name;
2765 EDataBookView *book_view;
2766 GroupwiseBackendSearchClosure *closure;
2767 GTimeVal start, end;
2773 g_mutex_lock (ebgw->priv->update_cache_mutex);
2776 g_get_current_time(&start);
2777 printf("updating cache for %s\n", ebgw->priv->book_name);
2780 book_view = find_book_view (ebgw);
2782 closure = get_closure (book_view);
2783 bonobo_object_ref (book_view);
2785 e_flag_set (closure->running);
2788 cache_file_name = e_book_backend_db_cache_get_filename(ebgw->priv->file_db);
2789 g_stat (cache_file_name, &buf);
2790 g_free (cache_file_name);
2791 mod_time = buf.st_mtime;
2792 tm = gmtime (&mod_time);
2793 strftime (cache_time_string, 100, "%Y-%m-%dT%H:%M:%SZ", tm);
2795 if (e_book_backend_summary_load (ebgw->priv->summary) == FALSE ||
2796 e_book_backend_summary_is_up_to_date (ebgw->priv->summary, mod_time) == FALSE) {
2798 build_summary (ebgw);
2801 filter = e_gw_filter_new ();
2802 e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_GREATERTHAN,
2803 "modified", cache_time_string);
2804 status = e_gw_connection_get_items (ebgw->priv->cnc, ebgw->priv->container_id,
2805 "name email default members", filter, &gw_items);
2806 if (status != E_GW_CONNECTION_STATUS_OK) {
2808 bonobo_object_unref (book_view);
2810 printf("No connection with the server \n");
2811 g_mutex_unlock (ebgw->priv->update_cache_mutex);
2815 for (; gw_items != NULL; gw_items = g_list_next(gw_items)) {
2818 contact = e_contact_new ();
2819 fill_contact_from_gw_item (contact, E_GW_ITEM (gw_items->data),
2820 ebgw->priv->categories_by_id);
2822 e_contact_set (contact, E_CONTACT_BOOK_URI, ebgw->priv->original_uri);
2823 id = e_contact_get_const (contact, E_CONTACT_UID);
2827 status_msg = g_strdup_printf (_("Updating contacts cache (%d)... "),
2829 book_view_notify_status (book_view, status_msg);
2830 g_free (status_msg);
2833 if (e_book_backend_db_cache_check_contact (ebgw->priv->file_db, id)) {
2834 e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
2835 e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
2836 e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
2838 e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
2839 e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
2842 g_object_unref(contact);
2843 g_object_unref (gw_items->data);
2846 ebgw->priv->is_cache_ready = TRUE;
2847 ebgw->priv->is_summary_ready = TRUE;
2849 ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
2852 e_data_book_view_notify_complete (book_view,
2853 GNOME_Evolution_Addressbook_Success);
2854 bonobo_object_unref (book_view);
2856 g_object_unref (filter);
2857 g_list_free (gw_items);
2860 g_get_current_time(&end);
2861 diff = end.tv_sec * 1000 + end.tv_usec/1000;
2862 diff -= start.tv_sec * 1000 + start.tv_usec/1000;
2863 printf("updating the cache for %s complated in %ld.%03ld seconds for %d contacts\n",
2864 ebgw->priv->book_name, diff / 1000, diff % 1000, contact_num);
2866 g_mutex_unlock (ebgw->priv->update_cache_mutex);
2871 update_address_book_deltas (EBookBackendGroupwise *ebgw)
2873 int status, contact_num = 0;
2874 gdouble server_first_sequence = -1, server_last_sequence = -1, server_last_po_rebuild_time = -1;
2875 gdouble cache_first_sequence = -1, cache_last_sequence = -1, cache_last_po_rebuild_time = -1;
2876 char *count, *sequence, *status_msg;
2877 gboolean sync_required = FALSE;
2878 GList *add_list = NULL, *delete_list = NULL;
2880 EDataBookView *book_view;
2881 GroupwiseBackendSearchClosure *closure;
2883 EBookBackendGroupwisePrivate *priv;
2885 GTimeVal start, end;
2887 char *cache_file_name;
2897 g_mutex_lock (priv->update_mutex);
2900 printf("\nupdating GroupWise system address book cache \n");
2902 /* builds or updates the cache for system address book */
2903 status = e_gw_connection_get_items_delta_info (priv->cnc,
2904 ebgw->priv->container_id,
2905 &server_first_sequence,
2906 &server_last_sequence,
2907 &server_last_po_rebuild_time);
2908 if (status != E_GW_CONNECTION_STATUS_OK) {
2910 printf("No connection with the server \n");
2911 g_mutex_unlock (priv->update_mutex);
2915 /* Check whether the sequence has been reset or not */
2916 if (server_first_sequence <= 0 || server_last_sequence <= 0) {
2917 /* build the cache */
2919 printf ("sequence is reset, rebuilding cache...\n");
2921 add_sequence_to_cache (priv->file_db, server_first_sequence,
2922 server_last_sequence, server_last_po_rebuild_time);
2923 ebgw->priv->file_db->sync (ebgw->priv->file_db, 0);
2924 g_mutex_unlock (priv->update_mutex);
2928 /* Read the last sequence and last poa rebuild time from cache */
2929 get_sequence_from_cache(priv->file_db, &cache_first_sequence, &cache_last_sequence, &cache_last_po_rebuild_time);
2931 /* check whether the all the sequences are available and also whether the PO is rebuilt */
2932 if (server_first_sequence > cache_last_sequence || cache_last_sequence == -1 ||
2933 server_last_po_rebuild_time != cache_last_po_rebuild_time) {
2934 /* build the cache again and update the cache with the sequence information */
2936 printf ("either the sequences missing or PO is rebuilt...rebuilding the cache\n");
2938 add_sequence_to_cache (priv->file_db, server_first_sequence,
2939 server_last_sequence, server_last_po_rebuild_time);
2940 ebgw->priv->file_db->sync (ebgw->priv->file_db, 0);
2941 g_mutex_unlock (priv->update_mutex);
2946 g_get_current_time(&start);
2948 book_view = find_book_view (ebgw);
2950 closure = get_closure (book_view);
2951 bonobo_object_ref (book_view);
2953 e_flag_set (closure->running);
2956 /* update the cache */
2957 sequence = g_strdup_printf ("%lf", cache_last_sequence +1);
2958 count = g_strdup_printf ("%d", CURSOR_ITEM_LIMIT);
2960 /* load summary file */
2961 cache_file_name = e_book_backend_db_cache_get_filename(ebgw->priv->file_db);
2962 g_stat (cache_file_name, &buf);
2963 g_free (cache_file_name);
2964 mod_time = buf.st_mtime;
2965 if (e_book_backend_summary_load (ebgw->priv->summary) == FALSE ||
2966 e_book_backend_summary_is_up_to_date (ebgw->priv->summary, mod_time) == FALSE) {
2968 build_summary (ebgw);
2971 if (cache_last_sequence != server_last_sequence) {
2974 printf("cache_last_sequence:%lf, server_last_sequence:%lf\n", cache_last_sequence, server_last_sequence);
2975 printf("Calling get_items_delta\n");
2977 e_gw_connection_get_items_delta (priv->cnc,
2978 ebgw->priv->container_id,
2979 "name email sync", count,
2981 &add_list, &delete_list);
2983 if (add_list == NULL && delete_list == NULL) {
2985 printf("sequence differs but no changes found !!!\n");
2986 add_sequence_to_cache (priv->file_db, server_first_sequence,
2987 server_last_sequence, server_last_po_rebuild_time);
2988 g_mutex_unlock (priv->update_mutex);
2993 sync_required = TRUE;
2995 printf("add_list size:%d\n", g_list_length(add_list));
2996 printf("delete_list size:%d\n", g_list_length(delete_list));
2999 for (; delete_list != NULL; delete_list = g_list_next(delete_list)) {
3002 /* deleted from the server */
3003 contact = e_contact_new ();
3004 fill_contact_from_gw_item (contact,
3005 E_GW_ITEM (delete_list->data),
3006 ebgw->priv->categories_by_id);
3008 printf("contact email:%s, contact name:%s\n", (char *) e_contact_get(contact, E_CONTACT_EMAIL_1), (char *) e_contact_get(contact, E_CONTACT_GIVEN_NAME));
3009 e_contact_set (contact,
3011 priv->original_uri);
3012 id = e_contact_get_const (contact, E_CONTACT_UID);
3014 if (e_book_backend_db_cache_check_contact (ebgw->priv->file_db, id)) {
3018 status_msg = g_strdup_printf (_("Updating contacts cache (%d)... "),
3020 book_view_notify_status (book_view, status_msg);
3021 g_free (status_msg);
3023 e_book_backend_db_cache_remove_contact (ebgw->priv->file_db, id);
3024 e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
3026 g_object_unref(contact);
3027 g_object_unref (delete_list->data);
3030 for (; add_list != NULL; add_list = g_list_next(add_list)) {
3033 /* newly added to server */
3034 contact = e_contact_new ();
3035 fill_contact_from_gw_item (contact,
3036 E_GW_ITEM (add_list->data),
3037 ebgw->priv->categories_by_id);
3039 /* When a distribution list is modified the server sends me a delete and add response.
3040 But it doesnt send me the members, so i have to explicitly request the server for the members of the distribution list */
3042 if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
3044 printf ("Contact List modified fetching the members of the contact list\n");
3046 status = e_gw_connection_get_item (ebgw->priv->cnc, ebgw->priv->container_id, e_contact_get (contact, E_CONTACT_UID), "name email default members", &item);
3047 g_object_unref (contact);
3048 contact = e_contact_new ();
3049 fill_contact_from_gw_item (contact, item, ebgw->priv->categories_by_id);
3050 g_object_unref (item);
3054 printf("contact email:%s, contact name:%s\n", (char *)e_contact_get(contact, E_CONTACT_EMAIL_1),(char *) e_contact_get(contact, E_CONTACT_GIVEN_NAME));
3055 e_contact_set (contact,
3057 priv->original_uri);
3058 id = e_contact_get_const (contact, E_CONTACT_UID);
3062 status_msg = g_strdup_printf (_("Updating contacts cache (%d)... "),
3064 book_view_notify_status (book_view, status_msg);
3065 g_free (status_msg);
3067 if (e_book_backend_db_cache_check_contact (ebgw->priv->file_db, id)) {
3069 printf("contact already there\n");
3070 e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
3071 e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
3072 e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
3075 printf("contact not there\n");
3076 e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
3077 e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
3080 g_object_unref(contact);
3081 g_object_unref (add_list->data);
3083 cache_last_sequence += contact_num;
3085 /* cache is updated, now adding the sequence information to the cache */
3087 add_sequence_to_cache (priv->file_db, server_first_sequence,
3088 server_last_sequence, server_last_po_rebuild_time);
3090 g_list_free (add_list);
3091 g_list_free (delete_list);
3096 ebgw->priv->is_cache_ready = TRUE;
3097 ebgw->priv->is_summary_ready = TRUE;
3100 ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
3104 e_data_book_view_notify_complete (book_view,
3105 GNOME_Evolution_Addressbook_Success);
3106 bonobo_object_unref (book_view);
3110 g_get_current_time(&end);
3111 diff = end.tv_sec * 1000 + end.tv_usec/1000;
3112 diff -= start.tv_sec * 1000 + start.tv_usec/1000;
3113 printf("updating GroupWise system address book cache took %ld.%03ld seconds for %d changes\n",
3114 diff / 1000, diff % 1000, contact_num);
3116 g_mutex_unlock(priv->update_mutex);
3122 update_address_book_cache (gpointer ebgw)
3125 GError *error = NULL;
3131 printf("GroupWise system addressbook cache time out, updating.. \n");
3133 thread = g_thread_create ((GThreadFunc) update_address_book_deltas, ebgw, FALSE, NULL);
3135 g_warning (G_STRLOC ": %s", error->message);
3136 g_error_free (error);
3143 #define CACHE_REFRESH_INTERVAL 600000
3145 e_book_backend_groupwise_authenticate_user (EBookBackend *backend,
3150 const char *auth_method)
3152 EBookBackendGroupwise *ebgw;
3153 EBookBackendGroupwisePrivate *priv;
3157 gboolean is_writable;
3158 const char *cache_refresh_interval_set;
3159 int cache_refresh_interval = CACHE_REFRESH_INTERVAL;
3161 ebgw = E_BOOK_BACKEND_GROUPWISE (backend);
3165 printf ("authenticate user ............\n");
3167 printf("book_name:%s\n", priv->book_name);
3171 switch (ebgw->priv->mode) {
3172 case GNOME_Evolution_Addressbook_MODE_LOCAL:
3173 /* load summary file for offline use */
3174 g_mkdir_with_parents (g_path_get_dirname (priv->summary_file_name), 0700);
3175 priv->summary = e_book_backend_summary_new (priv->summary_file_name,
3176 SUMMARY_FLUSH_TIMEOUT);
3177 e_book_backend_summary_load (priv->summary);
3179 e_book_backend_notify_writable (backend, FALSE);
3180 e_book_backend_notify_connection_status (backend, FALSE);
3181 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success);
3184 case GNOME_Evolution_Addressbook_MODE_REMOTE:
3186 if (priv->cnc) { /*we have already authenticated to server */
3187 printf("already authenticated\n");
3188 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success);
3192 priv->cnc = e_gw_connection_new (priv->uri, user, passwd);
3193 if (!E_IS_GW_CONNECTION(priv->cnc) && priv->use_ssl && g_str_equal (priv->use_ssl, "when-possible")) {
3194 http_uri = g_strconcat ("http://", priv->uri + 8, NULL);
3195 priv->cnc = e_gw_connection_new (http_uri, user, passwd);
3198 if (!E_IS_GW_CONNECTION(priv->cnc)) {
3199 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_AuthenticationFailed);
3204 is_writable = FALSE;
3205 status = e_gw_connection_get_address_book_id (priv->cnc, priv->book_name, &id, &is_writable);
3206 if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
3207 status = e_gw_connection_get_address_book_id (priv->cnc, priv->book_name, &id, &is_writable);
3208 if (status == E_GW_CONNECTION_STATUS_OK) {
3209 if ( (id == NULL) && !priv->only_if_exists ) {
3210 status = e_gw_connection_create_book (priv->cnc, priv->book_name, &id);
3212 if (status != E_GW_CONNECTION_STATUS_OK ) {
3213 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_OtherError);
3219 priv->container_id = g_strdup (id);
3221 e_book_backend_set_is_writable (backend, is_writable);
3222 e_book_backend_notify_writable (backend, is_writable);
3223 e_book_backend_notify_connection_status (backend, TRUE);
3224 priv->is_writable = is_writable;
3225 e_gw_connection_get_categories (priv->cnc, &priv->categories_by_id, &priv->categories_by_name);
3226 if (!e_gw_connection_get_version(priv->cnc))
3227 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_InvalidServerVersion);
3229 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success);
3231 e_book_backend_set_is_loaded (backend, FALSE);
3232 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_NoSuchBook);
3235 /* initialize summary file */
3236 tmpfile = g_path_get_dirname (priv->summary_file_name);
3237 g_mkdir_with_parents (tmpfile, 0700);
3239 priv->summary = e_book_backend_summary_new (priv->summary_file_name,
3240 SUMMARY_FLUSH_TIMEOUT);
3242 if (!ebgw->priv->file_db) {
3243 e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_OtherError);
3246 if (e_book_backend_db_cache_is_populated (ebgw->priv->file_db)) {
3248 printf("cache is populated\n");
3249 if (priv->is_writable){
3251 printf("is writable\n");
3252 printf("creating update_cache thread\n");
3254 g_thread_create ((GThreadFunc) update_cache, ebgw, FALSE, NULL);
3256 else if (priv->marked_for_offline) {
3259 printf("marked for offline\n");
3261 printf("creating update_address_book_deltas thread\n");
3263 t = g_thread_create ((GThreadFunc) update_address_book_deltas, ebgw, TRUE, NULL);
3265 /* spawn a thread to update the system address book cache
3266 * at given intervals
3268 cache_refresh_interval_set = g_getenv ("BOOK_CACHE_REFRESH_INTERVAL");
3269 if (cache_refresh_interval_set) {
3270 cache_refresh_interval = g_ascii_strtod (cache_refresh_interval_set,
3271 NULL); /* use this */
3272 cache_refresh_interval *= (60*1000);
3275 /* set the cache refresh time */
3278 printf ("creating cache refresh thread for GW system book \n");
3279 priv->cache_timeout = g_timeout_add (cache_refresh_interval,
3280 (GSourceFunc) update_address_book_cache,
3284 else if (priv->is_writable) { /* for personal books we always cache */
3285 /* Personal address book and frequent contacts */
3287 printf("else if is _writable");
3288 printf("build_cahe thread");
3290 g_thread_create ((GThreadFunc) build_cache, ebgw, FALSE, NULL);
3292 else if(priv->marked_for_offline) {
3295 printf("else if marked_for_offline\n");
3296 /* System address book */
3297 /* cache is not populated and book is not writable and marked for offline usage */
3299 printf("creating update_address_book_deltas thread\n");
3300 t = g_thread_create ((GThreadFunc) update_address_book_deltas, ebgw, TRUE, NULL);
3302 /* set the cache refresh time */
3304 printf ("creating cache refresh thread for GW system book \n");
3305 priv->cache_timeout = g_timeout_add (cache_refresh_interval,
3306 (GSourceFunc) update_address_book_cache,
3316 e_book_backend_groupwise_get_required_fields (EBookBackend *backend,
3320 GList *fields = NULL;
3323 printf ("\ne_book_backend_groupwise_get_required_fields...\n");
3325 fields = g_list_append (fields, (char *)e_contact_field_name (E_CONTACT_FILE_AS));
3326 e_data_book_respond_get_supported_fields (book, opid,
3327 GNOME_Evolution_Addressbook_Success,
3329 g_list_free (fields);
3334 e_book_backend_groupwise_get_supported_fields (EBookBackend *backend,
3338 GList *fields = NULL;
3342 printf ("\ne_book_backend_groupwise_get_supported_fields...\n");
3344 for (i = 0; i < G_N_ELEMENTS (mappings) ; i ++)
3345 fields = g_list_append (fields, g_strdup (e_contact_field_name (mappings[i].field_id)));
3346 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_2)));
3347 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_3)));
3348 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_ICQ)));
3349 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_YAHOO)));
3350 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_GADUGADU)));
3351 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_MSN)));
3352 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_JABBER)));
3353 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_GROUPWISE)));
3354 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_WORK)));
3355 e_data_book_respond_get_supported_fields (book, opid,
3356 GNOME_Evolution_Addressbook_Success,
3358 g_list_free (fields);
3361 static GNOME_Evolution_Addressbook_CallStatus
3362 e_book_backend_groupwise_cancel_operation (EBookBackend *backend, EDataBook *book)
3365 printf ("\ne_book_backend_groupwise_cancel_operation...\n");
3366 return GNOME_Evolution_Addressbook_CouldNotCancel;
3370 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
3371 file_errcall (const DB_ENV *env, const char *buf1, const char *buf2)
3373 file_errcall (const char *buf1, char *buf2)
3376 g_warning ("libdb error: %s", buf2);
3379 static GNOME_Evolution_Addressbook_CallStatus
3380 e_book_backend_groupwise_load_source (EBookBackend *backend,
3382 gboolean only_if_exists)
3384 EBookBackendGroupwise *ebgw;
3385 EBookBackendGroupwisePrivate *priv;
3386 char *dirname, *filename, *tmp;
3396 const char *use_ssl;
3397 const char *offline;
3401 printf("\ne_book_backend_groupwise_load_source.. \n");
3402 ebgw = E_BOOK_BACKEND_GROUPWISE (backend);
3404 g_object_ref (source);
3406 offline = e_source_get_property (source, "offline_sync");
3407 if (offline && g_str_equal (offline, "1"))
3408 priv->marked_for_offline = TRUE;
3410 if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL && !priv->marked_for_offline ) {
3411 return GNOME_Evolution_Addressbook_OfflineUnavailable;
3414 uri = e_source_get_uri (source);
3415 priv->original_uri = g_strdup (uri);
3417 return GNOME_Evolution_Addressbook_OtherError;
3419 tokens = g_strsplit (uri, ";", 2);
3422 uri = g_strdup(tokens[0]);
3423 book_name = g_strdup (tokens[1]);
3424 if(book_name == NULL)
3425 return GNOME_Evolution_Addressbook_OtherError;
3426 g_strfreev (tokens);
3427 parsed_uri = e_uri_new (uri);
3428 port = e_source_get_property (source, "port");
3431 use_ssl = e_source_get_property (source, "use_ssl");
3432 if (use_ssl && !g_str_equal (use_ssl, "never"))
3433 priv->uri = g_strconcat ("https://", parsed_uri->host,":", port, "/soap", NULL );
3435 priv->uri = g_strconcat ("http://", parsed_uri->host,":", port, "/soap", NULL );
3436 priv->use_ssl = g_strdup (use_ssl);
3437 priv->only_if_exists = only_if_exists;
3439 priv->book_name = book_name;
3440 e_book_backend_set_is_loaded (E_BOOK_BACKEND (backend), TRUE);
3441 e_book_backend_set_is_writable (E_BOOK_BACKEND(backend), FALSE);
3442 if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL) {
3443 e_book_backend_notify_writable (backend, FALSE);
3444 e_book_backend_notify_connection_status (backend, FALSE);
3447 e_book_backend_notify_connection_status (backend, TRUE);
3450 for (i = 0; i < strlen (uri); i++) {
3458 if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL)
3459 if (!e_book_backend_db_cache_exists (priv->original_uri)) {
3461 e_uri_free (parsed_uri);
3462 return GNOME_Evolution_Addressbook_OfflineUnavailable;
3465 g_free (priv->summary_file_name);
3466 tmp = g_build_filename (g_get_home_dir(), ".evolution/addressbook" , uri, priv->book_name, NULL);
3467 priv->summary_file_name = g_strconcat (tmp, ".summary", NULL);
3470 dirname = g_build_filename (g_get_home_dir(), ".evolution/cache/addressbook", uri, priv->book_name, NULL);
3471 filename = g_build_filename (dirname, "cache.db", NULL);
3473 db_error = e_db3_utils_maybe_recover (filename);
3475 g_warning ("db recovery failed with %d", db_error);
3478 return GNOME_Evolution_Addressbook_OtherError;
3481 g_static_mutex_lock(&global_env_lock);
3482 if (global_env.ref_count > 0) {
3483 env = global_env.env;
3484 global_env.ref_count++;
3487 db_error = db_env_create (&env, 0);
3488 if (db_error != 0) {
3489 g_warning ("db_env_create failed with %d", db_error);
3490 g_static_mutex_unlock (&global_env_lock);
3493 return GNOME_Evolution_Addressbook_OtherError;
3496 db_error = env->open (env, NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_THREAD, 0);
3497 if (db_error != 0) {
3499 g_warning ("db_env_open failed with %d", db_error);
3500 g_static_mutex_unlock(&global_env_lock);
3503 return GNOME_Evolution_Addressbook_OtherError;
3506 env->set_errcall (env, file_errcall);
3508 global_env.env = env;
3509 global_env.ref_count = 1;
3511 g_static_mutex_unlock(&global_env_lock);
3513 ebgw->priv->env = env;
3515 db_error = db_create (&db, env, 0);
3516 if (db_error != 0) {
3517 g_warning ("db_create failed with %d", db_error);
3520 return GNOME_Evolution_Addressbook_OtherError;
3523 db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_THREAD, 0666);
3525 if (db_error == DB_OLD_VERSION) {
3526 db_error = e_db3_utils_upgrade_format (filename);
3528 if (db_error != 0) {
3529 g_warning ("db format upgrade failed with %d", db_error);
3532 return GNOME_Evolution_Addressbook_OtherError;
3535 db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_THREAD, 0666);
3538 ebgw->priv->file_db = db;
3540 if (db_error != 0) {
3543 /* the databade didn't exist, so we create the
3544 directory then the .db */
3545 rv = g_mkdir_with_parents (dirname, 0777);
3546 if (rv == -1 && errno != EEXIST) {
3547 g_warning ("failed to make directory %s: %s", dirname, strerror (errno));
3550 if (errno == EACCES || errno == EPERM)
3551 return GNOME_Evolution_Addressbook_PermissionDenied;
3553 return GNOME_Evolution_Addressbook_OtherError;
3556 db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_CREATE | DB_THREAD, 0666);
3557 if (db_error != 0) {
3558 g_warning ("db->open (...DB_CREATE...) failed with %d", db_error);
3563 ebgw->priv->file_db = db;
3565 if (db_error != 0 || ebgw->priv->file_db == NULL) {
3566 ebgw->priv->file_db = NULL;
3569 return GNOME_Evolution_Addressbook_OtherError;
3572 e_book_backend_db_cache_set_filename (ebgw->priv->file_db, filename);
3576 e_uri_free (parsed_uri);
3578 /*if (enable_debug) {
3579 printf ("summary file name = %s\ncache file name = %s \n",
3580 priv->summary_file_name, e_file_cache_get_filename (E_FILE_CACHE(priv->cache)));
3583 return GNOME_Evolution_Addressbook_Success;
3587 e_book_backend_groupwise_remove (EBookBackend *backend,
3591 EBookBackendGroupwise *ebgw;
3595 printf ("\ne_book_backend_groupwise_remove...\n");
3596 ebgw = E_BOOK_BACKEND_GROUPWISE (backend);
3597 if (ebgw->priv->cnc == NULL) {
3598 e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_AuthenticationRequired);
3601 if (!ebgw->priv->is_writable) {
3602 e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_PermissionDenied);
3605 status = e_gw_connection_remove_item (ebgw->priv->cnc, NULL, ebgw->priv->container_id);
3606 if (status == E_GW_CONNECTION_STATUS_OK)
3607 e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_Success);
3609 e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_OtherError);
3610 g_unlink (e_book_backend_db_cache_get_filename(ebgw->priv->file_db));
3614 e_book_backend_groupwise_get_static_capabilities (EBookBackend *backend)
3616 EBookBackendGroupwise *ebgw;
3619 printf ("\ne_book_backend_groupwise_get_static_capabilities...\n");
3621 ebgw = E_BOOK_BACKEND_GROUPWISE (backend);
3623 /* do-initialy-query is enabled for system address book also, so that we get the
3624 * book_view, which is needed for displaying cache update progress.
3625 * and null query is handled for system address book.
3627 return g_strdup ("net,bulk-removes,do-initial-query,contact-lists");
3631 e_book_backend_groupwise_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid)
3633 GList *auth_methods = NULL;
3637 printf ("\ne_book_backend_groupwise_get_supported_auth_methods...\n");
3638 auth_method = g_strdup_printf ("plain/password");
3639 auth_methods = g_list_append (auth_methods, auth_method);
3640 e_data_book_respond_get_supported_auth_methods (book,
3642 GNOME_Evolution_Addressbook_Success,
3644 g_free (auth_method);
3645 g_list_free (auth_methods);
3649 e_book_backend_groupwise_set_mode (EBookBackend *backend, int mode)
3651 EBookBackendGroupwise *bg;
3654 printf ("\ne_book_backend_groupwise_set_mode...\n");
3655 bg = E_BOOK_BACKEND_GROUPWISE (backend);
3656 bg->priv->mode = mode;
3657 if (e_book_backend_is_loaded (backend)) {
3658 if (mode == GNOME_Evolution_Addressbook_MODE_LOCAL) {
3659 e_book_backend_notify_writable (backend, FALSE);
3660 e_book_backend_notify_connection_status (backend, FALSE);
3661 if (bg->priv->cnc) {
3662 g_object_unref (bg->priv->cnc);
3666 else if (mode == GNOME_Evolution_Addressbook_MODE_REMOTE) {
3667 if (bg->priv->is_writable)
3668 e_book_backend_notify_writable (backend, TRUE);
3670 e_book_backend_notify_writable (backend, FALSE);
3671 e_book_backend_notify_connection_status (backend, TRUE);
3672 e_book_backend_notify_auth_required (backend);
3678 * e_book_backend_groupwise_new:
3681 e_book_backend_groupwise_new (void)
3683 EBookBackendGroupwise *backend;
3686 printf ("\ne_book_backend_groupwise_new...\n");
3688 backend = g_object_new (E_TYPE_BOOK_BACKEND_GROUPWISE, NULL);
3690 return E_BOOK_BACKEND (backend);
3694 e_book_backend_groupwise_dispose (GObject *object)
3696 EBookBackendGroupwise *bgw;
3699 printf ("\ne_book_backend_groupwise_dispose...\n");
3701 bgw = E_BOOK_BACKEND_GROUPWISE (object);
3704 if (bgw->priv->file_db)
3705 bgw->priv->file_db->close (bgw->priv->file_db, 0);
3707 g_static_mutex_lock(&global_env_lock);
3708 global_env.ref_count--;
3709 if (global_env.ref_count == 0) {
3710 global_env.env->close (global_env.env, 0);
3711 global_env.env = NULL;
3713 g_static_mutex_unlock(&global_env_lock);
3714 if (bgw->priv->uri) {
3715 g_free (bgw->priv->uri);
3716 bgw->priv->uri = NULL;
3719 if (bgw->priv->original_uri) {
3720 g_free (bgw->priv->original_uri);
3721 bgw->priv->original_uri = NULL;
3724 if (bgw->priv->cnc) {
3725 g_object_unref (bgw->priv->cnc);
3726 bgw->priv->cnc = NULL;
3728 if (bgw->priv->container_id) {
3729 g_free (bgw->priv->container_id);
3730 bgw->priv->container_id = NULL;
3732 if (bgw->priv->book_name) {
3733 g_free (bgw->priv->book_name);
3734 bgw->priv->book_name = NULL;
3736 if (bgw->priv->summary_file_name) {
3737 g_free (bgw->priv->summary_file_name);
3738 bgw->priv->summary_file_name = NULL;
3740 if (bgw->priv->summary) {
3741 e_book_backend_summary_save(bgw->priv->summary);
3742 g_object_unref (bgw->priv->summary);
3743 bgw->priv->summary = NULL;
3745 if (bgw->priv->use_ssl) {
3746 g_free (bgw->priv->use_ssl);
3748 if (bgw->priv->cache_timeout) {
3749 g_source_remove (bgw->priv->cache_timeout);
3750 bgw->priv->cache_timeout = 0;
3752 if (bgw->priv->update_mutex)
3753 g_mutex_free (bgw->priv->update_mutex);
3754 if (bgw->priv->update_cache_mutex)
3755 g_mutex_free (bgw->priv->update_cache_mutex);
3761 G_OBJECT_CLASS (e_book_backend_groupwise_parent_class)->dispose (object);
3765 e_book_backend_groupwise_class_init (EBookBackendGroupwiseClass *klass)
3769 GObjectClass *object_class = G_OBJECT_CLASS (klass);
3770 EBookBackendClass *parent_class;
3773 e_book_backend_groupwise_parent_class = g_type_class_peek_parent (klass);
3775 parent_class = E_BOOK_BACKEND_CLASS (klass);
3777 /* Set the virtual methods. */
3778 parent_class->load_source = e_book_backend_groupwise_load_source;
3779 parent_class->get_static_capabilities = e_book_backend_groupwise_get_static_capabilities;
3781 parent_class->create_contact = e_book_backend_groupwise_create_contact;
3782 parent_class->remove_contacts = e_book_backend_groupwise_remove_contacts;
3783 parent_class->modify_contact = e_book_backend_groupwise_modify_contact;
3784 parent_class->get_contact = e_book_backend_groupwise_get_contact;
3785 parent_class->get_contact_list = e_book_backend_groupwise_get_contact_list;
3786 parent_class->start_book_view = e_book_backend_groupwise_start_book_view;
3787 parent_class->stop_book_view = e_book_backend_groupwise_stop_book_view;
3788 parent_class->get_changes = e_book_backend_groupwise_get_changes;
3789 parent_class->authenticate_user = e_book_backend_groupwise_authenticate_user;
3790 parent_class->get_required_fields = e_book_backend_groupwise_get_required_fields;
3791 parent_class->get_supported_fields = e_book_backend_groupwise_get_supported_fields;
3792 parent_class->get_supported_auth_methods = e_book_backend_groupwise_get_supported_auth_methods;
3793 parent_class->cancel_operation = e_book_backend_groupwise_cancel_operation;
3794 parent_class->remove = e_book_backend_groupwise_remove;
3795 parent_class->set_mode = e_book_backend_groupwise_set_mode;
3796 object_class->dispose = e_book_backend_groupwise_dispose;
3800 e_book_backend_groupwise_init (EBookBackendGroupwise *backend)
3802 EBookBackendGroupwisePrivate *priv;
3804 priv= g_new0 (EBookBackendGroupwisePrivate, 1);
3805 priv->is_writable = TRUE;
3806 priv->is_cache_ready = FALSE;
3807 priv->is_summary_ready = FALSE;
3808 priv->marked_for_offline = FALSE;
3809 priv->use_ssl = NULL;
3811 priv->original_uri = NULL;
3812 priv->cache_timeout = 0;
3813 priv->update_mutex = g_mutex_new();
3814 priv->update_cache_mutex = g_mutex_new();
3815 priv->reserved1 = NULL;
3816 backend->priv = priv;
3818 if (g_getenv ("GROUPWISE_DEBUG")) {
3819 if (atoi (g_getenv ("GROUPWISE_DEBUG")) == 2)
3820 enable_debug = TRUE;
3822 enable_debug = FALSE;
3828 * e_book_backend_groupwise_get_type:
3831 e_book_backend_groupwise_get_type (void)
3833 static GType type = 0;
3837 sizeof (EBookBackendGroupwiseClass),
3838 NULL, /* base_class_init */
3839 NULL, /* base_class_finalize */
3840 (GClassInitFunc) e_book_backend_groupwise_class_init,
3841 NULL, /* class_finalize */
3842 NULL, /* class_data */
3843 sizeof (EBookBackendGroupwise),
3844 0, /* n_preallocs */
3845 (GInstanceInitFunc) e_book_backend_groupwise_init
3848 type = g_type_register_static (E_TYPE_BOOK_BACKEND, "EBookBackendGroupwise", &info, 0);