diff options
Diffstat (limited to 'addressbook/backend/pas')
24 files changed, 3509 insertions, 3413 deletions
diff --git a/addressbook/backend/pas/Makefile.am b/addressbook/backend/pas/Makefile.am index c618050ca2..b602a21512 100644 --- a/addressbook/backend/pas/Makefile.am +++ b/addressbook/backend/pas/Makefile.am @@ -42,7 +42,7 @@ ldapschemadir = $(privdatadir) ldapschema_DATA= $(LDAP_SCHEMA) privlib_LIBRARIES = libpas.a -noinst_LIBRARIES = libpasfile.a $(LDAP_BACKEND) +noinst_LIBRARIES = libpasfile.a libpasvcf.a $(LDAP_BACKEND) pasincludedir = $(privincludedir)/pas @@ -54,7 +54,8 @@ pasinclude_HEADERS = \ pas-backend-card-sexp.h \ pas-backend.h \ pas-backend-summary.h \ - pas-card-cursor.h + pas-backend-sync.h \ + pas-types.h libpas_a_SOURCES = \ $(pasinclude_HEADERS) \ @@ -66,13 +67,18 @@ libpas_a_SOURCES = \ pas-backend-file.c \ pas-backend.c \ pas-backend-summary.c \ - pas-card-cursor.c \ - pas-marshal.c + pas-backend-sync.c \ + pas-marshal.c \ + ximian-vcard.h libpasfile_a_SOURCES = \ pas-backend-file.c \ pas-backend-file.h +libpasvcf_a_SOURCES = \ + pas-backend-vcf.c \ + pas-backend-vcf.h + if ENABLE_LDAP libpasldap_a_SOURCES = \ $(LDAP_BACKEND_FILES) diff --git a/addressbook/backend/pas/pas-backend-card-sexp.c b/addressbook/backend/pas/pas-backend-card-sexp.c index e7b5d8a87d..1ccb4f2433 100644 --- a/addressbook/backend/pas/pas-backend-card-sexp.c +++ b/addressbook/backend/pas/pas-backend-card-sexp.c @@ -22,7 +22,6 @@ #include <string.h> #include <e-util/e-sexp.h> -#include <ebook/e-card-simple.h> #include <gal/widgets/e-unicode.h> static GObjectClass *parent_class; @@ -35,17 +34,17 @@ struct _PASBackendCardSExpPrivate { }; struct _SearchContext { - ECardSimple *card; + EContact *contact; }; static gboolean -compare_email (ECardSimple *card, const char *str, +compare_email (EContact *contact, const char *str, char *(*compare)(const char*, const char*)) { int i; - for (i = E_CARD_SIMPLE_EMAIL_ID_EMAIL; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i ++) { - const char *email = e_card_simple_get_email (card, i); + for (i = E_CONTACT_EMAIL_1; i <= E_CONTACT_EMAIL_3; i ++) { + const char *email = e_contact_get_const (contact, i); if (email && compare(email, str)) return TRUE; @@ -55,32 +54,36 @@ compare_email (ECardSimple *card, const char *str, } static gboolean -compare_phone (ECardSimple *card, const char *str, +compare_phone (EContact *contact, const char *str, char *(*compare)(const char*, const char*)) { int i; + gboolean rv = FALSE; - for (i = E_CARD_SIMPLE_PHONE_ID_ASSISTANT; i < E_CARD_SIMPLE_PHONE_ID_LAST; i ++) { - const ECardPhone *phone = e_card_simple_get_phone (card, i); + for (i = E_CONTACT_FIRST_PHONE_ID; i <= E_CONTACT_LAST_PHONE_ID; i ++) { + char *phone = e_contact_get (contact, i); - if (phone && compare(phone->number, str)) - return TRUE; + rv = phone && compare(phone, str); + g_free (phone); + + if (rv) + break; } - return FALSE; + return rv; } static gboolean -compare_name (ECardSimple *card, const char *str, +compare_name (EContact *contact, const char *str, char *(*compare)(const char*, const char*)) { const char *name; - name = e_card_simple_get_const (card, E_CARD_SIMPLE_FIELD_FULL_NAME); + name = e_contact_get_const (contact, E_CONTACT_FULL_NAME); if (name && compare (name, str)) return TRUE; - name = e_card_simple_get_const (card, E_CARD_SIMPLE_FIELD_FAMILY_NAME); + name = e_contact_get_const (contact, E_CONTACT_FAMILY_NAME); if (name && compare (name, str)) return TRUE; @@ -88,7 +91,7 @@ compare_name (ECardSimple *card, const char *str, } static gboolean -compare_address (ECardSimple *card, const char *str, +compare_address (EContact *contact, const char *str, char *(*compare)(const char*, const char*)) { g_warning("address searching not implemented\n"); @@ -96,23 +99,17 @@ compare_address (ECardSimple *card, const char *str, } static gboolean -compare_category (ECardSimple *card, const char *str, +compare_category (EContact *contact, const char *str, char *(*compare)(const char*, const char*)) { - EList *categories; - EIterator *iterator; - ECard *ecard; + GList *categories; + GList *iterator; gboolean ret_val = FALSE; - g_object_get (card, - "card", &ecard, - NULL); - g_object_get (ecard, - "category_list", &categories, - NULL); + categories = e_contact_get (contact, E_CONTACT_CATEGORY_LIST); - for (iterator = e_list_get_iterator(categories); e_iterator_is_valid (iterator); e_iterator_next (iterator)) { - const char *category = e_iterator_get (iterator); + for (iterator = categories; iterator; iterator = iterator->next) { + const char *category = iterator->data; if (compare(category, str)) { ret_val = TRUE; @@ -120,83 +117,45 @@ compare_category (ECardSimple *card, const char *str, } } - g_object_unref (iterator); - e_card_free_empty_lists (ecard); - g_object_unref (categories); - g_object_unref (ecard); - return ret_val; -} - -static gboolean -compare_arbitrary (ECardSimple *card, const char *str, - char *(*compare)(const char*, const char*)) -{ - EList *list; - EIterator *iterator; - ECard *ecard; - gboolean ret_val = FALSE; - - g_object_get (card, - "card", &ecard, - NULL); - g_object_get (ecard, - "arbitrary", &list, - NULL); - - for (iterator = e_list_get_iterator(list); e_iterator_is_valid (iterator); e_iterator_next (iterator)) { - const ECardArbitrary *arbitrary = e_iterator_get (iterator); + g_list_foreach (categories, (GFunc)g_free, NULL); + g_list_free (categories); - if (compare(arbitrary->key, str)) { - ret_val = TRUE; - break; - } - } - - g_object_unref (iterator); - e_card_free_empty_lists (ecard); - g_object_unref (list); - g_object_unref (ecard); return ret_val; } static struct prop_info { - ECardSimpleField field_id; + EContactField field_id; const char *query_prop; - const char *ecard_prop; #define PROP_TYPE_NORMAL 0x01 #define PROP_TYPE_LIST 0x02 -#define PROP_TYPE_LISTITEM 0x03 -#define PROP_TYPE_ID 0x04 int prop_type; - gboolean (*list_compare)(ECardSimple *ecard, const char *str, + gboolean (*list_compare)(EContact *contact, const char *str, char *(*compare)(const char*, const char*)); } prop_info_table[] = { -#define NORMAL_PROP(f,q,e) {f, q, e, PROP_TYPE_NORMAL, NULL} -#define ID_PROP {0, "id", NULL, PROP_TYPE_ID, NULL} -#define LIST_PROP(q,e,c) {0, q, e, PROP_TYPE_LIST, c} - - /* query prop, ecard prop, type, list compare function */ - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_FILE_AS, "file_as", "file_as" ), - LIST_PROP ( "full_name", "full_name", compare_name), /* not really a list, but we need to compare both full and surname */ - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_URL, "url", "url" ), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_MAILER, "mailer", "mailer"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ORG, "org", "org"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ORG_UNIT, "org_unit", "org_unit"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_OFFICE, "office", "office"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_TITLE, "title", "title"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ROLE, "role", "role"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_MANAGER, "manager", "manager"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ASSISTANT, "assistant", "assistant"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_NICKNAME, "nickname", "nickname"), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_SPOUSE, "spouse", "spouse" ), - NORMAL_PROP ( E_CARD_SIMPLE_FIELD_NOTE, "note", "note"), - ID_PROP, - LIST_PROP ( "email", "email", compare_email ), - LIST_PROP ( "phone", "phone", compare_phone ), - LIST_PROP ( "address", "address", compare_address ), - LIST_PROP ( "category", "category", compare_category ), - LIST_PROP ( "arbitrary", "arbitrary", compare_arbitrary ) +#define NORMAL_PROP(f,q) {f, q, PROP_TYPE_NORMAL, NULL} +#define LIST_PROP(q,c) {0, q, PROP_TYPE_LIST, c} + + /* query prop, type, list compare function */ + NORMAL_PROP ( E_CONTACT_FILE_AS, "file_as" ), + LIST_PROP ( "full_name", compare_name), /* not really a list, but we need to compare both full and surname */ + NORMAL_PROP ( E_CONTACT_HOMEPAGE_URL, "url"), + NORMAL_PROP ( E_CONTACT_MAILER, "mailer"), + NORMAL_PROP ( E_CONTACT_ORG, "org"), + NORMAL_PROP ( E_CONTACT_ORG_UNIT, "org_unit"), + NORMAL_PROP ( E_CONTACT_OFFICE, "office"), + NORMAL_PROP ( E_CONTACT_TITLE, "title"), + NORMAL_PROP ( E_CONTACT_ROLE, "role"), + NORMAL_PROP ( E_CONTACT_MANAGER, "manager"), + NORMAL_PROP ( E_CONTACT_ASSISTANT, "assistant"), + NORMAL_PROP ( E_CONTACT_NICKNAME, "nickname"), + NORMAL_PROP ( E_CONTACT_SPOUSE, "spouse" ), + NORMAL_PROP ( E_CONTACT_NOTE, "note"), + NORMAL_PROP ( E_CONTACT_UID, "id"), + LIST_PROP ( "email", compare_email ), + LIST_PROP ( "phone", compare_phone ), + LIST_PROP ( "address", compare_address ), + LIST_PROP ( "category", compare_category ), }; static int num_prop_infos = sizeof(prop_info_table) / sizeof(prop_info_table[0]); @@ -225,28 +184,10 @@ entry_compare(SearchContext *ctx, struct _ESExp *f, info = &prop_info_table[i]; if (info->prop_type == PROP_TYPE_NORMAL) { - char *prop = NULL; - /* searches where the query's property - maps directly to an ecard property */ - - prop = e_card_simple_get (ctx->card, info->field_id); - - if (prop && compare(prop, argv[1]->value.string)) { - truth = TRUE; - } - if ((!prop) && compare("", argv[1]->value.string)) { - truth = TRUE; - } - g_free (prop); - } else if (info->prop_type == PROP_TYPE_LIST) { - /* the special searches that match any of the list elements */ - truth = info->list_compare (ctx->card, argv[1]->value.string, compare); - } else if (info->prop_type == PROP_TYPE_ID) { const char *prop = NULL; - /* searches where the query's property - maps directly to an ecard property */ + /* straight string property matches */ - prop = e_card_get_id (ctx->card->card); + prop = e_contact_get_const (ctx->contact, info->field_id); if (prop && compare(prop, argv[1]->value.string)) { truth = TRUE; @@ -255,6 +196,10 @@ entry_compare(SearchContext *ctx, struct _ESExp *f, truth = TRUE; } } + else if (info->prop_type == PROP_TYPE_LIST) { + /* the special searches that match any of the list elements */ + truth = info->list_compare (ctx->contact, argv[1]->value.string, compare); + } /* if we're looking at all fields and find a match, or if we're just looking at this one field, @@ -335,6 +280,51 @@ func_beginswith(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *da return entry_compare (ctx, f, argc, argv, beginswith_helper); } +static ESExpResult * +func_exists(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data) +{ + SearchContext *ctx = data; + ESExpResult *r; + int truth = FALSE; + + if (argc == 1 + && argv[0]->type == ESEXP_RES_STRING) { + char *propname; + struct prop_info *info = NULL; + int i; + + propname = argv[0]->value.string; + + for (i = 0; i < num_prop_infos; i ++) { + if (!strcmp (prop_info_table[i].query_prop, propname)) { + info = &prop_info_table[i]; + + if (info->prop_type == PROP_TYPE_NORMAL) { + const char *prop = NULL; + /* searches where the query's property + maps directly to an ecard property */ + + prop = e_contact_get_const (ctx->contact, info->field_id); + + if (prop && *prop) + truth = TRUE; + } + else if (info->prop_type == PROP_TYPE_LIST) { + /* the special searches that match any of the list elements */ + truth = info->list_compare (ctx->contact, "", (char *(*)(const char*, const char*)) e_utf8_strstrcase); + } + + break; + } + } + + } + r = e_sexp_result_new(f, ESEXP_RES_BOOL); + r->value.bool = truth; + + return r; +} + /* 'builtin' functions */ static struct { char *name; @@ -346,25 +336,27 @@ static struct { { "is", func_is, 0 }, { "beginswith", func_beginswith, 0 }, { "endswith", func_endswith, 0 }, + { "exists", func_exists, 0 }, }; gboolean -pas_backend_card_sexp_match_ecard (PASBackendCardSExp *sexp, ECard *ecard) +pas_backend_card_sexp_match_contact (PASBackendCardSExp *sexp, EContact *contact) { ESExpResult *r; gboolean retval; - sexp->priv->search_context->card = e_card_simple_new (ecard); - - /* if it's not a valid vcard why is it in our db? :) */ - if (!sexp->priv->search_context->card) + if (!contact) { + g_warning ("null EContact passed to pas_backend_card_sexp_match_contact"); return FALSE; + } + + sexp->priv->search_context->contact = g_object_ref (contact); r = e_sexp_eval(sexp->priv->search_sexp); retval = (r && r->type == ESEXP_RES_BOOL && r->value.bool); - g_object_unref(sexp->priv->search_context->card); + g_object_unref(sexp->priv->search_context->contact); e_sexp_result_free(sexp->priv->search_sexp, r); @@ -374,14 +366,14 @@ pas_backend_card_sexp_match_ecard (PASBackendCardSExp *sexp, ECard *ecard) gboolean pas_backend_card_sexp_match_vcard (PASBackendCardSExp *sexp, const char *vcard) { - ECard *card; + EContact *contact; gboolean retval; - card = e_card_new ((char*)vcard); + contact = e_contact_new_from_vcard (vcard); - retval = pas_backend_card_sexp_match_ecard (sexp, card); + retval = pas_backend_card_sexp_match_contact (sexp, contact); - g_object_unref(card); + g_object_unref(contact); return retval; } @@ -404,7 +396,8 @@ pas_backend_card_sexp_new (const char *text) if (symbols[i].type == 1) { e_sexp_add_ifunction(sexp->priv->search_sexp, 0, symbols[i].name, (ESExpIFunc *)symbols[i].func, sexp->priv->search_context); - } else { + } + else { e_sexp_add_function(sexp->priv->search_sexp, 0, symbols[i].name, symbols[i].func, sexp->priv->search_context); } diff --git a/addressbook/backend/pas/pas-backend-card-sexp.h b/addressbook/backend/pas/pas-backend-card-sexp.h index eb7c7c6641..7efb697fb0 100644 --- a/addressbook/backend/pas/pas-backend-card-sexp.h +++ b/addressbook/backend/pas/pas-backend-card-sexp.h @@ -26,7 +26,8 @@ #include <glib.h> #include <glib-object.h> -#include <ebook/e-card.h> +#include <ebook/e-contact.h> +#include <pas/pas-types.h> #define PAS_TYPE_BACKEND_CARD_SEXP (pas_backend_card_sexp_get_type ()) #define PAS_BACKEND_CARD_SEXP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BACKEND_CARD_SEXP, PASBackendCardSExp)) @@ -37,19 +38,19 @@ typedef struct _PASBackendCardSExpPrivate PASBackendCardSExpPrivate; -typedef struct { +struct _PASBackendCardSExp { GObject parent_object; PASBackendCardSExpPrivate *priv; -} PASBackendCardSExp; +}; -typedef struct { +struct _PASBackendCardSExpClass { GObjectClass parent_class; -} PASBackendCardSExpClass; +}; PASBackendCardSExp *pas_backend_card_sexp_new (const char *text); GType pas_backend_card_sexp_get_type (void); gboolean pas_backend_card_sexp_match_vcard (PASBackendCardSExp *sexp, const char *vcard); -gboolean pas_backend_card_sexp_match_ecard (PASBackendCardSExp *sexp, ECard *ecard); +gboolean pas_backend_card_sexp_match_contact (PASBackendCardSExp *sexp, EContact *contact); #endif /* __PAS_BACKEND_CARD_SEXP_H__ */ diff --git a/addressbook/backend/pas/pas-backend-file.c b/addressbook/backend/pas/pas-backend-file.c index b11c62cb86..06923d7b08 100644 --- a/addressbook/backend/pas/pas-backend-file.c +++ b/addressbook/backend/pas/pas-backend-file.c @@ -8,12 +8,18 @@ #include "config.h" #include "pas-backend-file.h" +#include "pas-backend-card-sexp.h" +#include "pas-backend-summary.h" +#include "pas-book.h" +#include "pas-book-view.h" #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> +#include <dirent.h> #include <time.h> +#include <errno.h> #include <db.h> #include <sys/stat.h> @@ -28,15 +34,12 @@ #include <gal/util/e-util.h> #include <gal/widgets/e-unicode.h> -#include <ebook/e-card-simple.h> +#include <ebook/e-contact.h> #include <e-util/e-dbhash.h> #include <e-util/e-db3-utils.h> #include <libgnome/gnome-i18n.h> -#include "pas-book.h" -#include "pas-card-cursor.h" -#include "pas-backend-card-sexp.h" -#include "pas-backend-summary.h" +#define CHANGES_DB_SUFFIX ".changes.db" #define PAS_BACKEND_FILE_VERSION_NAME "PAS-DB-VERSION" #define PAS_BACKEND_FILE_VERSION "0.2" @@ -44,47 +47,17 @@ #define PAS_ID_PREFIX "pas-id-" #define SUMMARY_FLUSH_TIMEOUT 5000 -static PASBackendClass *pas_backend_file_parent_class; -typedef struct _PASBackendFileCursorPrivate PASBackendFileCursorPrivate; -typedef struct _PASBackendFileBookView PASBackendFileBookView; -typedef struct _PASBackendFileSearchContext PASBackendFileSearchContext; -typedef struct _PasBackendFileChangeContext PASBackendFileChangeContext; +static PASBackendSyncClass *pas_backend_file_parent_class; struct _PASBackendFilePrivate { char *uri; + char *dirname; char *filename; + char *summary_filename; DB *file_db; - EList *book_views; - GHashTable *address_lists; PASBackendSummary *summary; }; -struct _PASBackendFileCursorPrivate { - PASBackend *backend; - PASBook *book; - - GList *elements; - guint32 num_elements; -}; - -struct _PASBackendFileBookView { - PASBookView *book_view; - gchar *search; - PASBackendCardSExp *card_sexp; - gchar *change_id; - PASBackendFileChangeContext *change_context; -}; - -struct _PasBackendFileChangeContext { - DB *db; - - GList *add_cards; - GList *add_ids; - GList *mod_cards; - GList *mod_ids; - GList *del_ids; -}; - static void string_to_dbt(const char *str, DBT *dbt) { @@ -104,7 +77,8 @@ build_summary (PASBackendFilePrivate *bfpriv) db_error = db->cursor (db, NULL, &dbc, 0); if (db_error != 0) { - g_warning ("pas_backend_file_build_all_cards_list: error building list\n"); + g_warning ("build_summary: error building list\n"); + return; } memset (&vcard_dbt, 0, sizeof (vcard_dbt)); @@ -117,7 +91,7 @@ build_summary (PASBackendFilePrivate *bfpriv) if (id_dbt.size != strlen(PAS_BACKEND_FILE_VERSION_NAME) + 1 || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { - pas_backend_summary_add_card (bfpriv->summary, vcard_dbt.data); + pas_backend_summary_add_contact (bfpriv->summary, vcard_dbt.data); } db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); @@ -126,21 +100,17 @@ build_summary (PASBackendFilePrivate *bfpriv) } static void -do_summary_query (PASBackendFile *bf, - PASBackendFileBookView *view, - gboolean completion_search) +do_summary_query (PASBackendFile *bf, + PASBookView *view) { - GPtrArray *ids = pas_backend_summary_search (bf->priv->summary, view->search); + GPtrArray *ids = pas_backend_summary_search (bf->priv->summary, pas_book_view_get_card_query (view)); int db_error = 0; - GList *cards = NULL; - gint card_count = 0, card_threshold = 20, card_threshold_max = 3000; DB *db = bf->priv->file_db; DBT id_dbt, vcard_dbt; int i; for (i = 0; i < ids->len; i ++) { char *id = g_ptr_array_index (ids, i); - char *vcard = NULL; #if SUMMARY_STORES_ENOUGH_INFO /* this is disabled for the time being because lists @@ -150,6 +120,11 @@ do_summary_query (PASBackendFile *bf, if (completion_search) { vcard = pas_backend_summary_get_summary_vcard (bf->priv->summary, id); + if (vcard) { + EContact *contact = e_contact_new_from_vcard (vcard_dbt.data); + pas_book_view_notify_update (view, contact); + g_object_unref (contact); + } } else { #endif @@ -159,166 +134,19 @@ do_summary_query (PASBackendFile *bf, db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); if (db_error == 0) - vcard = g_strdup (vcard_dbt.data); + pas_book_view_notify_update (view, vcard_dbt.data); #if SUMMARY_STORES_ENOUGH_INFO } #endif - - if (vcard) { - cards = g_list_prepend (cards, vcard); - card_count ++; - - /* If we've accumulated a number of checks, pass them off to the client. */ - if (card_count >= card_threshold) { - pas_book_view_notify_add (view->book_view, cards); - /* Clean up the handed-off data. */ - g_list_foreach (cards, (GFunc)g_free, NULL); - g_list_free (cards); - cards = NULL; - card_count = 0; - - /* Yeah, this scheme is overly complicated. But I like it. */ - if (card_threshold < card_threshold_max) { - card_threshold = MIN (2*card_threshold, card_threshold_max); - } - } - } - else - continue; /* XXX */ } g_ptr_array_free (ids, TRUE); - if (card_count) - pas_book_view_notify_add (view->book_view, cards); - - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - - g_list_foreach (cards, (GFunc)g_free, NULL); - g_list_free (cards); -} - -static PASBackendFileBookView * -pas_backend_file_book_view_copy(const PASBackendFileBookView *book_view, void *closure) -{ - PASBackendFileBookView *new_book_view; - new_book_view = g_new (PASBackendFileBookView, 1); - new_book_view->book_view = book_view->book_view; - - new_book_view->search = g_strdup(book_view->search); - new_book_view->card_sexp = book_view->card_sexp; - if (new_book_view->card_sexp) - g_object_ref(new_book_view->card_sexp); - - new_book_view->change_id = g_strdup(book_view->change_id); - if (book_view->change_context) { - new_book_view->change_context = g_new(PASBackendFileChangeContext, 1); - new_book_view->change_context->db = book_view->change_context->db; - new_book_view->change_context->add_cards = book_view->change_context->add_cards; - new_book_view->change_context->add_ids = book_view->change_context->add_ids; - new_book_view->change_context->mod_cards = book_view->change_context->mod_cards; - new_book_view->change_context->mod_ids = book_view->change_context->mod_ids; - new_book_view->change_context->del_ids = book_view->change_context->del_ids; - } else - new_book_view->change_context = NULL; - - return new_book_view; -} - -static void -pas_backend_file_book_view_free(PASBackendFileBookView *book_view, void *closure) -{ - g_free(book_view->search); - if (book_view->card_sexp) - g_object_unref (book_view->card_sexp); - - g_free(book_view->change_id); - if (book_view->change_context) { - g_list_foreach (book_view->change_context->add_cards, (GFunc)g_free, NULL); - g_list_foreach (book_view->change_context->add_ids, (GFunc)g_free, NULL); - g_list_foreach (book_view->change_context->mod_cards, (GFunc)g_free, NULL); - g_list_foreach (book_view->change_context->mod_ids, (GFunc)g_free, NULL); - g_list_foreach (book_view->change_context->del_ids, (GFunc)g_free, NULL); - g_list_free (book_view->change_context->add_cards); - g_list_free (book_view->change_context->add_ids); - g_list_free (book_view->change_context->mod_cards); - g_list_free (book_view->change_context->mod_ids); - g_list_free (book_view->change_context->del_ids); - } - g_free(book_view->change_context); - - g_free(book_view); -} - -static long -get_length(PASCardCursor *cursor, gpointer data) -{ - PASBackendFileCursorPrivate *cursor_data = (PASBackendFileCursorPrivate *) data; - - return cursor_data->num_elements; + pas_book_view_notify_complete (view, GNOME_Evolution_Addressbook_Success); } static char * -get_nth(PASCardCursor *cursor, long n, gpointer data) -{ - PASBackendFileCursorPrivate *cursor_data = (PASBackendFileCursorPrivate *) data; - GList *nth_item = g_list_nth(cursor_data->elements, n); - - return g_strdup((char*)nth_item->data); -} - -static void -cursor_destroy(gpointer data, GObject *where_object_was) -{ - CORBA_Environment ev; - GNOME_Evolution_Addressbook_Book corba_book; - PASBackendFileCursorPrivate *cursor_data = (PASBackendFileCursorPrivate *) data; - - corba_book = bonobo_object_corba_objref(BONOBO_OBJECT(cursor_data->book)); - - CORBA_exception_init(&ev); - - GNOME_Evolution_Addressbook_Book_unref(corba_book, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning("cursor_destroy: Exception unreffing " - "corba book.\n"); - } - - CORBA_exception_free(&ev); - - g_list_foreach(cursor_data->elements, (GFunc)g_free, NULL); - g_list_free (cursor_data->elements); - - g_free(cursor_data); -} - -static void -view_destroy(gpointer data, GObject *where_object_was) -{ - PASBook *book = (PASBook *)data; - PASBackendFile *bf; - EIterator *iterator; - gboolean success = FALSE; - - bf = PAS_BACKEND_FILE(pas_book_get_backend(book)); - for (iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - const PASBackendFileBookView *view = e_iterator_get(iterator); - if (view->book_view == (PASBookView*)where_object_was) { - e_iterator_delete(iterator); - success = TRUE; - break; - } - } - if (!success) - g_warning ("Failed to remove from book_views list"); - g_object_unref(iterator); - - bonobo_object_unref(BONOBO_OBJECT(book)); -} - -static char * -pas_backend_file_create_unique_id (char *vcard) +pas_backend_file_create_unique_id (void) { /* use a 32 counter and the 32 bit timestamp to make an id. it's doubtful 2^32 id's will be created in a second, so we @@ -327,46 +155,18 @@ pas_backend_file_create_unique_id (char *vcard) return g_strdup_printf (PAS_ID_PREFIX "%08lX%08X", time(NULL), c++); } -static gboolean -vcard_matches_search (const PASBackendFileBookView *view, char *vcard_string) -{ - /* If this is not a search context view, it doesn't match be default */ - if (view->card_sexp == NULL) - return FALSE; - - return pas_backend_card_sexp_match_vcard (view->card_sexp, vcard_string); -} - -static gboolean -ecard_matches_search (const PASBackendFileBookView *view, ECard *card) -{ - /* If this is not a search context view, it doesn't match be default */ - if (view->card_sexp == NULL) - return FALSE; - - return pas_backend_card_sexp_match_ecard (view->card_sexp, card); -} - typedef struct { PASBackendFile *bf; PASBook *book; - const PASBackendFileBookView *view; + PASBookView *view; DBC *dbc; - int card_count; - int card_threshold; - int card_threshold_max; - GList *cards; - gboolean done_first; - gboolean search_needed; } FileBackendSearchClosure; static void free_search_closure (FileBackendSearchClosure *closure) { - g_list_foreach (closure->cards, (GFunc)g_free, NULL); - g_list_free (closure->cards); g_free (closure); } @@ -397,32 +197,11 @@ pas_backend_file_search_timeout (gpointer data) /* don't include the version in the list of cards */ if (strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { char *vcard_string = vcard_dbt.data; + EContact *contact = e_contact_new_from_vcard (vcard_string); - /* check if the vcard matches the search sexp */ - if ((!closure->search_needed) || vcard_matches_search (closure->view, vcard_string)) { - closure->cards = g_list_prepend (closure->cards, g_strdup (vcard_string)); - closure->card_count ++; - } - - /* If we've accumulated a number of checks, pass them off to the client. */ - if (closure->card_count >= closure->card_threshold) { - pas_book_view_notify_add (closure->view->book_view, closure->cards); - /* Clean up the handed-off data. */ - g_list_foreach (closure->cards, (GFunc)g_free, NULL); - g_list_free (closure->cards); - closure->cards = NULL; - closure->card_count = 0; - - /* Yeah, this scheme is overly complicated. But I like it. */ - if (closure->card_threshold < closure->card_threshold_max) { - closure->card_threshold = MIN (2*closure->card_threshold, closure->card_threshold_max); - } - - /* return here, we'll do the next lump in the next callback */ - g_timeout_add (200, pas_backend_file_search_timeout, closure); - - return FALSE; - } + /* notify_update will check if it matches for us */ + pas_book_view_notify_update (closure->view, contact); + g_object_unref (contact); } db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); @@ -435,10 +214,7 @@ pas_backend_file_search_timeout (gpointer data) free_search_closure (closure); } - if (closure->card_count) - pas_book_view_notify_add (closure->view->book_view, closure->cards); - - pas_book_view_notify_complete (closure->view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); + pas_book_view_notify_complete (closure->view, GNOME_Evolution_Addressbook_Success); free_search_closure (closure); @@ -448,49 +224,25 @@ pas_backend_file_search_timeout (gpointer data) static void pas_backend_file_search (PASBackendFile *bf, - PASBook *book, - const PASBackendFileBookView *cnstview, - gboolean completion_search) + PASBookView *book_view) { - PASBackendFileBookView *view = (PASBackendFileBookView *)cnstview; - gboolean search_needed; - - search_needed = TRUE; - - if ( ! strcmp (view->search, "(contains \"x-evolution-any-field\" \"\")")) - search_needed = FALSE; + const char *query = pas_book_view_get_card_query (book_view); - if (search_needed) - pas_book_view_notify_status_message (view->book_view, _("Searching...")); + if ( ! strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) + pas_book_view_notify_status_message (book_view, _("Loading...")); else - pas_book_view_notify_status_message (view->book_view, _("Loading...")); - - if (view->card_sexp) { - g_object_unref (view->card_sexp); - view->card_sexp = NULL; - } - - view->card_sexp = pas_backend_card_sexp_new (view->search); - - if (!view->card_sexp) { - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_InvalidQuery); - return; - } + pas_book_view_notify_status_message (book_view, _("Searching...")); - if (pas_backend_summary_is_summary_query (bf->priv->summary, view->search)) { - do_summary_query (bf, view, completion_search); + if (pas_backend_summary_is_summary_query (bf->priv->summary, query)) { + do_summary_query (bf, book_view); } else { FileBackendSearchClosure *closure = g_new0 (FileBackendSearchClosure, 1); DB *db = bf->priv->file_db; int db_error; - closure->card_threshold = 20; - closure->card_threshold_max = 3000; - closure->search_needed = search_needed; - closure->view = view; + closure->view = book_view; closure->bf = bf; - closure->book = book; db_error = db->cursor (db, NULL, &closure->dbc, 0); @@ -502,257 +254,81 @@ pas_backend_file_search (PASBackendFile *bf, } } -static void -pas_backend_file_changes_foreach_key (const char *key, gpointer user_data) +static EContact * +do_create(PASBackendFile *bf, + const char *vcard_req) { - PASBackendFileChangeContext *ctx = user_data; - DB *db = ctx->db; - DBT id_dbt, vcard_dbt; - int db_error = 0; - - string_to_dbt (key, &id_dbt); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); - - if (db_error != 0) { - char *id = id_dbt.data; - - ctx->del_ids = g_list_append (ctx->del_ids, g_strdup (id)); - } -} - -static void -pas_backend_file_changes (PASBackendFile *bf, - PASBook *book, - const PASBackendFileBookView *cnstview) -{ - int db_error = 0; - DBT id_dbt, vcard_dbt; - char *filename; - EDbHash *ehash; - GList *i, *v; - DB *db = bf->priv->file_db; - DBC *dbc; - PASBackendFileBookView *view = (PASBackendFileBookView *)cnstview; - PASBackendFileChangeContext *ctx = cnstview->change_context; - char *dirname, *slash; - - memset (&id_dbt, 0, sizeof (id_dbt)); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - - /* Find the changed ids */ - dirname = g_strdup (bf->priv->filename); - slash = strrchr (dirname, '/'); - *slash = '\0'; - - filename = g_strdup_printf ("%s/%s.db", dirname, view->change_id); - ehash = e_dbhash_new (filename); - g_free (filename); - g_free (dirname); - - db_error = db->cursor (db, NULL, &dbc, 0); - - if (db_error != 0) { - g_warning ("pas_backend_file_changes: error building list\n"); - } else { - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST); - - while (db_error == 0) { - - /* don't include the version in the list of cards */ - if (id_dbt.size != strlen(PAS_BACKEND_FILE_VERSION_NAME) + 1 - || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { - ECard *card; - char *id = id_dbt.data; - char *vcard_string; - - /* Remove fields the user can't change - * and can change without the rest of the - * card changing - */ - card = e_card_new (vcard_dbt.data); - g_object_set (card, "last_use", NULL, "use_score", 0.0, NULL); - vcard_string = e_card_get_vcard_assume_utf8 (card); - g_object_unref (card); - - /* check what type of change has occurred, if any */ - switch (e_dbhash_compare (ehash, id, vcard_string)) { - case E_DBHASH_STATUS_SAME: - break; - case E_DBHASH_STATUS_NOT_FOUND: - ctx->add_cards = g_list_append (ctx->add_cards, - vcard_string); - ctx->add_ids = g_list_append (ctx->add_ids, g_strdup(id)); - break; - case E_DBHASH_STATUS_DIFFERENT: - ctx->mod_cards = g_list_append (ctx->mod_cards, - vcard_string); - ctx->mod_ids = g_list_append (ctx->mod_ids, g_strdup(id)); - break; - } - } - - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); - } - dbc->c_close (dbc); - } - - e_dbhash_foreach_key (ehash, (EDbHashFunc)pas_backend_file_changes_foreach_key, view->change_context); - - /* Send the changes */ - if (db_error != DB_NOTFOUND) { - g_warning ("pas_backend_file_changes: error building list\n"); - } else { - if (ctx->add_cards != NULL) - pas_book_view_notify_add (view->book_view, ctx->add_cards); - - if (ctx->mod_cards != NULL) - pas_book_view_notify_change (view->book_view, ctx->mod_cards); - - for (v = ctx->del_ids; v != NULL; v = v->next){ - char *id = v->data; - pas_book_view_notify_remove_1 (view->book_view, id); - } - - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - } - - /* Update the hash */ - for (i = ctx->add_ids, v = ctx->add_cards; i != NULL; i = i->next, v = v->next){ - char *id = i->data; - char *vcard = v->data; - - e_dbhash_add (ehash, id, vcard); - g_free (i->data); - g_free (v->data); - } - for (i = ctx->mod_ids, v = ctx->mod_cards; i != NULL; i = i->next, v = v->next){ - char *id = i->data; - char *vcard = v->data; - - e_dbhash_add (ehash, id, vcard); - g_free (i->data); - g_free (v->data); - } - for (i = ctx->del_ids; i != NULL; i = i->next){ - char *id = i->data; - - e_dbhash_remove (ehash, id); - g_free (i->data); - } - - e_dbhash_write (ehash); - e_dbhash_destroy (ehash); -} - -static char * -do_create(PASBackend *backend, - char *vcard_req, - char **vcard_ptr) -{ - PASBackendFile *bf = PAS_BACKEND_FILE (backend); DB *db = bf->priv->file_db; DBT id_dbt, vcard_dbt; int db_error; char *id; - ECard *card; + EContact *contact; char *vcard; - char *ret_val; - id = pas_backend_file_create_unique_id (vcard_req); + id = pas_backend_file_create_unique_id (); string_to_dbt (id, &id_dbt); - - card = e_card_new(vcard_req); - e_card_set_id(card, id); - vcard = e_card_get_vcard_assume_utf8(card); + + contact = e_contact_new_from_vcard (vcard_req); + e_contact_set(contact, E_CONTACT_UID, id); + vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); string_to_dbt (vcard, &vcard_dbt); db_error = db->put (db, NULL, &id_dbt, &vcard_dbt, 0); + g_free (vcard); + if (0 == db_error) { db_error = db->sync (db, 0); if (db_error != 0) g_warning ("db->sync failed.\n"); - ret_val = id; - } else { - g_free (id); - ret_val = NULL; + g_object_unref (contact); + contact = NULL; } - g_object_unref(card); - card = NULL; - - if (vcard_ptr && ret_val) - *vcard_ptr = vcard; - else - g_free (vcard); - - return ret_val; + g_free (id); + return contact; } -static void -pas_backend_file_process_create_card (PASBackend *backend, - PASBook *book, - PASCreateCardRequest *req) +static PASBackendSyncStatus +pas_backend_file_create_contact (PASBackendSync *backend, + PASBook *book, + const char *vcard, + EContact **contact) { - char *id; - char *vcard; - EIterator *iterator; PASBackendFile *bf = PAS_BACKEND_FILE (backend); - id = do_create(backend, req->vcard, &vcard); - if (id) { - for (iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - const PASBackendFileBookView *view = e_iterator_get(iterator); - if (vcard_matches_search (view, vcard)) { - bonobo_object_ref (BONOBO_OBJECT (view->book_view)); - pas_book_view_notify_add_1 (view->book_view, vcard); - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - bonobo_object_unref (BONOBO_OBJECT (view->book_view)); - } - } - g_object_unref(iterator); - - pas_book_respond_create ( - book, - GNOME_Evolution_Addressbook_BookListener_Success, - id); - - pas_backend_summary_add_card (bf->priv->summary, vcard); - - g_free(vcard); - g_free(id); + *contact = do_create (bf, vcard); + if (*contact) { + pas_backend_summary_add_contact (bf->priv->summary, *contact); + return GNOME_Evolution_Addressbook_Success; } else { /* XXX need a different call status for this case, i think */ - pas_book_respond_create ( - book, - GNOME_Evolution_Addressbook_BookListener_CardNotFound, - ""); + return GNOME_Evolution_Addressbook_ContactNotFound; } } -static void -pas_backend_file_process_remove_cards (PASBackend *backend, - PASBook *book, - PASRemoveCardsRequest *req) +static PASBackendSyncStatus +pas_backend_file_remove_contacts (PASBackendSync *backend, + PASBook *book, + GList *id_list, + GList **ids) { PASBackendFile *bf = PAS_BACKEND_FILE (backend); DB *db = bf->priv->file_db; DBT id_dbt, vcard_dbt; int db_error; - EIterator *iterator; - const char *id; + char *id; GList *l; GList *removed_cards = NULL; - GNOME_Evolution_Addressbook_BookListener_CallStatus rv = GNOME_Evolution_Addressbook_BookListener_Success; + GNOME_Evolution_Addressbook_CallStatus rv = GNOME_Evolution_Addressbook_Success; - for (l = req->ids; l; l = l->next) { + for (l = id_list; l; l = l->next) { id = l->data; string_to_dbt (id, &id_dbt); @@ -760,17 +336,17 @@ pas_backend_file_process_remove_cards (PASBackend *backend, db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); if (0 != db_error) { - rv = GNOME_Evolution_Addressbook_BookListener_CardNotFound; + rv = GNOME_Evolution_Addressbook_ContactNotFound; continue; } db_error = db->del (db, NULL, &id_dbt, 0); if (0 != db_error) { - rv = GNOME_Evolution_Addressbook_BookListener_CardNotFound; + rv = GNOME_Evolution_Addressbook_ContactNotFound; continue; } - removed_cards = g_list_prepend (removed_cards, e_card_new (vcard_dbt.data)); + removed_cards = g_list_prepend (removed_cards, id); } /* if we actually removed some, try to sync */ @@ -780,53 +356,30 @@ pas_backend_file_process_remove_cards (PASBackend *backend, g_warning ("db->sync failed.\n"); } - for (iterator = e_list_get_iterator (bf->priv->book_views); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - const PASBackendFileBookView *view = e_iterator_get(iterator); - GList *view_removed = NULL; - for (l = removed_cards; l; l = l->next) { - ECard *removed_card = l->data; - if (ecard_matches_search (view, removed_card)) { - view_removed = g_list_prepend (view_removed, (char*)e_card_get_id (removed_card)); - } - } - if (view_removed) { - bonobo_object_ref (BONOBO_OBJECT (view->book_view)); - pas_book_view_notify_remove (view->book_view, view_removed); - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - bonobo_object_unref (BONOBO_OBJECT (view->book_view)); - g_list_free (view_removed); - } - } - g_object_unref(iterator); - - pas_book_respond_remove (book, rv); + *ids = removed_cards; for (l = removed_cards; l; l = l->next) { - ECard *c = l->data; - pas_backend_summary_remove_card (bf->priv->summary, e_card_get_id (c)); - g_object_unref (c); + char *id = l->data; + pas_backend_summary_remove_contact (bf->priv->summary, id); } - g_list_free (removed_cards); + return rv; } -static void -pas_backend_file_process_modify_card (PASBackend *backend, - PASBook *book, - PASModifyCardRequest *req) +static PASBackendSyncStatus +pas_backend_file_modify_contact (PASBackendSync *backend, + PASBook *book, + const char *vcard, + EContact **contact) { PASBackendFile *bf = PAS_BACKEND_FILE (backend); DB *db = bf->priv->file_db; DBT id_dbt, vcard_dbt; int db_error; - EIterator *iterator; - ECard *card; - const char *id, *lookup_id; - char *old_vcard_string; + char *id, *lookup_id; - /* create a new ecard from the request data */ - card = e_card_new(req->vcard); - id = e_card_get_id(card); + *contact = e_contact_new_from_vcard (vcard); + id = e_contact_get(*contact, E_CONTACT_UID); /* This is disgusting, but for a time cards were added with ID's that are no longer used (they contained both the uri @@ -844,15 +397,10 @@ pas_backend_file_process_modify_card (PASBackend *backend, /* get the old ecard - the one that's presently in the db */ db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); - if (0 != db_error) { - pas_book_respond_modify ( - book, - GNOME_Evolution_Addressbook_BookListener_CardNotFound); - return; - } - old_vcard_string = g_strdup(vcard_dbt.data); + if (0 != db_error) + return GNOME_Evolution_Addressbook_ContactNotFound; - string_to_dbt (req->vcard, &vcard_dbt); + string_to_dbt (vcard, &vcard_dbt); db_error = db->put (db, NULL, &id_dbt, &vcard_dbt, 0); @@ -861,55 +409,50 @@ pas_backend_file_process_modify_card (PASBackend *backend, if (db_error != 0) g_warning ("db->sync failed.\n"); - for (iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - CORBA_Environment ev; - const PASBackendFileBookView *view = e_iterator_get(iterator); - gboolean old_match, new_match; - - CORBA_exception_init(&ev); - - bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - old_match = vcard_matches_search (view, old_vcard_string); - new_match = vcard_matches_search (view, req->vcard); - if (old_match && new_match) - pas_book_view_notify_change_1 (view->book_view, req->vcard); - else if (new_match) - pas_book_view_notify_add_1 (view->book_view, req->vcard); - else /* if (old_match) */ - pas_book_view_notify_remove_1 (view->book_view, id); + pas_backend_summary_remove_contact (bf->priv->summary, id); + pas_backend_summary_add_contact (bf->priv->summary, *contact); + } + g_free (id); - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); + if (0 == db_error) + return GNOME_Evolution_Addressbook_Success; + else + return GNOME_Evolution_Addressbook_ContactNotFound; +} - bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); +static PASBackendSyncStatus +pas_backend_file_get_contact (PASBackendSync *backend, + PASBook *book, + const char *id, + char **vcard) +{ + PASBackendFile *bf; + DB *db; + DBT id_dbt, vcard_dbt; + int db_error = 0; - CORBA_exception_free (&ev); - } + bf = PAS_BACKEND_FILE (pas_book_get_backend (book)); + db = bf->priv->file_db; - g_object_unref(iterator); + string_to_dbt (id, &id_dbt); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - pas_book_respond_modify ( - book, - GNOME_Evolution_Addressbook_BookListener_Success); + db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); - pas_backend_summary_remove_card (bf->priv->summary, id); - pas_backend_summary_add_card (bf->priv->summary, req->vcard); - } - else { - pas_book_respond_modify ( - book, - GNOME_Evolution_Addressbook_BookListener_CardNotFound); + if (db_error == 0) { + *vcard = g_strdup (vcard_dbt.data); + return GNOME_Evolution_Addressbook_Success; + } else { + *vcard = g_strdup (""); + return GNOME_Evolution_Addressbook_ContactNotFound; } - - g_free(old_vcard_string); - - g_object_unref(card); } -static void -pas_backend_file_build_cards_list(PASBackend *backend, - PASBackendFileCursorPrivate *cursor_data, - char *search) +static PASBackendSyncStatus +pas_backend_file_get_contact_list (PASBackendSync *backend, + PASBook *book, + const char *query, + GList **contacts) { PASBackendFile *bf = PAS_BACKEND_FILE (backend); DB *db = bf->priv->file_db; @@ -918,8 +461,10 @@ pas_backend_file_build_cards_list(PASBackend *backend, DBT id_dbt, vcard_dbt; PASBackendCardSExp *card_sexp = NULL; gboolean search_needed; - - cursor_data->elements = NULL; + const char *search = query; + GList *contact_list = NULL; + + printf ("pas_backend_file_get_contact_list (%s)\n", search); search_needed = TRUE; @@ -927,14 +472,16 @@ pas_backend_file_build_cards_list(PASBackend *backend, search_needed = FALSE; card_sexp = pas_backend_card_sexp_new (search); - - if (!card_sexp) - g_warning ("pas_backend_file_build_all_cards_list: error building list\n"); + if (!card_sexp) { + /* XXX this needs to be an invalid query error of some sort*/ + return GNOME_Evolution_Addressbook_ContactNotFound; + } db_error = db->cursor (db, NULL, &dbc, 0); if (db_error != 0) { - g_warning ("pas_backend_file_build_all_cards_list: error building list\n"); + /* XXX this needs to be some CouldNotOpen error */ + return GNOME_Evolution_Addressbook_ContactNotFound; } memset (&vcard_dbt, 0, sizeof (vcard_dbt)); @@ -948,7 +495,7 @@ pas_backend_file_build_cards_list(PASBackend *backend, || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { if ((!search_needed) || (card_sexp != NULL && pas_backend_card_sexp_match_vcard (card_sexp, vcard_dbt.data))) { - cursor_data->elements = g_list_prepend (cursor_data->elements, g_strdup (vcard_dbt.data)); + contact_list = g_list_append (contact_list, g_strdup (vcard_dbt.data)); } } @@ -956,274 +503,211 @@ pas_backend_file_build_cards_list(PASBackend *backend, } - if (db_error != DB_NOTFOUND) { - g_warning ("pas_backend_file_build_all_cards_list: error building list\n"); - } - else { - cursor_data->num_elements = g_list_length (cursor_data->elements); - cursor_data->elements = g_list_reverse (cursor_data->elements); - } + *contacts = contact_list; + return db_error != DB_NOTFOUND + ? GNOME_Evolution_Addressbook_OtherError + : GNOME_Evolution_Addressbook_Success; } static void -pas_backend_file_process_get_vcard (PASBackend *backend, - PASBook *book, - PASGetVCardRequest *req) +pas_backend_file_start_book_view (PASBackend *backend, + PASBookView *book_view) { - PASBackendFile *bf; - DB *db; - DBT id_dbt, vcard_dbt; - int db_error = 0; - char *card; - GNOME_Evolution_Addressbook_BookListener_CallStatus status; - - bf = PAS_BACKEND_FILE (pas_book_get_backend (book)); - db = bf->priv->file_db; - - string_to_dbt (req->id, &id_dbt); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - - db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); + pas_backend_file_search (PAS_BACKEND_FILE (backend), book_view); +} - if (db_error == 0) { - card = vcard_dbt.data; - status = GNOME_Evolution_Addressbook_BookListener_Success; - } else { - card = ""; - status = GNOME_Evolution_Addressbook_BookListener_CardNotFound; - } +typedef struct { + DB *db; - pas_book_respond_get_vcard (book, - status, - card); -} + GList *add_cards; + GList *add_ids; + GList *mod_cards; + GList *mod_ids; + GList *del_ids; +} PASBackendFileChangeContext; static void -pas_backend_file_process_get_cursor (PASBackend *backend, - PASBook *book, - PASGetCursorRequest *req) +pas_backend_file_changes_foreach_key (const char *key, gpointer user_data) { - /* - PASBackendFile *bf = PAS_BACKEND_FILE (backend); - DB *db = bf->priv->file_db; - DBT id_dbt, vcard_dbt; - */ - CORBA_Environment ev; - int db_error = 0; - PASBackendFileCursorPrivate *cursor_data; - PASCardCursor *cursor; - GNOME_Evolution_Addressbook_Book corba_book; - - cursor_data = g_new(PASBackendFileCursorPrivate, 1); - cursor_data->backend = backend; - cursor_data->book = book; - - pas_backend_file_build_cards_list(backend, cursor_data, req->search); - - corba_book = bonobo_object_corba_objref(BONOBO_OBJECT(book)); - - CORBA_exception_init(&ev); - - GNOME_Evolution_Addressbook_Book_ref(corba_book, &ev); + PASBackendFileChangeContext *ctx = user_data; + DB *db = ctx->db; + DBT id_dbt, vcard_dbt; + int db_error = 0; - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning("pas_backend_file_process_get_cursor: Exception reffing " - "corba book.\n"); - } - - CORBA_exception_free(&ev); + string_to_dbt (key, &id_dbt); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); + db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); - cursor = pas_card_cursor_new(get_length, - get_nth, - cursor_data); + if (db_error != 0) { + char *id = id_dbt.data; - g_object_weak_ref (G_OBJECT (cursor), - cursor_destroy, cursor_data); - - pas_book_respond_get_cursor ( - book, - (db_error == 0 - ? GNOME_Evolution_Addressbook_BookListener_Success - : GNOME_Evolution_Addressbook_BookListener_CardNotFound), - cursor); + ctx->del_ids = g_list_append (ctx->del_ids, + g_strdup (id)); + } } -static void -pas_backend_file_process_get_book_view (PASBackend *backend, - PASBook *book, - PASGetBookViewRequest *req) +static PASBackendSyncStatus +pas_backend_file_get_changes (PASBackendSync *backend, + PASBook *book, + const char *change_id, + GList **changes_out) { PASBackendFile *bf = PAS_BACKEND_FILE (backend); - PASBookView *book_view; - PASBackendFileBookView view; - EIterator *iterator; - - bonobo_object_ref(BONOBO_OBJECT(book)); - - book_view = pas_book_view_new (req->listener); - - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); - - view.book_view = book_view; - view.search = g_strdup (req->search); - view.card_sexp = NULL; - view.change_id = NULL; - view.change_context = NULL; - - e_list_append(bf->priv->book_views, &view); - - pas_book_respond_get_book_view (book, - (book_view != NULL - ? GNOME_Evolution_Addressbook_BookListener_Success - : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */), - book_view); - - if (!pas_backend_is_loaded (backend)) - return; + int db_error = 0; + DBT id_dbt, vcard_dbt; + char *filename; + EDbHash *ehash; + GList *i, *v; + DB *db = bf->priv->file_db; + DBC *dbc; + GList *changes = NULL; + PASBackendFileChangeContext ctx; + PASBackendSyncStatus result; - iterator = e_list_get_iterator(bf->priv->book_views); - e_iterator_last(iterator); - pas_backend_file_search (bf, book, e_iterator_get(iterator), FALSE); - g_object_unref(iterator); -} + memset (&id_dbt, 0, sizeof (id_dbt)); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); -static void -pas_backend_file_process_get_completion_view (PASBackend *backend, - PASBook *book, - PASGetCompletionViewRequest *req) -{ - PASBackendFile *bf = PAS_BACKEND_FILE (backend); - PASBookView *book_view; - PASBackendFileBookView view; - EIterator *iterator; + memset (&ctx, 0, sizeof (ctx)); - bonobo_object_ref(BONOBO_OBJECT(book)); + ctx.db = db; - book_view = pas_book_view_new (req->listener); + /* Find the changed ids */ + filename = g_strdup_printf ("%s/%s" CHANGES_DB_SUFFIX, bf->priv->dirname, change_id); + ehash = e_dbhash_new (filename); + g_free (filename); - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); + db_error = db->cursor (db, NULL, &dbc, 0); - view.book_view = book_view; - view.search = g_strdup (req->search); - view.card_sexp = NULL; - view.change_id = NULL; - view.change_context = NULL; + if (db_error != 0) { + g_warning ("pas_backend_file_changes: error building list\n"); + } else { + db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST); - e_list_append(bf->priv->book_views, &view); + while (db_error == 0) { - pas_book_respond_get_completion_view (book, - (book_view != NULL - ? GNOME_Evolution_Addressbook_BookListener_Success - : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */), - book_view); + /* don't include the version in the list of cards */ + if (id_dbt.size != strlen(PAS_BACKEND_FILE_VERSION_NAME) + 1 + || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { + EContact *contact; + char *id = id_dbt.data; + char *vcard_string; + + /* Remove fields the user can't change + * and can change without the rest of the + * card changing + */ + contact = e_contact_new_from_vcard (vcard_dbt.data); +#if notyet + g_object_set (card, "last_use", NULL, "use_score", 0.0, NULL); +#endif + vcard_string = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); + g_object_unref (contact); + + /* check what type of change has occurred, if any */ + switch (e_dbhash_compare (ehash, id, vcard_string)) { + case E_DBHASH_STATUS_SAME: + break; + case E_DBHASH_STATUS_NOT_FOUND: + ctx.add_cards = g_list_append (ctx.add_cards, vcard_string); + ctx.add_ids = g_list_append (ctx.add_ids, g_strdup(id)); + break; + case E_DBHASH_STATUS_DIFFERENT: + ctx.mod_cards = g_list_append (ctx.mod_cards, vcard_string); + ctx.mod_ids = g_list_append (ctx.mod_ids, g_strdup(id)); + break; + } + } - if (!pas_backend_is_loaded (backend)) - return; + db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); + } + dbc->c_close (dbc); + } - iterator = e_list_get_iterator(bf->priv->book_views); - e_iterator_last(iterator); - pas_backend_file_search (bf, book, e_iterator_get(iterator), TRUE); - g_object_unref(iterator); -} + e_dbhash_foreach_key (ehash, (EDbHashFunc)pas_backend_file_changes_foreach_key, &ctx); -static void -pas_backend_file_process_get_changes (PASBackend *backend, - PASBook *book, - PASGetChangesRequest *req) -{ - PASBackendFile *bf = PAS_BACKEND_FILE (backend); - PASBookView *book_view; - PASBackendFileBookView view; - PASBackendFileChangeContext ctx; - EIterator *iterator; - - bonobo_object_ref(BONOBO_OBJECT(book)); - - book_view = pas_book_view_new (req->listener); - - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); - - pas_book_respond_get_changes (book, - (book_view != NULL - ? GNOME_Evolution_Addressbook_BookListener_Success - : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */), - book_view); - - view.book_view = book_view; - view.change_id = req->change_id; - view.change_context = &ctx; - ctx.db = bf->priv->file_db; - ctx.add_cards = NULL; - ctx.add_ids = NULL; - ctx.mod_cards = NULL; - ctx.mod_ids = NULL; - ctx.del_ids = NULL; - view.search = NULL; - view.card_sexp = NULL; - - e_list_append(bf->priv->book_views, &view); + /* Send the changes */ + if (db_error != DB_NOTFOUND) { + g_warning ("pas_backend_file_changes: error building list\n"); + *changes_out = NULL; + result = GNOME_Evolution_Addressbook_OtherError; + } + else { + /* Update the hash and build our changes list */ + for (i = ctx.add_ids, v = ctx.add_cards; i != NULL; i = i->next, v = v->next){ + char *id = i->data; + char *vcard = v->data; + + e_dbhash_add (ehash, id, vcard); + changes = g_list_prepend (changes, + pas_backend_change_add_new (vcard)); + + g_free (i->data); + g_free (v->data); + } + for (i = ctx.mod_ids, v = ctx.mod_cards; i != NULL; i = i->next, v = v->next){ + char *id = i->data; + char *vcard = v->data; + + e_dbhash_add (ehash, id, vcard); + changes = g_list_prepend (changes, + pas_backend_change_modify_new (vcard)); + + g_free (i->data); + g_free (v->data); + } + for (i = ctx.del_ids; i != NULL; i = i->next){ + char *id = i->data; + + e_dbhash_remove (ehash, id); + changes = g_list_prepend (changes, + pas_backend_change_delete_new (id)); + g_free (i->data); + } - if (!pas_backend_is_loaded (backend)) - return; + e_dbhash_write (ehash); - iterator = e_list_get_iterator(bf->priv->book_views); - e_iterator_last(iterator); - pas_backend_file_changes (bf, book, e_iterator_get(iterator)); - g_object_unref(iterator); -} + result = GNOME_Evolution_Addressbook_Success; + *changes_out = changes; + } -static void -pas_backend_file_process_check_connection (PASBackend *backend, - PASBook *book, - PASCheckConnectionRequest *req) -{ - PASBackendFile *bf = PAS_BACKEND_FILE (backend); + e_dbhash_destroy (ehash); - pas_book_report_connection (book, bf->priv->file_db != NULL); + return GNOME_Evolution_Addressbook_Success; } static char * pas_backend_file_extract_path_from_uri (const char *uri) { - g_assert (strncasecmp (uri, "file:", 5) == 0); + g_assert (strncasecmp (uri, "file://", 7) == 0); - return g_strdup (uri + 5); + return g_strdup (uri + 7); } -static void -pas_backend_file_process_authenticate_user (PASBackend *backend, - PASBook *book, - PASAuthenticateUserRequest *req) +static PASBackendSyncStatus +pas_backend_file_authenticate_user (PASBackendSync *backend, + PASBook *book, + const char *user, + const char *passwd, + const char *auth_method) { - pas_book_respond_authenticate_user (book, - GNOME_Evolution_Addressbook_BookListener_Success); + return GNOME_Evolution_Addressbook_Success; } -static void -pas_backend_file_process_get_supported_fields (PASBackend *backend, - PASBook *book, - PASGetSupportedFieldsRequest *req) +static PASBackendSyncStatus +pas_backend_file_get_supported_fields (PASBackendSync *backend, + PASBook *book, + GList **fields_out) { - EList *fields = e_list_new ((EListCopyFunc)g_strdup, (EListFreeFunc)g_free, NULL); - ECardSimple *simple; - ECard *card; + GList *fields = NULL; int i; - /* we support everything, so instantiate an e-card, and loop - through all fields, adding their ecard_fields. */ + /* XXX we need a way to say "we support everything", since the + file backend does */ + for (i = 1; i < E_CONTACT_FIELD_LAST; i ++) + fields = g_list_append (fields, g_strdup (e_contact_field_name (i))); - card = e_card_new (""); - simple = e_card_simple_new (card); - - for (i = 0; i < E_CARD_SIMPLE_FIELD_LAST; i ++) - e_list_append (fields, e_card_simple_get_ecard_field (simple, i)); - - g_object_unref (card); - g_object_unref (simple); - - pas_book_respond_get_supported_fields (book, - GNOME_Evolution_Addressbook_BookListener_Success, - fields); + *fields_out = fields; + return GNOME_Evolution_Addressbook_Success; } /* @@ -1273,9 +757,9 @@ pas_backend_file_upgrade_db (PASBackendFile *bf, char *old_version) while (db_error == 0) { if (id_dbt.size != strlen(PAS_BACKEND_FILE_VERSION_NAME) + 1 || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { - ECard *card; + EContact *contact; - card = e_card_new (vcard_dbt.data); + contact = e_contact_new_from_vcard (vcard_dbt.data); /* the cards we're looking for are created with a normal id dbt, but @@ -1283,12 +767,12 @@ pas_backend_file_upgrade_db (PASBackendFile *bf, char *old_version) to something that doesn't match. so, we need to modify the card to have the same id as the the dbt. */ - if (strcmp (id_dbt.data, e_card_get_id (card))) { + if (strcmp (id_dbt.data, e_contact_get_const (contact, E_CONTACT_UID))) { char *vcard; - e_card_set_id (card, id_dbt.data); + e_contact_set (contact, E_CONTACT_UID, id_dbt.data); - vcard = e_card_get_vcard (card); + vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); string_to_dbt (vcard, &vcard_dbt); db_error = db->put (db, NULL, @@ -1300,7 +784,7 @@ pas_backend_file_upgrade_db (PASBackendFile *bf, char *old_version) card_failed++; } - g_object_unref (card); + g_object_unref (contact); } db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); @@ -1352,30 +836,21 @@ pas_backend_file_maybe_upgrade_db (PASBackendFile *bf) return ret_val; } -#define INITIAL_VCARD "BEGIN:VCARD\n\ -X-EVOLUTION-FILE-AS:Ximian, Inc.\n\ -LABEL;WORK;QUOTED-PRINTABLE:401 Park Drive 3 West=0ABoston, MA 02215=0AUSA\n\ -TEL;WORK;VOICE:(617) 375-3800\n\ -TEL;WORK;FAX:(617) 236-8630\n\ -EMAIL;INTERNET:hello@ximian.com\n\ -URL:www.ximian.com/\n\ -ORG:Ximian, Inc.;\n\ -NOTE:Welcome to the Ximian Addressbook.\n\ -END:VCARD" - -static GNOME_Evolution_Addressbook_BookListener_CallStatus +#include "ximian-vcard.h" + +static GNOME_Evolution_Addressbook_CallStatus pas_backend_file_load_uri (PASBackend *backend, - const char *uri) + const char *uri, + gboolean only_if_exists) { PASBackendFile *bf = PAS_BACKEND_FILE (backend); - char *filename; + char *dirname, *filename; gboolean writable = FALSE; int db_error; DB *db; int major, minor, patch; time_t db_mtime; struct stat sb; - char *summary_filename; g_free(bf->priv->uri); bf->priv->uri = g_strdup (uri); @@ -1386,18 +861,19 @@ pas_backend_file_load_uri (PASBackend *backend, minor != 1 || patch != 17) { g_warning ("Wrong version of libdb."); - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; } - filename = pas_backend_file_extract_path_from_uri (uri); + dirname = pas_backend_file_extract_path_from_uri (uri); + filename = g_build_filename (dirname, "addressbook.db", NULL); db_error = e_db3_utils_maybe_recover (filename); if (db_error != 0) - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; db_error = db_create (&db, NULL, 0); if (db_error != 0) - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; db_error = db->open (db, filename, NULL, DB_HASH, 0, 0666); @@ -1405,7 +881,7 @@ pas_backend_file_load_uri (PASBackend *backend, db_error = e_db3_utils_upgrade_format (filename); if (db_error != 0) - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; db_error = db->open (db, filename, NULL, DB_HASH, 0, 0666); } @@ -1418,23 +894,27 @@ pas_backend_file_load_uri (PASBackend *backend, db_error = db->open (db, filename, NULL, DB_HASH, DB_RDONLY, 0666); if (db_error != 0) { - db_error = db->open (db, filename, NULL, DB_HASH, DB_CREATE, 0666); - - if (db_error == 0) { - char *create_initial_file; - char *dir; + int rv; + + /* the database didn't exist, so we create the + directory then the .db */ + rv = mkdir (dirname, 0777); + if (rv == -1 && errno != EEXIST) { + g_warning ("failed to make directory %s: %s", dirname, strerror (errno)); + if (errno == EACCES || errno == EPERM) + return GNOME_Evolution_Addressbook_PermissionDenied; + else + return GNOME_Evolution_Addressbook_OtherError; + } - dir = g_path_get_dirname(filename); - create_initial_file = g_build_filename (dir, "create-initial", NULL); + db_error = db->open (db, filename, NULL, DB_HASH, DB_CREATE, 0666); - if (g_file_test(create_initial_file, G_FILE_TEST_EXISTS)) { - char *id; - id = do_create(backend, INITIAL_VCARD, NULL); - g_free (id); - } + if (db_error == 0 && !only_if_exists) { + EContact *contact; - g_free(create_initial_file); - g_free(dir); + contact = do_create(bf, XIMIAN_VCARD); + /* XXX check errors here */ + g_object_unref (contact); writable = TRUE; } @@ -1443,28 +923,30 @@ pas_backend_file_load_uri (PASBackend *backend, if (db_error != 0) { bf->priv->file_db = NULL; - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; } if (!pas_backend_file_maybe_upgrade_db (bf)) { db->close (db, 0); bf->priv->file_db = NULL; - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; } + g_free (bf->priv->dirname); g_free (bf->priv->filename); + bf->priv->dirname = dirname; bf->priv->filename = filename; if (stat (bf->priv->filename, &sb) == -1) { db->close (db, 0); bf->priv->file_db = NULL; - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; } db_mtime = sb.st_mtime; - summary_filename = g_strconcat (bf->priv->filename, ".summary", NULL); - bf->priv->summary = pas_backend_summary_new (summary_filename, SUMMARY_FLUSH_TIMEOUT); - g_free (summary_filename); + g_free (bf->priv->summary_filename); + bf->priv->summary_filename = g_strconcat (bf->priv->filename, ".summary", NULL); + bf->priv->summary = pas_backend_summary_new (bf->priv->summary_filename, SUMMARY_FLUSH_TIMEOUT); if (pas_backend_summary_is_up_to_date (bf->priv->summary, db_mtime) == FALSE || pas_backend_summary_load (bf->priv->summary) == FALSE ) { @@ -1473,20 +955,76 @@ pas_backend_file_load_uri (PASBackend *backend, pas_backend_set_is_loaded (backend, TRUE); pas_backend_set_is_writable (backend, writable); - return GNOME_Evolution_Addressbook_BookListener_Success; + + return GNOME_Evolution_Addressbook_Success; } -/* Get_uri handler for the addressbook file backend */ -static const char * -pas_backend_file_get_uri (PASBackend *backend) +static int +select_changes (const struct dirent *d) { - PASBackendFile *bf; + char *p; + + if (strlen (d->d_name) < strlen (CHANGES_DB_SUFFIX)) + return 0; + + p = strstr (d->d_name, CHANGES_DB_SUFFIX); + if (!p) + return 0; + + if (strlen (p) != strlen (CHANGES_DB_SUFFIX)) + return 0; + + return 1; +} + +static PASBackendSyncStatus +pas_backend_file_remove (PASBackendSync *backend, + PASBook *book) +{ + PASBackendFile *bf = PAS_BACKEND_FILE (backend); + struct dirent **namelist; + int n; + + if (-1 == unlink (bf->priv->filename)) { + if (errno == EACCES || errno == EPERM) + return GNOME_Evolution_Addressbook_PermissionDenied; + else + return GNOME_Evolution_Addressbook_OtherError; + } - bf = PAS_BACKEND_FILE (backend); + /* unref the summary before we remove the file so it's not written out again */ + g_object_unref (bf->priv->summary); + bf->priv->summary = NULL; + if (-1 == unlink (bf->priv->filename)) + g_warning ("failed to remove summary file `%s`: %s", bf->priv->summary_filename, strerror (errno)); + + /* scandir to select all the "*.changes.db" files, then remove them */ + n = scandir (bf->priv->dirname, + &namelist, select_changes, alphasort); + if (n < 0) { + g_warning ("scandir of directory `%s' failed: %s", bf->priv->dirname, strerror (errno)); + } + else { + while (n -- ) { + char *full_path = g_build_filename (bf->priv->dirname, namelist[n]->d_name, NULL); + if (-1 == unlink (full_path)) { + g_warning ("failed to remove change db `%s': %s", full_path, strerror (errno)); + } + g_free (full_path); + free (namelist[n]); + } + free (namelist); + } - g_assert (bf->priv->uri != NULL); + if (-1 == rmdir (bf->priv->dirname)) + g_warning ("failed to remove directory `%s`: %s", bf->priv->dirname, strerror (errno)); - return bf->priv->uri; + /* we may not have actually succeeded in removing the + backend's files/dirs, but there's nothing we can do about + it here.. the only time we should return failure is if we + failed to remove the actual data. a failure should mean + that the addressbook is still valid */ + return GNOME_Evolution_Addressbook_Success; } static char * @@ -1495,6 +1033,12 @@ pas_backend_file_get_static_capabilities (PASBackend *backend) return g_strdup("local,do-initial-query,bulk-removes"); } +static GNOME_Evolution_Addressbook_CallStatus +pas_backend_file_cancel_operation (PASBackend *backend, PASBook *book) +{ + return GNOME_Evolution_Addressbook_CouldNotCancel; +} + static gboolean pas_backend_file_construct (PASBackendFile *backend) { @@ -1534,11 +1078,12 @@ pas_backend_file_dispose (GObject *object) bf = PAS_BACKEND_FILE (object); if (bf->priv) { - g_object_unref(bf->priv->book_views); if (bf->priv->summary) g_object_unref(bf->priv->summary); g_free (bf->priv->uri); g_free (bf->priv->filename); + g_free (bf->priv->dirname); + g_free (bf->priv->summary_filename); g_free (bf->priv); bf->priv = NULL; @@ -1551,28 +1096,29 @@ static void pas_backend_file_class_init (PASBackendFileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - PASBackendClass *parent_class; + PASBackendSyncClass *sync_class; + PASBackendClass *backend_class; pas_backend_file_parent_class = g_type_class_peek_parent (klass); - parent_class = PAS_BACKEND_CLASS (klass); + sync_class = PAS_BACKEND_SYNC_CLASS (klass); + backend_class = PAS_BACKEND_CLASS (klass); /* Set the virtual methods. */ - parent_class->load_uri = pas_backend_file_load_uri; - parent_class->get_uri = pas_backend_file_get_uri; - parent_class->get_static_capabilities = pas_backend_file_get_static_capabilities; - - parent_class->create_card = pas_backend_file_process_create_card; - parent_class->remove_cards = pas_backend_file_process_remove_cards; - parent_class->modify_card = pas_backend_file_process_modify_card; - parent_class->check_connection = pas_backend_file_process_check_connection; - parent_class->get_vcard = pas_backend_file_process_get_vcard; - parent_class->get_cursor = pas_backend_file_process_get_cursor; - parent_class->get_book_view = pas_backend_file_process_get_book_view; - parent_class->get_completion_view = pas_backend_file_process_get_completion_view; - parent_class->get_changes = pas_backend_file_process_get_changes; - parent_class->authenticate_user = pas_backend_file_process_authenticate_user; - parent_class->get_supported_fields = pas_backend_file_process_get_supported_fields; + backend_class->load_uri = pas_backend_file_load_uri; + backend_class->get_static_capabilities = pas_backend_file_get_static_capabilities; + backend_class->start_book_view = pas_backend_file_start_book_view; + backend_class->cancel_operation = pas_backend_file_cancel_operation; + + sync_class->remove_sync = pas_backend_file_remove; + sync_class->create_contact_sync = pas_backend_file_create_contact; + sync_class->remove_contacts_sync = pas_backend_file_remove_contacts; + sync_class->modify_contact_sync = pas_backend_file_modify_contact; + sync_class->get_contact_sync = pas_backend_file_get_contact; + sync_class->get_contact_list_sync = pas_backend_file_get_contact_list; + sync_class->get_changes_sync = pas_backend_file_get_changes; + sync_class->authenticate_user_sync = pas_backend_file_authenticate_user; + sync_class->get_supported_fields_sync = pas_backend_file_get_supported_fields; object_class->dispose = pas_backend_file_dispose; } @@ -1583,7 +1129,6 @@ pas_backend_file_init (PASBackendFile *backend) PASBackendFilePrivate *priv; priv = g_new0 (PASBackendFilePrivate, 1); - priv->book_views = e_list_new((EListCopyFunc) pas_backend_file_book_view_copy, (EListFreeFunc) pas_backend_file_book_view_free, NULL); priv->uri = NULL; backend->priv = priv; @@ -1610,7 +1155,7 @@ pas_backend_file_get_type (void) (GInstanceInitFunc) pas_backend_file_init }; - type = g_type_register_static (PAS_TYPE_BACKEND, "PASBackendFile", &info, 0); + type = g_type_register_static (PAS_TYPE_BACKEND_SYNC, "PASBackendFile", &info, 0); } return type; diff --git a/addressbook/backend/pas/pas-backend-file.h b/addressbook/backend/pas/pas-backend-file.h index fd98d2cdd5..6e1a77b119 100644 --- a/addressbook/backend/pas/pas-backend-file.h +++ b/addressbook/backend/pas/pas-backend-file.h @@ -5,7 +5,7 @@ #ifndef __PAS_BACKEND_FILE_H__ #define __PAS_BACKEND_FILE_H__ -#include "pas-backend.h" +#include "pas-backend-sync.h" #define PAS_TYPE_BACKEND_FILE (pas_backend_file_get_type ()) #define PAS_BACKEND_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BACKEND_FILE, PASBackendFile)) @@ -17,12 +17,12 @@ typedef struct _PASBackendFilePrivate PASBackendFilePrivate; typedef struct { - PASBackend parent_object; + PASBackendSync parent_object; PASBackendFilePrivate *priv; } PASBackendFile; typedef struct { - PASBackendClass parent_class; + PASBackendSyncClass parent_class; } PASBackendFileClass; PASBackend *pas_backend_file_new (void); diff --git a/addressbook/backend/pas/pas-backend-ldap.c b/addressbook/backend/pas/pas-backend-ldap.c index 1e8677e559..9c44e9983f 100644 --- a/addressbook/backend/pas/pas-backend-ldap.c +++ b/addressbook/backend/pas/pas-backend-ldap.c @@ -34,13 +34,13 @@ #include <sys/time.h> #include <e-util/e-sexp.h> -#include <ebook/e-card-simple.h> +#include <ebook/e-contact.h> #include <libgnome/gnome-i18n.h> #include "pas-backend-ldap.h" #include "pas-backend-card-sexp.h" #include "pas-book.h" -#include "pas-card-cursor.h" +#include "pas-book-view.h" #include <stdlib.h> @@ -59,14 +59,6 @@ typedef enum { /* timeout for ldap_result */ #define LDAP_RESULT_TIMEOUT_MILLIS 10 -/* smart grouping stuff */ -#define GROUPING_INITIAL_SIZE 1 -#define GROUPING_MAXIMUM_SIZE 200 - -/* the next two are in milliseconds */ -#define GROUPING_MINIMUM_WAIT 0 /* we never send updates faster than this, to avoid totally spamming the UI */ -#define GROUPING_MAXIMUM_WAIT 250 /* we always send updates (if there are pending cards) when we hit this */ - #define TV_TO_MILLIS(timeval) ((timeval).tv_sec * 1000 + (timeval).tv_usec / 1000) /* the objectClasses we need */ @@ -107,12 +99,10 @@ struct _PASBackendLDAPPrivate { was not built into openldap. */ PASBackendLDAPUseTLS use_tls; - EList *book_views; - LDAP *ldap; - EList *supported_fields; - EList *supported_auth_methods; + GList *supported_fields; + GList *supported_auth_methods; /* whether or not there's support for the objectclass we need to store all our additional fields */ @@ -138,7 +128,6 @@ struct _PASBackendLDAPBookView { PASBookView *book_view; PASBackendLDAPPrivate *blpriv; gchar *search; - PASBackendCardSExp *card_sexp; int limit; LDAPOp *search_op; @@ -160,122 +149,129 @@ static void ldap_op_add (LDAPOp *op, PASBackend *backend, PASBook *book, PASBookView *view, int id, LDAPOpHandler handler, LDAPOpDtor dtor); static void ldap_op_finished (LDAPOp *op); -static void ldap_search_op_timeout (LDAPOp *op, glong cur_millis); - static gboolean poll_ldap (PASBackendLDAP *bl); -static ECardSimple *build_card_from_entry (LDAP *ldap, LDAPMessage *e, GList **existing_objectclasses); +static EContact *build_contact_from_entry (LDAP *ldap, LDAPMessage *e, GList **existing_objectclasses); + +static void email_populate (EContact *contact, char **values); +struct berval** email_ber (EContact *contact); +static gboolean email_compare (EContact *contact1, EContact *contact2); -static void email_populate (ECardSimple *card, char **values); -struct berval** email_ber (ECardSimple *card); -static gboolean email_compare (ECardSimple *ecard1, ECardSimple *ecard2); +static void homephone_populate (EContact *contact, char **values); +struct berval** homephone_ber (EContact *contact); +static gboolean homephone_compare (EContact *contact1, EContact *contact2); -static void homephone_populate (ECardSimple *card, char **values); -struct berval** homephone_ber (ECardSimple *card); -static gboolean homephone_compare (ECardSimple *ecard1, ECardSimple *ecard2); +static void business_populate (EContact *contact, char **values); +struct berval** business_ber (EContact *contact); +static gboolean business_compare (EContact *contact1, EContact *contact2); -static void business_populate (ECardSimple *card, char **values); -struct berval** business_ber (ECardSimple *card); -static gboolean business_compare (ECardSimple *ecard1, ECardSimple *ecard2); +static void anniversary_populate (EContact *contact, char **values); +struct berval** anniversary_ber (EContact *contact); +static gboolean anniversary_compare (EContact *contact1, EContact *contact2); -static void anniversary_populate (ECardSimple *card, char **values); -struct berval** anniversary_ber (ECardSimple *card); -static gboolean anniversary_compare (ECardSimple *ecard1, ECardSimple *ecard2); +static void birthday_populate (EContact *contact, char **values); +struct berval** birthday_ber (EContact *contact); +static gboolean birthday_compare (EContact *contact1, EContact *contact2); -static void birthday_populate (ECardSimple *card, char **values); -struct berval** birthday_ber (ECardSimple *card); -static gboolean birthday_compare (ECardSimple *ecard1, ECardSimple *ecard2); +static void category_populate (EContact *contact, char **values); +struct berval** category_ber (EContact *contact); +static gboolean category_compare (EContact *contact1, EContact *contact2); -static void category_populate (ECardSimple *card, char **values); -struct berval** category_ber (ECardSimple *card); -static gboolean category_compare (ECardSimple *ecard1, ECardSimple *ecard2); +static void photo_populate (EContact *contact, struct berval **ber_values); struct prop_info { - ECardSimpleField field_id; - char *query_prop; + EContactField field_id; char *ldap_attr; #define PROP_TYPE_STRING 0x01 -#define PROP_TYPE_COMPLEX 0x02 -#define PROP_DN 0x04 -#define PROP_EVOLVE 0x08 +#define PROP_TYPE_COMPLEX 0x02 +#define PROP_TYPE_BINARY 0x04 +#define PROP_DN 0x08 +#define PROP_EVOLVE 0x10 +#define PROP_WRITE_ONLY 0x20 int prop_type; /* the remaining items are only used for the TYPE_COMPLEX props */ - /* used when reading from the ldap server populates ECard with the values in **values. */ - void (*populate_ecard_func)(ECardSimple *card, char **values); + /* used when reading from the ldap server populates EContact with the values in **values. */ + void (*populate_contact_func)(EContact *contact, char **values); /* used when writing to an ldap server. returns a NULL terminated array of berval*'s */ - struct berval** (*ber_func)(ECardSimple *card); + struct berval** (*ber_func)(EContact *contact); /* used to compare list attributes */ - gboolean (*compare_func)(ECardSimple *card1, ECardSimple *card2); + gboolean (*compare_func)(EContact *contact1, EContact *contact2); + + void (*binary_populate_contact_func)(EContact *contact, struct berval **ber_values); } prop_info[] = { -#define COMPLEX_PROP(fid,q,a,ctor,ber,cmp) {fid, q, a, PROP_TYPE_COMPLEX, ctor, ber, cmp} -#define E_COMPLEX_PROP(fid,q,a,ctor,ber,cmp) {fid, q, a, PROP_TYPE_COMPLEX | PROP_EVOLVE, ctor, ber, cmp} -#define STRING_PROP(fid,q,a) {fid, q, a, PROP_TYPE_STRING} -#define E_STRING_PROP(fid,q,a) {fid, q, a, PROP_TYPE_STRING | PROP_EVOLVE} +#define BINARY_PROP(fid,a,ctor,ber,cmp) {fid, a, PROP_TYPE_BINARY, NULL, ber, cmp, ctor} +#define COMPLEX_PROP(fid,a,ctor,ber,cmp) {fid, a, PROP_TYPE_COMPLEX, ctor, ber, cmp} +#define E_COMPLEX_PROP(fid,a,ctor,ber,cmp) {fid, a, PROP_TYPE_COMPLEX | PROP_EVOLVE, ctor, ber, cmp} +#define STRING_PROP(fid,a) {fid, a, PROP_TYPE_STRING} +#define WRITE_ONLY_STRING_PROP(fid,a) {fid, a, PROP_TYPE_STRING | PROP_WRITE_ONLY} +#define E_STRING_PROP(fid,a) {fid, a, PROP_TYPE_STRING | PROP_EVOLVE} /* name fields */ - STRING_PROP (E_CARD_SIMPLE_FIELD_FULL_NAME, "full_name", "cn" ), - STRING_PROP (E_CARD_SIMPLE_FIELD_FAMILY_NAME, "family_name", "sn" ), + STRING_PROP (E_CONTACT_FULL_NAME, "cn" ), + WRITE_ONLY_STRING_PROP (E_CONTACT_FAMILY_NAME, "sn" ), /* email addresses */ - COMPLEX_PROP (E_CARD_SIMPLE_FIELD_EMAIL, "email", "mail", email_populate, email_ber, email_compare), + COMPLEX_PROP (E_CONTACT_EMAIL, "mail", email_populate, email_ber, email_compare), /* phone numbers */ - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_PRIMARY, "primary_phone", "primaryPhone"), - COMPLEX_PROP (E_CARD_SIMPLE_FIELD_PHONE_BUSINESS, "business_phone", "telephoneNumber", business_populate, business_ber, business_compare), - COMPLEX_PROP (E_CARD_SIMPLE_FIELD_PHONE_HOME, "home_phone", "homePhone", homephone_populate, homephone_ber, homephone_compare), - STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_MOBILE, "mobile_phone", "mobile"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_CAR, "car_phone", "carPhone"), - STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_FAX, "business_fax", "facsimileTelephoneNumber"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_HOME_FAX, "home_fax", "homeFacsimileTelephoneNumber"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_OTHER, "other_phone", "otherPhone"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_OTHER_FAX, "other_fax", "otherFacsimileTelephoneNumber"), - STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_ISDN, "isdn", "internationaliSDNNumber"), - STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_PAGER, "pager", "pager"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_RADIO, "radio", "radio"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_TELEX, "telex", "telex"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_ASSISTANT, "assistant_phone", "assistantPhone"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_COMPANY, "company_phone", "companyPhone"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_CALLBACK, "callback_phone", "callbackPhone"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_PHONE_TTYTDD, "tty", "tty"), + E_STRING_PROP (E_CONTACT_PHONE_PRIMARY, "primaryPhone"), + COMPLEX_PROP (E_CONTACT_PHONE_BUSINESS, "telephoneNumber", business_populate, business_ber, business_compare), + COMPLEX_PROP (E_CONTACT_PHONE_HOME, "homePhone", homephone_populate, homephone_ber, homephone_compare), + STRING_PROP (E_CONTACT_PHONE_MOBILE, "mobile"), + E_STRING_PROP (E_CONTACT_PHONE_CAR, "carPhone"), + STRING_PROP (E_CONTACT_PHONE_BUSINESS_FAX, "facsimileTelephoneNumber"), + E_STRING_PROP (E_CONTACT_PHONE_HOME_FAX, "homeFacsimileTelephoneNumber"), + E_STRING_PROP (E_CONTACT_PHONE_OTHER, "otherPhone"), + E_STRING_PROP (E_CONTACT_PHONE_OTHER_FAX, "otherFacsimileTelephoneNumber"), + STRING_PROP (E_CONTACT_PHONE_ISDN, "internationaliSDNNumber"), + STRING_PROP (E_CONTACT_PHONE_PAGER, "pager"), + E_STRING_PROP (E_CONTACT_PHONE_RADIO, "radio"), + E_STRING_PROP (E_CONTACT_PHONE_TELEX, "telex"), + E_STRING_PROP (E_CONTACT_PHONE_ASSISTANT, "assistantPhone"), + E_STRING_PROP (E_CONTACT_PHONE_COMPANY, "companyPhone"), + E_STRING_PROP (E_CONTACT_PHONE_CALLBACK, "callbackPhone"), + E_STRING_PROP (E_CONTACT_PHONE_TTYTDD, "tty"), /* org information */ - STRING_PROP (E_CARD_SIMPLE_FIELD_ORG, "org", "o"), - STRING_PROP (E_CARD_SIMPLE_FIELD_ORG_UNIT, "org_unit", "ou"), - STRING_PROP (E_CARD_SIMPLE_FIELD_OFFICE, "office", "roomNumber"), - STRING_PROP (E_CARD_SIMPLE_FIELD_TITLE, "title", "title"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_ROLE, "role", "businessRole"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_MANAGER, "manager", "managerName"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_ASSISTANT, "assistant", "assistantName"), + STRING_PROP (E_CONTACT_ORG, "o"), + STRING_PROP (E_CONTACT_ORG_UNIT, "ou"), + STRING_PROP (E_CONTACT_OFFICE, "roomNumber"), + STRING_PROP (E_CONTACT_TITLE, "title"), + E_STRING_PROP (E_CONTACT_ROLE, "businessRole"), + E_STRING_PROP (E_CONTACT_MANAGER, "managerName"), + E_STRING_PROP (E_CONTACT_ASSISTANT, "assistantName"), /* addresses */ - STRING_PROP (E_CARD_SIMPLE_FIELD_ADDRESS_BUSINESS, "business_address", "postalAddress"), - STRING_PROP (E_CARD_SIMPLE_FIELD_ADDRESS_HOME, "home_address", "homePostalAddress"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_ADDRESS_OTHER, "other_address", "otherPostalAddress"), + STRING_PROP (E_CONTACT_ADDRESS_LABEL_WORK, "postalAddress"), + STRING_PROP (E_CONTACT_ADDRESS_LABEL_HOME, "homePostalAddress"), + E_STRING_PROP (E_CONTACT_ADDRESS_LABEL_OTHER, "otherPostalAddress"), + + /* photos */ + BINARY_PROP (E_CONTACT_PHOTO, "jpegPhoto", photo_populate, NULL/*XXX*/, NULL/*XXX*/), /* misc fields */ - STRING_PROP (E_CARD_SIMPLE_FIELD_URL, "url", "labeledURI"), + STRING_PROP (E_CONTACT_HOMEPAGE_URL, "labeledURI"), /* map nickname to displayName */ - STRING_PROP (E_CARD_SIMPLE_FIELD_NICKNAME, "nickname", "displayName"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_SPOUSE, "spouse", "spouseName"), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_NOTE, "note", "note"), - E_COMPLEX_PROP (E_CARD_SIMPLE_FIELD_ANNIVERSARY, "anniversary", "anniversary", anniversary_populate, anniversary_ber, anniversary_compare), - E_COMPLEX_PROP (E_CARD_SIMPLE_FIELD_BIRTH_DATE, "birth_date", "birthDate", birthday_populate, birthday_ber, birthday_compare), - E_STRING_PROP (E_CARD_SIMPLE_FIELD_MAILER, "mailer", "mailer"), - - E_STRING_PROP (E_CARD_SIMPLE_FIELD_FILE_AS, "file_as", "fileAs"), - E_COMPLEX_PROP (E_CARD_SIMPLE_FIELD_CATEGORIES, "categories", "category", category_populate, category_ber, category_compare), - - STRING_PROP (E_CARD_SIMPLE_FIELD_CALURI, "caluri", "calCalURI"), - STRING_PROP (E_CARD_SIMPLE_FIELD_FBURL, "fburl", "calFBURL"), - STRING_PROP (E_CARD_SIMPLE_FIELD_ICSCALENDAR, "icscalendar", "icsCalendar"), - -/* E_CARD_SIMPLE_FIELD_NAME_OR_ORG, */ - + STRING_PROP (E_CONTACT_NICKNAME, "displayName"), + E_STRING_PROP (E_CONTACT_SPOUSE, "spouseName"), + E_STRING_PROP (E_CONTACT_NOTE, "note"), + E_COMPLEX_PROP (E_CONTACT_ANNIVERSARY, "anniversary", anniversary_populate, anniversary_ber, anniversary_compare), + E_COMPLEX_PROP (E_CONTACT_BIRTH_DATE, "birthDate", birthday_populate, birthday_ber, birthday_compare), + E_STRING_PROP (E_CONTACT_MAILER, "mailer"), + + E_STRING_PROP (E_CONTACT_FILE_AS, "fileAs"), +#if notyet + E_COMPLEX_PROP (E_CONTACT_CATEGORIES, "category", category_populate, category_ber, category_compare), + + STRING_PROP (E_CONTACT_CALURI, "calCalURI"), + STRING_PROP (E_CONTACT_FBURL, "calFBURL"), + STRING_PROP (E_CONTACT_ICSCALENDAR, "icsCalendar"), +#endif #undef E_STRING_PROP #undef STRING_PROP @@ -285,6 +281,7 @@ struct prop_info { static int num_prop_infos = sizeof(prop_info) / sizeof(prop_info[0]); +#if 0 static void remove_view (int msgid, LDAPOp *op, PASBookView *view) { @@ -321,7 +318,6 @@ view_destroy(gpointer data, GObject *where_object_was) /* free up the view structure */ g_free (view->search); - g_object_unref (view->card_sexp); g_free (view); /* and remove it from our list */ @@ -349,6 +345,7 @@ view_destroy(gpointer data, GObject *where_object_was) g_object_unref (iter); } +#endif static void book_view_notify_status (PASBookView *view, const char *status) @@ -361,6 +358,7 @@ book_view_notify_status (PASBookView *view, const char *status) static PASBookView* find_book_view (PASBackendLDAP *bl) { +#if 0 EIterator *iter = e_list_get_iterator (bl->priv->book_views); PASBookView *rv = NULL; @@ -374,6 +372,7 @@ find_book_view (PASBackendLDAP *bl) g_object_unref (iter); return rv; +#endif } static void @@ -381,21 +380,21 @@ add_to_supported_fields (PASBackendLDAP *bl, char **attrs, GHashTable *attr_hash { int i; for (i = 0; attrs[i]; i ++) { - char *query_prop = g_hash_table_lookup (attr_hash, attrs[i]); + char *query_prop = g_hash_table_lookup (attr_hash, g_strdup (attrs[i])); if (query_prop) { - e_list_append (bl->priv->supported_fields, query_prop); + bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (query_prop)); /* handle the list attributes here */ if (!strcmp (query_prop, "email")) { - e_list_append (bl->priv->supported_fields, "email_2"); - e_list_append (bl->priv->supported_fields, "email_3"); + bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup ("email_2")); + bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup ("email_3")); } else if (!strcmp (query_prop, "business_phone")) { - e_list_append (bl->priv->supported_fields, "business_phone_2"); + bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup ("business_phone_2")); } else if (!strcmp (query_prop, "home_phone")) { - e_list_append (bl->priv->supported_fields, "home_phone_2"); + bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup ("home_phone_2")); } } } @@ -408,7 +407,7 @@ add_oc_attributes_to_supported_fields (PASBackendLDAP *bl, LDAPObjectClass *oc) GHashTable *attr_hash = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < num_prop_infos; i ++) - g_hash_table_insert (attr_hash, prop_info[i].ldap_attr, prop_info[i].query_prop); + g_hash_table_insert (attr_hash, prop_info[i].ldap_attr, (char*)e_contact_field_name (prop_info[i].field_id)); if (oc->oc_at_oids_must) add_to_supported_fields (bl, oc->oc_at_oids_must, attr_hash); @@ -591,22 +590,21 @@ query_ldap_root_dse (PASBackendLDAP *bl) values = ldap_get_values (ldap, resp, "supportedSASLMechanisms"); if (values) { char *auth_method; - if (bl->priv->supported_auth_methods) - g_object_unref (bl->priv->supported_auth_methods); - bl->priv->supported_auth_methods = e_list_new ((EListCopyFunc)g_strdup, (EListFreeFunc)g_free, NULL); + if (bl->priv->supported_auth_methods) { + g_list_foreach (bl->priv->supported_auth_methods, (GFunc)g_free, NULL); + g_list_free (bl->priv->supported_auth_methods); + } + bl->priv->supported_auth_methods = NULL; auth_method = g_strdup_printf ("ldap/simple-binddn|%s", _("Using Distinguished Name (DN)")); - e_list_append (bl->priv->supported_auth_methods, auth_method); - g_free (auth_method); + bl->priv->supported_auth_methods = g_list_append (bl->priv->supported_auth_methods, auth_method); auth_method = g_strdup_printf ("ldap/simple-email|%s", _("Using Email Address")); - e_list_append (bl->priv->supported_auth_methods, auth_method); - g_free (auth_method); + bl->priv->supported_fields = g_list_append (bl->priv->supported_auth_methods, auth_method); for (i = 0; values[i]; i++) { auth_method = g_strdup_printf ("sasl/%s|%s", values[i], values[i]); - e_list_append (bl->priv->supported_auth_methods, auth_method); - g_free (auth_method); + bl->priv->supported_fields = g_list_append (bl->priv->supported_auth_methods, auth_method); g_message ("supported SASL mechanism: %s", values[i]); } ldap_value_free (values); @@ -633,7 +631,7 @@ query_ldap_root_dse (PASBackendLDAP *bl) return LDAP_SUCCESS; } -static GNOME_Evolution_Addressbook_BookListener_CallStatus +static GNOME_Evolution_Addressbook_CallStatus pas_backend_ldap_connect (PASBackendLDAP *bl) { PASBackendLDAPPrivate *blpriv = bl->priv; @@ -667,7 +665,7 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) g_message ("TLS not available (fatal version), v3 protocol could not be established (ldap_error 0x%02x)", ldap_error); ldap_unbind (blpriv->ldap); blpriv->ldap = NULL; - return GNOME_Evolution_Addressbook_BookListener_TLSNotAvailable; + return GNOME_Evolution_Addressbook_TLSNotAvailable; } if (bl->priv->ldap_port == LDAPS_PORT && bl->priv->use_tls == PAS_BACKEND_LDAP_TLS_ALWAYS) { @@ -681,7 +679,7 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) g_message ("TLS not available (fatal version), (ldap_error 0x%02x)", ldap_error); ldap_unbind (blpriv->ldap); blpriv->ldap = NULL; - return GNOME_Evolution_Addressbook_BookListener_TLSNotAvailable; + return GNOME_Evolution_Addressbook_TLSNotAvailable; } else { g_message ("TLS not available (ldap_error 0x%02x)", ldap_error); @@ -700,7 +698,7 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) if (ldap_error == LDAP_SERVER_DOWN) { /* we only want this to be fatal if the server is down. */ g_warning ("failed to bind anonymously while connecting (ldap_error 0x%02x)", ldap_error); - return GNOME_Evolution_Addressbook_BookListener_RepositoryOffline; + return GNOME_Evolution_Addressbook_RepositoryOffline; } ldap_error = query_ldap_root_dse (bl); @@ -722,7 +720,7 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) check_schema_support (bl); pas_backend_set_is_loaded (PAS_BACKEND (bl), TRUE); - return GNOME_Evolution_Addressbook_BookListener_Success; + return GNOME_Evolution_Addressbook_Success; } else g_warning ("Failed to perform root dse query anonymously, (ldap_error 0x%02x)", ldap_error); @@ -734,7 +732,7 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) blpriv->ldap_port, blpriv->ldap_rootdn ? blpriv->ldap_rootdn : ""); blpriv->connected = FALSE; - return GNOME_Evolution_Addressbook_BookListener_RepositoryOffline; + return GNOME_Evolution_Addressbook_RepositoryOffline; } static gboolean @@ -742,14 +740,14 @@ pas_backend_ldap_reconnect (PASBackendLDAP *bl, PASBookView *book_view, int ldap { /* we need to reconnect if we were previously connected */ if (bl->priv->connected && ldap_status == LDAP_SERVER_DOWN) { - GNOME_Evolution_Addressbook_BookListener_CallStatus status; + GNOME_Evolution_Addressbook_CallStatus status; int ldap_error = LDAP_SUCCESS; book_view_notify_status (book_view, _("Reconnecting to LDAP server...")); status = pas_backend_ldap_connect (bl); - if (status != GNOME_Evolution_Addressbook_BookListener_Success) { + if (status != GNOME_Evolution_Addressbook_Success) { book_view_notify_status (book_view, ""); return FALSE; } @@ -836,27 +834,27 @@ static int ldap_error_to_response (int ldap_error) { if (ldap_error == LDAP_SUCCESS) - return GNOME_Evolution_Addressbook_BookListener_Success; + return GNOME_Evolution_Addressbook_Success; else if (LDAP_NAME_ERROR (ldap_error)) - return GNOME_Evolution_Addressbook_BookListener_CardNotFound; + return GNOME_Evolution_Addressbook_ContactNotFound; else if (ldap_error == LDAP_INSUFFICIENT_ACCESS) - return GNOME_Evolution_Addressbook_BookListener_PermissionDenied; + return GNOME_Evolution_Addressbook_PermissionDenied; else if (ldap_error == LDAP_SERVER_DOWN) - return GNOME_Evolution_Addressbook_BookListener_RepositoryOffline; + return GNOME_Evolution_Addressbook_RepositoryOffline; else if (ldap_error == LDAP_ALREADY_EXISTS) - return GNOME_Evolution_Addressbook_BookListener_CardIdAlreadyExists; + return GNOME_Evolution_Addressbook_ContactIdAlreadyExists; else - return GNOME_Evolution_Addressbook_BookListener_OtherError; + return GNOME_Evolution_Addressbook_OtherError; } static char * -create_dn_from_ecard (ECardSimple *card, const char *root_dn) +create_dn_from_contact (EContact *contact, const char *root_dn) { char *cn, *cn_part = NULL; char *dn; - cn = e_card_simple_get (card, E_CARD_SIMPLE_FIELD_FULL_NAME); + cn = e_contact_get (contact, E_CONTACT_FULL_NAME); if (cn) { if (strchr (cn, ',')) { /* need to escape commas */ @@ -921,7 +919,7 @@ free_mods (GPtrArray *mods) } static GPtrArray* -build_mods_from_ecards (PASBackendLDAP *bl, ECardSimple *current, ECardSimple *new, gboolean *new_dn_needed) +build_mods_from_contacts (PASBackendLDAP *bl, EContact *current, EContact *new, gboolean *new_dn_needed) { gboolean adding = (current == NULL); GPtrArray *result = g_ptr_array_new(); @@ -946,12 +944,12 @@ build_mods_from_ecards (PASBackendLDAP *bl, ECardSimple *current, ECardSimple *n if (prop_info[i].prop_type & PROP_EVOLVE && !bl->priv->evolutionPersonSupported) continue; - /* get the value for the new card, and compare it to - the value in the current card to see if we should + /* get the value for the new contact, and compare it to + the value in the current contact to see if we should update it -- if adding is TRUE, short circuit the check. */ if (prop_info[i].prop_type & PROP_TYPE_STRING) { - new_prop = e_card_simple_get (new, prop_info[i].field_id); + new_prop = e_contact_get (new, prop_info[i].field_id); new_prop_present = (new_prop != NULL); } else { @@ -962,7 +960,7 @@ build_mods_from_ecards (PASBackendLDAP *bl, ECardSimple *current, ECardSimple *n /* need to set INCLUDE to true if the field needs to show up in the ldap modify request */ if (adding) { - /* if we're creating a new card, include it if the + /* if we're creating a new contact, include it if the field is there at all */ if (prop_info[i].prop_type & PROP_TYPE_STRING) include = (new_prop_present && *new_prop); /* empty strings cause problems */ @@ -970,13 +968,13 @@ build_mods_from_ecards (PASBackendLDAP *bl, ECardSimple *current, ECardSimple *n include = new_prop_present; } else { - /* if we're modifying an existing card, + /* if we're modifying an existing contact, include it if the current field value is different than the new one, if it didn't exist previously, or if it's been removed. */ if (prop_info[i].prop_type & PROP_TYPE_STRING) { - current_prop = e_card_simple_get (current, prop_info[i].field_id); + current_prop = e_contact_get (current, prop_info[i].field_id); current_prop_present = (current_prop != NULL); if (new_prop && current_prop) @@ -1112,23 +1110,24 @@ add_objectclass_mod (PASBackendLDAP *bl, GPtrArray *mod_array, GList *existing_o typedef struct { LDAPOp op; char *dn; - ECardSimple *new_card; + EContact *new_contact; } LDAPCreateOp; static void -create_card_handler (LDAPOp *op, LDAPMessage *res) +create_contact_handler (LDAPOp *op, LDAPMessage *res) { LDAPCreateOp *create_op = (LDAPCreateOp*)op; PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); LDAP *ldap = bl->priv->ldap; + EContact *contact; int ldap_error; int response; if (LDAP_RES_ADD != ldap_msgtype (res)) { - g_warning ("incorrect msg type %d passed to create_card_handler", ldap_msgtype (res)); + g_warning ("incorrect msg type %d passed to create_contact_handler", ldap_msgtype (res)); pas_book_respond_create (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError, - create_op->dn); + GNOME_Evolution_Addressbook_OtherError, + NULL); ldap_op_finished (op); return; } @@ -1136,75 +1135,34 @@ create_card_handler (LDAPOp *op, LDAPMessage *res) ldap_parse_result (ldap, res, &ldap_error, NULL, NULL, NULL, NULL, 0); - if (ldap_error == LDAP_SUCCESS) { - /* the card was created, let's let the views know about it */ - EIterator *iter; - - iter = e_list_get_iterator (bl->priv->book_views); - while (e_iterator_is_valid (iter)) { - CORBA_Environment ev; - gboolean match; - PASBackendLDAPBookView *view = (PASBackendLDAPBookView*)e_iterator_get (iter); - char *new_vcard; - - CORBA_exception_init(&ev); - - bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - new_vcard = e_card_simple_get_vcard_assume_utf8 (create_op->new_card); - - match = pas_backend_card_sexp_match_vcard (view->card_sexp, - new_vcard); - if (match) { - pas_book_view_notify_add_1 (view->book_view, - new_vcard); - } - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - - g_free (new_vcard); - - bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - e_iterator_next (iter); - } - g_object_unref (iter); - } - else { - ldap_perror (ldap, "create_card"); - } - - if (op->view) - pas_book_view_notify_complete (op->view, GNOME_Evolution_Addressbook_BookViewListener_Success); - /* and lastly respond */ response = ldap_error_to_response (ldap_error); pas_book_respond_create (op->book, response, - create_op->dn); + create_op->new_contact); ldap_op_finished (op); } static void -create_card_dtor (LDAPOp *op) +create_contact_dtor (LDAPOp *op) { LDAPCreateOp *create_op = (LDAPCreateOp*)op; g_free (create_op->dn); - g_object_unref (create_op->new_card); + g_object_unref (create_op->new_contact); g_free (create_op); } static void -pas_backend_ldap_process_create_card (PASBackend *backend, - PASBook *book, - PASCreateCardRequest *req) +pas_backend_ldap_process_create_contact (PASBackend *backend, + PASBook *book, + const char *vcard) { LDAPCreateOp *create_op = g_new (LDAPCreateOp, 1); PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); PASBookView *book_view; - int create_card_msgid; - ECard *new_ecard; + int create_contact_msgid; int response; int err; GPtrArray *mod_array; @@ -1213,18 +1171,17 @@ pas_backend_ldap_process_create_card (PASBackend *backend, book_view = find_book_view (bl); - printf ("vcard = %s\n", req->vcard); + printf ("vcard = %s\n", vcard); - new_ecard = e_card_new (req->vcard); - create_op->new_card = e_card_simple_new (new_ecard); + create_op->new_contact = e_contact_new_from_vcard (vcard); - create_op->dn = create_dn_from_ecard (create_op->new_card, bl->priv->ldap_rootdn); - e_card_simple_set_id (create_op->new_card, create_op->dn); /* for the notification code below */ + create_op->dn = create_dn_from_contact (create_op->new_contact, bl->priv->ldap_rootdn); + e_contact_set (create_op->new_contact, E_CONTACT_UID, create_op->dn); ldap = bl->priv->ldap; /* build our mods */ - mod_array = build_mods_from_ecards (bl, NULL, create_op->new_card, NULL); + mod_array = build_mods_from_contacts (bl, NULL, create_op->new_contact, NULL); #if 0 if (!mod_array) { @@ -1232,10 +1189,10 @@ pas_backend_ldap_process_create_card (PASBackend *backend, UnsupportedAttribute back */ pas_book_respond_create (book, GNOME_Evolution_Addressbook_BookListener_UnsupportedField, - create_op->dn); + NULL); g_free (create_op->dn); - g_object_unref (create_op->new_card); + g_object_unref (create_op->new_contact); g_free (create_op); return; } @@ -1288,10 +1245,10 @@ pas_backend_ldap_process_create_card (PASBackend *backend, ldap_mods = (LDAPMod**)mod_array->pdata; do { - book_view_notify_status (book_view, _("Adding card to LDAP server...")); + book_view_notify_status (book_view, _("Adding contact to LDAP server...")); err = ldap_add_ext (ldap, create_op->dn, ldap_mods, - NULL, NULL, &create_card_msgid); + NULL, NULL, &create_contact_msgid); } while (pas_backend_ldap_reconnect (bl, book_view, err)); @@ -1302,15 +1259,15 @@ pas_backend_ldap_process_create_card (PASBackend *backend, response = ldap_error_to_response (err); pas_book_respond_create (create_op->op.book, response, - create_op->dn); - create_card_dtor ((LDAPOp*)create_op); + NULL); + create_contact_dtor ((LDAPOp*)create_op); return; } else { g_print ("ldap_add_ext returned %d\n", err); ldap_op_add ((LDAPOp*)create_op, backend, book, - book_view, create_card_msgid, - create_card_handler, create_card_dtor); + book_view, create_contact_msgid, + create_contact_handler, create_contact_dtor); } } @@ -1321,16 +1278,18 @@ typedef struct { } LDAPRemoveOp; static void -remove_card_handler (LDAPOp *op, LDAPMessage *res) +remove_contact_handler (LDAPOp *op, LDAPMessage *res) { LDAPRemoveOp *remove_op = (LDAPRemoveOp*)op; PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); int ldap_error; + GList *ids = NULL; if (LDAP_RES_DELETE != ldap_msgtype (res)) { - g_warning ("incorrect msg type %d passed to remove_card_handler", ldap_msgtype (res)); - pas_book_respond_remove (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError); + g_warning ("incorrect msg type %d passed to remove_contact_handler", ldap_msgtype (res)); + pas_book_respond_remove_contacts (op->book, + GNOME_Evolution_Addressbook_OtherError, + NULL); ldap_op_finished (op); return; } @@ -1338,39 +1297,15 @@ remove_card_handler (LDAPOp *op, LDAPMessage *res) ldap_parse_result (bl->priv->ldap, res, &ldap_error, NULL, NULL, NULL, NULL, 0); - if (ldap_error == LDAP_SUCCESS) { - /* the card was removed, let's let the views know about it */ - EIterator *iter = e_list_get_iterator (bl->priv->book_views); - - while (e_iterator_is_valid (iter)) { - CORBA_Environment ev; - PASBackendLDAPBookView *view = (PASBackendLDAPBookView*)e_iterator_get (iter); - - CORBA_exception_init(&ev); - - bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - pas_book_view_notify_remove_1 (view->book_view, remove_op->id); - - bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - e_iterator_next (iter); - } - g_object_unref (iter); - } - else { - ldap_perror (bl->priv->ldap, "remove_card"); - } - - pas_book_respond_remove (remove_op->op.book, - ldap_error_to_response (ldap_error)); - - if (op->view) - pas_book_view_notify_complete (op->view, GNOME_Evolution_Addressbook_BookViewListener_Success); + ids = g_list_append (ids, remove_op->id); + pas_book_respond_remove_contacts (remove_op->op.book, + ldap_error_to_response (ldap_error), + ids); + g_list_free (ids); } static void -remove_card_dtor (LDAPOp *op) +remove_contact_dtor (LDAPOp *op) { LDAPRemoveOp *remove_op = (LDAPRemoveOp*)op; @@ -1379,9 +1314,9 @@ remove_card_dtor (LDAPOp *op) } static void -pas_backend_ldap_process_remove_cards (PASBackend *backend, - PASBook *book, - PASRemoveCardsRequest *req) +pas_backend_ldap_process_remove_contacts (PASBackend *backend, + PASBook *book, + GList *ids) { LDAPRemoveOp *remove_op = g_new (LDAPRemoveOp, 1); PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); @@ -1396,10 +1331,10 @@ pas_backend_ldap_process_remove_cards (PASBackend *backend, ** capabilities, we should only get 1 length lists here, so ** the id we're deleting is the first and only id in the list. */ - remove_op->id = g_strdup (req->ids->data); + remove_op->id = g_strdup (ids->data); do { - book_view_notify_status (book_view, _("Removing card from LDAP server...")); + book_view_notify_status (book_view, _("Removing contact from LDAP server...")); ldap_error = ldap_delete_ext (bl->priv->ldap, remove_op->id, @@ -1407,16 +1342,17 @@ pas_backend_ldap_process_remove_cards (PASBackend *backend, } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error != LDAP_SUCCESS) { - pas_book_respond_remove (remove_op->op.book, - ldap_error_to_response (ldap_error)); - remove_card_dtor ((LDAPOp*)remove_op); + pas_book_respond_remove_contacts (remove_op->op.book, + ldap_error_to_response (ldap_error), + NULL); + remove_contact_dtor ((LDAPOp*)remove_op); return; } else { g_print ("ldap_delete_ext returned %d\n", ldap_error); ldap_op_add ((LDAPOp*)remove_op, backend, book, book_view, remove_msgid, - remove_card_handler, remove_card_dtor); + remove_contact_handler, remove_contact_dtor); } } @@ -1427,23 +1363,21 @@ pas_backend_ldap_process_remove_cards (PASBackend *backend, ** The modification request is actually composed of 2 separate ** requests. Since we need to get a list of theexisting objectclasses ** used by the ldap server for the entry, and since the UI only sends -** us the current card, we need to query the ldap server for the -** existing card. +** us the current contact, we need to query the ldap server for the +** existing contact. ** */ typedef struct { LDAPOp op; - const char *id; /* the id of the card we're modifying */ - char *current_vcard; /* current in the LDAP db */ - ECardSimple *current_card; - char *vcard; /* the VCard we want to store */ - ECardSimple *card; + const char *id; /* the id of the contact we're modifying */ + EContact *current_contact; + EContact *contact; GList *existing_objectclasses; } LDAPModifyOp; static void -modify_card_modify_handler (LDAPOp *op, LDAPMessage *res) +modify_contact_modify_handler (LDAPOp *op, LDAPMessage *res) { LDAPModifyOp *modify_op = (LDAPModifyOp*)op; PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); @@ -1451,9 +1385,10 @@ modify_card_modify_handler (LDAPOp *op, LDAPMessage *res) int ldap_error; if (LDAP_RES_MODIFY != ldap_msgtype (res)) { - g_warning ("incorrect msg type %d passed to modify_card_handler", ldap_msgtype (res)); + g_warning ("incorrect msg type %d passed to modify_contact_handler", ldap_msgtype (res)); pas_book_respond_modify (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError); + GNOME_Evolution_Addressbook_OtherError, + NULL); ldap_op_finished (op); return; } @@ -1461,48 +1396,15 @@ modify_card_modify_handler (LDAPOp *op, LDAPMessage *res) ldap_parse_result (ldap, res, &ldap_error, NULL, NULL, NULL, NULL, 0); - if (ldap_error == LDAP_SUCCESS) { - /* the card was modified, let's let the views know about it */ - EIterator *iter = e_list_get_iterator (bl->priv->book_views); - while (e_iterator_is_valid (iter)) { - CORBA_Environment ev; - gboolean old_match, new_match; - PASBackendLDAPBookView *view = (PASBackendLDAPBookView*)e_iterator_get (iter); - - CORBA_exception_init(&ev); - - bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - old_match = pas_backend_card_sexp_match_vcard (view->card_sexp, - modify_op->current_vcard); - new_match = pas_backend_card_sexp_match_vcard (view->card_sexp, - modify_op->vcard); - if (old_match && new_match) - pas_book_view_notify_change_1 (view->book_view, modify_op->vcard); - else if (new_match) - pas_book_view_notify_add_1 (view->book_view, modify_op->vcard); - else /* if (old_match) */ - pas_book_view_notify_remove_1 (view->book_view, e_card_simple_get_id (modify_op->card)); - pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - - bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), &ev); - - e_iterator_next (iter); - } - g_object_unref (iter); - } - else { - ldap_perror (ldap, "ldap_modify_s"); - } - /* and lastly respond */ pas_book_respond_modify (op->book, - ldap_error_to_response (ldap_error)); + ldap_error_to_response (ldap_error), + modify_op->contact); ldap_op_finished (op); } static void -modify_card_search_handler (LDAPOp *op, LDAPMessage *res) +modify_contact_search_handler (LDAPOp *op, LDAPMessage *res) { LDAPModifyOp *modify_op = (LDAPModifyOp*)op; PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); @@ -1520,14 +1422,14 @@ modify_card_search_handler (LDAPOp *op, LDAPMessage *res) if (!e) { g_warning ("uh, this shouldn't happen"); pas_book_respond_modify (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError); + GNOME_Evolution_Addressbook_OtherError, + NULL); ldap_op_finished (op); return; } - modify_op->current_card = build_card_from_entry (ldap, e, - &modify_op->existing_objectclasses); - modify_op->current_vcard = e_card_simple_get_vcard_assume_utf8 (modify_op->current_card); + modify_op->current_contact = build_contact_from_entry (ldap, e, + &modify_op->existing_objectclasses); } else if (msg_type == LDAP_RES_SEARCH_RESULT) { int ldap_error; @@ -1535,7 +1437,7 @@ modify_card_search_handler (LDAPOp *op, LDAPMessage *res) GPtrArray *mod_array; gboolean differences; gboolean need_new_dn; - int modify_card_msgid; + int modify_contact_msgid; /* grab the result code, and set up the actual modify if it was successful */ @@ -1545,13 +1447,14 @@ modify_card_search_handler (LDAPOp *op, LDAPMessage *res) if (ldap_error != LDAP_SUCCESS) { /* more here i'm sure */ pas_book_respond_modify (op->book, - ldap_error_to_response (ldap_error)); + ldap_error_to_response (ldap_error), + NULL); ldap_op_finished (op); return; } /* build our mods */ - mod_array = build_mods_from_ecards (bl, modify_op->current_card, modify_op->card, &need_new_dn); + mod_array = build_mods_from_contacts (bl, modify_op->current_contact, modify_op->contact, &need_new_dn); differences = mod_array->len > 0; if (differences) { @@ -1569,17 +1472,18 @@ modify_card_search_handler (LDAPOp *op, LDAPMessage *res) /* actually perform the ldap modify */ ldap_error = ldap_modify_ext (ldap, modify_op->id, ldap_mods, - NULL, NULL, &modify_card_msgid); + NULL, NULL, &modify_contact_msgid); if (ldap_error == LDAP_SUCCESS) { - op->handler = modify_card_modify_handler; + op->handler = modify_contact_modify_handler; ldap_op_change_id ((LDAPOp*)modify_op, - modify_card_msgid); + modify_contact_msgid); } else { g_warning ("ldap_modify_ext returned %d\n", ldap_error); pas_book_respond_modify (op->book, - ldap_error_to_response (ldap_error)); + ldap_error_to_response (ldap_error), + NULL); ldap_op_finished (op); return; } @@ -1591,84 +1495,80 @@ modify_card_search_handler (LDAPOp *op, LDAPMessage *res) else { g_warning ("unhandled result type %d returned", msg_type); pas_book_respond_modify (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError); + GNOME_Evolution_Addressbook_OtherError, + NULL); ldap_op_finished (op); } } static void -modify_card_dtor (LDAPOp *op) +modify_contact_dtor (LDAPOp *op) { LDAPModifyOp *modify_op = (LDAPModifyOp*)op; g_list_foreach (modify_op->existing_objectclasses, (GFunc)g_free, NULL); g_list_free (modify_op->existing_objectclasses); - g_free (modify_op->current_vcard); - if (modify_op->current_card) - g_object_unref (modify_op->current_card); - g_free (modify_op->vcard); - if (modify_op->card) - g_object_unref (modify_op->card); + if (modify_op->current_contact) + g_object_unref (modify_op->current_contact); + if (modify_op->contact) + g_object_unref (modify_op->contact); g_free (modify_op); } static void -pas_backend_ldap_process_modify_card (PASBackend *backend, - PASBook *book, - PASModifyCardRequest *req) +pas_backend_ldap_process_modify_contact (PASBackend *backend, + PASBook *book, + const char *vcard) { LDAPModifyOp *modify_op = g_new0 (LDAPModifyOp, 1); PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - ECard *new_ecard; int ldap_error; LDAP *ldap; - int modify_card_msgid; + int modify_contact_msgid; PASBookView *book_view; book_view = find_book_view (bl); - modify_op->vcard = g_strdup (req->vcard); - new_ecard = e_card_new (modify_op->vcard); - modify_op->card = e_card_simple_new (new_ecard); - g_object_unref (new_ecard); - modify_op->id = e_card_simple_get_id(modify_op->card); + modify_op->contact = e_contact_new_from_vcard (vcard); + modify_op->id = e_contact_get_const (modify_op->contact, E_CONTACT_UID); ldap = bl->priv->ldap; - book_view_notify_status (book_view, _("Modifying card from LDAP server...")); + book_view_notify_status (book_view, _("Modifying contact from LDAP server...")); do { - book_view_notify_status (book_view, _("Modifying card from LDAP server...")); + book_view_notify_status (book_view, _("Modifying contact from LDAP server...")); ldap_error = ldap_search_ext (ldap, modify_op->id, LDAP_SCOPE_BASE, "(objectclass=*)", NULL, 0, NULL, NULL, NULL, /* XXX timeout */ - 1, &modify_card_msgid); + 1, &modify_contact_msgid); } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error == LDAP_SUCCESS) { ldap_op_add ((LDAPOp*)modify_op, backend, book, - book_view, modify_card_msgid, - modify_card_search_handler, modify_card_dtor); + book_view, modify_contact_msgid, + modify_contact_search_handler, modify_contact_dtor); } else { g_warning ("ldap_search_ext returned %d\n", ldap_error); pas_book_respond_modify (book, - GNOME_Evolution_Addressbook_BookListener_OtherError); - modify_card_dtor ((LDAPOp*)modify_op); + GNOME_Evolution_Addressbook_OtherError, + NULL); + modify_contact_dtor ((LDAPOp*)modify_op); } } typedef struct { LDAPOp op; -} LDAPGetVCardOp; +} LDAPGetContactOp; static void -get_vcard_handler (LDAPOp *op, LDAPMessage *res) +get_contact_handler (LDAPOp *op, LDAPMessage *res) { PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); int msg_type; @@ -1679,37 +1579,37 @@ get_vcard_handler (LDAPOp *op, LDAPMessage *res) msg_type = ldap_msgtype (res); if (msg_type == LDAP_RES_SEARCH_ENTRY) { LDAPMessage *e = ldap_first_entry(bl->priv->ldap, res); - ECardSimple *simple; + EContact *contact; char *vcard; if (!e) { g_warning ("uh, this shouldn't happen"); - pas_book_respond_get_vcard (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError, - ""); + pas_book_respond_get_contact (op->book, + GNOME_Evolution_Addressbook_OtherError, + ""); ldap_op_finished (op); return; } - simple = build_card_from_entry (bl->priv->ldap, e, NULL); - vcard = e_card_simple_get_vcard_assume_utf8 (simple); - pas_book_respond_get_vcard (op->book, - GNOME_Evolution_Addressbook_BookListener_Success, - vcard); + contact = build_contact_from_entry (bl->priv->ldap, e, NULL); + vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); + pas_book_respond_get_contact (op->book, + GNOME_Evolution_Addressbook_Success, + vcard); g_free (vcard); - g_object_unref (simple); + g_object_unref (contact); ldap_op_finished (op); } else if (msg_type == LDAP_RES_SEARCH_RESULT) { int ldap_error; ldap_parse_result (bl->priv->ldap, res, &ldap_error, NULL, NULL, NULL, NULL, 0); - pas_book_respond_get_vcard (op->book, ldap_error_to_response (ldap_error), ""); + pas_book_respond_get_contact (op->book, ldap_error_to_response (ldap_error), ""); ldap_op_finished (op); } else { g_warning ("unhandled result type %d returned", msg_type); - pas_book_respond_get_vcard (op->book, GNOME_Evolution_Addressbook_BookListener_OtherError, + pas_book_respond_get_contact (op->book, GNOME_Evolution_Addressbook_OtherError, ""); ldap_op_finished (op); } @@ -1717,254 +1617,75 @@ get_vcard_handler (LDAPOp *op, LDAPMessage *res) } static void -get_vcard_dtor (LDAPOp *op) +get_contact_dtor (LDAPOp *op) { - LDAPGetVCardOp *get_vcard_op = (LDAPGetVCardOp*)op; + LDAPGetContactOp *get_contact_op = (LDAPGetContactOp*)op; - g_free (get_vcard_op); + g_free (get_contact_op); } static void -pas_backend_ldap_process_get_vcard (PASBackend *backend, - PASBook *book, - PASGetVCardRequest *req) +pas_backend_ldap_process_get_contact (PASBackend *backend, + PASBook *book, + const char *id) { - LDAPGetVCardOp *get_vcard_op = g_new0 (LDAPGetVCardOp, 1); + LDAPGetContactOp *get_contact_op = g_new0 (LDAPGetContactOp, 1); PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); LDAP *ldap = bl->priv->ldap; - int get_vcard_msgid; + int get_contact_msgid; PASBookView *book_view; int ldap_error; book_view = find_book_view (bl); do { - ldap_error = ldap_search_ext (ldap, req->id, + ldap_error = ldap_search_ext (ldap, id, LDAP_SCOPE_BASE, "(objectclass=*)", NULL, 0, NULL, NULL, NULL, /* XXX timeout */ - 1, &get_vcard_msgid); + 1, &get_contact_msgid); } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error == LDAP_SUCCESS) { - ldap_op_add ((LDAPOp*)get_vcard_op, backend, book, - book_view, get_vcard_msgid, - get_vcard_handler, get_vcard_dtor); + ldap_op_add ((LDAPOp*)get_contact_op, backend, book, + book_view, get_contact_msgid, + get_contact_handler, get_contact_dtor); } else { - pas_book_respond_get_vcard (book, + pas_book_respond_get_contact (book, ldap_error_to_response (ldap_error), ""); - get_vcard_dtor ((LDAPOp*)get_vcard_op); + get_contact_dtor ((LDAPOp*)get_contact_op); } } -typedef struct { - LDAPOp op; - PASBackendLDAPCursorPrivate *cursor_data; - gboolean responded; /* if FALSE, we need to free cursor_data in the dtor */ -} LDAPGetCursorOp; - -static long -get_length(PASCardCursor *cursor, gpointer data) -{ - PASBackendLDAPCursorPrivate *cursor_data = (PASBackendLDAPCursorPrivate *) data; - - return cursor_data->num_elements; -} - -static char * -get_nth(PASCardCursor *cursor, long n, gpointer data) -{ - PASBackendLDAPCursorPrivate *cursor_data = (PASBackendLDAPCursorPrivate *) data; - - g_return_val_if_fail (n < cursor_data->num_elements, NULL); - - return (char*)g_list_nth (cursor_data->elements, n); -} - -static void -cursor_destroy(gpointer data, GObject *where_object_was) -{ - PASBackendLDAPCursorPrivate *cursor_data = (PASBackendLDAPCursorPrivate *) data; - if (cursor_data->book) { - CORBA_Environment ev; - GNOME_Evolution_Addressbook_Book corba_book; - - corba_book = bonobo_object_corba_objref(BONOBO_OBJECT(cursor_data->book)); - - CORBA_exception_init(&ev); - - GNOME_Evolution_Addressbook_Book_unref(corba_book, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning("cursor_destroy: Exception unreffing " - "corba book.\n"); - } - - CORBA_exception_free(&ev); - } - - /* free the ldap specific cursor information */ - g_list_foreach (cursor_data->elements, (GFunc)g_free, NULL); - g_list_free (cursor_data->elements); - - g_free(cursor_data); -} - -static void -get_cursor_handler (LDAPOp *op, LDAPMessage *res) -{ - LDAPGetCursorOp *cursor_op = (LDAPGetCursorOp*)op; - PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); - LDAP *ldap = bl->priv->ldap; - int msg_type; - - msg_type = ldap_msgtype (res); - if (msg_type == LDAP_RES_SEARCH_ENTRY) { - LDAPMessage *e; - - e = ldap_first_entry (ldap, res); - while (e) { - ECardSimple *simple; - - simple = build_card_from_entry (ldap, e, NULL); - if (simple) { - char *vcard = e_card_simple_get_vcard_assume_utf8 (simple); - cursor_op->cursor_data->num_elements ++; - cursor_op->cursor_data->elements = g_list_prepend (cursor_op->cursor_data->elements, - vcard); - g_object_unref (simple); - } - } - } - else if (msg_type == LDAP_RES_SEARCH_RESULT) { - PASCardCursor *cursor = CORBA_OBJECT_NIL; - int ldap_error; - ldap_parse_result (bl->priv->ldap, res, &ldap_error, - NULL, NULL, NULL, NULL, 0); - - if (ldap_error == LDAP_SUCCESS) { - cursor = pas_card_cursor_new(get_length, - get_nth, - cursor_op->cursor_data); - - g_object_weak_ref (G_OBJECT (cursor), cursor_destroy, cursor_op->cursor_data); - - cursor_op->responded = TRUE; - } - - pas_book_respond_get_cursor (cursor_op->cursor_data->book, - ldap_error_to_response (ldap_error), - cursor); - - ldap_op_finished (op); - } - else { - g_warning ("unhandled result type %d returned", msg_type); - pas_book_respond_get_cursor (op->book, - GNOME_Evolution_Addressbook_BookListener_OtherError, - CORBA_OBJECT_NIL); - ldap_op_finished (op); - } -} - -static void -get_cursor_dtor (LDAPOp *op) -{ - LDAPGetCursorOp *cursor_op = (LDAPGetCursorOp*)op; - - if (!cursor_op->responded) { - cursor_destroy (cursor_op->cursor_data, NULL); - } - - g_free (op); -} - -static void -pas_backend_ldap_process_get_cursor (PASBackend *backend, - PASBook *book, - PASGetCursorRequest *req) -{ - PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - LDAP *ldap = bl->priv->ldap; - int ldap_error; - int get_cursor_msgid; - LDAPGetCursorOp *cursor_op; - PASBookView *book_view; - - book_view = find_book_view (bl); - - cursor_op = g_new0 (LDAPGetCursorOp, 1); - cursor_op->cursor_data = g_new0 (PASBackendLDAPCursorPrivate, 1); - - do { - ldap_error = ldap_search_ext (ldap, - bl->priv->ldap_rootdn, - bl->priv->ldap_scope, - "(objectclass=*)", - NULL, 0, - NULL, NULL, NULL, /* timeout */ - 0, &get_cursor_msgid); - } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); - - if (ldap_error == LDAP_SUCCESS) { - CORBA_Environment ev; - GNOME_Evolution_Addressbook_Book corba_book; - - corba_book = bonobo_object_corba_objref(BONOBO_OBJECT(book)); - - CORBA_exception_init(&ev); - - GNOME_Evolution_Addressbook_Book_ref(corba_book, &ev); - - cursor_op->cursor_data->backend = backend; - cursor_op->cursor_data->book = book; - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning("pas_backend_ldap_process_get_cursor: Exception reffing " - "corba book.\n"); - } - - CORBA_exception_free(&ev); - - - ldap_op_add ((LDAPOp*)cursor_op, backend, book, - NULL, get_cursor_msgid, get_cursor_handler, get_cursor_dtor); - } - else { - pas_book_respond_get_cursor (book, - ldap_error_to_response (ldap_error), - CORBA_OBJECT_NIL); - get_cursor_dtor ((LDAPOp*)cursor_op); - } -} +static EContactField email_ids[3] = { + E_CONTACT_EMAIL_1, + E_CONTACT_EMAIL_2, + E_CONTACT_EMAIL_3 +}; - /* List property functions */ static void -email_populate(ECardSimple *card, char **values) +email_populate(EContact *contact, char **values) { int i; - - for (i = 0; values[i] && i < 3; i ++) { - e_card_simple_set_email (card, i, values[i]); - } + for (i = 0; values[i] && i < 3; i ++) + e_contact_set (contact, email_ids[i], values[i]); } struct berval** -email_ber(ECardSimple *card) +email_ber(EContact *contact) { struct berval** result; const char *emails[3]; - int i, j, num; + int i, j, num = 0; - num = 0; for (i = 0; i < 3; i ++) { - emails[i] = e_card_simple_get_email (card, E_CARD_SIMPLE_EMAIL_ID_EMAIL + i); + emails[i] = e_contact_get (contact, email_ids[i]); if (emails[i]) num++; } @@ -1991,15 +1712,15 @@ email_ber(ECardSimple *card) } static gboolean -email_compare (ECardSimple *ecard1, ECardSimple *ecard2) +email_compare (EContact *contact1, EContact *contact2) { const char *email1, *email2; int i; for (i = 0; i < 3; i ++) { gboolean equal; - email1 = e_card_simple_get_email (ecard1, E_CARD_SIMPLE_EMAIL_ID_EMAIL + i); - email2 = e_card_simple_get_email (ecard2, E_CARD_SIMPLE_EMAIL_ID_EMAIL + i); + email1 = e_contact_get_const (contact1, email_ids[i]); + email2 = e_contact_get_const (contact2, email_ids[i]); if (email1 && email2) equal = !strcmp (email1, email2); @@ -2014,26 +1735,26 @@ email_compare (ECardSimple *ecard1, ECardSimple *ecard2) } static void -homephone_populate(ECardSimple *card, char **values) +homephone_populate(EContact *contact, char **values) { if (values[0]) { - e_card_simple_set (card, E_CARD_SIMPLE_FIELD_PHONE_HOME, values[0]); + e_contact_set (contact, E_CONTACT_PHONE_HOME, values[0]); if (values[1]) - e_card_simple_set (card, E_CARD_SIMPLE_FIELD_PHONE_HOME_2, values[1]); + e_contact_set (contact, E_CONTACT_PHONE_HOME_2, values[1]); } } struct berval** -homephone_ber(ECardSimple *card) +homephone_ber(EContact *contact) { struct berval** result; const char *homephones[3]; int i, j, num; num = 0; - if ((homephones[0] = e_card_simple_get (card, E_CARD_SIMPLE_FIELD_PHONE_HOME))) + if ((homephones[0] = e_contact_get (contact, E_CONTACT_PHONE_HOME))) num++; - if ((homephones[1] = e_card_simple_get (card, E_CARD_SIMPLE_FIELD_PHONE_HOME_2))) + if ((homephones[1] = e_contact_get (contact, E_CONTACT_PHONE_HOME_2))) num++; if (num == 0) @@ -2058,16 +1779,16 @@ homephone_ber(ECardSimple *card) } static gboolean -homephone_compare (ECardSimple *ecard1, ECardSimple *ecard2) +homephone_compare (EContact *contact1, EContact *contact2) { - int phone_ids[2] = { E_CARD_SIMPLE_FIELD_PHONE_HOME, E_CARD_SIMPLE_FIELD_PHONE_HOME_2 }; + int phone_ids[2] = { E_CONTACT_PHONE_HOME, E_CONTACT_PHONE_HOME_2 }; const char *phone1, *phone2; int i; for (i = 0; i < 2; i ++) { gboolean equal; - phone1 = e_card_simple_get (ecard1, phone_ids[i]); - phone2 = e_card_simple_get (ecard2, phone_ids[i]); + phone1 = e_contact_get (contact1, phone_ids[i]); + phone2 = e_contact_get (contact2, phone_ids[i]); if (phone1 && phone2) equal = !strcmp (phone1, phone2); @@ -2082,26 +1803,26 @@ homephone_compare (ECardSimple *ecard1, ECardSimple *ecard2) } static void -business_populate(ECardSimple *card, char **values) +business_populate(EContact *contact, char **values) { if (values[0]) { - e_card_simple_set (card, E_CARD_SIMPLE_FIELD_PHONE_BUSINESS, values[0]); + e_contact_set (contact, E_CONTACT_PHONE_BUSINESS, values[0]); if (values[1]) - e_card_simple_set (card, E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_2, values[1]); + e_contact_set (contact, E_CONTACT_PHONE_BUSINESS_2, values[1]); } } struct berval** -business_ber(ECardSimple *card) +business_ber(EContact *contact) { struct berval** result; const char *business_phones[3]; int i, j, num; num = 0; - if ((business_phones[0] = e_card_simple_get (card, E_CARD_SIMPLE_FIELD_PHONE_BUSINESS))) + if ((business_phones[0] = e_contact_get (contact, E_CONTACT_PHONE_BUSINESS))) num++; - if ((business_phones[1] = e_card_simple_get (card, E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_2))) + if ((business_phones[1] = e_contact_get (contact, E_CONTACT_PHONE_BUSINESS_2))) num++; if (num == 0) @@ -2126,16 +1847,16 @@ business_ber(ECardSimple *card) } static gboolean -business_compare (ECardSimple *ecard1, ECardSimple *ecard2) +business_compare (EContact *contact1, EContact *contact2) { - int phone_ids[2] = { E_CARD_SIMPLE_FIELD_PHONE_BUSINESS, E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_2 }; + int phone_ids[2] = { E_CONTACT_PHONE_BUSINESS, E_CONTACT_PHONE_BUSINESS_2 }; const char *phone1, *phone2; int i; for (i = 0; i < 2; i ++) { gboolean equal; - phone1 = e_card_simple_get (ecard1, phone_ids[i]); - phone2 = e_card_simple_get (ecard2, phone_ids[i]); + phone1 = e_contact_get (contact1, phone_ids[i]); + phone2 = e_contact_get (contact2, phone_ids[i]); if (phone1 && phone2) equal = !strcmp (phone1, phone2); @@ -2150,30 +1871,26 @@ business_compare (ECardSimple *ecard1, ECardSimple *ecard2) } static void -anniversary_populate (ECardSimple *card, char **values) +anniversary_populate (EContact *contact, char **values) { if (values[0]) { - ECardDate dt = e_card_date_from_string (values[0]); - g_object_set (card->card, - "anniversary", &dt, - NULL); + EContactDate *dt = e_contact_date_from_string (values[0]); + e_contact_set (contact, E_CONTACT_ANNIVERSARY, &dt); } } struct berval** -anniversary_ber (ECardSimple *card) +anniversary_ber (EContact *contact) { - ECardDate *dt; + EContactDate *dt; struct berval** result = NULL; - g_object_get (card->card, - "anniversary", &dt, - NULL); + dt = e_contact_get (contact, E_CONTACT_ANNIVERSARY); if (dt) { char *anniversary; - anniversary = e_card_date_to_string (dt); + anniversary = e_contact_date_to_string (dt); result = g_new (struct berval*, 2); result[0] = g_new (struct berval, 1); @@ -2181,29 +1898,31 @@ anniversary_ber (ECardSimple *card) result[0]->bv_len = strlen (anniversary); result[1] = NULL; + + e_contact_date_free (dt); } return result; } static gboolean -anniversary_compare (ECardSimple *ecard1, ECardSimple *ecard2) +anniversary_compare (EContact *contact1, EContact *contact2) { - ECardDate *dt; + EContactDate *dt; char *date1 = NULL, *date2 = NULL; gboolean equal; - g_object_get (ecard1->card, - "anniversary", &dt, - NULL); - if (dt) - date1 = e_card_date_to_string (dt); - - g_object_get (ecard2->card, - "anniversary", &dt, - NULL); - if (dt) - date2 = e_card_date_to_string (dt); + dt = e_contact_get (contact1, E_CONTACT_ANNIVERSARY); + if (dt) { + date1 = e_contact_date_to_string (dt); + e_contact_date_free (dt); + } + + dt = e_contact_get (contact2, E_CONTACT_ANNIVERSARY); + if (dt) { + date2 = e_contact_date_to_string (dt); + e_contact_date_free (dt); + } if (date1 && date2) equal = !strcmp (date1, date2); @@ -2217,30 +1936,26 @@ anniversary_compare (ECardSimple *ecard1, ECardSimple *ecard2) } static void -birthday_populate (ECardSimple *card, char **values) +birthday_populate (EContact *contact, char **values) { if (values[0]) { - ECardDate dt = e_card_date_from_string (values[0]); - g_object_set (card->card, - "birth_date", &dt, - NULL); + EContactDate *dt = e_contact_date_from_string (values[0]); + e_contact_set (contact, E_CONTACT_BIRTH_DATE, dt); + e_contact_date_free (dt); } } struct berval** -birthday_ber (ECardSimple *card) +birthday_ber (EContact *contact) { - ECardDate *dt; + EContactDate *dt; struct berval** result = NULL; - g_object_get (card->card, - "birth_date", &dt, - NULL); - + dt = e_contact_get (contact, E_CONTACT_BIRTH_DATE); if (dt) { char *birthday; - birthday = e_card_date_to_string (dt); + birthday = e_contact_date_to_string (dt); result = g_new (struct berval*, 2); result[0] = g_new (struct berval, 1); @@ -2248,29 +1963,31 @@ birthday_ber (ECardSimple *card) result[0]->bv_len = strlen (birthday); result[1] = NULL; + + e_contact_date_free (dt); } return result; } static gboolean -birthday_compare (ECardSimple *ecard1, ECardSimple *ecard2) +birthday_compare (EContact *contact1, EContact *contact2) { - ECardDate *dt; + EContactDate *dt; char *date1 = NULL, *date2 = NULL; gboolean equal; - g_object_get (ecard1->card, - "birth_date", &dt, - NULL); - if (dt) - date1 = e_card_date_to_string (dt); + dt = e_contact_get (contact1, E_CONTACT_BIRTH_DATE); + if (dt) { + date1 = e_contact_date_to_string (dt); + e_contact_date_free (dt); + } - g_object_get (ecard2->card, - "birth_date", &dt, - NULL); - if (dt) - date2 = e_card_date_to_string (dt); + dt = e_contact_get (contact2, E_CONTACT_BIRTH_DATE); + if (dt) { + date2 = e_contact_date_to_string (dt); + e_contact_date_free (dt); + } if (date1 && date2) equal = !strcmp (date1, date2); @@ -2284,10 +2001,11 @@ birthday_compare (ECardSimple *ecard1, ECardSimple *ecard2) } static void -category_populate (ECardSimple *card, char **values) +category_populate (EContact *contact, char **values) { +#if notyet int i; - ECard *ecard; + EContact *ecard; EList *categories; g_object_get (card, @@ -2309,15 +2027,17 @@ category_populate (ECardSimple *card, char **values) e_card_simple_sync_card (card); g_object_unref (ecard); +#endif } struct berval** -category_ber (ECardSimple *card) +category_ber (EContact *contact) { +#if notyet struct berval** result = NULL; EList *categories; EIterator *iterator; - ECard *ecard; + EContact *ecard; int i; g_object_get (card, @@ -2346,16 +2066,18 @@ category_ber (ECardSimple *card) g_object_unref (categories); g_object_unref (ecard); return result; +#endif } static gboolean -category_compare (ECardSimple *ecard1, ECardSimple *ecard2) +category_compare (EContact *contact1, EContact *contact2) { +#if notyet char *categories1, *categories2; gboolean equal; - categories1 = e_card_simple_get (ecard1, E_CARD_SIMPLE_FIELD_CATEGORIES); - categories2 = e_card_simple_get (ecard2, E_CARD_SIMPLE_FIELD_CATEGORIES); + categories1 = e_card_simple_get (ecard1, E_CONTACT_CATEGORIES); + categories2 = e_card_simple_get (ecard2, E_CONTACT_CATEGORIES); equal = !strcmp (categories1, categories2); @@ -2363,6 +2085,19 @@ category_compare (ECardSimple *ecard1, ECardSimple *ecard2) g_free (categories2); return equal; +#endif +} + +static void +photo_populate (EContact *contact, struct berval **ber_values) +{ + if (ber_values && ber_values[0]) { + EContactPhoto photo; + photo.data = ber_values[0]->bv_val; + photo.length = ber_values[0]->bv_len; + + e_contact_set (contact, E_CONTACT_PHOTO, &photo); + } } typedef struct { @@ -2670,6 +2405,58 @@ func_endswith(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data return r; } +static ESExpResult * +func_exists(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data) +{ + PASBackendLDAPSExpData *ldap_data = data; + ESExpResult *r; + + if (argc == 1 + && argv[0]->type == ESEXP_RES_STRING) { + char *propname = argv[0]->value.string; + + if (!strcmp (propname, "x-evolution-any-field")) { + int i; + int query_length; + char *big_query; + char *match_str; + + match_str = g_strdup("=*)"); + + query_length = 3; /* strlen ("(|") + strlen (")") */ + + for (i = 0; i < num_prop_infos; i ++) { + query_length += 1 /* strlen ("(") */ + strlen(prop_info[i].ldap_attr) + strlen (match_str); + } + + big_query = g_malloc0(query_length + 1); + strcat (big_query, "(|"); + for (i = 0; i < num_prop_infos; i ++) { + strcat (big_query, "("); + strcat (big_query, prop_info[i].ldap_attr); + strcat (big_query, match_str); + } + strcat (big_query, ")"); + + ldap_data->list = g_list_prepend(ldap_data->list, big_query); + + g_free (match_str); + } + else { + char *ldap_attr = query_prop_to_ldap(propname); + + if (ldap_attr) + ldap_data->list = g_list_prepend(ldap_data->list, + g_strdup_printf("(%s=*)", ldap_attr)); + } + } + + r = e_sexp_result_new(f, ESEXP_RES_BOOL); + r->value.bool = FALSE; + + return r; +} + /* 'builtin' functions */ static struct { char *name; @@ -2684,10 +2471,11 @@ static struct { { "is", func_is, 0 }, { "beginswith", func_beginswith, 0 }, { "endswith", func_endswith, 0 }, + { "exists", func_exists, 0 }, }; static gchar * -pas_backend_ldap_build_query (PASBackendLDAP *bl, gchar *query) +pas_backend_ldap_build_query (PASBackendLDAP *bl, const char *query) { ESExp *sexp; ESExpResult *r; @@ -2743,7 +2531,7 @@ query_prop_to_ldap(gchar *query_prop) int i; for (i = 0; i < num_prop_infos; i ++) - if (!strcmp (query_prop, prop_info[i].query_prop)) + if (!strcmp (query_prop, e_contact_field_name (prop_info[i].field_id))) return prop_info[i].ldap_attr; return NULL; @@ -2752,31 +2540,22 @@ query_prop_to_ldap(gchar *query_prop) typedef struct { LDAPOp op; - PASBackendLDAPBookView *view; - - /* grouping stuff */ - GList *pending_adds; /* the cards we're sending */ - int num_pending_adds; /* the number waiting to be sent */ - int target_pending_adds; /* the cutoff that forces a flush to the client, if it happens before the timeout */ - int num_sent_this_time; /* the number of cards we sent to the client before the most recent timeout */ - int num_sent_last_time; /* the number of cards we sent to the client before the previous timeout */ - glong grouping_time_start; - + PASBookView *view; + /* used by search_handler to only send the status messages once */ gboolean notified_receiving_results; } LDAPSearchOp; -static ECardSimple * -build_card_from_entry (LDAP *ldap, LDAPMessage *e, GList **existing_objectclasses) +static EContact * +build_contact_from_entry (LDAP *ldap, LDAPMessage *e, GList **existing_objectclasses) { - ECard *ecard = e_card_new (""); - ECardSimple *card = e_card_simple_new (ecard); + EContact *contact = e_contact_new (); char *dn; char *attr; BerElement *ber = NULL; dn = ldap_get_dn(ldap, e); - e_card_simple_set_id (card, dn); + e_contact_set (contact, E_CONTACT_UID, dn); ldap_memfree (dn); for (attr = ldap_first_attribute (ldap, e, &ber); attr; @@ -2799,24 +2578,41 @@ build_card_from_entry (LDAP *ldap, LDAPMessage *e, GList **existing_objectclasse break; } + printf ("attr = %s, ", attr); + printf ("info = %p\n", info); + if (info) { - values = ldap_get_values (ldap, e, attr); + if (info->prop_type & PROP_WRITE_ONLY) + continue; + + if (info->prop_type & PROP_TYPE_BINARY) { + struct berval **ber_values = ldap_get_values_len (ldap, e, attr); - if (values) { - if (info->prop_type & PROP_TYPE_STRING) { - /* if it's a normal property just set the string */ - if (values[0]) - e_card_simple_set (card, info->field_id, values[0]); + if (ber_values) { + info->binary_populate_contact_func (contact, ber_values); + ldap_value_free_len (ber_values); } - else if (info->prop_type & PROP_TYPE_COMPLEX) { - /* if it's a list call the ecard-populate function, - which calls g_object_set to set the property */ - info->populate_ecard_func(card, - values); + } + else { + values = ldap_get_values (ldap, e, attr); + + if (values) { + if (info->prop_type & PROP_TYPE_STRING) { + printf ("value = %s\n", values[0]); + /* if it's a normal property just set the string */ + if (values[0]) + e_contact_set (contact, info->field_id, values[0]); + } + else if (info->prop_type & PROP_TYPE_COMPLEX) { + /* if it's a list call the contact-populate function, + which calls g_object_set to set the property */ + info->populate_contact_func(contact, + values); + } + + ldap_value_free (values); } - - ldap_value_free (values); } } } @@ -2827,11 +2623,7 @@ build_card_from_entry (LDAP *ldap, LDAPMessage *e, GList **existing_objectclasse if (ber) ber_free (ber, 0); - e_card_simple_sync_card (card); - - g_object_unref (ecard); - - return card; + return contact; } static gboolean @@ -2840,10 +2632,7 @@ poll_ldap (PASBackendLDAP *bl) LDAP *ldap = bl->priv->ldap; int rc; LDAPMessage *res; - GTimeVal cur_time; - glong cur_millis; struct timeval timeout; - EIterator *iter; if (!bl->priv->active_ops) { g_warning ("poll_ldap being called for backend with no active operations"); @@ -2880,81 +2669,20 @@ poll_ldap (PASBackendLDAP *bl) } } - g_get_current_time (&cur_time); - cur_millis = TV_TO_MILLIS (cur_time); - - iter = e_list_get_iterator (bl->priv->book_views); - while (e_iterator_is_valid (iter)) { - PASBackendLDAPBookView *view = (PASBackendLDAPBookView *)e_iterator_get (iter); - if (view->search_op) { - bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), NULL); - - ldap_search_op_timeout (view->search_op, cur_millis); - - bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), NULL); - } - e_iterator_next (iter); - } - g_object_unref (iter); - return TRUE; } static void -send_pending_adds (LDAPSearchOp *search_op) -{ - search_op->num_sent_this_time += search_op->num_pending_adds; - pas_book_view_notify_add (search_op->op.view, search_op->pending_adds); - g_list_foreach (search_op->pending_adds, (GFunc)g_free, NULL); - g_list_free (search_op->pending_adds); - search_op->pending_adds = NULL; - search_op->num_pending_adds = 0; -} - -static void -ldap_search_op_timeout (LDAPOp *op, glong cur_millis) -{ - LDAPSearchOp *search_op = (LDAPSearchOp*)op; - - if (cur_millis - search_op->grouping_time_start > GROUPING_MINIMUM_WAIT) { - - if (search_op->num_pending_adds >= search_op->target_pending_adds) - send_pending_adds (search_op); - - if (cur_millis - search_op->grouping_time_start > GROUPING_MAXIMUM_WAIT) { - GTimeVal new_start; - - if (search_op->num_pending_adds) - send_pending_adds (search_op); - search_op->target_pending_adds = MIN (GROUPING_MAXIMUM_SIZE, - (search_op->num_sent_this_time + search_op->num_sent_last_time) / 2); - search_op->target_pending_adds = MAX (search_op->target_pending_adds, 1); - -#ifdef PERFORMANCE_SPEW - printf ("num sent this time %d, last time %d, target pending adds set to %d\n", - search_op->num_sent_this_time, - search_op->num_sent_last_time, - search_op->target_pending_adds); -#endif - g_get_current_time (&new_start); - search_op->grouping_time_start = TV_TO_MILLIS (new_start); - search_op->num_sent_last_time = search_op->num_sent_this_time; - search_op->num_sent_this_time = 0; - } - } -} - -static void ldap_search_handler (LDAPOp *op, LDAPMessage *res) { LDAPSearchOp *search_op = (LDAPSearchOp*)op; - PASBackendLDAPBookView *view = search_op->view; + PASBookView *view = search_op->view; PASBackendLDAP *bl = PAS_BACKEND_LDAP (op->backend); LDAP *ldap = bl->priv->ldap; LDAPMessage *e; int msg_type; - bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), NULL); + bonobo_object_dup_ref(bonobo_object_corba_objref(BONOBO_OBJECT(view)), NULL); if (!search_op->notified_receiving_results) { search_op->notified_receiving_results = TRUE; @@ -2966,13 +2694,11 @@ ldap_search_handler (LDAPOp *op, LDAPMessage *res) e = ldap_first_entry(ldap, res); while (NULL != e) { - ECardSimple *card = build_card_from_entry (ldap, e, NULL); + EContact *contact = build_contact_from_entry (ldap, e, NULL); - search_op->pending_adds = g_list_append (search_op->pending_adds, - e_card_simple_get_vcard_assume_utf8 (card)); - search_op->num_pending_adds ++; + pas_book_view_notify_update (view, contact); - g_object_unref (card); + g_object_unref (contact); e = ldap_next_entry(ldap, e); } @@ -2985,31 +2711,25 @@ ldap_search_handler (LDAPOp *op, LDAPMessage *res) g_warning ("search returned %d\n", ldap_error); - /* the entry that marks the end of our search */ - if (search_op->num_pending_adds) - send_pending_adds (search_op); - if (ldap_error == LDAP_TIMELIMIT_EXCEEDED) - pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_BookViewListener_SearchTimeLimitExceeded); + pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_SearchTimeLimitExceeded); else if (ldap_error == LDAP_SIZELIMIT_EXCEEDED) - pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_BookViewListener_SearchSizeLimitExceeded); + pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_SearchSizeLimitExceeded); else if (ldap_error == LDAP_SUCCESS) - pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_BookViewListener_Success); + pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_Success); else - pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_BookViewListener_OtherError); + pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_OtherError); ldap_op_finished (op); } else { g_warning ("unhandled search result type %d returned", msg_type); - if (search_op->num_pending_adds) - send_pending_adds (search_op); - pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_BookViewListener_OtherError); + pas_book_view_notify_complete (search_op->op.view, GNOME_Evolution_Addressbook_OtherError); ldap_op_finished (op); } - bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view->book_view)), NULL); + bonobo_object_release_unref(bonobo_object_corba_objref(BONOBO_OBJECT(view)), NULL); } static void @@ -3017,14 +2737,11 @@ ldap_search_dtor (LDAPOp *op) { LDAPSearchOp *search_op = (LDAPSearchOp*) op; +#if notyet /* unhook us from our PASBackendLDAPBookView */ if (search_op->view) search_op->view->search_op = NULL; - - g_list_foreach (search_op->pending_adds, (GFunc)g_free, NULL); - g_list_free (search_op->pending_adds); - search_op->pending_adds = NULL; - search_op->num_pending_adds = 0; +#endif g_free (search_op); } @@ -3032,22 +2749,21 @@ ldap_search_dtor (LDAPOp *op) static void pas_backend_ldap_search (PASBackendLDAP *bl, PASBook *book, - PASBackendLDAPBookView *view) + PASBookView *view) { char *ldap_query; - ldap_query = pas_backend_ldap_build_query(bl, view->search); + ldap_query = pas_backend_ldap_build_query (bl, pas_book_view_get_card_query (view)); if (ldap_query != NULL) { LDAP *ldap = bl->priv->ldap; int ldap_err; - GTimeVal search_start; int search_msgid; printf ("searching server using filter: %s\n", ldap_query); do { - book_view_notify_status (view->book_view, _("Searching...")); + book_view_notify_status (view, _("Searching...")); ldap_err = ldap_search_ext (ldap, bl->priv->ldap_rootdn, bl->priv->ldap_scope, @@ -3056,33 +2772,30 @@ pas_backend_ldap_search (PASBackendLDAP *bl, NULL, /* XXX */ NULL, /* XXX */ NULL, /* XXX timeout */ - view->limit, &search_msgid); - } while (pas_backend_ldap_reconnect (bl, view->book_view, ldap_err)); + 0 /* XXX we need this back in view->limit*/, &search_msgid); + } while (pas_backend_ldap_reconnect (bl, view, ldap_err)); g_free (ldap_query); if (ldap_err != LDAP_SUCCESS) { - book_view_notify_status (view->book_view, ldap_err2string(ldap_err)); + book_view_notify_status (view, ldap_err2string(ldap_err)); return; } else if (search_msgid == -1) { - book_view_notify_status (view->book_view, + book_view_notify_status (view, _("Error performing search")); return; } else { LDAPSearchOp *op = g_new0 (LDAPSearchOp, 1); - op->target_pending_adds = GROUPING_INITIAL_SIZE; - - g_get_current_time (&search_start); - op->grouping_time_start = TV_TO_MILLIS (search_start); - op->view = view; +#if notyet view->search_op = (LDAPOp*)op; +#endif - ldap_op_add ((LDAPOp*)op, PAS_BACKEND(bl), book, view->book_view, + ldap_op_add ((LDAPOp*)op, PAS_BACKEND(bl), book, view, search_msgid, ldap_search_handler, ldap_search_dtor); @@ -3090,106 +2803,49 @@ pas_backend_ldap_search (PASBackendLDAP *bl, return; } else { - pas_book_view_notify_complete (view->book_view, - GNOME_Evolution_Addressbook_BookViewListener_InvalidQuery); + pas_book_view_notify_complete (view, + GNOME_Evolution_Addressbook_InvalidQuery); return; } } static void -ldap_get_view (PASBackend *backend, - PASBook *book, - const char *search, - GNOME_Evolution_Addressbook_BookViewListener listener, - int limit) -{ - PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - PASBookView *book_view; - PASBackendLDAPBookView *view; - - book_view = pas_book_view_new (listener); - - bonobo_object_ref(BONOBO_OBJECT(book)); - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); - - view = g_new0(PASBackendLDAPBookView, 1); - view->book_view = book_view; - view->search = g_strdup(search); - view->card_sexp = pas_backend_card_sexp_new (view->search); - view->blpriv = bl->priv; - view->limit = limit; - - e_list_append(bl->priv->book_views, view); - - pas_book_respond_get_book_view (book, - (book_view != NULL - ? GNOME_Evolution_Addressbook_BookListener_Success - : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */), - book_view); - - pas_backend_ldap_search (bl, book, view); - - bonobo_object_unref (BONOBO_OBJECT (book_view)); -} - -static void -pas_backend_ldap_process_get_book_view (PASBackend *backend, - PASBook *book, - PASGetBookViewRequest *req) -{ - PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - - ldap_get_view (backend, book, req->search, req->listener, - bl->priv->ldap_limit); -} - -static void -pas_backend_ldap_process_get_completion_view (PASBackend *backend, - PASBook *book, - PASGetCompletionViewRequest *req) +pas_backend_ldap_process_start_book_view (PASBackend *backend, + PASBookView *view) { PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - ldap_get_view (backend, book, req->search, req->listener, - MIN (bl->priv->ldap_limit, 100)); + pas_backend_ldap_search (bl, NULL /* XXX ugh */, view); } static void pas_backend_ldap_process_get_changes (PASBackend *backend, PASBook *book, - PASGetChangesRequest *req) + const char *change_id) { /* FIXME: implement */ } -static void -pas_backend_ldap_process_check_connection (PASBackend *backend, - PASBook *book, - PASCheckConnectionRequest *req) -{ - PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - - pas_book_report_connection (book, bl->priv->connected); -} - #define LDAP_SIMPLE_PREFIX "ldap/simple-" #define SASL_PREFIX "sasl/" static void pas_backend_ldap_process_authenticate_user (PASBackend *backend, PASBook *book, - PASAuthenticateUserRequest *req) + const char *user, + const char *passwd, + const char *auth_method) { PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); int ldap_error; char *dn = NULL; - if (!strncasecmp (req->auth_method, LDAP_SIMPLE_PREFIX, strlen (LDAP_SIMPLE_PREFIX))) { + if (!strncasecmp (auth_method, LDAP_SIMPLE_PREFIX, strlen (LDAP_SIMPLE_PREFIX))) { - if (!strcmp (req->auth_method, "ldap/simple-email")) { + if (!strcmp (auth_method, "ldap/simple-email")) { LDAPMessage *res, *e; - char *query = g_strdup_printf ("(mail=%s)", req->user); + char *query = g_strdup_printf ("(mail=%s)", user); ldap_error = ldap_search_s (bl->priv->ldap, bl->priv->ldap_rootdn, @@ -3211,37 +2867,37 @@ pas_backend_ldap_process_authenticate_user (PASBackend *backend, } else { pas_book_respond_authenticate_user (book, - GNOME_Evolution_Addressbook_BookListener_PermissionDenied); + GNOME_Evolution_Addressbook_PermissionDenied); return; } } - else if (!strcmp (req->auth_method, "ldap/simple-binddn")) { - dn = g_strdup (req->user); + else if (!strcmp (auth_method, "ldap/simple-binddn")) { + dn = g_strdup (user); } /* now authenticate against the DN we were either supplied or queried for */ printf ("simple auth as %s\n", dn); ldap_error = ldap_simple_bind_s(bl->priv->ldap, dn, - req->passwd); + passwd); pas_book_respond_authenticate_user (book, ldap_error_to_response (ldap_error)); } #ifdef ENABLE_SASL_BINDS - else if (!strncasecmp (req->auth_method, SASL_PREFIX, strlen (SASL_PREFIX))) { - g_print ("sasl bind (mech = %s) as %s", req->auth_method + strlen (SASL_PREFIX), req->user); + else if (!strncasecmp (auth_method, SASL_PREFIX, strlen (SASL_PREFIX))) { + g_print ("sasl bind (mech = %s) as %s", auth_method + strlen (SASL_PREFIX), user); ldap_error = ldap_sasl_bind_s (bl->priv->ldap, NULL, - req->auth_method + strlen (SASL_PREFIX), - req->passwd, + auth_method + strlen (SASL_PREFIX), + passwd, NULL, NULL, NULL); if (ldap_error == LDAP_NOT_SUPPORTED) pas_book_respond_authenticate_user (book, - GNOME_Evolution_Addressbook_BookListener_UnsupportedAuthenticationMethod); + GNOME_Evolution_Addressbook_UnsupportedAuthenticationMethod); else pas_book_respond_authenticate_user (book, ldap_error_to_response (ldap_error)); @@ -3249,13 +2905,13 @@ pas_backend_ldap_process_authenticate_user (PASBackend *backend, #endif else { pas_book_respond_authenticate_user (book, - GNOME_Evolution_Addressbook_BookListener_UnsupportedAuthenticationMethod); + GNOME_Evolution_Addressbook_UnsupportedAuthenticationMethod); return; } if (ldap_error == LDAP_SUCCESS) { bl->priv->auth_dn = dn; - bl->priv->auth_passwd = g_strdup (req->passwd); + bl->priv->auth_passwd = g_strdup (passwd); pas_backend_set_is_writable (backend, TRUE); @@ -3281,33 +2937,32 @@ pas_backend_ldap_process_authenticate_user (PASBackend *backend, static void pas_backend_ldap_process_get_supported_fields (PASBackend *backend, - PASBook *book, - PASGetSupportedFieldsRequest *req) + PASBook *book) { PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); pas_book_respond_get_supported_fields (book, - GNOME_Evolution_Addressbook_BookListener_Success, + GNOME_Evolution_Addressbook_Success, bl->priv->supported_fields); } static void pas_backend_ldap_process_get_supported_auth_methods (PASBackend *backend, - PASBook *book, - PASGetSupportedAuthMethodsRequest *req) + PASBook *book) { PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); pas_book_respond_get_supported_auth_methods (book, - GNOME_Evolution_Addressbook_BookListener_Success, + GNOME_Evolution_Addressbook_Success, bl->priv->supported_auth_methods); } -static GNOME_Evolution_Addressbook_BookListener_CallStatus +static GNOME_Evolution_Addressbook_CallStatus pas_backend_ldap_load_uri (PASBackend *backend, - const char *uri) + const char *uri, + gboolean only_if_exists) { PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); LDAPURLDesc *lud; @@ -3383,17 +3038,7 @@ pas_backend_ldap_load_uri (PASBackend *backend, return pas_backend_ldap_connect (bl); } else - return GNOME_Evolution_Addressbook_BookListener_OtherError; -} - -/* Get_uri handler for the addressbook LDAP backend */ -static const char * -pas_backend_ldap_get_uri (PASBackend *backend) -{ - PASBackendLDAP *bl; - - bl = PAS_BACKEND_LDAP (backend); - return bl->priv->uri; + return GNOME_Evolution_Addressbook_OtherError; } static char* @@ -3459,13 +3104,15 @@ pas_backend_ldap_dispose (GObject *object) g_source_remove (bl->priv->poll_timeout); } - g_object_unref (bl->priv->book_views); - - if (bl->priv->supported_fields) - g_object_unref (bl->priv->supported_fields); + if (bl->priv->supported_fields) { + g_list_foreach (bl->priv->supported_fields, (GFunc)g_free, NULL); + g_list_free (bl->priv->supported_fields); + } - if (bl->priv->supported_auth_methods) - g_object_unref (bl->priv->supported_auth_methods); + if (bl->priv->supported_auth_methods) { + g_list_foreach (bl->priv->supported_auth_methods, (GFunc)g_free, NULL); + g_list_free (bl->priv->supported_auth_methods); + } g_free (bl->priv->uri); @@ -3492,17 +3139,13 @@ pas_backend_ldap_class_init (PASBackendLDAPClass *klass) /* Set the virtual methods. */ parent_class->load_uri = pas_backend_ldap_load_uri; - parent_class->get_uri = pas_backend_ldap_get_uri; parent_class->get_static_capabilities = pas_backend_ldap_get_static_capabilities; - parent_class->create_card = pas_backend_ldap_process_create_card; - parent_class->remove_cards = pas_backend_ldap_process_remove_cards; - parent_class->modify_card = pas_backend_ldap_process_modify_card; - parent_class->check_connection = pas_backend_ldap_process_check_connection; - parent_class->get_vcard = pas_backend_ldap_process_get_vcard; - parent_class->get_cursor = pas_backend_ldap_process_get_cursor; - parent_class->get_book_view = pas_backend_ldap_process_get_book_view; - parent_class->get_completion_view = pas_backend_ldap_process_get_completion_view; + parent_class->create_contact = pas_backend_ldap_process_create_contact; + parent_class->remove_contacts = pas_backend_ldap_process_remove_contacts; + parent_class->modify_contact = pas_backend_ldap_process_modify_contact; + parent_class->get_contact = pas_backend_ldap_process_get_contact; + parent_class->start_book_view = pas_backend_ldap_process_start_book_view; parent_class->get_changes = pas_backend_ldap_process_get_changes; parent_class->authenticate_user = pas_backend_ldap_process_authenticate_user; parent_class->get_supported_fields = pas_backend_ldap_process_get_supported_fields; @@ -3518,11 +3161,11 @@ pas_backend_ldap_init (PASBackendLDAP *backend) priv = g_new0 (PASBackendLDAPPrivate, 1); - priv->supported_fields = e_list_new ((EListCopyFunc)g_strdup, (EListFreeFunc)g_free, NULL); - priv->ldap_limit = 100; - priv->id_to_op = g_hash_table_new (g_int_hash, g_int_equal); - priv->poll_timeout = -1; - priv->book_views = e_list_new (NULL, NULL, NULL); + priv->supported_fields = NULL; + priv->supported_auth_methods = NULL; + priv->ldap_limit = 100; + priv->id_to_op = g_hash_table_new (g_int_hash, g_int_equal); + priv->poll_timeout = -1; backend->priv = priv; } diff --git a/addressbook/backend/pas/pas-backend-summary.c b/addressbook/backend/pas/pas-backend-summary.c index 6c2c9a45c8..15f12cebc1 100644 --- a/addressbook/backend/pas/pas-backend-summary.c +++ b/addressbook/backend/pas/pas-backend-summary.c @@ -33,7 +33,7 @@ #include <gal/widgets/e-unicode.h> -#include "ebook/e-card-simple.h" +#include "ebook/e-contact.h" #include "pas-backend-summary.h" #include "e-util/e-sexp.h" @@ -689,36 +689,29 @@ pas_backend_summary_save (PASBackendSummary *summary) } void -pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard) +pas_backend_summary_add_contact (PASBackendSummary *summary, EContact *contact) { - ECard *card; - ECardSimple *simple; PASBackendSummaryItem *new_item; - card = e_card_new ((char*)vcard); - simple = e_card_simple_new (card); - - new_item = g_new (PASBackendSummaryItem, 1); - - new_item->id = g_strdup (e_card_simple_get_id (simple)); - new_item->nickname = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_NICKNAME); - new_item->full_name = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_FULL_NAME); - new_item->given_name = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_GIVEN_NAME); - new_item->surname = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_FAMILY_NAME); - new_item->file_as = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_FILE_AS); - new_item->email_1 = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_EMAIL); - new_item->email_2 = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_EMAIL_2); - new_item->email_3 = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_EMAIL_3); - new_item->list = e_card_evolution_list (card); - new_item->list_show_addresses = e_card_evolution_list_show_addresses (card); - new_item->wants_html = card->wants_html; - new_item->wants_html_set = card->wants_html_set; + new_item = g_new0 (PASBackendSummaryItem, 1); + + new_item->id = e_contact_get (contact, E_CONTACT_UID); + new_item->nickname = e_contact_get (contact, E_CONTACT_NICKNAME); + new_item->full_name = e_contact_get (contact, E_CONTACT_FULL_NAME); + new_item->given_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); + new_item->surname = e_contact_get (contact, E_CONTACT_FAMILY_NAME); + new_item->file_as = e_contact_get (contact, E_CONTACT_FILE_AS); + new_item->email_1 = e_contact_get (contact, E_CONTACT_EMAIL_1); + new_item->email_2 = e_contact_get (contact, E_CONTACT_EMAIL_2); + new_item->email_3 = e_contact_get (contact, E_CONTACT_EMAIL_3); + new_item->list = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_IS_LIST)); + new_item->list_show_addresses = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_LIST_SHOW_ADDRESSES)); + new_item->wants_html = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_WANTS_HTML)); g_ptr_array_add (summary->priv->items, new_item); g_hash_table_insert (summary->priv->id_to_item, new_item->id, new_item); - g_object_unref (simple); - g_object_unref (card); + g_object_unref (contact); #ifdef SUMMARY_STATS summary->priv->size += sizeof (PASBackendSummaryItem); @@ -736,7 +729,7 @@ pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard) } void -pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id) +pas_backend_summary_remove_contact (PASBackendSummary *summary, const char *id) { PASBackendSummaryItem *item = g_hash_table_lookup (summary->priv->id_to_item, id); @@ -748,7 +741,7 @@ pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id) return; } - g_warning ("pas_backend_summary_remove_card: unable to locate id `%s'", id); + g_warning ("pas_backend_summary_remove_contact: unable to locate id `%s'", id); } static gboolean @@ -1056,31 +1049,26 @@ pas_backend_summary_get_summary_vcard(PASBackendSummary *summary, const char *id PASBackendSummaryItem *item = g_hash_table_lookup (summary->priv->id_to_item, id); if (item) { - ECard *card = e_card_new (""); - ECardSimple *simple = e_card_simple_new (card); + EContact *contact = e_contact_new (); char *vcard; - e_card_simple_set_id (simple, item->id); - e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FILE_AS, item->file_as); - e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_GIVEN_NAME, item->given_name); - e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FAMILY_NAME, item->surname); - e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_NICKNAME, item->nickname); - e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FULL_NAME, item->full_name); - e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL, item->email_1); - e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL_2, item->email_2); - e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL_3, item->email_3); + e_contact_set (contact, E_CONTACT_UID, item->id); + e_contact_set (contact, E_CONTACT_FILE_AS, item->file_as); + e_contact_set (contact, E_CONTACT_GIVEN_NAME, item->given_name); + e_contact_set (contact, E_CONTACT_FAMILY_NAME, item->surname); + e_contact_set (contact, E_CONTACT_NICKNAME, item->nickname); + e_contact_set (contact, E_CONTACT_FULL_NAME, item->full_name); + e_contact_set (contact, E_CONTACT_EMAIL_1, item->email_1); + e_contact_set (contact, E_CONTACT_EMAIL_2, item->email_2); + e_contact_set (contact, E_CONTACT_EMAIL_3, item->email_3); - e_card_simple_sync_card (simple); + e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (item->list)); + e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (item->list_show_addresses)); + e_contact_set (contact, E_CONTACT_WANTS_HTML, GINT_TO_POINTER (item->wants_html)); - card->list = item->list; - card->wants_html = item->wants_html; - card->wants_html_set = item->wants_html_set; - card->list_show_addresses = item->list_show_addresses; + vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); - vcard = e_card_simple_get_vcard (simple); - - g_object_unref (simple); - g_object_unref (card); + g_object_unref (contact); return vcard; } diff --git a/addressbook/backend/pas/pas-backend-summary.h b/addressbook/backend/pas/pas-backend-summary.h index 54083855d5..bb07e0fb27 100644 --- a/addressbook/backend/pas/pas-backend-summary.h +++ b/addressbook/backend/pas/pas-backend-summary.h @@ -26,6 +26,8 @@ #include <glib.h> #include <glib-object.h> +#include <pas/pas-types.h> +#include <ebook/e-contact.h> #define PAS_TYPE_BACKEND_SUMMARY (pas_backend_summary_get_type ()) #define PAS_BACKEND_SUMMARY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BACKEND_SUMMARY, PASBackendSummary)) @@ -36,14 +38,14 @@ typedef struct _PASBackendSummaryPrivate PASBackendSummaryPrivate; -typedef struct { +struct _PASBackendSummary{ GObject parent_object; PASBackendSummaryPrivate *priv; -} PASBackendSummary; +}; -typedef struct { +struct _PASBackendSummaryClass{ GObjectClass parent_class; -} PASBackendSummaryClass; +}; PASBackendSummary* pas_backend_summary_new (const char *summary_path, int flush_timeout_millis); @@ -55,8 +57,8 @@ gboolean pas_backend_summary_load (PASBackendSummary *summ /* returns FALSE if the save fails, TRUE if it succeeds (or isn't required due to no changes) */ gboolean pas_backend_summary_save (PASBackendSummary *summary); -void pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard); -void pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id); +void pas_backend_summary_add_contact (PASBackendSummary *summary, EContact *contact); +void pas_backend_summary_remove_contact (PASBackendSummary *summary, const char *id); void pas_backend_summary_touch (PASBackendSummary *summary); diff --git a/addressbook/backend/pas/pas-backend-sync.c b/addressbook/backend/pas/pas-backend-sync.c new file mode 100644 index 0000000000..45063eddc6 --- /dev/null +++ b/addressbook/backend/pas/pas-backend-sync.c @@ -0,0 +1,395 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Author: + * Chris Toshok (toshok@ximian.com) + * + * Copyright (C) 2003, Ximian, Inc. + */ + +#include <config.h> +#include "pas-backend-sync.h" +#include "pas-marshal.h" + +struct _PASBackendSyncPrivate { + int mumble; +}; + +static GObjectClass *parent_class; + +gboolean +pas_backend_sync_construct (PASBackendSync *backend) +{ + return TRUE; +} + +PASBackendSyncStatus +pas_backend_sync_create_contact (PASBackendSync *backend, + PASBook *book, + const char *vcard, + EContact **contact) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (vcard, GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (contact, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->create_contact_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->create_contact_sync) (backend, book, vcard, contact); +} + +PASBackendSyncStatus +pas_backend_sync_remove (PASBackendSync *backend, + PASBook *book) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->remove_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->remove_sync) (backend, book); +} + +PASBackendSyncStatus +pas_backend_sync_remove_contacts (PASBackendSync *backend, + PASBook *book, + GList *id_list, + GList **removed_ids) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (id_list, GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (removed_ids, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->remove_contacts_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->remove_contacts_sync) (backend, book, id_list, removed_ids); +} + +PASBackendSyncStatus +pas_backend_sync_modify_contact (PASBackendSync *backend, + PASBook *book, + const char *vcard, + EContact **contact) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (vcard, GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (contact, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->modify_contact_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->modify_contact_sync) (backend, book, vcard, contact); +} + +PASBackendSyncStatus +pas_backend_sync_get_contact (PASBackendSync *backend, + PASBook *book, + const char *id, + char **vcard) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (id, GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (vcard, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->get_contact_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->get_contact_sync) (backend, book, id, vcard); +} + +PASBackendSyncStatus +pas_backend_sync_get_contact_list (PASBackendSync *backend, + PASBook *book, + const char *query, + GList **contacts) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (query, GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (contacts, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->get_contact_list_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->get_contact_list_sync) (backend, book, query, contacts); +} + +PASBackendSyncStatus +pas_backend_sync_get_changes (PASBackendSync *backend, + PASBook *book, + const char *change_id, + GList **changes) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (change_id, GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (changes, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->get_changes_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->get_changes_sync) (backend, book, change_id, changes); +} + +PASBackendSyncStatus +pas_backend_sync_authenticate_user (PASBackendSync *backend, + PASBook *book, + const char *user, + const char *passwd, + const char *auth_method) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (user && passwd && auth_method, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync) (backend, book, user, passwd, auth_method); +} + +PASBackendSyncStatus +pas_backend_sync_get_supported_fields (PASBackendSync *backend, + PASBook *book, + GList **fields) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (fields, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->get_supported_fields_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->get_supported_fields_sync) (backend, book, fields); +} + +PASBackendSyncStatus +pas_backend_sync_get_supported_auth_methods (PASBackendSync *backend, + PASBook *book, + GList **methods) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND_SYNC (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (methods, GNOME_Evolution_Addressbook_OtherError); + + g_assert (PAS_BACKEND_SYNC_GET_CLASS (backend)->get_supported_auth_methods_sync); + + return (* PAS_BACKEND_SYNC_GET_CLASS (backend)->get_supported_auth_methods_sync) (backend, book, methods); +} + +static void +_pas_backend_remove (PASBackend *backend, + PASBook *book) +{ + PASBackendSyncStatus status; + + status = pas_backend_sync_remove (PAS_BACKEND_SYNC (backend), book); + + pas_book_respond_remove (book, status); +} + +static void +_pas_backend_create_contact (PASBackend *backend, + PASBook *book, + const char *vcard) +{ + PASBackendSyncStatus status; + EContact *contact; + + status = pas_backend_sync_create_contact (PAS_BACKEND_SYNC (backend), book, vcard, &contact); + + pas_book_respond_create (book, status, contact); + + g_object_unref (contact); +} + +static void +_pas_backend_remove_contacts (PASBackend *backend, + PASBook *book, + GList *id_list) +{ + PASBackendSyncStatus status; + GList *ids = NULL; + + status = pas_backend_sync_remove_contacts (PAS_BACKEND_SYNC (backend), book, id_list, &ids); + + pas_book_respond_remove_contacts (book, status, ids); + + g_list_free (ids); +} + +static void +_pas_backend_modify_contact (PASBackend *backend, + PASBook *book, + const char *vcard) +{ + PASBackendSyncStatus status; + EContact *contact; + + status = pas_backend_sync_modify_contact (PAS_BACKEND_SYNC (backend), book, vcard, &contact); + + pas_book_respond_modify (book, status, contact); + + g_object_unref (contact); +} + +static void +_pas_backend_get_contact (PASBackend *backend, + PASBook *book, + const char *id) +{ + PASBackendSyncStatus status; + char *vcard; + + status = pas_backend_sync_get_contact (PAS_BACKEND_SYNC (backend), book, id, &vcard); + + pas_book_respond_get_contact (book, status, vcard); + + g_free (vcard); +} + +static void +_pas_backend_get_contact_list (PASBackend *backend, + PASBook *book, + const char *query) +{ + PASBackendSyncStatus status; + GList *cards = NULL; + + status = pas_backend_sync_get_contact_list (PAS_BACKEND_SYNC (backend), book, query, &cards); + + pas_book_respond_get_contact_list (book, status, cards); +} + +static void +_pas_backend_get_changes (PASBackend *backend, + PASBook *book, + const char *change_id) +{ + PASBackendSyncStatus status; + GList *changes = NULL; + + status = pas_backend_sync_get_changes (PAS_BACKEND_SYNC (backend), book, change_id, &changes); + + pas_book_respond_get_changes (book, status, changes); + + /* XXX free view? */ +} + +static void +_pas_backend_authenticate_user (PASBackend *backend, + PASBook *book, + const char *user, + const char *passwd, + const char *auth_method) +{ + PASBackendSyncStatus status; + + status = pas_backend_sync_authenticate_user (PAS_BACKEND_SYNC (backend), book, user, passwd, auth_method); + + pas_book_respond_authenticate_user (book, status); +} + +static void +_pas_backend_get_supported_fields (PASBackend *backend, + PASBook *book) +{ + PASBackendSyncStatus status; + GList *fields = NULL; + + status = pas_backend_sync_get_supported_fields (PAS_BACKEND_SYNC (backend), book, &fields); + + pas_book_respond_get_supported_fields (book, status, fields); + + g_list_foreach (fields, (GFunc)g_free, NULL); + g_list_free (fields); +} + +static void +_pas_backend_get_supported_auth_methods (PASBackend *backend, + PASBook *book) +{ + PASBackendSyncStatus status; + GList *methods = NULL; + + status = pas_backend_sync_get_supported_auth_methods (PAS_BACKEND_SYNC (backend), book, &methods); + + pas_book_respond_get_supported_auth_methods (book, status, methods); + + g_list_foreach (methods, (GFunc)g_free, NULL); + g_list_free (methods); +} + +static void +pas_backend_sync_init (PASBackendSync *backend) +{ + PASBackendSyncPrivate *priv; + + priv = g_new0 (PASBackendSyncPrivate, 1); + + backend->priv = priv; +} + +static void +pas_backend_sync_dispose (GObject *object) +{ + PASBackendSync *backend; + + backend = PAS_BACKEND_SYNC (object); + + if (backend->priv) { + g_free (backend->priv); + + backend->priv = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +pas_backend_sync_class_init (PASBackendSyncClass *klass) +{ + GObjectClass *object_class; + PASBackendClass *backend_class = PAS_BACKEND_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class = (GObjectClass *) klass; + + backend_class->remove = _pas_backend_remove; + backend_class->create_contact = _pas_backend_create_contact; + backend_class->remove_contacts = _pas_backend_remove_contacts; + backend_class->modify_contact = _pas_backend_modify_contact; + backend_class->get_contact = _pas_backend_get_contact; + backend_class->get_contact_list = _pas_backend_get_contact_list; + backend_class->get_changes = _pas_backend_get_changes; + backend_class->authenticate_user = _pas_backend_authenticate_user; + backend_class->get_supported_fields = _pas_backend_get_supported_fields; + backend_class->get_supported_auth_methods = _pas_backend_get_supported_auth_methods; + + object_class->dispose = pas_backend_sync_dispose; +} + +/** + * pas_backend_get_type: + */ +GType +pas_backend_sync_get_type (void) +{ + static GType type = 0; + + if (! type) { + GTypeInfo info = { + sizeof (PASBackendSyncClass), + NULL, /* base_class_init */ + NULL, /* base_class_finalize */ + (GClassInitFunc) pas_backend_sync_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PASBackendSync), + 0, /* n_preallocs */ + (GInstanceInitFunc) pas_backend_sync_init + }; + + type = g_type_register_static (PAS_TYPE_BACKEND, "PASBackendSync", &info, 0); + } + + return type; +} diff --git a/addressbook/backend/pas/pas-backend-sync.h b/addressbook/backend/pas/pas-backend-sync.h new file mode 100644 index 0000000000..2e176d9f5d --- /dev/null +++ b/addressbook/backend/pas/pas-backend-sync.h @@ -0,0 +1,81 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + */ + +#ifndef __PAS_BACKEND_SYNC_H__ +#define __PAS_BACKEND_SYNC_H__ + +#include <glib.h> +#include <pas/pas-types.h> +#include <pas/pas-backend.h> +#include <pas/addressbook.h> + +#define PAS_TYPE_BACKEND_SYNC (pas_backend_sync_get_type ()) +#define PAS_BACKEND_SYNC(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BACKEND_SYNC, PASBackendSync)) +#define PAS_BACKEND_SYNC_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PAS_TYPE_BACKEND_SYNC, PASBackendSyncClass)) +#define PAS_IS_BACKEND_SYNC(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAS_TYPE_BACKEND_SYNC)) +#define PAS_IS_BACKEND_SYNC_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PAS_TYPE_BACKEND_SYNC)) +#define PAS_BACKEND_SYNC_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), PAS_TYPE_BACKEND_SYNC, PASBackendSyncClass)) + +typedef struct _PASBackendSyncPrivate PASBackendSyncPrivate; + +typedef GNOME_Evolution_Addressbook_CallStatus PASBackendSyncStatus; + +struct _PASBackendSync { + PASBackend parent_object; + PASBackendSyncPrivate *priv; +}; + +struct _PASBackendSyncClass { + PASBackendClass parent_class; + + /* Virtual methods */ + PASBackendSyncStatus (*remove_sync) (PASBackendSync *backend, PASBook *book); + PASBackendSyncStatus (*create_contact_sync) (PASBackendSync *backend, PASBook *book, + const char *vcard, EContact **contact); + PASBackendSyncStatus (*remove_contacts_sync) (PASBackendSync *backend, PASBook *book, + GList *id_list, GList **removed_ids); + PASBackendSyncStatus (*modify_contact_sync) (PASBackendSync *backend, PASBook *book, + const char *vcard, EContact **contact); + PASBackendSyncStatus (*get_contact_sync) (PASBackendSync *backend, PASBook *book, + const char *id, char **vcard); + PASBackendSyncStatus (*get_contact_list_sync) (PASBackendSync *backend, PASBook *book, + const char *query, GList **contacts); + PASBackendSyncStatus (*get_changes_sync) (PASBackendSync *backend, PASBook *book, + const char *change_id, GList **changes); + PASBackendSyncStatus (*authenticate_user_sync) (PASBackendSync *backend, PASBook *book, + const char *user, + const char *passwd, + const char *auth_method); + PASBackendSyncStatus (*get_supported_fields_sync) (PASBackendSync *backend, PASBook *book, + GList **fields); + PASBackendSyncStatus (*get_supported_auth_methods_sync) (PASBackendSync *backend, PASBook *book, + GList **methods); + + /* Padding for future expansion */ + void (*_pas_reserved0) (void); + void (*_pas_reserved1) (void); + void (*_pas_reserved2) (void); + void (*_pas_reserved3) (void); + void (*_pas_reserved4) (void); + +}; + +typedef PASBackendSync * (*PASBackendSyncFactoryFn) (void); + +gboolean pas_backend_sync_construct (PASBackendSync *backend); + +GType pas_backend_sync_get_type (void); + +PASBackendSyncStatus pas_backend_sync_remove (PASBackendSync *backend, PASBook *book); +PASBackendSyncStatus pas_backend_sync_create_contact (PASBackendSync *backend, PASBook *book, const char *vcard, EContact **contact); +PASBackendSyncStatus pas_backend_sync_remove_contacts (PASBackendSync *backend, PASBook *book, GList *id_list, GList **removed_ids); +PASBackendSyncStatus pas_backend_sync_modify_contact (PASBackendSync *backend, PASBook *book, const char *vcard, EContact **contact); +PASBackendSyncStatus pas_backend_sync_get_contact (PASBackendSync *backend, PASBook *book, const char *id, char **vcard); +PASBackendSyncStatus pas_backend_sync_get_contact_list (PASBackendSync *backend, PASBook *book, const char *query, GList **contacts); +PASBackendSyncStatus pas_backend_sync_get_changes (PASBackendSync *backend, PASBook *book, const char *change_id, GList **changes); +PASBackendSyncStatus pas_backend_sync_authenticate_user (PASBackendSync *backend, PASBook *book, const char *user, const char *passwd, const char *auth_method); +PASBackendSyncStatus pas_backend_sync_get_supported_fields (PASBackendSync *backend, PASBook *book, GList **fields); +PASBackendSyncStatus pas_backend_sync_get_supported_auth_methods (PASBackendSync *backend, PASBook *book, GList **methods); + +#endif /* ! __PAS_BACKEND_SYNC_H__ */ diff --git a/addressbook/backend/pas/pas-backend-vcf.c b/addressbook/backend/pas/pas-backend-vcf.c new file mode 100644 index 0000000000..3765fd978e --- /dev/null +++ b/addressbook/backend/pas/pas-backend-vcf.c @@ -0,0 +1,632 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Author: + * Chris Toshok (toshok@ximian.com) + * + * Copyright (C) 2003, Ximian, Inc. + */ + +#include "config.h" +#include "pas-backend-vcf.h" +#include "pas-backend-card-sexp.h" +#include "pas-book.h" +#include "pas-book-view.h" + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <time.h> +#include <sys/stat.h> + +#include <gal/util/e-util.h> +#include <gal/widgets/e-unicode.h> + +#include <ebook/e-contact.h> +#include <libgnome/gnome-i18n.h> + +#define PAS_ID_PREFIX "pas-id-" +#define FILE_FLUSH_TIMEOUT 5000 + +static PASBackendSyncClass *pas_backend_vcf_parent_class; +typedef struct _PASBackendVCFBookView PASBackendVCFBookView; +typedef struct _PASBackendVCFSearchContext PASBackendVCFSearchContext; + +struct _PASBackendVCFPrivate { + char *uri; + char *filename; + GHashTable *contacts; + gboolean dirty; + int flush_timeout_tag; +}; + +static char * +pas_backend_vcf_create_unique_id () +{ + /* use a 32 counter and the 32 bit timestamp to make an id. + it's doubtful 2^32 id's will be created in a second, so we + should be okay. */ + static guint c = 0; + return g_strdup_printf (PAS_ID_PREFIX "%08lX%08X", time(NULL), c++); +} + +typedef struct { + PASBackendVCF *bvcf; + PASBook *book; + PASBookView *view; +} VCFBackendSearchClosure; + +static void +free_search_closure (VCFBackendSearchClosure *closure) +{ + g_free (closure); +} + +static void +foreach_search_compare (char *id, char *vcard_string, VCFBackendSearchClosure *closure) +{ + EContact *contact; + + contact = e_contact_new_from_vcard (vcard_string); + pas_book_view_notify_update (closure->view, contact); + g_object_unref (contact); +} + +static gboolean +pas_backend_vcf_search_timeout (gpointer data) +{ + VCFBackendSearchClosure *closure = data; + + g_hash_table_foreach (closure->bvcf->priv->contacts, + (GHFunc)foreach_search_compare, + closure); + + pas_book_view_notify_complete (closure->view, GNOME_Evolution_Addressbook_Success); + + free_search_closure (closure); + + return FALSE; +} + + +static void +pas_backend_vcf_search (PASBackendVCF *bvcf, + PASBookView *book_view) +{ + const char *query = pas_book_view_get_card_query (book_view); + VCFBackendSearchClosure *closure = g_new0 (VCFBackendSearchClosure, 1); + + if ( ! strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) + pas_book_view_notify_status_message (book_view, _("Loading...")); + else + pas_book_view_notify_status_message (book_view, _("Searching...")); + + closure->view = book_view; + closure->bvcf = bvcf; + + g_idle_add (pas_backend_vcf_search_timeout, closure); +} + +static void +insert_contact (PASBackendVCF *vcf, char *vcard) +{ + EContact *contact = e_contact_new_from_vcard (vcard); + char *id; + + id = e_contact_get (contact, E_CONTACT_UID); + if (id) + g_hash_table_insert (vcf->priv->contacts, + id, + e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30)); +} + +static void +load_file (PASBackendVCF *vcf) +{ + FILE *fp; + GString *str; + char buf[1024]; + + fp = fopen (vcf->priv->filename, "r"); + if (!fp) { + g_warning ("failed to open `%s' for reading", vcf->priv->filename); + return; + } + + str = g_string_new (""); + + while (fgets (buf, sizeof (buf), fp)) { + if (!strcmp (buf, "\r\n")) { + /* if the string has accumulated some stuff, create a contact for it and start over */ + if (str->len) { + insert_contact (vcf, str->str); + g_string_assign (str, ""); + } + } + else { + g_string_append (str, buf); + } + } + if (str->len) { + insert_contact (vcf, str->str); + } + + g_string_free (str, TRUE); + + fclose (fp); +} + +static void +foreach_build_list (char *id, char *vcard_string, GList **list) +{ + *list = g_list_append (*list, e_contact_new_from_vcard (vcard_string)); +} + +static gboolean +save_file (PASBackendVCF *vcf) +{ + GList *contacts = NULL; + GList *l; + char *new_path; + int fd, rv; + + g_hash_table_foreach (vcf->priv->contacts, (GHFunc)foreach_build_list, &contacts); + + new_path = g_strdup_printf ("%s.new", vcf->priv->filename); + + fd = open (new_path, O_CREAT | O_TRUNC | O_WRONLY, 0666); + + for (l = contacts; l; l = l->next) { + EContact *contact = l->data; + char *vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); + int len = strlen (vcard_str); + + rv = write (fd, vcard_str, len); + g_free (vcard_str); + if (rv < len) { + /* XXX */ + g_warning ("write failed. we need to handle short writes\n"); + close (fd); + unlink (new_path); + return FALSE; + } + + rv = write (fd, "\r\n", 2); + if (rv < 2) { + /* XXX */ + g_warning ("write failed. we need to handle short writes\n"); + close (fd); + unlink (new_path); + return FALSE; + } + } + + if (0 > rename (new_path, vcf->priv->filename)) { + g_warning ("Failed to rename %s: %s\n", vcf->priv->filename, strerror(errno)); + unlink (new_path); + return FALSE; + } + + g_list_foreach (contacts, (GFunc)g_object_unref, NULL); + g_list_free (contacts); + g_free (new_path); + + vcf->priv->dirty = FALSE; + + return TRUE; +} + +static gboolean +vcf_flush_file (gpointer data) +{ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (data); + + if (!bvcf->priv->dirty) { + bvcf->priv->flush_timeout_tag = 0; + return FALSE; + } + + if (!save_file (bvcf)) { + g_warning ("failed to flush the .vcf file to disk, will try again next timeout"); + return TRUE; + } + + bvcf->priv->flush_timeout_tag = 0; + return FALSE; +} + +static EContact * +do_create(PASBackendVCF *bvcf, + const char *vcard_req, + gboolean dirty_the_file) +{ + char *id; + EContact *contact; + char *vcard; + + id = pas_backend_vcf_create_unique_id (); + + contact = e_contact_new_from_vcard (vcard_req); + e_contact_set(contact, E_CONTACT_UID, id); + vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); + + g_hash_table_insert (bvcf->priv->contacts, id, vcard); + + if (dirty_the_file) { + bvcf->priv->dirty = TRUE; + + if (!bvcf->priv->flush_timeout_tag) + bvcf->priv->flush_timeout_tag = g_timeout_add (FILE_FLUSH_TIMEOUT, + vcf_flush_file, bvcf); + } + + return contact; +} + +static PASBackendSyncStatus +pas_backend_vcf_process_create_contact (PASBackendSync *backend, + PASBook *book, + const char *vcard, + EContact **contact) +{ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); + + *contact = do_create(bvcf, vcard, TRUE); + if (*contact) { + return GNOME_Evolution_Addressbook_Success; + } + else { + /* XXX need a different call status for this case, i + think */ + return GNOME_Evolution_Addressbook_ContactNotFound; + } +} + +static PASBackendSyncStatus +pas_backend_vcf_process_remove_contacts (PASBackendSync *backend, + PASBook *book, + GList *id_list, + GList **ids) +{ + /* FIXME: make this handle bulk deletes like the file backend does */ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); + char *id = id_list->data; + + if (!g_hash_table_remove (bvcf->priv->contacts, id)) { + return GNOME_Evolution_Addressbook_ContactNotFound; + } + else { + bvcf->priv->dirty = TRUE; + if (!bvcf->priv->flush_timeout_tag) + bvcf->priv->flush_timeout_tag = g_timeout_add (FILE_FLUSH_TIMEOUT, + vcf_flush_file, bvcf); + + *ids = g_list_append (*ids, id); + + return GNOME_Evolution_Addressbook_Success; + } +} + +static PASBackendSyncStatus +pas_backend_vcf_process_modify_contact (PASBackendSync *backend, + PASBook *book, + const char *vcard, + EContact **contact) +{ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); + char *old_id, *old_vcard_string; + const char *id; + + /* create a new ecard from the request data */ + *contact = e_contact_new_from_vcard (vcard); + id = e_contact_get_const (*contact, E_CONTACT_UID); + + if (!g_hash_table_lookup_extended (bvcf->priv->contacts, id, (gpointer)&old_id, (gpointer)&old_vcard_string)) { + return GNOME_Evolution_Addressbook_ContactNotFound; + } + else { + g_hash_table_insert (bvcf->priv->contacts, old_id, g_strdup (vcard)); + + g_free (old_vcard_string); + + return GNOME_Evolution_Addressbook_Success; + } +} + +static PASBackendSyncStatus +pas_backend_vcf_process_get_contact (PASBackendSync *backend, + PASBook *book, + const char *id, + char **vcard) +{ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); + char *v; + + v = g_hash_table_lookup (bvcf->priv->contacts, id); + + if (v) { + *vcard = g_strdup (v); + return GNOME_Evolution_Addressbook_Success; + } else { + *vcard = g_strdup (""); + return GNOME_Evolution_Addressbook_ContactNotFound; + } +} + + +typedef struct { + PASBackendVCF *bvcf; + gboolean search_needed; + PASBackendCardSExp *card_sexp; + GList *list; +} GetContactListClosure; + +static void +foreach_get_contact_compare (char *id, char *vcard_string, GetContactListClosure *closure) +{ + if ((!closure->search_needed) || pas_backend_card_sexp_match_vcard (closure->card_sexp, vcard_string)) { + closure->list = g_list_append (closure->list, g_strdup (vcard_string)); + } +} + +static PASBackendSyncStatus +pas_backend_vcf_process_get_contact_list (PASBackendSync *backend, + PASBook *book, + const char *query, + GList **contacts) +{ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); + const char *search = query; + GetContactListClosure closure; + + closure.bvcf = bvcf; + closure.search_needed = strcmp (search, "(contains \"x-evolution-any-field\" \"\")"); + closure.card_sexp = pas_backend_card_sexp_new (search); + closure.list = NULL; + + g_hash_table_foreach (bvcf->priv->contacts, (GHFunc)foreach_get_contact_compare, &closure); + + g_object_unref (closure.card_sexp); + + *contacts = closure.list; + return GNOME_Evolution_Addressbook_Success; +} + +static void +pas_backend_vcf_start_book_view (PASBackend *backend, + PASBookView *book_view) +{ + pas_backend_vcf_search (PAS_BACKEND_VCF (backend), book_view); +} + +static char * +pas_backend_vcf_extract_path_from_uri (const char *uri) +{ + g_assert (strncasecmp (uri, "vcf://", 6) == 0); + + return g_strdup (uri + 6); +} + +static PASBackendSyncStatus +pas_backend_vcf_process_authenticate_user (PASBackendSync *backend, + PASBook *book, + const char *user, + const char *passwd, + const char *auth_method) +{ + return GNOME_Evolution_Addressbook_Success; +} + +static PASBackendSyncStatus +pas_backend_vcf_process_get_supported_fields (PASBackendSync *backend, + PASBook *book, + GList **fields_out) +{ + GList *fields = NULL; + int i; + + /* XXX we need a way to say "we support everything", since the + vcf backend does */ + for (i = 0; i < E_CONTACT_FIELD_LAST; i ++) + fields = g_list_append (fields, (char*)e_contact_field_name (i)); + + *fields_out = fields; + return GNOME_Evolution_Addressbook_Success; +} + +#include "ximian-vcard.h" + +static GNOME_Evolution_Addressbook_CallStatus +pas_backend_vcf_load_uri (PASBackend *backend, + const char *uri, + gboolean only_if_exists) +{ + PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); + char *filename; + gboolean writable = FALSE; + int fd; + + g_free(bvcf->priv->uri); + bvcf->priv->uri = g_strdup (uri); + + bvcf->priv->filename = filename = pas_backend_vcf_extract_path_from_uri (uri); + + fd = open (filename, O_RDWR); + + bvcf->priv->contacts = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); + + if (fd != -1) { + writable = TRUE; + } else { + fd = open (filename, O_RDONLY); + + if (fd == -1) { + fd = open (filename, O_CREAT, 0666); + + if (fd != -1 && !only_if_exists) { + EContact *contact; + + contact = do_create(bvcf, XIMIAN_VCARD, FALSE); + save_file (bvcf); + + /* XXX check errors here */ + g_object_unref (contact); + + writable = TRUE; + } + } + } + + if (fd == -1) { + g_warning ("Failed to open addressbook at uri `%s'", uri); + g_warning ("error == %s", strerror(errno)); + return GNOME_Evolution_Addressbook_OtherError; + } + + close (fd); /* XXX ugh */ + load_file (bvcf); + + pas_backend_set_is_loaded (backend, TRUE); + pas_backend_set_is_writable (backend, writable); + + return GNOME_Evolution_Addressbook_Success; +} + +static char * +pas_backend_vcf_get_static_capabilities (PASBackend *backend) +{ + return g_strdup("local,do-initial-query"); +} + +static GNOME_Evolution_Addressbook_CallStatus +pas_backend_vcf_cancel_operation (PASBackend *backend, PASBook *book) +{ + return GNOME_Evolution_Addressbook_CouldNotCancel; +} + +static gboolean +pas_backend_vcf_construct (PASBackendVCF *backend) +{ + g_assert (backend != NULL); + g_assert (PAS_IS_BACKEND_VCF (backend)); + + if (! pas_backend_construct (PAS_BACKEND (backend))) + return FALSE; + + return TRUE; +} + +/** + * pas_backend_vcf_new: + */ +PASBackend * +pas_backend_vcf_new (void) +{ + PASBackendVCF *backend; + + backend = g_object_new (PAS_TYPE_BACKEND_VCF, NULL); + + if (! pas_backend_vcf_construct (backend)) { + g_object_unref (backend); + + return NULL; + } + + return PAS_BACKEND (backend); +} + +static void +pas_backend_vcf_dispose (GObject *object) +{ + PASBackendVCF *bvcf; + + bvcf = PAS_BACKEND_VCF (object); + + if (bvcf->priv) { + + if (bvcf->priv->dirty) + save_file (bvcf); + + if (bvcf->priv->flush_timeout_tag) { + g_source_remove (bvcf->priv->flush_timeout_tag); + bvcf->priv->flush_timeout_tag = 0; + } + + g_free (bvcf->priv->uri); + g_free (bvcf->priv->filename); + + g_free (bvcf->priv); + bvcf->priv = NULL; + } + + G_OBJECT_CLASS (pas_backend_vcf_parent_class)->dispose (object); +} + +static void +pas_backend_vcf_class_init (PASBackendVCFClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + PASBackendSyncClass *sync_class; + PASBackendClass *backend_class; + + pas_backend_vcf_parent_class = g_type_class_peek_parent (klass); + + sync_class = PAS_BACKEND_SYNC_CLASS (klass); + backend_class = PAS_BACKEND_CLASS (klass); + + /* Set the virtual methods. */ + backend_class->load_uri = pas_backend_vcf_load_uri; + backend_class->get_static_capabilities = pas_backend_vcf_get_static_capabilities; + backend_class->start_book_view = pas_backend_vcf_start_book_view; + backend_class->cancel_operation = pas_backend_vcf_cancel_operation; + + sync_class->create_contact_sync = pas_backend_vcf_process_create_contact; + sync_class->remove_contacts_sync = pas_backend_vcf_process_remove_contacts; + sync_class->modify_contact_sync = pas_backend_vcf_process_modify_contact; + sync_class->get_contact_sync = pas_backend_vcf_process_get_contact; + sync_class->get_contact_list_sync = pas_backend_vcf_process_get_contact_list; + sync_class->authenticate_user_sync = pas_backend_vcf_process_authenticate_user; + sync_class->get_supported_fields_sync = pas_backend_vcf_process_get_supported_fields; + + object_class->dispose = pas_backend_vcf_dispose; +} + +static void +pas_backend_vcf_init (PASBackendVCF *backend) +{ + PASBackendVCFPrivate *priv; + + priv = g_new0 (PASBackendVCFPrivate, 1); + priv->uri = NULL; + + backend->priv = priv; +} + +/** + * pas_backend_vcf_get_type: + */ +GType +pas_backend_vcf_get_type (void) +{ + static GType type = 0; + + if (! type) { + GTypeInfo info = { + sizeof (PASBackendVCFClass), + NULL, /* base_class_init */ + NULL, /* base_class_finalize */ + (GClassInitFunc) pas_backend_vcf_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PASBackendVCF), + 0, /* n_preallocs */ + (GInstanceInitFunc) pas_backend_vcf_init + }; + + type = g_type_register_static (PAS_TYPE_BACKEND_SYNC, "PASBackendVCF", &info, 0); + } + + return type; +} diff --git a/addressbook/backend/pas/pas-backend-vcf.h b/addressbook/backend/pas/pas-backend-vcf.h new file mode 100644 index 0000000000..81c872dcf1 --- /dev/null +++ b/addressbook/backend/pas/pas-backend-vcf.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Author: + * Chris Toshok (toshok@ximian.com) + * Copyright (C) 2003, Ximian, Inc. + */ + +#ifndef __PAS_BACKEND_VCF_H__ +#define __PAS_BACKEND_VCF_H__ + +#include "pas-backend-sync.h" + +#define PAS_TYPE_BACKEND_VCF (pas_backend_vcf_get_type ()) +#define PAS_BACKEND_VCF(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BACKEND_VCF, PASBackendVCF)) +#define PAS_BACKEND_VCF_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PAS_BACKEND_TYPE, PASBackendVCFClass)) +#define PAS_IS_BACKEND_VCF(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAS_TYPE_BACKEND_VCF)) +#define PAS_IS_BACKEND_VCF_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PAS_TYPE_BACKEND_VCF)) +#define PAS_BACKEND_VCF_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), PAS_TYPE_BACKEND_VCF, PASBackendVCFClass)) + +typedef struct _PASBackendVCFPrivate PASBackendVCFPrivate; + +typedef struct { + PASBackendSync parent_object; + PASBackendVCFPrivate *priv; +} PASBackendVCF; + +typedef struct { + PASBackendSyncClass parent_class; +} PASBackendVCFClass; + +PASBackend *pas_backend_vcf_new (void); +GType pas_backend_vcf_get_type (void); + +#endif /* ! __PAS_BACKEND_VCF_H__ */ + diff --git a/addressbook/backend/pas/pas-backend.c b/addressbook/backend/pas/pas-backend.c index acc6ed2a2c..076565de07 100644 --- a/addressbook/backend/pas/pas-backend.c +++ b/addressbook/backend/pas/pas-backend.c @@ -7,12 +7,22 @@ */ #include <config.h> +#include <pthread.h> +#include "pas-book-view.h" #include "pas-backend.h" #include "pas-marshal.h" struct _PASBackendPrivate { + GMutex *open_mutex; + + GMutex *clients_mutex; GList *clients; - gboolean loaded, writable; + + char *uri; + gboolean loaded, writable, removed; + + GMutex *views_mutex; + EList *views; }; /* Signal IDs */ @@ -31,18 +41,25 @@ pas_backend_construct (PASBackend *backend) return TRUE; } -GNOME_Evolution_Addressbook_BookListener_CallStatus +GNOME_Evolution_Addressbook_CallStatus pas_backend_load_uri (PASBackend *backend, - const char *uri) + const char *uri, + gboolean only_if_exists) { - g_return_val_if_fail (backend != NULL, FALSE); - g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE); - g_return_val_if_fail (uri != NULL, FALSE); + GNOME_Evolution_Addressbook_CallStatus status; + + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), FALSE); + g_return_val_if_fail (uri, FALSE); g_return_val_if_fail (backend->priv->loaded == FALSE, FALSE); - g_assert (PAS_BACKEND_GET_CLASS (backend)->load_uri != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->load_uri); + + status = (* PAS_BACKEND_GET_CLASS (backend)->load_uri) (backend, uri, only_if_exists); + + if (status == GNOME_Evolution_Addressbook_Success) + backend->priv->uri = g_strdup (uri); - return (* PAS_BACKEND_GET_CLASS (backend)->load_uri) (backend, uri); + return status; } /** @@ -56,246 +73,198 @@ pas_backend_load_uri (PASBackend *backend, const char * pas_backend_get_uri (PASBackend *backend) { - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (PAS_IS_BACKEND (backend), NULL); + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), NULL); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_uri != NULL); - - return (* PAS_BACKEND_GET_CLASS (backend)->get_uri) (backend); + return backend->priv->uri; } - void -pas_backend_create_card (PASBackend *backend, - PASBook *book, - PASCreateCardRequest *req) +pas_backend_open (PASBackend *backend, + PASBook *book, + gboolean only_if_exists) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->vcard != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + + g_mutex_lock (backend->priv->open_mutex); - g_assert (PAS_BACKEND_GET_CLASS (backend)->create_card != NULL); + if (backend->priv->loaded) { + pas_book_respond_open ( + book, GNOME_Evolution_Addressbook_Success); - (* PAS_BACKEND_GET_CLASS (backend)->create_card) (backend, book, req); + pas_book_report_writable (book, backend->priv->writable); + } else { + GNOME_Evolution_Addressbook_CallStatus status = + pas_backend_load_uri (backend, pas_book_get_uri (book), only_if_exists); + + pas_book_respond_open (book, status); + + if (status == GNOME_Evolution_Addressbook_Success) + pas_book_report_writable (book, backend->priv->writable); + } + + g_mutex_unlock (backend->priv->open_mutex); } void -pas_backend_remove_cards (PASBackend *backend, - PASBook *book, - PASRemoveCardsRequest *req) +pas_backend_remove (PASBackend *backend, + PASBook *book) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->ids != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); - g_assert (PAS_BACKEND_GET_CLASS (backend)->remove_cards != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->remove); - (* PAS_BACKEND_GET_CLASS (backend)->remove_cards) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->remove) (backend, book); } void -pas_backend_modify_card (PASBackend *backend, - PASBook *book, - PASModifyCardRequest *req) +pas_backend_create_contact (PASBackend *backend, + PASBook *book, + const char *vcard) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->vcard != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (vcard); - g_assert (PAS_BACKEND_GET_CLASS (backend)->modify_card != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->create_contact); - (* PAS_BACKEND_GET_CLASS (backend)->modify_card) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->create_contact) (backend, book, vcard); } void -pas_backend_check_connection (PASBackend *backend, - PASBook *book, - PASCheckConnectionRequest *req) +pas_backend_remove_contacts (PASBackend *backend, + PASBook *book, + GList *id_list) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (id_list); - g_assert (PAS_BACKEND_GET_CLASS (backend)->check_connection != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->remove_contacts); - (* PAS_BACKEND_GET_CLASS (backend)->check_connection) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->remove_contacts) (backend, book, id_list); } void -pas_backend_get_vcard (PASBackend *backend, - PASBook *book, - PASGetVCardRequest *req) +pas_backend_modify_contact (PASBackend *backend, + PASBook *book, + const char *vcard) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->id != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (vcard); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_vcard != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->modify_contact); - (* PAS_BACKEND_GET_CLASS (backend)->get_vcard) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->modify_contact) (backend, book, vcard); } void -pas_backend_get_cursor (PASBackend *backend, - PASBook *book, - PASGetCursorRequest *req) +pas_backend_get_contact (PASBackend *backend, + PASBook *book, + const char *id) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->search != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (id); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_cursor != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->get_contact); - (* PAS_BACKEND_GET_CLASS (backend)->get_cursor) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->get_contact) (backend, book, id); } void -pas_backend_get_book_view (PASBackend *backend, - PASBook *book, - PASGetBookViewRequest *req) +pas_backend_get_contact_list (PASBackend *backend, + PASBook *book, + const char *query) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->search != NULL && req->listener != CORBA_OBJECT_NIL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (query); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_book_view != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->get_contact_list); - (* PAS_BACKEND_GET_CLASS (backend)->get_book_view) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->get_contact_list) (backend, book, query); } void -pas_backend_get_completion_view (PASBackend *backend, - PASBook *book, - PASGetCompletionViewRequest *req) +pas_backend_start_book_view (PASBackend *backend, + PASBookView *book_view) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->search != NULL && req->listener != CORBA_OBJECT_NIL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book_view && PAS_IS_BOOK_VIEW (book_view)); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_completion_view != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->start_book_view); - (* PAS_BACKEND_GET_CLASS (backend)->get_completion_view) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->start_book_view) (backend, book_view); } void pas_backend_get_changes (PASBackend *backend, PASBook *book, - PASGetChangesRequest *req) + const char *change_id) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL && req->change_id != NULL && req->listener != CORBA_OBJECT_NIL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (change_id); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_changes != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->get_changes); - (* PAS_BACKEND_GET_CLASS (backend)->get_changes) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->get_changes) (backend, book, change_id); } void pas_backend_authenticate_user (PASBackend *backend, PASBook *book, - PASAuthenticateUserRequest *req) + const char *user, + const char *passwd, + const char *auth_method) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + g_return_if_fail (user && passwd && auth_method); - g_assert (PAS_BACKEND_GET_CLASS (backend)->authenticate_user != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->authenticate_user); - (* PAS_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, book, user, passwd, auth_method); } void pas_backend_get_supported_fields (PASBackend *backend, - PASBook *book, - PASGetSupportedFieldsRequest *req) + PASBook *book) + { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_supported_fields != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->get_supported_fields); - (* PAS_BACKEND_GET_CLASS (backend)->get_supported_fields) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->get_supported_fields) (backend, book); } void pas_backend_get_supported_auth_methods (PASBackend *backend, - PASBook *book, - PASGetSupportedAuthMethodsRequest *req) + PASBook *book) { - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - g_return_if_fail (req != NULL); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_supported_auth_methods != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->get_supported_auth_methods); - (* PAS_BACKEND_GET_CLASS (backend)->get_supported_auth_methods) (backend, book, req); + (* PAS_BACKEND_GET_CLASS (backend)->get_supported_auth_methods) (backend, book); } -static void -process_client_requests (PASBook *book, gpointer user_data) +GNOME_Evolution_Addressbook_CallStatus +pas_backend_cancel_operation (PASBackend *backend, + PASBook *book) { - PASBackend *backend; - PASRequest *req; - - backend = PAS_BACKEND (user_data); - - req = pas_book_pop_request (book); - if (req == NULL) - return; - - switch (req->op) { - case CreateCard: - pas_backend_create_card (backend, book, &req->create); - break; - - case RemoveCards: - pas_backend_remove_cards (backend, book, &req->remove); - break; - - case ModifyCard: - pas_backend_modify_card (backend, book, &req->modify); - break; - - case CheckConnection: - pas_backend_check_connection (backend, book, &req->check_connection); - break; - - case GetVCard: - pas_backend_get_vcard (backend, book, &req->get_vcard); - break; - - case GetCursor: - pas_backend_get_cursor (backend, book, &req->get_cursor); - break; + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), GNOME_Evolution_Addressbook_OtherError); + g_return_val_if_fail (book && PAS_IS_BOOK (book), GNOME_Evolution_Addressbook_OtherError); - case GetBookView: - pas_backend_get_book_view (backend, book, &req->get_book_view); - break; + g_assert (PAS_BACKEND_GET_CLASS (backend)->cancel_operation); - case GetCompletionView: - pas_backend_get_completion_view (backend, book, &req->get_completion_view); - break; - - case GetChanges: - pas_backend_get_changes (backend, book, &req->get_changes); - break; - - case AuthenticateUser: - pas_backend_authenticate_user (backend, book, &req->auth_user); - break; - - case GetSupportedFields: - pas_backend_get_supported_fields (backend, book, &req->get_supported_fields); - break; - - case GetSupportedAuthMethods: - pas_backend_get_supported_auth_methods (backend, book, &req->get_supported_auth_methods); - break; - } - - pas_book_free_request (req); + return (* PAS_BACKEND_GET_CLASS (backend)->cancel_operation) (backend, book); } static void @@ -307,74 +276,82 @@ book_destroy_cb (gpointer data, GObject *where_book_was) } static void +listener_died_cb (gpointer cnx, gpointer user_data) +{ + PASBook *book = PAS_BOOK (user_data); + + pas_backend_remove_client (pas_book_get_backend (book), book); +} + +static void last_client_gone (PASBackend *backend) { g_signal_emit (backend, pas_backend_signals[LAST_CLIENT_GONE], 0); } -static gboolean -add_client (PASBackend *backend, - GNOME_Evolution_Addressbook_BookListener listener) +EList* +pas_backend_get_book_views (PASBackend *backend) { - PASBook *book; - - book = pas_book_new (backend, listener); - if (!book) { - if (!backend->priv->clients) - last_client_gone (backend); - - return FALSE; - } - - g_object_weak_ref (G_OBJECT (book), book_destroy_cb, backend); - - g_signal_connect (book, "requests_queued", - G_CALLBACK (process_client_requests), backend); + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), FALSE); - backend->priv->clients = g_list_prepend (backend->priv->clients, book); - - if (backend->priv->loaded) { - pas_book_respond_open ( - book, GNOME_Evolution_Addressbook_BookListener_Success); - } else { - pas_book_respond_open ( - book, GNOME_Evolution_Addressbook_BookListener_OtherError); - } + return g_object_ref (backend->priv->views); +} - pas_book_report_writable (book, backend->priv->writable); +void +pas_backend_add_book_view (PASBackend *backend, + PASBookView *view) +{ + g_mutex_lock (backend->priv->views_mutex); - bonobo_object_unref (BONOBO_OBJECT (book)); + e_list_append (backend->priv->views, view); - return TRUE; + g_mutex_unlock (backend->priv->views_mutex); } /** * pas_backend_add_client: * @backend: An addressbook backend. - * @listener: Listener for notification to the client. + * @book: the corba object representing the client connection. * * Adds a client to an addressbook backend. * * Return value: TRUE on success, FALSE on failure to add the client. */ gboolean -pas_backend_add_client (PASBackend *backend, - GNOME_Evolution_Addressbook_BookListener listener) +pas_backend_add_client (PASBackend *backend, + PASBook *book) { - g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE); - g_return_val_if_fail (listener != CORBA_OBJECT_NIL, FALSE); + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), FALSE); + g_return_val_if_fail (book && PAS_IS_BOOK (book), FALSE); + + bonobo_object_set_immortal (BONOBO_OBJECT (book), TRUE); + + g_object_weak_ref (G_OBJECT (book), book_destroy_cb, backend); + + ORBit_small_listen_for_broken (pas_book_get_listener (book), G_CALLBACK (listener_died_cb), book); - g_assert (PAS_BACKEND_GET_CLASS (backend)->add_client != NULL); + g_mutex_lock (backend->priv->clients_mutex); + backend->priv->clients = g_list_prepend (backend->priv->clients, book); + g_mutex_unlock (backend->priv->clients_mutex); - return PAS_BACKEND_GET_CLASS (backend)->add_client (backend, listener); + return TRUE; } -static void -remove_client (PASBackend *backend, - PASBook *book) +void +pas_backend_remove_client (PASBackend *backend, + PASBook *book) { + /* XXX this needs a bit more thinking wrt the mutex - we + should be holding it when we check to see if clients is + NULL */ + + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + g_return_if_fail (book && PAS_IS_BOOK (book)); + /* Disconnect */ + g_mutex_lock (backend->priv->clients_mutex); backend->priv->clients = g_list_remove (backend->priv->clients, book); + g_mutex_unlock (backend->priv->clients_mutex); /* When all clients go away, notify the parent factory about it so that * it may decide whether to kill the backend or not. @@ -383,25 +360,12 @@ remove_client (PASBackend *backend, last_client_gone (backend); } -void -pas_backend_remove_client (PASBackend *backend, - PASBook *book) -{ - g_return_if_fail (PAS_IS_BACKEND (backend)); - g_return_if_fail (PAS_IS_BOOK (book)); - - g_assert (PAS_BACKEND_GET_CLASS (backend)->remove_client != NULL); - - PAS_BACKEND_GET_CLASS (backend)->remove_client (backend, book); -} - char * pas_backend_get_static_capabilities (PASBackend *backend) { - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (PAS_IS_BACKEND (backend), NULL); + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), NULL); - g_assert (PAS_BACKEND_GET_CLASS (backend)->get_static_capabilities != NULL); + g_assert (PAS_BACKEND_GET_CLASS (backend)->get_static_capabilities); return PAS_BACKEND_GET_CLASS (backend)->get_static_capabilities (backend); } @@ -409,7 +373,7 @@ pas_backend_get_static_capabilities (PASBackend *backend) gboolean pas_backend_is_loaded (PASBackend *backend) { - g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE); + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), FALSE); return backend->priv->loaded; } @@ -417,7 +381,7 @@ pas_backend_is_loaded (PASBackend *backend) void pas_backend_set_is_loaded (PASBackend *backend, gboolean is_loaded) { - g_return_if_fail (PAS_IS_BACKEND (backend)); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); backend->priv->loaded = is_loaded; } @@ -425,7 +389,7 @@ pas_backend_set_is_loaded (PASBackend *backend, gboolean is_loaded) gboolean pas_backend_is_writable (PASBackend *backend) { - g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE); + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), FALSE); return backend->priv->writable; } @@ -433,18 +397,175 @@ pas_backend_is_writable (PASBackend *backend) void pas_backend_set_is_writable (PASBackend *backend, gboolean is_writable) { - g_return_if_fail (PAS_IS_BACKEND (backend)); + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); backend->priv->writable = is_writable; } +gboolean +pas_backend_is_removed (PASBackend *backend) +{ + g_return_val_if_fail (backend && PAS_IS_BACKEND (backend), FALSE); + + return backend->priv->removed; +} + +void +pas_backend_set_is_removed (PASBackend *backend, gboolean is_removed) +{ + g_return_if_fail (backend && PAS_IS_BACKEND (backend)); + + backend->priv->removed = is_removed; +} + + + +GNOME_Evolution_Addressbook_BookChangeItem* +pas_backend_change_add_new (const char *vcard) +{ + GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc(); + + new_change->_d = GNOME_Evolution_Addressbook_ContactAdded; + new_change->_u.add_vcard = CORBA_string_dup (vcard); + + return new_change; +} + +GNOME_Evolution_Addressbook_BookChangeItem* +pas_backend_change_modify_new (const char *vcard) +{ + GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc(); + + new_change->_d = GNOME_Evolution_Addressbook_ContactModified; + new_change->_u.mod_vcard = CORBA_string_dup (vcard); + + return new_change; +} + +GNOME_Evolution_Addressbook_BookChangeItem* +pas_backend_change_delete_new (const char *id) +{ + GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc(); + + new_change->_d = GNOME_Evolution_Addressbook_ContactDeleted; + new_change->_u.del_id = CORBA_string_dup (id); + + return new_change; +} + + + +static void +pas_backend_foreach_view (PASBackend *backend, + void (*callback) (PASBookView *, gpointer), + gpointer user_data) +{ + EList *views; + PASBookView *view; + EIterator *iter; + + views = pas_backend_get_book_views (backend); + iter = e_list_get_iterator (views); + + while (e_iterator_is_valid (iter)) { + view = (PASBookView*)e_iterator_get (iter); + + bonobo_object_ref (view); + callback (view, user_data); + bonobo_object_unref (view); + + e_iterator_next (iter); + } + + g_object_unref (iter); + g_object_unref (views); +} + + +static void +view_notify_update (PASBookView *view, gpointer contact) +{ + pas_book_view_notify_update (view, contact); +} + +/** + * pas_backend_notify_update: + * @backend: an addressbook backend + * @contact: a new or modified contact + * + * Notifies all of @backend's book views about the new or modified + * contacts @contact. + * + * pas_book_respond_create() and pas_book_respond_modify() call this + * function for you. You only need to call this from your backend if + * contacts are created or modified by another (non-PAS-using) client. + **/ +void +pas_backend_notify_update (PASBackend *backend, EContact *contact) +{ + pas_backend_foreach_view (backend, view_notify_update, contact); +} + + +static void +view_notify_remove (PASBookView *view, gpointer id) +{ + pas_book_view_notify_remove (view, id); +} + +/** + * pas_backend_notify_remove: + * @backend: an addressbook backend + * @id: a contact id + * + * Notifies all of @backend's book views that the contact with UID + * @id has been removed. + * + * pas_book_respond_remove_contacts() calls this function for you. You + * only need to call this from your backend if contacts are removed by + * another (non-PAS-using) client. + **/ +void +pas_backend_notify_remove (PASBackend *backend, const char *id) +{ + pas_backend_foreach_view (backend, view_notify_remove, (gpointer)id); +} + + +static void +view_notify_complete (PASBookView *view, gpointer unused) +{ + pas_book_view_notify_complete (view, GNOME_Evolution_Addressbook_Success); +} + +/** + * pas_backend_notify_complete: + * @backend: an addressbook backend + * + * Notifies all of @backend's book views that the current set of + * notifications is complete; use this after a series of + * pas_backend_notify_update() and pas_backend_notify_remove() calls. + **/ +void +pas_backend_notify_complete (PASBackend *backend) +{ + pas_backend_foreach_view (backend, view_notify_complete, NULL); +} + + + static void pas_backend_init (PASBackend *backend) { PASBackendPrivate *priv; priv = g_new0 (PASBackendPrivate, 1); + priv->uri = NULL; priv->clients = NULL; + priv->views = e_list_new((EListCopyFunc) g_object_ref, (EListFreeFunc) g_object_unref, NULL); + priv->open_mutex = g_mutex_new (); + priv->clients_mutex = g_mutex_new (); + priv->views_mutex = g_mutex_new (); backend->priv = priv; } @@ -458,8 +579,20 @@ pas_backend_dispose (GObject *object) if (backend->priv) { g_list_free (backend->priv->clients); - g_free (backend->priv); + if (backend->priv->uri) + g_free (backend->priv->uri); + + if (backend->priv->views) { + g_object_unref (backend->priv->views); + backend->priv->views = NULL; + } + + g_mutex_free (backend->priv->open_mutex); + g_mutex_free (backend->priv->clients_mutex); + g_mutex_free (backend->priv->views_mutex); + + g_free (backend->priv); backend->priv = NULL; } @@ -475,9 +608,6 @@ pas_backend_class_init (PASBackendClass *klass) object_class = (GObjectClass *) klass; - klass->add_client = add_client; - klass->remove_client = remove_client; - object_class->dispose = pas_backend_dispose; pas_backend_signals[LAST_CLIENT_GONE] = diff --git a/addressbook/backend/pas/pas-backend.h b/addressbook/backend/pas/pas-backend.h index b33518116e..41f6542213 100644 --- a/addressbook/backend/pas/pas-backend.h +++ b/addressbook/backend/pas/pas-backend.h @@ -25,6 +25,8 @@ #include <glib.h> #include <glib-object.h> #include <pas/addressbook.h> +#include <pas/pas-types.h> +#include <ebook/e-contact.h> #define PAS_TYPE_BACKEND (pas_backend_get_type ()) #define PAS_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BACKEND, PASBackend)) @@ -33,7 +35,6 @@ #define PAS_IS_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PAS_TYPE_BACKEND)) #define PAS_BACKEND_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), PAS_TYPE_BACKEND, PASBackendClass)) -typedef struct _PASBackend PASBackend; typedef struct _PASBackendPrivate PASBackendPrivate; #include <pas/pas-book.h> @@ -43,44 +44,49 @@ struct _PASBackend { PASBackendPrivate *priv; }; -typedef struct { +struct _PASBackendClass { GObjectClass parent_class; /* Virtual methods */ - GNOME_Evolution_Addressbook_BookListener_CallStatus (*load_uri) (PASBackend *backend, const char *uri); - const char *(* get_uri) (PASBackend *backend); - gboolean (*add_client) (PASBackend *backend, GNOME_Evolution_Addressbook_BookListener listener); - void (*remove_client) (PASBackend *backend, PASBook *book); + GNOME_Evolution_Addressbook_CallStatus (*load_uri) (PASBackend *backend, const char *uri, gboolean only_if_exists); + void (*remove) (PASBackend *backend, PASBook *book); char *(*get_static_capabilities) (PASBackend *backend); - void (*create_card) (PASBackend *backend, PASBook *book, PASCreateCardRequest *req); - void (*remove_cards) (PASBackend *backend, PASBook *book, PASRemoveCardsRequest *req); - void (*modify_card) (PASBackend *backend, PASBook *book, PASModifyCardRequest *req); - void (*check_connection) (PASBackend *backend, PASBook *book, PASCheckConnectionRequest *req); - void (*get_vcard) (PASBackend *backend, PASBook *book, PASGetVCardRequest *req); - void (*get_cursor) (PASBackend *backend, PASBook *book, PASGetCursorRequest *req); - void (*get_book_view) (PASBackend *backend, PASBook *book, PASGetBookViewRequest *req); - void (*get_completion_view) (PASBackend *backend, PASBook *book, PASGetCompletionViewRequest *req); - void (*get_changes) (PASBackend *backend, PASBook *book, PASGetChangesRequest *req); - void (*authenticate_user) (PASBackend *backend, PASBook *book, PASAuthenticateUserRequest *req); - void (*get_supported_fields) (PASBackend *backend, PASBook *book, PASGetSupportedFieldsRequest *req); - void (*get_supported_auth_methods) (PASBackend *backend, PASBook *book, PASGetSupportedAuthMethodsRequest *req); + void (*create_contact) (PASBackend *backend, PASBook *book, const char *vcard); + void (*remove_contacts) (PASBackend *backend, PASBook *book, GList *id_list); + void (*modify_contact) (PASBackend *backend, PASBook *book, const char *vcard); + void (*get_contact) (PASBackend *backend, PASBook *book, const char *id); + void (*get_contact_list) (PASBackend *backend, PASBook *book, const char *query); + void (*start_book_view) (PASBackend *backend, PASBookView *book_view); + void (*get_changes) (PASBackend *backend, PASBook *book, const char *change_id); + void (*authenticate_user) (PASBackend *backend, PASBook *book, const char *user, const char *passwd, const char *auth_method); + void (*get_supported_fields) (PASBackend *backend, PASBook *book); + void (*get_supported_auth_methods) (PASBackend *backend, PASBook *book); + GNOME_Evolution_Addressbook_CallStatus (*cancel_operation) (PASBackend *backend, PASBook *book); /* Notification signals */ void (* last_client_gone) (PASBackend *backend); -} PASBackendClass; + + /* Padding for future expansion */ + void (*_pas_reserved0) (void); + void (*_pas_reserved1) (void); + void (*_pas_reserved2) (void); + void (*_pas_reserved3) (void); + void (*_pas_reserved4) (void); +}; typedef PASBackend * (*PASBackendFactoryFn) (void); gboolean pas_backend_construct (PASBackend *backend); -GNOME_Evolution_Addressbook_BookListener_CallStatus +GNOME_Evolution_Addressbook_CallStatus pas_backend_load_uri (PASBackend *backend, - const char *uri); + const char *uri, + gboolean only_if_exists); const char *pas_backend_get_uri (PASBackend *backend); gboolean pas_backend_add_client (PASBackend *backend, - GNOME_Evolution_Addressbook_BookListener listener); + PASBook *book); void pas_backend_remove_client (PASBackend *backend, PASBook *book); char *pas_backend_get_static_capabilities (PASBackend *backend); @@ -89,42 +95,56 @@ gboolean pas_backend_is_loaded (PASBackend *backen gboolean pas_backend_is_writable (PASBackend *backend); -void pas_backend_create_card (PASBackend *backend, - PASBook *book, - PASCreateCardRequest *req); -void pas_backend_remove_cards (PASBackend *backend, - PASBook *book, - PASRemoveCardsRequest *req); -void pas_backend_modify_card (PASBackend *backend, +gboolean pas_backend_is_removed (PASBackend *backend); + +void pas_backend_open (PASBackend *backend, PASBook *book, - PASModifyCardRequest *req); -void pas_backend_check_connection (PASBackend *backend, + gboolean only_if_exists); +void pas_backend_remove (PASBackend *backend, + PASBook *book); +void pas_backend_create_contact (PASBackend *backend, PASBook *book, - PASCheckConnectionRequest *req); -void pas_backend_get_vcard (PASBackend *backend, + const char *vcard); +void pas_backend_remove_contacts (PASBackend *backend, PASBook *book, - PASGetVCardRequest *req); -void pas_backend_get_cursor (PASBackend *backend, + GList *id_list); +void pas_backend_modify_contact (PASBackend *backend, PASBook *book, - PASGetCursorRequest *req); -void pas_backend_get_book_view (PASBackend *backend, + const char *vcard); +void pas_backend_get_contact (PASBackend *backend, PASBook *book, - PASGetBookViewRequest *req); -void pas_backend_get_completion_view (PASBackend *backend, + const char *id); +void pas_backend_get_contact_list (PASBackend *backend, PASBook *book, - PASGetCompletionViewRequest *req); + const char *query); void pas_backend_get_changes (PASBackend *backend, PASBook *book, - PASGetChangesRequest *req); + const char *change_id); void pas_backend_authenticate_user (PASBackend *backend, PASBook *book, - PASAuthenticateUserRequest *req); + const char *user, + const char *passwd, + const char *auth_method); void pas_backend_get_supported_fields (PASBackend *backend, - PASBook *book, - PASGetSupportedFieldsRequest *req); + PASBook *book); void pas_backend_get_supported_auth_methods (PASBackend *backend, - PASBook *book, - PASGetSupportedAuthMethodsRequest *req); + PASBook *book); +GNOME_Evolution_Addressbook_CallStatus pas_backend_cancel_operation (PASBackend *backend, + PASBook *book); + +void pas_backend_start_book_view (PASBackend *backend, + PASBookView *view); + +void pas_backend_add_book_view (PASBackend *backend, + PASBookView *view); + +EList *pas_backend_get_book_views (PASBackend *backend); + +void pas_backend_notify_update (PASBackend *backend, + EContact *contact); +void pas_backend_notify_remove (PASBackend *backend, + const char *id); +void pas_backend_notify_complete (PASBackend *backend); GType pas_backend_get_type (void); @@ -135,6 +155,13 @@ void pas_backend_set_is_loaded (PASBackend *backen gboolean is_loaded); void pas_backend_set_is_writable (PASBackend *backend, gboolean is_writable); +void pas_backend_set_is_removed (PASBackend *backend, + gboolean is_removed); + +/* useful for implementing _get_changes in backends */ +GNOME_Evolution_Addressbook_BookChangeItem* pas_backend_change_add_new (const char *vcard); +GNOME_Evolution_Addressbook_BookChangeItem* pas_backend_change_modify_new (const char *vcard); +GNOME_Evolution_Addressbook_BookChangeItem* pas_backend_change_delete_new (const char *id); #endif /* ! __PAS_BACKEND_H__ */ diff --git a/addressbook/backend/pas/pas-book-factory.c b/addressbook/backend/pas/pas-book-factory.c index 2d6ed1e65b..34e97aa780 100644 --- a/addressbook/backend/pas/pas-book-factory.c +++ b/addressbook/backend/pas/pas-book-factory.c @@ -8,6 +8,7 @@ */ #include <config.h> +#include <pthread.h> #include <string.h> #include "addressbook.h" @@ -15,21 +16,22 @@ #include "pas-marshal.h" #include <bonobo-activation/bonobo-activation.h> #include <bonobo/bonobo-main.h> +#include <bonobo/bonobo-arg.h> #define DEFAULT_PAS_BOOK_FACTORY_OAF_ID "OAFIID:GNOME_Evolution_Wombat_ServerFactory" static BonoboObjectClass *pas_book_factory_parent_class; typedef struct { - char *uri; - GNOME_Evolution_Addressbook_BookListener listener; + char *uri; + GNOME_Evolution_Addressbook_BookListener listener; } PASBookFactoryQueuedRequest; struct _PASBookFactoryPrivate { - gint idle_id; + GMutex *map_mutex; + GHashTable *backends; GHashTable *active_server_map; - GList *queued_requests; /* OAFIID of the factory */ char *iid; @@ -108,10 +110,16 @@ pas_book_factory_register_backend (PASBookFactory *factory, int pas_book_factory_get_n_backends (PASBookFactory *factory) { + int n_backends; + g_return_val_if_fail (factory != NULL, -1); g_return_val_if_fail (PAS_IS_BOOK_FACTORY (factory), -1); - return g_hash_table_size (factory->priv->active_server_map); + g_mutex_lock (factory->priv->map_mutex); + n_backends = g_hash_table_size (factory->priv->active_server_map); + g_mutex_unlock (factory->priv->map_mutex); + + return n_backends; } static void @@ -131,10 +139,11 @@ pas_book_factory_dump_active_backends (PASBookFactory *factory) { g_message ("Active PAS backends"); + g_mutex_lock (factory->priv->map_mutex); g_hash_table_foreach (factory->priv->active_server_map, dump_active_server_map_entry, NULL); - + g_mutex_unlock (factory->priv->map_mutex); } /* Callback used when a backend loses its last connected client */ @@ -154,6 +163,8 @@ backend_last_client_gone_cb (PASBackend *backend, gpointer data) gboolean result; char *orig_uri; + g_mutex_lock (factory->priv->map_mutex); + result = g_hash_table_lookup_extended (factory->priv->active_server_map, uri, &orig_key, NULL); g_assert (result != FALSE); @@ -165,13 +176,17 @@ backend_last_client_gone_cb (PASBackend *backend, gpointer data) g_object_unref (backend); - /* Notify upstream if there are no more backends */ + g_mutex_unlock (factory->priv->map_mutex); } - if (g_hash_table_size (factory->priv->active_server_map) == 0) + if (g_hash_table_size (factory->priv->active_server_map) == 0) { + /* Notify upstream if there are no more backends */ g_signal_emit (G_OBJECT (factory), factory_signals[LAST_BOOK_GONE], 0); + } } + + static PASBackendFactoryFn pas_book_factory_lookup_backend_factory (PASBookFactory *factory, const char *uri) @@ -203,52 +218,16 @@ pas_book_factory_lookup_backend_factory (PASBookFactory *factory, } static PASBackend * -pas_book_factory_launch_backend (PASBookFactory *factory, - GNOME_Evolution_Addressbook_BookListener listener, - const char *uri) +pas_book_factory_launch_backend (PASBookFactory *factory, + PASBackendFactoryFn backend_factory, + GNOME_Evolution_Addressbook_BookListener listener, + const char *uri) { - PASBackendFactoryFn backend_factory; PASBackend *backend; - backend_factory = pas_book_factory_lookup_backend_factory ( - factory, uri); - - if (!backend_factory) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyBookOpened ( - listener, - GNOME_Evolution_Addressbook_BookListener_ProtocolNotSupported, - CORBA_OBJECT_NIL, - &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - g_message ("pas_book_factory_launch_backend(): could not notify " - "the listener"); - - CORBA_exception_free (&ev); - return NULL; - } - backend = (* backend_factory) (); - if (!backend) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyBookOpened ( - listener, - GNOME_Evolution_Addressbook_BookListener_OtherError, - CORBA_OBJECT_NIL, - &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - g_message ("pas_book_factory_launch_backend(): could not notify " - "the listener"); - - CORBA_exception_free (&ev); + if (!backend) return NULL; - } g_hash_table_insert (factory->priv->active_server_map, g_strdup (uri), @@ -261,154 +240,63 @@ pas_book_factory_launch_backend (PASBookFactory *factory, return backend; } -static void -pas_book_factory_process_request (PASBookFactory *factory, - PASBookFactoryQueuedRequest *request) +static GNOME_Evolution_Addressbook_Book +impl_GNOME_Evolution_Addressbook_BookFactory_getBook (PortableServer_Servant servant, + const CORBA_char *uri, + const GNOME_Evolution_Addressbook_BookListener listener, + CORBA_Environment *ev) { + PASBookFactory *factory = PAS_BOOK_FACTORY (bonobo_object (servant)); PASBackend *backend; - char *uri; - GNOME_Evolution_Addressbook_BookListener listener; - CORBA_Environment ev; + PASBook *book; - uri = request->uri; - listener = request->listener; - g_free (request); + printf ("impl_GNOME_Evolution_Addressbook_BookFactory_getBook\n"); /* Look up the backend and create one if needed */ + g_mutex_lock (factory->priv->map_mutex); backend = g_hash_table_lookup (factory->priv->active_server_map, uri); if (!backend) { - GNOME_Evolution_Addressbook_BookListener_CallStatus status; - - backend = pas_book_factory_launch_backend (factory, listener, uri); - if (!backend) - goto out; + PASBackendFactoryFn backend_factory; - status = pas_backend_load_uri (backend, uri); - if (status != GNOME_Evolution_Addressbook_BookListener_Success) { - /* tell the listener that we failed to open the book */ - CORBA_exception_init (&ev); - - GNOME_Evolution_Addressbook_BookListener_notifyBookOpened ( - listener, status, - CORBA_OBJECT_NIL, - &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_respond_open: Exception " - "responding to BookListener!\n"); - } + backend_factory = pas_book_factory_lookup_backend_factory (factory, uri); + + if (backend_factory == NULL) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported, + NULL); - CORBA_exception_free (&ev); - - backend_last_client_gone_cb (backend, factory); + g_mutex_unlock (factory->priv->map_mutex); - goto out; + return CORBA_OBJECT_NIL; } - pas_backend_add_client (backend, listener); - - goto out; + backend = pas_book_factory_launch_backend (factory, backend_factory, listener, uri); } - pas_backend_add_client (backend, listener); + if (backend) { + GNOME_Evolution_Addressbook_BookListener listener_copy; - out: - g_free (uri); - - CORBA_exception_init (&ev); - CORBA_Object_release (listener, &ev); + listener_copy = bonobo_object_dup_ref (listener, NULL); - if (ev._major != CORBA_NO_EXCEPTION) - g_message ("pas_book_factory_process_request(): could not release the listener"); + g_mutex_unlock (factory->priv->map_mutex); - CORBA_exception_free (&ev); -} + book = pas_book_new (backend, uri, listener); -static gboolean -pas_book_factory_process_queue (PASBookFactory *factory) -{ - /* Process pending Book-creation requests. */ - if (factory->priv->queued_requests != NULL) { - PASBookFactoryQueuedRequest *request; - GList *l; + pas_backend_add_client (backend, book); - l = factory->priv->queued_requests; - request = l->data; - - pas_book_factory_process_request (factory, request); - - factory->priv->queued_requests = g_list_remove_link ( - factory->priv->queued_requests, l); - g_list_free_1 (l); - } - - if (factory->priv->queued_requests == NULL) { - - factory->priv->idle_id = 0; - return FALSE; - } - - return TRUE; -} - -static void -pas_book_factory_queue_request (PASBookFactory *factory, - const char *uri, - const GNOME_Evolution_Addressbook_BookListener listener) -{ - PASBookFactoryQueuedRequest *request; - GNOME_Evolution_Addressbook_BookListener listener_copy; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - listener_copy = CORBA_Object_duplicate (listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("PASBookFactory: Could not duplicate BookListener!\n"); - CORBA_exception_free (&ev); - return; - } - - CORBA_exception_free (&ev); - - request = g_new0 (PASBookFactoryQueuedRequest, 1); - request->listener = listener_copy; - request->uri = g_strdup (uri); - - factory->priv->queued_requests = - g_list_prepend (factory->priv->queued_requests, request); - - if (! factory->priv->idle_id) { - factory->priv->idle_id = - g_idle_add ((GSourceFunc) pas_book_factory_process_queue, factory); + return bonobo_object_corba_objref (BONOBO_OBJECT (book)); } -} - -static void -impl_GNOME_Evolution_Addressbook_BookFactory_openBook (PortableServer_Servant servant, - const CORBA_char *uri, - const GNOME_Evolution_Addressbook_BookListener listener, - CORBA_Environment *ev) -{ - PASBookFactory *factory = PAS_BOOK_FACTORY (bonobo_object (servant)); - PASBackendFactoryFn backend_factory; - - backend_factory = pas_book_factory_lookup_backend_factory (factory, uri); - - if (backend_factory == NULL) { - GNOME_Evolution_Addressbook_BookListener_notifyBookOpened ( - listener, - GNOME_Evolution_Addressbook_BookListener_ProtocolNotSupported, - CORBA_OBJECT_NIL, - ev); - - return; + else { + /* probably need a more descriptive exception here */ + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported, + NULL); + g_mutex_unlock (factory->priv->map_mutex); + + return CORBA_OBJECT_NIL; } - - pas_book_factory_queue_request (factory, uri, listener); } static void @@ -425,7 +313,9 @@ pas_book_factory_new (void) { PASBookFactory *factory; - factory = g_object_new (PAS_TYPE_BOOK_FACTORY, NULL); + factory = g_object_new (PAS_TYPE_BOOK_FACTORY, + "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL), + NULL); pas_book_factory_construct (factory); @@ -483,9 +373,9 @@ pas_book_factory_init (PASBookFactory *factory) { factory->priv = g_new0 (PASBookFactoryPrivate, 1); + factory->priv->map_mutex = g_mutex_new(); factory->priv->active_server_map = g_hash_table_new (g_str_hash, g_str_equal); factory->priv->backends = g_hash_table_new (g_str_hash, g_str_equal); - factory->priv->queued_requests = NULL; factory->priv->registered = FALSE; } @@ -518,22 +408,8 @@ pas_book_factory_dispose (GObject *object) if (factory->priv) { PASBookFactoryPrivate *priv = factory->priv; - GList *l; - for (l = priv->queued_requests; l != NULL; l = l->next) { - PASBookFactoryQueuedRequest *request = l->data; - CORBA_Environment ev; - - g_free (request->uri); - - CORBA_exception_init (&ev); - CORBA_Object_release (request->listener, &ev); - CORBA_exception_free (&ev); - - g_free (request); - } - g_list_free (priv->queued_requests); - priv->queued_requests = NULL; + g_mutex_free (priv->map_mutex); g_hash_table_foreach (priv->active_server_map, free_active_server_map_entry, @@ -585,7 +461,7 @@ pas_book_factory_class_init (PASBookFactoryClass *klass) epv = &klass->epv; - epv->openBook = impl_GNOME_Evolution_Addressbook_BookFactory_openBook; + epv->getBook = impl_GNOME_Evolution_Addressbook_BookFactory_getBook; } BONOBO_TYPE_FUNC_FULL ( diff --git a/addressbook/backend/pas/pas-book-view.c b/addressbook/backend/pas/pas-book-view.c index fce4173f0f..712997d258 100644 --- a/addressbook/backend/pas/pas-book-view.c +++ b/addressbook/backend/pas/pas-book-view.c @@ -6,158 +6,266 @@ */ #include <config.h> +#include <string.h> #include <glib.h> #include <bonobo/bonobo-main.h> +#include "pas-backend.h" +#include "pas-backend-card-sexp.h" #include "pas-book-view.h" static BonoboObjectClass *pas_book_view_parent_class; struct _PASBookViewPrivate { GNOME_Evolution_Addressbook_BookViewListener listener; + +#define INITIAL_THRESHOLD 20 + GMutex *pending_mutex; + + CORBA_sequence_GNOME_Evolution_Addressbook_VCard adds; + int next_threshold; + int threshold_max; + + CORBA_sequence_GNOME_Evolution_Addressbook_VCard changes; + CORBA_sequence_GNOME_Evolution_Addressbook_ContactId removes; + + PASBackend *backend; + char *card_query; + PASBackendCardSExp *card_sexp; + GHashTable *ids; }; -/** - * pas_book_view_notify_change: - */ -void -pas_book_view_notify_change (PASBookView *book_view, - const GList *cards) +static void +send_pending_adds (PASBookView *book_view, gboolean reset) { CORBA_Environment ev; - gint i, length; - CORBA_sequence_GNOME_Evolution_Addressbook_VCard card_sequence; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds; + + adds = &book_view->priv->adds; + if (adds->_length == 0) + return; - length = g_list_length((GList *) cards); + CORBA_exception_init (&ev); - card_sequence._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf(length); - card_sequence._maximum = length; - card_sequence._length = length; + GNOME_Evolution_Addressbook_BookViewListener_notifyContactsAdded ( + book_view->priv->listener, adds, &ev); - for ( i = 0; cards; cards = g_list_next(cards), i++ ) { - card_sequence._buffer[i] = CORBA_string_dup((char *) cards->data); + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("send_pending_adds: Exception signaling BookViewListener!\n"); } + CORBA_exception_free (&ev); + + CORBA_free (adds->_buffer); + adds->_buffer = NULL; + adds->_maximum = 0; + adds->_length = 0; + + if (reset) + book_view->priv->next_threshold = INITIAL_THRESHOLD; +} + +static void +send_pending_changes (PASBookView *book_view) +{ + CORBA_Environment ev; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes; + + changes = &book_view->priv->changes; + if (changes->_length == 0) + return; + CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookViewListener_notifyCardChanged ( - book_view->priv->listener, &card_sequence, &ev); + GNOME_Evolution_Addressbook_BookViewListener_notifyContactsChanged ( + book_view->priv->listener, changes, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_view_notify_change: Exception signaling BookViewListener!\n"); + g_warning ("send_pending_changes: Exception signaling BookViewListener!\n"); } CORBA_exception_free (&ev); - CORBA_free(card_sequence._buffer); + CORBA_free (changes->_buffer); + changes->_buffer = NULL; + changes->_maximum = 0; + changes->_length = 0; } -void -pas_book_view_notify_change_1 (PASBookView *book_view, - const char *card) +static void +send_pending_removes (PASBookView *book_view) { - GList *list = g_list_append(NULL, (char *) card); - pas_book_view_notify_change(book_view, list); - g_list_free(list); + CORBA_Environment ev; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *removes; + + removes = &book_view->priv->removes; + if (removes->_length == 0) + return; + + CORBA_exception_init (&ev); + + GNOME_Evolution_Addressbook_BookViewListener_notifyContactsRemoved ( + book_view->priv->listener, removes, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("send_pending_removes: Exception signaling BookViewListener!\n"); + } + + CORBA_exception_free (&ev); + + CORBA_free (removes->_buffer); + removes->_buffer = NULL; + removes->_maximum = 0; + removes->_length = 0; } -/** - * pas_book_view_notify_remove: - */ -void -pas_book_view_notify_remove_1 (PASBookView *book_view, - const char *id) +#define MAKE_REALLOC(type) \ +static void \ +CORBA_sequence_ ## type ## _realloc (CORBA_sequence_ ## type *seq, \ + CORBA_unsigned_long new_max) \ +{ \ + type *new_buf; \ + \ + new_buf = CORBA_sequence_ ## type ## _allocbuf (new_max); \ + memcpy (new_buf, seq->_buffer, seq->_maximum * sizeof (type)); \ + CORBA_free (seq->_buffer); \ + seq->_buffer = new_buf; \ + seq->_maximum = new_max; \ +} + +MAKE_REALLOC (GNOME_Evolution_Addressbook_VCard) +MAKE_REALLOC (GNOME_Evolution_Addressbook_ContactId) + +static void +notify_change (PASBookView *book_view, const char *vcard) { - GList *ids = NULL; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes; + + send_pending_adds (book_view, TRUE); + send_pending_removes (book_view); - ids = g_list_prepend (ids, (char*)id); + changes = &book_view->priv->changes; - pas_book_view_notify_remove (book_view, ids); + if (changes->_length == changes->_maximum) { + CORBA_sequence_GNOME_Evolution_Addressbook_VCard_realloc ( + changes, 2 * (changes->_maximum + 1)); + } - g_list_free (ids); + changes->_buffer[changes->_length++] = CORBA_string_dup (vcard); } -void -pas_book_view_notify_remove (PASBookView *book_view, - const GList *ids) +static void +notify_remove (PASBookView *book_view, const char *id) { - GNOME_Evolution_Addressbook_CardIdList idlist; - CORBA_Environment ev; - const GList *l; - int num_ids, i; + CORBA_sequence_GNOME_Evolution_Addressbook_ContactId *removes; - CORBA_exception_init (&ev); + send_pending_adds (book_view, TRUE); + send_pending_changes (book_view); - num_ids = g_list_length ((GList*)ids); - idlist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_CardId_allocbuf (num_ids); - idlist._maximum = num_ids; - idlist._length = num_ids; + removes = &book_view->priv->removes; - for (l = ids, i = 0; l; l=l->next, i ++) { - idlist._buffer[i] = CORBA_string_dup (l->data); + if (removes->_length == removes->_maximum) { + CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_realloc ( + removes, 2 * (removes->_maximum + 1)); } - GNOME_Evolution_Addressbook_BookViewListener_notifyCardsRemoved ( - book_view->priv->listener, &idlist, &ev); + removes->_buffer[removes->_length++] = CORBA_string_dup (id); + g_hash_table_remove (book_view->priv->ids, id); +} - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_view_notify_remove: Exception signaling BookViewListener!\n"); - } +static void +notify_add (PASBookView *book_view, const char *id, const char *vcard) +{ + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds; + PASBookViewPrivate *priv = book_view->priv; - CORBA_free(idlist._buffer); + send_pending_changes (book_view); + send_pending_removes (book_view); - CORBA_exception_free (&ev); + adds = &priv->adds; + + if (adds->_length == adds->_maximum) { + send_pending_adds (book_view, FALSE); + + adds->_buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf (priv->next_threshold); + adds->_maximum = priv->next_threshold; + + if (priv->next_threshold < priv->threshold_max) { + priv->next_threshold = MIN (2 * priv->next_threshold, + priv->threshold_max); + } + } + + adds->_buffer[adds->_length++] = CORBA_string_dup (vcard); + g_hash_table_insert (book_view->priv->ids, g_strdup (id), + GUINT_TO_POINTER (1)); } /** - * pas_book_view_notify_add: + * pas_book_view_notify_update: */ void -pas_book_view_notify_add (PASBookView *book_view, - const GList *cards) +pas_book_view_notify_update (PASBookView *book_view, + EContact *contact) { - CORBA_Environment ev; - gint i, length; - CORBA_sequence_GNOME_Evolution_Addressbook_VCard card_sequence; + gboolean currently_in_view, want_in_view; + const char *id; + char *vcard; - length = g_list_length((GList *)cards); + g_mutex_lock (book_view->priv->pending_mutex); - card_sequence._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf(length); - card_sequence._maximum = length; - card_sequence._length = length; + id = e_contact_get_const (contact, E_CONTACT_UID); - for ( i = 0; cards; cards = g_list_next(cards), i++ ) { - card_sequence._buffer[i] = CORBA_string_dup((char *) cards->data); - } + currently_in_view = + g_hash_table_lookup (book_view->priv->ids, id) != NULL; + want_in_view = pas_backend_card_sexp_match_contact ( + book_view->priv->card_sexp, contact); - CORBA_exception_init (&ev); + if (want_in_view) { + vcard = e_vcard_to_string (E_VCARD (contact), + EVC_FORMAT_VCARD_30); - GNOME_Evolution_Addressbook_BookViewListener_notifyCardAdded ( - book_view->priv->listener, &card_sequence, &ev); + if (currently_in_view) + notify_change (book_view, vcard); + else + notify_add (book_view, id, vcard); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_view_notify_add: Exception signaling BookViewListener!\n"); + g_free (vcard); + } else { + if (currently_in_view) + pas_book_view_notify_remove (book_view, id); + /* else nothing; we're removing a card that wasn't there */ } - CORBA_exception_free (&ev); - - CORBA_free(card_sequence._buffer); + g_mutex_unlock (book_view->priv->pending_mutex); } +/** + * pas_book_view_notify_remove: + */ void -pas_book_view_notify_add_1 (PASBookView *book_view, - const char *card) +pas_book_view_notify_remove (PASBookView *book_view, + const char *id) { - GList *list = g_list_append(NULL, (char *) card); - pas_book_view_notify_add(book_view, list); - g_list_free(list); + g_mutex_lock (book_view->priv->pending_mutex); + notify_remove (book_view, id); + g_mutex_unlock (book_view->priv->pending_mutex); } + void pas_book_view_notify_complete (PASBookView *book_view, - GNOME_Evolution_Addressbook_BookViewListener_CallStatus status) + GNOME_Evolution_Addressbook_CallStatus status) { CORBA_Environment ev; + g_mutex_lock (book_view->priv->pending_mutex); + + send_pending_adds (book_view, TRUE); + send_pending_changes (book_view); + send_pending_removes (book_view); + + g_mutex_unlock (book_view->priv->pending_mutex); + CORBA_exception_init (&ev); GNOME_Evolution_Addressbook_BookViewListener_notifySequenceComplete ( @@ -178,8 +286,8 @@ pas_book_view_notify_status_message (PASBookView *book_view, CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookViewListener_notifyStatusMessage ( - book_view->priv->listener, message, &ev); + GNOME_Evolution_Addressbook_BookViewListener_notifyProgress ( + book_view->priv->listener, message, 0, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("pas_book_view_notify_status_message: Exception signaling BookViewListener!\n"); @@ -190,7 +298,10 @@ pas_book_view_notify_status_message (PASBookView *book_view, static void pas_book_view_construct (PASBookView *book_view, - GNOME_Evolution_Addressbook_BookViewListener listener) + PASBackend *backend, + GNOME_Evolution_Addressbook_BookViewListener listener, + const char *card_query, + PASBackendCardSExp *card_sexp) { PASBookViewPrivate *priv; CORBA_Environment ev; @@ -202,29 +313,70 @@ pas_book_view_construct (PASBookView *book_view, CORBA_exception_init (&ev); - bonobo_object_dup_ref (listener, &ev); + priv->listener = CORBA_Object_duplicate (listener, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_warning("Unable to duplicate & ref listener object in pas-book-view.c\n"); + g_warning("Unable to duplicate listener object in pas-book-view.c\n"); CORBA_exception_free (&ev); return; } CORBA_exception_free (&ev); - priv->listener = listener; + priv->backend = backend; + priv->card_query = g_strdup (card_query); + priv->card_sexp = card_sexp; +} + +/** + * pas_book_view_new: + */ +static void +impl_GNOME_Evolution_Addressbook_BookView_start (PortableServer_Servant servant, + CORBA_Environment *ev) +{ + PASBookView *view = PAS_BOOK_VIEW (bonobo_object (servant)); + + pas_backend_start_book_view (pas_book_view_get_backend (view), view); +} + +/** + * pas_book_view_get_card_query + */ +const char* +pas_book_view_get_card_query (PASBookView *book_view) +{ + return book_view->priv->card_query; +} + +/** + * pas_book_view_get_card_sexp + */ +PASBackendCardSExp* +pas_book_view_get_card_sexp (PASBookView *book_view) +{ + return book_view->priv->card_sexp; +} + +PASBackend* +pas_book_view_get_backend (PASBookView *book_view) +{ + return book_view->priv->backend; } /** * pas_book_view_new: */ PASBookView * -pas_book_view_new (GNOME_Evolution_Addressbook_BookViewListener listener) +pas_book_view_new (PASBackend *backend, + GNOME_Evolution_Addressbook_BookViewListener listener, + const char *card_query, + PASBackendCardSExp *card_sexp) { PASBookView *book_view; book_view = g_object_new (PAS_TYPE_BOOK_VIEW, NULL); - pas_book_view_construct (book_view, listener); + pas_book_view_construct (book_view, backend, listener, card_query, card_sexp); return book_view; } @@ -237,6 +389,19 @@ pas_book_view_dispose (GObject *object) if (book_view->priv) { bonobo_object_release_unref (book_view->priv->listener, NULL); + if (book_view->priv->adds._buffer) + CORBA_free (book_view->priv->adds._buffer); + if (book_view->priv->changes._buffer) + CORBA_free (book_view->priv->changes._buffer); + if (book_view->priv->removes._buffer) + CORBA_free (book_view->priv->removes._buffer); + + g_free (book_view->priv->card_query); + g_object_unref (book_view->priv->card_sexp); + + g_mutex_free (book_view->priv->pending_mutex); + book_view->priv->pending_mutex = NULL; + g_free (book_view->priv); book_view->priv = NULL; } @@ -249,17 +414,30 @@ static void pas_book_view_class_init (PASBookViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + POA_GNOME_Evolution_Addressbook_BookView__epv *epv; pas_book_view_parent_class = g_type_class_peek_parent (klass); object_class->dispose = pas_book_view_dispose; + + epv = &klass->epv; + + epv->start = impl_GNOME_Evolution_Addressbook_BookView_start; + } static void pas_book_view_init (PASBookView *book_view) { - book_view->priv = g_new0 (PASBookViewPrivate, 1); - book_view->priv->listener = CORBA_OBJECT_NIL; + book_view->priv = g_new0 (PASBookViewPrivate, 1); + + book_view->priv->pending_mutex = g_mutex_new(); + + book_view->priv->next_threshold = INITIAL_THRESHOLD; + book_view->priv->threshold_max = 3000; + + book_view->priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); } BONOBO_TYPE_FUNC_FULL ( diff --git a/addressbook/backend/pas/pas-book-view.h b/addressbook/backend/pas/pas-book-view.h index dd6c74c596..0cacab6bf0 100644 --- a/addressbook/backend/pas/pas-book-view.h +++ b/addressbook/backend/pas/pas-book-view.h @@ -16,6 +16,8 @@ #include <pas/addressbook.h> #include <glib.h> #include <glib-object.h> +#include <pas/pas-types.h> +#include <ebook/e-contact.h> #define PAS_TYPE_BOOK_VIEW (pas_book_view_get_type ()) #define PAS_BOOK_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BOOK_VIEW, PASBookView)) @@ -24,8 +26,6 @@ #define PAS_IS_BOOK_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PAS_TYPE_BOOK_VIEW)) #define PAS_BOOK_VIEW_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), PAS_TYPE_BOOK_VIEW, PASBookView)) -typedef struct _PASBookView PASBookView; -typedef struct _PASBookViewClass PASBookViewClass; typedef struct _PASBookViewPrivate PASBookViewPrivate; struct _PASBookView { @@ -40,25 +40,24 @@ struct _PASBookViewClass { }; -PASBookView *pas_book_view_new (GNOME_Evolution_Addressbook_BookViewListener listener); +PASBookView *pas_book_view_new (PASBackend *backend, + GNOME_Evolution_Addressbook_BookViewListener listener, + const char *card_query, + PASBackendCardSExp *card_sexp); -void pas_book_view_notify_change (PASBookView *book_view, - const GList *cards); -void pas_book_view_notify_change_1 (PASBookView *book_view, - const char *card); +const char* pas_book_view_get_card_query (PASBookView *book_view); +PASBackendCardSExp* pas_book_view_get_card_sexp (PASBookView *book_view); +PASBackend* pas_book_view_get_backend (PASBookView *book_view); + +void pas_book_view_notify_update (PASBookView *book_view, + EContact *contact); void pas_book_view_notify_remove (PASBookView *book_view, - const GList *ids); -void pas_book_view_notify_remove_1 (PASBookView *book_view, const char *id); -void pas_book_view_notify_add (PASBookView *book_view, - const GList *cards); -void pas_book_view_notify_add_1 (PASBookView *book_view, - const char *card); void pas_book_view_notify_complete (PASBookView *book_view, - GNOME_Evolution_Addressbook_BookViewListener_CallStatus); + GNOME_Evolution_Addressbook_CallStatus); void pas_book_view_notify_status_message (PASBookView *book_view, const char *message); -GType pas_book_view_get_type (void); +GType pas_book_view_get_type (void); #endif /* ! __PAS_BOOK_VIEW_H__ */ diff --git a/addressbook/backend/pas/pas-book.c b/addressbook/backend/pas/pas-book.c index dc626e59e1..7b6e0c9a2b 100644 --- a/addressbook/backend/pas/pas-book.c +++ b/addressbook/backend/pas/pas-book.c @@ -7,261 +7,68 @@ #include <config.h> #include <bonobo/bonobo-main.h> +#include <bonobo/bonobo-arg.h> #include "e-util/e-list.h" +#include "ebook/e-contact.h" +#include "pas-book-view.h" #include "pas-backend.h" +#include "pas-backend-card-sexp.h" #include "pas-marshal.h" static BonoboObjectClass *pas_book_parent_class; POA_GNOME_Evolution_Addressbook_Book__vepv pas_book_vepv; -enum { - REQUESTS_QUEUED, - LAST_SIGNAL -}; - -static guint pas_book_signals [LAST_SIGNAL]; - struct _PASBookPrivate { - PASBackend *backend; + PASBackend *backend; GNOME_Evolution_Addressbook_BookListener listener; - - GList *request_queue; - gint timeout_id; - - guint timeout_lock : 1; + char *uri; }; -static gboolean -pas_book_check_queue (PASBook *book) -{ - if (book->priv->timeout_lock) - return TRUE; - - book->priv->timeout_lock = TRUE; - - if (book->priv->request_queue != NULL) { - g_signal_emit (book, pas_book_signals [REQUESTS_QUEUED], 0); - } - - if (book->priv->request_queue == NULL) { - book->priv->timeout_id = 0; - book->priv->timeout_lock = FALSE; - bonobo_object_unref (BONOBO_OBJECT (book)); - return FALSE; - } - - book->priv->timeout_lock = FALSE; - - return TRUE; -} - -static void -pas_book_queue_request (PASBook *book, PASRequest *req) -{ - book->priv->request_queue = - g_list_append (book->priv->request_queue, req); - - if (book->priv->timeout_id == 0) { - bonobo_object_ref (BONOBO_OBJECT (book)); - book->priv->timeout_id = g_timeout_add (20, (GSourceFunc) pas_book_check_queue, book); - } -} - -static void -pas_book_queue_create_card (PASBook *book, const char *vcard) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = CreateCard; - req->create.vcard = g_strdup (vcard); - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_remove_cards (PASBook *book, - const GNOME_Evolution_Addressbook_CardIdList *ids) -{ - PASRequest *req; - int i; - - req = g_new0 (PASRequest, 1); - req->op = RemoveCards; - req->remove.ids = NULL; - - for (i = 0; i < ids->_length; i ++) { - req->remove.ids = g_list_append (req->remove.ids, g_strdup (ids->_buffer[i])); - } - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_modify_card (PASBook *book, const char *vcard) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = ModifyCard; - req->modify.vcard = g_strdup (vcard); - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_get_cursor (PASBook *book, const char *search) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = GetCursor; - req->get_cursor.search = g_strdup(search); - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_get_vcard (PASBook *book, const char *id) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = GetVCard; - req->get_vcard.id = g_strdup(id); - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_authenticate_user (PASBook *book, - const char *user, const char *passwd, const char *auth_method) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = AuthenticateUser; - req->auth_user.user = g_strdup(user); - req->auth_user.passwd = g_strdup(passwd); - req->auth_user.auth_method = g_strdup(auth_method); - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_get_supported_fields (PASBook *book) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = GetSupportedFields; - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_get_supported_auth_methods (PASBook *book) -{ - PASRequest *req; - - req = g_new0 (PASRequest, 1); - req->op = GetSupportedAuthMethods; - - pas_book_queue_request (book, req); -} - - static void -pas_book_queue_get_book_view (PASBook *book, const GNOME_Evolution_Addressbook_BookViewListener listener, const char *search) +impl_GNOME_Evolution_Addressbook_Book_open (PortableServer_Servant servant, + const CORBA_boolean only_if_exists, + CORBA_Environment *ev) { - PASRequest *req; - CORBA_Environment ev; - - req = g_new0 (PASRequest, 1); - req->op = GetBookView; - req->get_book_view.search = g_strdup(search); - - CORBA_exception_init (&ev); - - req->get_book_view.listener = bonobo_object_dup_ref(listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_queue_get_book_view: Exception " - "duplicating BookViewListener!\n"); - } + PASBook *book = PAS_BOOK (bonobo_object (servant)); - CORBA_exception_free (&ev); + printf ("impl_GNOME_Evolution_Addressbook_Book_open\n"); - pas_book_queue_request (book, req); + pas_backend_open (pas_book_get_backend (book), book, only_if_exists); } static void -pas_book_queue_get_completion_view (PASBook *book, const GNOME_Evolution_Addressbook_BookViewListener listener, const char *search) +impl_GNOME_Evolution_Addressbook_Book_remove (PortableServer_Servant servant, + CORBA_Environment *ev) { - PASRequest *req; - CORBA_Environment ev; - - req = g_new0 (PASRequest, 1); - req->op = GetCompletionView; - req->get_book_view.search = g_strdup(search); - - CORBA_exception_init (&ev); - - req->get_book_view.listener = bonobo_object_dup_ref(listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_queue_get_completion_view: Exception " - "duplicating BookViewListener!\n"); - } + PASBook *book = PAS_BOOK (bonobo_object (servant)); - CORBA_exception_free (&ev); + printf ("impl_GNOME_Evolution_Addressbook_Book_open\n"); - pas_book_queue_request (book, req); + pas_backend_remove (pas_book_get_backend (book), book); } static void -pas_book_queue_get_changes (PASBook *book, const GNOME_Evolution_Addressbook_BookViewListener listener, const char *change_id) -{ - PASRequest *req; - CORBA_Environment ev; - - req = g_new0 (PASRequest, 1); - req->op = GetChanges; - req->get_changes.change_id= g_strdup(change_id); - - CORBA_exception_init (&ev); - - req->get_changes.listener = bonobo_object_dup_ref(listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_queue_get_changes: Exception " - "duplicating BookViewListener!\n"); - } - - CORBA_exception_free (&ev); - - pas_book_queue_request (book, req); -} - -static void -pas_book_queue_check_connection (PASBook *book) +impl_GNOME_Evolution_Addressbook_Book_getContact (PortableServer_Servant servant, + const CORBA_char *id, + CORBA_Environment *ev) { - PASRequest *req; + PASBook *book = PAS_BOOK (bonobo_object (servant)); - req = g_new0 (PASRequest, 1); - req->op = CheckConnection; + printf ("impl_GNOME_Evolution_Addressbook_Book_getContact\n"); - pas_book_queue_request (book, req); + pas_backend_get_contact (pas_book_get_backend (book), book, id); } static void -impl_GNOME_Evolution_Addressbook_Book_getVCard (PortableServer_Servant servant, - const CORBA_char *id, - CORBA_Environment *ev) +impl_GNOME_Evolution_Addressbook_Book_getContactList (PortableServer_Servant servant, + const CORBA_char *query, + CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_get_vcard (book, id); + printf ("impl_GNOME_Evolution_Addressbook_Book_getContactList\n"); + + pas_backend_get_contact_list (pas_book_get_backend (book), book, query); } static void @@ -273,90 +80,97 @@ impl_GNOME_Evolution_Addressbook_Book_authenticateUser (PortableServer_Servant s { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_authenticate_user (book, user, passwd, auth_method); + pas_backend_authenticate_user (pas_book_get_backend (book), book, + user, passwd, auth_method); } static void -impl_GNOME_Evolution_Addressbook_Book_addCard (PortableServer_Servant servant, - const CORBA_char *vcard, - CORBA_Environment *ev) +impl_GNOME_Evolution_Addressbook_Book_addContact (PortableServer_Servant servant, + const CORBA_char *vcard, + CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_create_card (book, (const char *) vcard); + pas_backend_create_contact (pas_book_get_backend (book), book, vcard); } static void -impl_GNOME_Evolution_Addressbook_Book_removeCards (PortableServer_Servant servant, - const GNOME_Evolution_Addressbook_CardIdList *ids, - CORBA_Environment *ev) +impl_GNOME_Evolution_Addressbook_Book_removeContacts (PortableServer_Servant servant, + const GNOME_Evolution_Addressbook_ContactIdList *ids, + CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object (servant)); + int i; + GList *id_list = NULL; + + for (i = 0; i < ids->_length; i ++) + id_list = g_list_append (id_list, ids->_buffer[i]); - pas_book_queue_remove_cards (book, ids); -} - -static void -impl_GNOME_Evolution_Addressbook_Book_modifyCard (PortableServer_Servant servant, - const CORBA_char *vcard, - CORBA_Environment *ev) -{ - PASBook *book = PAS_BOOK (bonobo_object (servant)); + pas_backend_remove_contacts (pas_book_get_backend (book), book, id_list); - pas_book_queue_modify_card (book, (const char *) vcard); + g_list_free (id_list); } static void -impl_GNOME_Evolution_Addressbook_Book_getCursor (PortableServer_Servant servant, - const CORBA_char *search, - CORBA_Environment *ev) +impl_GNOME_Evolution_Addressbook_Book_modifyContact (PortableServer_Servant servant, + const CORBA_char *vcard, + CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_get_cursor (book, search); + pas_backend_modify_contact (pas_book_get_backend (book), book, vcard); } static void impl_GNOME_Evolution_Addressbook_Book_getBookView (PortableServer_Servant servant, const GNOME_Evolution_Addressbook_BookViewListener listener, const CORBA_char *search, + const GNOME_Evolution_Addressbook_stringlist* requested_fields, + const CORBA_long max_results, CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object (servant)); + PASBackend *backend = pas_book_get_backend (book); + PASBackendCardSExp *card_sexp; + PASBookView *view; - pas_book_queue_get_book_view (book, listener, search); -} + g_warning ("impl_GNOME_Evolution_Addressbook_Book_getBookView (%s)\n", search); + /* we handle this entirely here, since it doesn't require any + backend involvement now that we have pas_book_view_start to + actually kick off the search. */ -static void -impl_GNOME_Evolution_Addressbook_Book_getCompletionView (PortableServer_Servant servant, - const GNOME_Evolution_Addressbook_BookViewListener listener, - const CORBA_char *search, - CORBA_Environment *ev) -{ - PASBook *book = PAS_BOOK (bonobo_object (servant)); + card_sexp = pas_backend_card_sexp_new (search); + if (!card_sexp) { + pas_book_respond_get_book_view (book, GNOME_Evolution_Addressbook_InvalidQuery, NULL); + return; + } + + view = pas_book_view_new (backend, listener, search, card_sexp); - pas_book_queue_get_completion_view (book, listener, search); + if (!view) { + g_object_unref (card_sexp); + pas_book_respond_get_book_view (book, GNOME_Evolution_Addressbook_OtherError, NULL); + return; + } + + + pas_backend_add_book_view (backend, view); + + pas_book_respond_get_book_view (book, GNOME_Evolution_Addressbook_Success, view); + + g_object_unref (view); } + static void impl_GNOME_Evolution_Addressbook_Book_getChanges (PortableServer_Servant servant, - const GNOME_Evolution_Addressbook_BookViewListener listener, const CORBA_char *change_id, CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_get_changes (book, listener, change_id); -} - -static void -impl_GNOME_Evolution_Addressbook_Book_checkConnection (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - PASBook *book = PAS_BOOK (bonobo_object (servant)); - - pas_book_queue_check_connection (book); + pas_backend_get_changes (pas_book_get_backend (book), book, change_id); } static char * @@ -379,7 +193,7 @@ impl_GNOME_Evolution_Addressbook_Book_getSupportedFields (PortableServer_Servant { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_get_supported_fields (book); + pas_backend_get_supported_fields (pas_book_get_backend (book), book); } static void @@ -388,7 +202,16 @@ impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods (PortableServer_Se { PASBook *book = PAS_BOOK (bonobo_object (servant)); - pas_book_queue_get_supported_auth_methods (book); + pas_backend_get_supported_auth_methods (pas_book_get_backend (book), book); +} + +static GNOME_Evolution_Addressbook_CallStatus +impl_GNOME_Evolution_Addressbook_Book_cancelOperation (PortableServer_Servant servant, + CORBA_Environment *ev) +{ + PASBook *book = PAS_BOOK (bonobo_object (servant)); + + return pas_backend_cancel_operation (pas_book_get_backend (book), book); } /** @@ -397,87 +220,59 @@ impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods (PortableServer_Se PASBackend * pas_book_get_backend (PASBook *book) { - g_return_val_if_fail (book != NULL, NULL); - g_return_val_if_fail (PAS_IS_BOOK (book), NULL); + g_return_val_if_fail (book && PAS_IS_BOOK (book), NULL); return book->priv->backend; } -/** - * pas_book_get_listener: - */ GNOME_Evolution_Addressbook_BookListener pas_book_get_listener (PASBook *book) { - g_return_val_if_fail (book != NULL, CORBA_OBJECT_NIL); - g_return_val_if_fail (PAS_IS_BOOK (book), CORBA_OBJECT_NIL); + g_return_val_if_fail (book && PAS_IS_BOOK (book), CORBA_OBJECT_NIL); return book->priv->listener; } -/** - * pas_book_check_pending - */ -gint -pas_book_check_pending (PASBook *book) +const char* +pas_book_get_uri (PASBook *book) { - g_return_val_if_fail (book != NULL, -1); - g_return_val_if_fail (PAS_IS_BOOK (book), -1); - - return g_list_length (book->priv->request_queue); + return book->priv->uri; } /** - * pas_book_pop_request: + * pas_book_respond_open: */ -PASRequest * -pas_book_pop_request (PASBook *book) +void +pas_book_respond_open (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status) { - GList *popped; - PASRequest *req; - - g_return_val_if_fail (book != NULL, NULL); - g_return_val_if_fail (PAS_IS_BOOK (book), NULL); - - if (book->priv->request_queue == NULL) - return NULL; - - req = book->priv->request_queue->data; + CORBA_Environment ev; - popped = book->priv->request_queue; - book->priv->request_queue = - g_list_remove_link (book->priv->request_queue, popped); + CORBA_exception_init (&ev); + GNOME_Evolution_Addressbook_BookListener_notifyBookOpened (book->priv->listener, status, &ev); - g_list_free_1 (popped); + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("pas_book_respond_open: Exception " + "responding to BookListener!\n"); + } - return req; + CORBA_exception_free (&ev); } /** - * pas_book_respond_open: + * pas_book_respond_remove: */ void -pas_book_respond_open (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status) +pas_book_respond_remove (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status) { CORBA_Environment ev; CORBA_exception_init (&ev); - - if (status == GNOME_Evolution_Addressbook_BookListener_Success) { - GNOME_Evolution_Addressbook_BookListener_notifyBookOpened ( - book->priv->listener, status, - bonobo_object_corba_objref (BONOBO_OBJECT (book)), - &ev); - } else { - GNOME_Evolution_Addressbook_BookListener_notifyBookOpened ( - book->priv->listener, status, - CORBA_OBJECT_NIL, &ev); - } - + GNOME_Evolution_Addressbook_BookListener_notifyBookRemoved (book->priv->listener, status, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_respond_open: Exception " + g_warning ("pas_book_respond_remove: Exception " "responding to BookListener!\n"); } @@ -488,16 +283,22 @@ pas_book_respond_open (PASBook *book, * pas_book_respond_create: */ void -pas_book_respond_create (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - const char *id) +pas_book_respond_create (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + EContact *contact) { CORBA_Environment ev; + if (status == GNOME_Evolution_Addressbook_Success) { + pas_backend_notify_update (book->priv->backend, contact); + pas_backend_notify_complete (book->priv->backend); + } + CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyCardCreated ( - book->priv->listener, status, (char *)id, &ev); + GNOME_Evolution_Addressbook_BookListener_notifyContactCreated ( + book->priv->listener, status, + e_contact_get (contact, E_CONTACT_UID), &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("pas_book_respond_create: Exception " @@ -508,17 +309,25 @@ pas_book_respond_create (PASBook *book, } /** - * pas_book_respond_remove: + * pas_book_respond_remove_contacts: */ void -pas_book_respond_remove (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status) +pas_book_respond_remove_contacts (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *ids) { CORBA_Environment ev; + GList *i; CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyCardsRemoved ( + if (ids) { + for (i = ids; i; i = i->next) + pas_backend_notify_remove (book->priv->backend, i->data); + pas_backend_notify_complete (book->priv->backend); + } + + GNOME_Evolution_Addressbook_BookListener_notifyContactsRemoved ( book->priv->listener, status, &ev); if (ev._major != CORBA_NO_EXCEPTION) { @@ -533,14 +342,20 @@ pas_book_respond_remove (PASBook *book, * pas_book_respond_modify: */ void -pas_book_respond_modify (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status) +pas_book_respond_modify (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + EContact *contact) { CORBA_Environment ev; + if (status == GNOME_Evolution_Addressbook_Success) { + pas_backend_notify_update (book->priv->backend, contact); + pas_backend_notify_complete (book->priv->backend); + } + CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyCardModified ( + GNOME_Evolution_Addressbook_BookListener_notifyContactModified ( book->priv->listener, status, &ev); if (ev._major != CORBA_NO_EXCEPTION) { @@ -556,7 +371,7 @@ pas_book_respond_modify (PASBook *book, */ void pas_book_respond_authenticate_user (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status) + GNOME_Evolution_Addressbook_CallStatus status) { CORBA_Environment ev; @@ -575,30 +390,28 @@ pas_book_respond_authenticate_user (PASBook *book, void pas_book_respond_get_supported_fields (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - EList *fields) + GNOME_Evolution_Addressbook_CallStatus status, + GList *fields) { CORBA_Environment ev; GNOME_Evolution_Addressbook_stringlist stringlist; int num_fields; - EIterator *iter; int i; + GList *iter; CORBA_exception_init (&ev); - num_fields = e_list_length (fields); + num_fields = g_list_length (fields); stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields); stringlist._maximum = num_fields; stringlist._length = num_fields; - iter = e_list_get_iterator (fields); - - for (i = 0; e_iterator_is_valid (iter); e_iterator_next (iter), i ++) { - stringlist._buffer[i] = CORBA_string_dup (e_iterator_get(iter)); + for (i = 0, iter = fields; iter; iter = iter->next, i ++) { + stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data); } - g_object_unref (fields); + printf ("calling GNOME_Evolution_Addressbook_BookListener_notifySupportedFields\n"); GNOME_Evolution_Addressbook_BookListener_notifySupportedFields ( book->priv->listener, status, @@ -612,31 +425,27 @@ pas_book_respond_get_supported_fields (PASBook *book, void pas_book_respond_get_supported_auth_methods (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - EList *auth_methods) + GNOME_Evolution_Addressbook_CallStatus status, + GList *auth_methods) { CORBA_Environment ev; GNOME_Evolution_Addressbook_stringlist stringlist; int num_auth_methods; - EIterator *iter; + GList *iter; int i; CORBA_exception_init (&ev); - num_auth_methods = e_list_length (auth_methods); + num_auth_methods = g_list_length (auth_methods); stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_auth_methods); stringlist._maximum = num_auth_methods; stringlist._length = num_auth_methods; - iter = e_list_get_iterator (auth_methods); - - for (i = 0; e_iterator_is_valid (iter); e_iterator_next (iter), i ++) { - stringlist._buffer[i] = CORBA_string_dup (e_iterator_get(iter)); + for (i = 0, iter = auth_methods; iter; iter = iter->next, i ++) { + stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data); } - g_object_unref (auth_methods); - GNOME_Evolution_Addressbook_BookListener_notifySupportedAuthMethods ( book->priv->listener, status, &stringlist, @@ -647,30 +456,28 @@ pas_book_respond_get_supported_auth_methods (PASBook *book, CORBA_free(stringlist._buffer); } -/** - * pas_book_respond_get_cursor: - */ -void -pas_book_respond_get_cursor (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - PASCardCursor *cursor) -{ - CORBA_Environment ev; - CORBA_Object object; - - CORBA_exception_init (&ev); - - object = bonobo_object_corba_objref(BONOBO_OBJECT(cursor)); - - GNOME_Evolution_Addressbook_BookListener_notifyCursorRequested ( - book->priv->listener, status, object, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_respond_get_cursor: Exception " - "responding to BookListener!\n"); +static void +view_destroy(gpointer data, GObject *where_object_was) +{ + PASBook *book = (PASBook *)data; + EIterator *iterator; + gboolean success = FALSE; + EList *views = pas_backend_get_book_views (book->priv->backend); + + for (iterator = e_list_get_iterator(views); + e_iterator_is_valid(iterator); + e_iterator_next(iterator)) { + const PASBookView *view = e_iterator_get(iterator); + if (view == (PASBookView*)where_object_was) { + e_iterator_delete(iterator); + success = TRUE; + break; + } } - - CORBA_exception_free (&ev); + if (!success) + g_warning ("Failed to remove from book_views list"); + g_object_unref(iterator); + g_object_unref(views); } /** @@ -678,15 +485,21 @@ pas_book_respond_get_cursor (PASBook *book, */ void pas_book_respond_get_book_view (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, + GNOME_Evolution_Addressbook_CallStatus status, PASBookView *book_view) { CORBA_Environment ev; - CORBA_Object object; + CORBA_Object object = CORBA_OBJECT_NIL; + + printf ("pas_book_respond_get_book_view\n"); CORBA_exception_init (&ev); - - object = bonobo_object_corba_objref(BONOBO_OBJECT(book_view)); + + if (book_view) { + object = bonobo_object_corba_objref(BONOBO_OBJECT(book_view)); + + g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); + } GNOME_Evolution_Addressbook_BookListener_notifyViewRequested ( book->priv->listener, status, object, &ev); @@ -700,100 +513,122 @@ pas_book_respond_get_book_view (PASBook *book, } /** - * pas_book_respond_get_book_view: + * pas_book_respond_get_contact: */ void -pas_book_respond_get_completion_view (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - PASBookView *completion_view) +pas_book_respond_get_contact (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + char *vcard) { CORBA_Environment ev; - CORBA_Object object; CORBA_exception_init (&ev); - - object = bonobo_object_corba_objref(BONOBO_OBJECT(completion_view)); - GNOME_Evolution_Addressbook_BookListener_notifyViewRequested ( - book->priv->listener, status, object, &ev); + GNOME_Evolution_Addressbook_BookListener_notifyContactRequested (book->priv->listener, + status, + vcard, + &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_respond_get_completion_view: Exception " - "responding to BookListener!\n"); - } + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("could not notify listener of get-contact response"); CORBA_exception_free (&ev); } /** - * pas_book_respond_get_changes: + * pas_book_respond_get_contact_list: */ void -pas_book_respond_get_vcard (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - char *vcard) +pas_book_respond_get_contact_list (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *card_list) { CORBA_Environment ev; + GNOME_Evolution_Addressbook_stringlist stringlist; + int num_cards; + int i; + GList *l; CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyCardRequested ( - book->priv->listener, status, vcard, &ev); + num_cards = g_list_length (card_list); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_respond_get_card: Exception " - "responding to BookListener!\n"); - } + stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_cards); + stringlist._maximum = num_cards; + stringlist._length = num_cards; - CORBA_exception_free (&ev); -} + for (i = 0, l = card_list; l; l = l->next, i ++) + stringlist._buffer[i] = CORBA_string_dup (l->data); -/** - * pas_book_respond_get_changes: - */ -void -pas_book_respond_get_changes (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - PASBookView *book_view) -{ - CORBA_Environment ev; - CORBA_Object object; + g_list_foreach (card_list, (GFunc)g_free, NULL); + g_list_free (card_list); - CORBA_exception_init (&ev); - - object = bonobo_object_corba_objref(BONOBO_OBJECT(book_view)); - GNOME_Evolution_Addressbook_BookListener_notifyChangesRequested ( - book->priv->listener, status, object, &ev); + GNOME_Evolution_Addressbook_BookListener_notifyContactListRequested (book->priv->listener, + status, + &stringlist, + &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_respond_get_changes: Exception " - "responding to BookListener!\n"); - } + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("could not notify listener of get-contact-list response"); CORBA_exception_free (&ev); + + CORBA_free(stringlist._buffer); } /** - * pas_book_report_connection: + * pas_book_respond_get_changes: */ void -pas_book_report_connection (PASBook *book, - gboolean connected) +pas_book_respond_get_changes (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *changes) { CORBA_Environment ev; + GNOME_Evolution_Addressbook_BookChangeList changelist; + int num_changes; + int i; + GList *l; CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyConnectionStatus ( - book->priv->listener, (CORBA_boolean) connected, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_report_connection: Exception " - "responding to BookListener!\n"); + num_changes = g_list_length (changes); + + changelist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_BookChangeItem_allocbuf (num_changes); + changelist._maximum = num_changes; + changelist._length = num_changes; + + for (i = 0, l = changes; l; l = l->next, i ++) { + GNOME_Evolution_Addressbook_BookChangeItem *change = (GNOME_Evolution_Addressbook_BookChangeItem*)l->data; + changelist._buffer[i] = *change; + switch (change->_d) { + case GNOME_Evolution_Addressbook_ContactAdded: + changelist._buffer[i]._u.add_vcard = CORBA_string_dup (change->_u.add_vcard); + break; + case GNOME_Evolution_Addressbook_ContactModified: + changelist._buffer[i]._u.mod_vcard = CORBA_string_dup (change->_u.mod_vcard); + break; + case GNOME_Evolution_Addressbook_ContactDeleted: + changelist._buffer[i]._u.del_id = CORBA_string_dup (change->_u.del_id); + break; + } } + g_list_foreach (changes, (GFunc)CORBA_free, NULL); + g_list_free (changes); + + GNOME_Evolution_Addressbook_BookListener_notifyChangesRequested (book->priv->listener, + status, + &changelist, + &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("could not notify listener of get-changes response"); + CORBA_exception_free (&ev); + + CORBA_free(changelist._buffer); } /** @@ -821,7 +656,8 @@ pas_book_report_writable (PASBook *book, static void pas_book_construct (PASBook *book, PASBackend *backend, - GNOME_Evolution_Addressbook_BookListener listener) + const char *uri, + GNOME_Evolution_Addressbook_BookListener listener) { PASBookPrivate *priv; CORBA_Environment ev; @@ -830,8 +666,6 @@ pas_book_construct (PASBook *book, priv = book->priv; - priv->backend = backend; - CORBA_exception_init (&ev); book->priv->listener = CORBA_Object_duplicate (listener, &ev); @@ -843,94 +677,31 @@ pas_book_construct (PASBook *book, CORBA_exception_free (&ev); - priv->listener = listener; + priv->backend = backend; + priv->uri = g_strdup (uri); + } /** * pas_book_new: */ PASBook * -pas_book_new (PASBackend *backend, +pas_book_new (PASBackend *backend, + const char *uri, GNOME_Evolution_Addressbook_BookListener listener) { PASBook *book; + char *caps = pas_backend_get_static_capabilities (backend); - book = g_object_new (PAS_TYPE_BOOK, NULL); - - pas_book_construct (book, backend, listener); + book = g_object_new (PAS_TYPE_BOOK, + "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL), + NULL); - return book; -} + pas_book_construct (book, backend, uri, listener); -void -pas_book_free_request (PASRequest *req) -{ - CORBA_Environment ev; - switch (req->op) { - case CreateCard: - g_free (req->create.id); - g_free (req->create.vcard); - break; - case RemoveCards: - g_list_foreach (req->remove.ids, (GFunc)g_free, NULL); - g_list_free (req->remove.ids); - break; - case ModifyCard: - g_free (req->modify.vcard); - break; - case GetVCard: - g_free (req->get_vcard.id); - break; - case GetCursor: - g_free (req->get_cursor.search); - break; - case GetBookView: - g_free (req->get_book_view.search); - CORBA_exception_init (&ev); - bonobo_object_release_unref (req->get_book_view.listener, &ev); + g_free (caps); - if (ev._major != CORBA_NO_EXCEPTION) - g_message ("pas_book_free_request(GetBookView): could not release the listener"); - - CORBA_exception_free (&ev); - break; - case GetCompletionView: - g_free (req->get_completion_view.search); - CORBA_exception_init (&ev); - bonobo_object_release_unref (req->get_completion_view.listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - g_message ("pas_book_free_request(GetCompletionView): could not release the listener"); - - CORBA_exception_free (&ev); - break; - case GetChanges: - g_free (req->get_changes.change_id); - CORBA_exception_init (&ev); - bonobo_object_release_unref (req->get_changes.listener, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - g_message ("pas_book_free_request(GetChanges): could not release the listener"); - - CORBA_exception_free (&ev); - break; - case CheckConnection: - /* nothing to free */ - break; - case AuthenticateUser: - g_free (req->auth_user.user); - g_free (req->auth_user.passwd); - g_free (req->auth_user.auth_method); - break; - case GetSupportedFields: - /* nothing to free */ - break; - case GetSupportedAuthMethods: - /* nothing to free */ - break; - } - - g_free (req); + return book; } static void @@ -939,24 +710,8 @@ pas_book_dispose (GObject *object) PASBook *book = PAS_BOOK (object); if (book->priv) { - GList *l; CORBA_Environment ev; - for (l = book->priv->request_queue; l != NULL; l = l->next) { - pas_book_free_request ((PASRequest *)l->data); - } - g_list_free (book->priv->request_queue); - - /* We should never ever have timeout_id == 0 when we - get destroyed, unless there is some sort of - reference counting bug. Still, we do this to try - to avoid horrible crashes in those situations. */ - if (book->priv->timeout_id) { - g_warning ("PASBook destroyed with non-zero timeout_id. This shouldn't happen."); - g_source_remove (book->priv->timeout_id); - book->priv->timeout_id = 0; - } - CORBA_exception_init (&ev); CORBA_Object_release (book->priv->listener, &ev); @@ -965,6 +720,7 @@ pas_book_dispose (GObject *object) CORBA_exception_free (&ev); + g_free (book->priv->uri); g_free (book->priv); book->priv = NULL; } @@ -981,42 +737,30 @@ pas_book_class_init (PASBookClass *klass) pas_book_parent_class = g_type_class_peek_parent (klass); - pas_book_signals [REQUESTS_QUEUED] = - g_signal_new ("requests_queued", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PASBookClass, requests_queued), - NULL, NULL, - pas_marshal_NONE__NONE, - G_TYPE_NONE, 0); - object_class->dispose = pas_book_dispose; epv = &klass->epv; - epv->getVCard = impl_GNOME_Evolution_Addressbook_Book_getVCard; + epv->open = impl_GNOME_Evolution_Addressbook_Book_open; + epv->remove = impl_GNOME_Evolution_Addressbook_Book_remove; + epv->getContact = impl_GNOME_Evolution_Addressbook_Book_getContact; + epv->getContactList = impl_GNOME_Evolution_Addressbook_Book_getContactList; epv->authenticateUser = impl_GNOME_Evolution_Addressbook_Book_authenticateUser; - epv->addCard = impl_GNOME_Evolution_Addressbook_Book_addCard; - epv->removeCards = impl_GNOME_Evolution_Addressbook_Book_removeCards; - epv->modifyCard = impl_GNOME_Evolution_Addressbook_Book_modifyCard; - epv->checkConnection = impl_GNOME_Evolution_Addressbook_Book_checkConnection; + epv->addContact = impl_GNOME_Evolution_Addressbook_Book_addContact; + epv->removeContacts = impl_GNOME_Evolution_Addressbook_Book_removeContacts; + epv->modifyContact = impl_GNOME_Evolution_Addressbook_Book_modifyContact; epv->getStaticCapabilities = impl_GNOME_Evolution_Addressbook_Book_getStaticCapabilities; epv->getSupportedFields = impl_GNOME_Evolution_Addressbook_Book_getSupportedFields; epv->getSupportedAuthMethods = impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods; - epv->getCursor = impl_GNOME_Evolution_Addressbook_Book_getCursor; epv->getBookView = impl_GNOME_Evolution_Addressbook_Book_getBookView; - epv->getCompletionView = impl_GNOME_Evolution_Addressbook_Book_getCompletionView; epv->getChanges = impl_GNOME_Evolution_Addressbook_Book_getChanges; + epv->cancelOperation = impl_GNOME_Evolution_Addressbook_Book_cancelOperation; } static void pas_book_init (PASBook *book) { book->priv = g_new0 (PASBookPrivate, 1); - book->priv->timeout_id = 0; - book->priv->request_queue = NULL; - book->priv->timeout_id = 0; - book->priv->timeout_lock = FALSE; } BONOBO_TYPE_FUNC_FULL ( diff --git a/addressbook/backend/pas/pas-book.h b/addressbook/backend/pas/pas-book.h index 761f906437..2cb84569c2 100644 --- a/addressbook/backend/pas/pas-book.h +++ b/addressbook/backend/pas/pas-book.h @@ -12,13 +12,11 @@ #ifndef __PAS_BOOK_H__ #define __PAS_BOOK_H__ -#include <bonobo/bonobo-object.h> #include <pas/addressbook.h> -#include <pas/pas-book-view.h> +#include <bonobo/bonobo-object.h> #include "e-util/e-list.h" -#include <pas/pas-backend.h> -#include <pas/pas-card-cursor.h> +#include <pas/pas-types.h> #define PAS_TYPE_BOOK (pas_book_get_type ()) #define PAS_BOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_BOOK, PASBook)) @@ -27,164 +25,68 @@ #define PAS_IS_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PAS_TYPE_BOOK)) #define PAS_BOOK_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), PAS_TYPE_BOOK, PASBookClass)) -typedef struct _PASBook PASBook; typedef struct _PASBookPrivate PASBookPrivate; -typedef enum { - CreateCard, - RemoveCards, - ModifyCard, - GetVCard, - GetCursor, - GetBookView, - GetCompletionView, - GetChanges, - CheckConnection, - AuthenticateUser, - GetSupportedFields, - GetSupportedAuthMethods -} PASOperation; - -typedef struct { - PASOperation op; - char *id; - char *vcard; -} PASCreateCardRequest; - -typedef struct { - PASOperation op; - GList *ids; -} PASRemoveCardsRequest; - -typedef struct { - PASOperation op; - char *vcard; -} PASModifyCardRequest; - -typedef struct { - PASOperation op; - char *id; -} PASGetVCardRequest; - -typedef struct { - PASOperation op; - char *search; -} PASGetCursorRequest; - -typedef struct { - PASOperation op; - char *search; - GNOME_Evolution_Addressbook_BookViewListener listener; -} PASGetBookViewRequest; - -typedef struct { - PASOperation op; - char *search; - GNOME_Evolution_Addressbook_BookViewListener listener; -} PASGetCompletionViewRequest; - -typedef struct { - PASOperation op; - char *change_id; - GNOME_Evolution_Addressbook_BookViewListener listener; -} PASGetChangesRequest; - -typedef struct { - PASOperation op; -} PASCheckConnectionRequest; - -typedef struct { - PASOperation op; - char *user; - char *passwd; - char *auth_method; -} PASAuthenticateUserRequest; - -typedef struct { - PASOperation op; -} PASGetSupportedFieldsRequest; - -typedef struct { - PASOperation op; -} PASGetSupportedAuthMethodsRequest; - -typedef union { - PASOperation op; - - PASCreateCardRequest create; - PASRemoveCardsRequest remove; - PASModifyCardRequest modify; - PASGetVCardRequest get_vcard; - PASGetCursorRequest get_cursor; - PASGetBookViewRequest get_book_view; - PASGetCompletionViewRequest get_completion_view; - PASGetChangesRequest get_changes; - PASCheckConnectionRequest check_connection; - PASAuthenticateUserRequest auth_user; - PASGetSupportedFieldsRequest get_supported_fields; - PASGetSupportedAuthMethodsRequest get_supported_auth_methods; -} PASRequest; - struct _PASBook { - BonoboObject parent_object; - PASBookPrivate *priv; + BonoboObject parent_object; + PASBookPrivate *priv; }; -typedef struct { +struct _PASBookClass { BonoboObjectClass parent_class; POA_GNOME_Evolution_Addressbook_Book__epv epv; - /* Signals */ - void (*requests_queued) (void); -} PASBookClass; - - -typedef gboolean (*PASBookCanWriteFn) (PASBook *book); -typedef gboolean (*PASBookCanWriteCardFn) (PASBook *book, const char *id); - -PASBook *pas_book_new (PASBackend *backend, - GNOME_Evolution_Addressbook_BookListener listener); -PASBackend *pas_book_get_backend (PASBook *book); -GNOME_Evolution_Addressbook_BookListener pas_book_get_listener (PASBook *book); -int pas_book_check_pending (PASBook *book); -PASRequest *pas_book_pop_request (PASBook *book); -void pas_book_free_request (PASRequest *request); -void pas_book_respond_open (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status); -void pas_book_respond_create (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - const char *id); -void pas_book_respond_remove (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status); -void pas_book_respond_modify (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status); -void pas_book_respond_authenticate_user (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status); -void pas_book_respond_get_supported_fields (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - EList *fields); -void pas_book_respond_get_supported_auth_methods (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - EList *fields); - -void pas_book_respond_get_cursor (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - PASCardCursor *cursor); + /* Padding for future expansion */ + void (*_pas_reserved0) (void); + void (*_pas_reserved1) (void); + void (*_pas_reserved2) (void); + void (*_pas_reserved3) (void); + void (*_pas_reserved4) (void); +}; + + +PASBook *pas_book_new (PASBackend *backend, + const char *uri, + GNOME_Evolution_Addressbook_BookListener listener); +GNOME_Evolution_Addressbook_BookListener pas_book_get_listener (PASBook *book); +PASBackend *pas_book_get_backend (PASBook *book); +const char *pas_book_get_uri (PASBook *book); + +void pas_book_respond_open (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status); +void pas_book_respond_remove (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status); +void pas_book_respond_create (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + EContact *contact); +void pas_book_respond_remove_contacts (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *ids); +void pas_book_respond_modify (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + EContact *contact); +void pas_book_respond_authenticate_user (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status); +void pas_book_respond_get_supported_fields (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *fields); +void pas_book_respond_get_supported_auth_methods (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *fields); + void pas_book_respond_get_book_view (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, + GNOME_Evolution_Addressbook_CallStatus status, PASBookView *book_view); -void pas_book_respond_get_completion_view (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - PASBookView *completion_view); -void pas_book_respond_get_vcard (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, +void pas_book_respond_get_contact (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, char *vcard); -void pas_book_respond_get_changes (PASBook *book, - GNOME_Evolution_Addressbook_BookListener_CallStatus status, - PASBookView *book_view); -void pas_book_report_connection (PASBook *book, - gboolean connected); +void pas_book_respond_get_contact_list (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *cards); +void pas_book_respond_get_changes (PASBook *book, + GNOME_Evolution_Addressbook_CallStatus status, + GList *changes); void pas_book_report_writable (PASBook *book, gboolean writable); diff --git a/addressbook/backend/pas/pas-card-cursor.c b/addressbook/backend/pas/pas-card-cursor.c deleted file mode 100644 index 9637bb1fb7..0000000000 --- a/addressbook/backend/pas/pas-card-cursor.c +++ /dev/null @@ -1,139 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * pas-card-cursor.c: Implements card cursors. - * - * Author: - * Christopher James Lahey <clahey@ximian.com. - */ - -#include <config.h> -#include <bonobo/bonobo-main.h> -#include "addressbook.h" -#include "pas-card-cursor.h" - -struct _PASCardCursorPrivate { - long (*get_length) (PASCardCursor *cursor, gpointer data); - char * (*get_nth) (PASCardCursor *cursor, long n, gpointer data); - gpointer data; -}; - -/* - * A pointer to our parent object class - */ -static BonoboObjectClass *parent_class; - -/* - * Implemented GObject::dispose - */ -static void -pas_card_cursor_dispose (GObject *object) -{ - PASCardCursor *cursor = PAS_CARD_CURSOR (object); - - if ( cursor->priv ) { - g_free ( cursor->priv ); - cursor->priv = NULL; - } - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -/* - * CORBA Demo::Echo::echo method implementation - */ -static CORBA_long -impl_pas_card_cursor_get_length (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - PASCardCursor *cursor = PAS_CARD_CURSOR (bonobo_object (servant)); - if ( cursor->priv->get_length ) - return cursor->priv->get_length( cursor, cursor->priv->data ); - else - return 0; -} - -/* - * CORBA Demo::Echo::echo method implementation - */ -static char * -impl_pas_card_cursor_get_nth (PortableServer_Servant servant, - const CORBA_long n, - CORBA_Environment *ev) -{ - PASCardCursor *cursor = PAS_CARD_CURSOR (bonobo_object (servant)); - if ( cursor->priv->get_nth ) { - char *vcard = cursor->priv->get_nth( cursor, n, cursor->priv->data ); - char *retval = CORBA_string_dup (vcard); - g_free (vcard); - return retval; - } else - return CORBA_string_dup (""); -} - -static void -pas_card_cursor_class_init (PASCardCursorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - POA_GNOME_Evolution_Addressbook_CardCursor__epv *epv; - - parent_class = g_type_class_peek_parent (klass); - - object_class->dispose = pas_card_cursor_dispose; - - - epv = &klass->epv; - - epv->count = impl_pas_card_cursor_get_length; - epv->getNth = impl_pas_card_cursor_get_nth; -} - -static void -pas_card_cursor_init (PASCardCursor *cursor) -{ - cursor->priv = g_new0(PASCardCursorPrivate, 1); - cursor->priv->get_length = NULL; - cursor->priv->get_nth = NULL; - cursor->priv->data = NULL; -} - -static void -pas_card_cursor_construct (PASCardCursor *cursor, - PASCardCursorLengthFunc get_length, - PASCardCursorNthFunc get_nth, - gpointer data) -{ - PASCardCursorPrivate *priv; - - g_return_if_fail (cursor != NULL); - g_return_if_fail (PAS_IS_CARD_CURSOR (cursor)); - - priv = cursor->priv; - - priv->get_length = get_length; - priv->get_nth = get_nth; - priv->data = data; -} - -PASCardCursor * -pas_card_cursor_new (PASCardCursorLengthFunc get_length, - PASCardCursorNthFunc get_nth, - gpointer data) -{ - PASCardCursor *cursor; - - cursor = g_object_new (PAS_TYPE_CARD_CURSOR, NULL); - - pas_card_cursor_construct (cursor, - get_length, - get_nth, - data); - - return cursor; -} - -BONOBO_TYPE_FUNC_FULL ( - PASCardCursor, - GNOME_Evolution_Addressbook_CardCursor, - BONOBO_TYPE_OBJECT, - pas_card_cursor); diff --git a/addressbook/backend/pas/pas-card-cursor.h b/addressbook/backend/pas/pas-card-cursor.h deleted file mode 100644 index db5b05c0c2..0000000000 --- a/addressbook/backend/pas/pas-card-cursor.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * - * Author: - * Nat Friedman (nat@ximian.com) - * - * Copyright 2000, Ximian, Inc. - */ - -#ifndef __PAS_CARD_CURSOR_H__ -#define __PAS_CARD_CURSOR_H__ - -#include <bonobo/bonobo-object.h> -#include <pas/addressbook.h> - -G_BEGIN_DECLS - -#define PAS_TYPE_CARD_CURSOR (pas_card_cursor_get_type ()) -#define PAS_CARD_CURSOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PAS_TYPE_CARD_CURSOR, PASCardCursor)) -#define PAS_CARD_CURSOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PAS_TYPE_CARD_CURSOR, PASCardCursorClass)) -#define PAS_IS_CARD_CURSOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAS_TYPE_CARD_CURSOR)) -#define PAS_IS_CARD_CURSOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PAS_TYPE_CARD_CURSOR)) -#define PAS_CARD_CURSOR_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), PAS_TYPE_CARD_CURSOR, PASCardCursorClass)) - -typedef struct _PASCardCursor PASCardCursor; -typedef struct _PASCardCursorPrivate PASCardCursorPrivate; -typedef struct _PASCardCursorClass PASCardCursorClass; - -typedef long (*PASCardCursorLengthFunc) (PASCardCursor *cursor, gpointer data); -typedef char * (*PASCardCursorNthFunc) (PASCardCursor *cursor, long n, gpointer data); - -struct _PASCardCursor { - BonoboObject parent; - PASCardCursorPrivate *priv; -}; - -struct _PASCardCursorClass { - BonoboObjectClass parent; - - POA_GNOME_Evolution_Addressbook_CardCursor__epv epv; -}; - - - -/* Creating a new addressbook. */ -PASCardCursor *pas_card_cursor_new (PASCardCursorLengthFunc get_length, - PASCardCursorNthFunc get_nth, - gpointer data); - -GType pas_card_cursor_get_type (void); -POA_GNOME_Evolution_Addressbook_CardCursor__epv * - pas_card_cursor_get_epv (void); - -G_END_DECLS - -#endif /* ! __PAS_CARD_CURSOR_H__ */ diff --git a/addressbook/backend/pas/pas-marshal.list b/addressbook/backend/pas/pas-marshal.list index fa33740eaa..9d6744db44 100644 --- a/addressbook/backend/pas/pas-marshal.list +++ b/addressbook/backend/pas/pas-marshal.list @@ -1 +1,2 @@ NONE:NONE +NONE:POINTER diff --git a/addressbook/backend/pas/pas-types.h b/addressbook/backend/pas/pas-types.h new file mode 100644 index 0000000000..19611a4e23 --- /dev/null +++ b/addressbook/backend/pas/pas-types.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Blanket header containing the typedefs for object types used in the + * PAS stuff, so we can disentangle the #includes. + * + * Author: Chris Toshok <toshok@ximian.com> + * + * Copyright 2003, Ximian, Inc. + */ + +#ifndef __PAS_TYPES_H__ +#define __PAS_TYPES_H__ + +typedef struct _PASBookView PASBookView; +typedef struct _PASBookViewClass PASBookViewClass; + +typedef struct _PASBackendCardSExp PASBackendCardSExp; +typedef struct _PASBackendCardSExpClass PASBackendCardSExpClass; + +typedef struct _PASBackend PASBackend; +typedef struct _PASBackendClass PASBackendClass; + +typedef struct _PASBackendSummary PASBackendSummary; +typedef struct _PASBackendSummaryClass PASBackendSummaryClass; + +typedef struct _PASBackendSync PASBackendSync; +typedef struct _PASBackendSyncClass PASBackendSyncClass; + +typedef struct _PASBook PASBook; +typedef struct _PASBookClass PASBookClass; + +#endif /* __PAS_TYPES_H__ */ diff --git a/addressbook/backend/pas/ximian-vcard.h b/addressbook/backend/pas/ximian-vcard.h new file mode 100644 index 0000000000..961a5cadb4 --- /dev/null +++ b/addressbook/backend/pas/ximian-vcard.h @@ -0,0 +1,81 @@ +#define XIMIAN_VCARD \ +"BEGIN:VCARD\n" \ +"X-EVOLUTION-FILE-AS:Ximian\\, Inc.\n" \ +"ADR;TYPE=WORK:;Suite 3 West;401 Park Drive;Boston;MA;02215;USA\n" \ +"LABEL;TYPE=WORK:401 Park Drive\\nSuite 3 West\\nBoston\\, MA\\n02215\\nUSA\n" \ +"TEL;WORK;VOICE:(617) 375-3800\n" \ +"TEL;WORK;FAX:(617) 236-8630\n" \ +"EMAIL;INTERNET:hello@ximian.com\n" \ +"URL:http://www.ximian.com/\n" \ +"ORG:Ximian\\, Inc.;\n" \ +"NOTE:Welcome to the Ximian Addressbook.\n" \ +"PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQEARwBHAAD//gAXQ3JlYXRlZCB3aXRo\n" \ +" IFRoZSBHSU1Q/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCM\n" \ +" cHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMj\n" \ +" IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgAbgBkAwEiAAIRAQMRAf/EA\n" \ +" BwAAAIDAQEBAQAAAAAAAAAAAAAHBQYIBAMBAv/EAEYQAAEDAwEFBgMEBgQPAAAAAAECAwQABREG\n" \ +" BxIhMWETIkFRcYEUkaEIMkLBFSNSsbLRFmJydRgkMzY3Q0RGgpKTosLh8P/EABsBAQACAwEBAAA\n" \ +" AAAAAAAAAAAAEBQIDBgEH/8QALREAAQMCAwYGAgMAAAAAAAAAAQACAwQREiFRBRMiMUFhMnGBkb\n" \ +" HRBsEUofD/2gAMAwEAAhEDEQA/AH/RRRREVwXe9W2wwFzbpNZixkc1uqwPQeZ6CoHXevLfom1ds\n" \ +" 9h6a6D8PGCsFZHMk+CR4n86yzdbrqfaZqYBSnp0hRPZMoG62ynoOSR1Pua8Lg0XPJegX5Jv6k+0\n" \ +" bBjrWxp22LlkcBIlHs0HqEjiR64peT9umupqyWrhHhpP4WI6eHureNW7Tmw+DGaTI1FJVJdxksM\n" \ +" qKG09CrmfbFMCHpCw2xATDs8JrH4gykq+Z4mqifbMUZsxpd/QUllK53M2SCb2xa+bXvf0gcV0Uw\n" \ +" 0R/DVktH2hdUwlpFxjQrg1490tLPuOH0pvv2qE4jdchx1p8lNAj91Va87OtM3RCt+2Nx3Dyci/q\n" \ +" yPYcD7g1EZ+RR4rSMI9b/S2mhdbhKsmkdtWmNTuNxnXVW2cvgGZRASo+SV8j74PSmOlQUMpORWP\n" \ +" NU7MrjY0rlQFmdDTxOE4cQOo8R1Hyqe2Z7ZJ2m32bXfHnJVpJCUuqO8uP7+Kenh4eVXkFRFUMxx\n" \ +" G4UOSN0Zs4LU1FeEOWxOityYzqHWXEhSFoOQoHkQa963rBFFFFERUdfr1E09Y5d1mr3Y8ZsrV5n\n" \ +" yA6k4A6mpGkL9ojUym0W/TrLmAsGU+AeYBwgfPJ/4RREqrrcb1tJ1oUpBXLmObqUZ7rSByT0SkZ\n" \ +" J8zk1pHQmiLXo+zpbabC3SAp55Q7zyvM9PIUudiGmURbS7fpCMvzFFton8LSTxx6qH0FM7VV9VY\n" \ +" 9MzZ7aQt5tASw3+26ohKB/zEVSVFVvZzGMw02tqe/kpbI8LMR6/C/Xxq9QagfbbP+IW1QQ4Rycf\n" \ +" xncHRAIJ/rEfsmu2a9Fgsl2XIZjtj8bqwgfM1+9L2VFksESAV9o6hG886ebjqjvLWepUSarutdn\n" \ +" MXV+obRcZks/CwCQ5DKMpeBOTxzwzgA9KwfTtfxPOSB5GQUXc9pOjoC+zXe2HV5xiOC6PmkEfWp\n" \ +" xe6tAWghSVDIIOQRXxekNOx4b0WPZYLLTram19mwlJKSMHjjNUzQd2dZM7SNxczcLOsttqVzdYz\n" \ +" 3FewI9iKpK2mjMZdFe7ed9NfT9qZDI4OAd1Vkko50ndoui22kuXq2NBOO9JZSOH9sD9/z86c8gc\n" \ +" DUJNQlaFJUkKSoYII4EVGoKp9PIHt9e6lyRNlZhcqlsJ2guQpydL3F4mO7kw1KP3Fcyj0PEjrnz\n" \ +" rSAIIyOVYfvsJ3TGqlCKpTfYuJfjLHMDOR8jw9q2Foy+o1FpWBckY/XMpUoeRxxHsciu/jeJGB7\n" \ +" eRXPvaWuLT0U/RRRWaxQeVY82x3BVw2oXbJyhgoZR0AQM/UmthK+6fSsWbRQW9pV73x/tZPtwNE\n" \ +" Wj9Nw0WuwwIKQAGI6G/cAZ+tRW0lx5nTEW4Ntqdat9xjy5CEjJLSFZP5H2qaYdCkpUk5BGQa7Ap\n" \ +" DrSm3EpWhYKVJUMgg8wRXz+kqyyTG7VXUsV22Clrfc48+CzMiPIejvIC23EHIUDXNe79b7HbXbh\n" \ +" c5SI8ZvmtZ5nyA5k9BS7d0nfdMPuSdD3JtEZaitdom5Uznx3DzT6cPWkvq/V1611fGW5nZtBCgy\n" \ +" zFbXhtCycE5JxknxPhXR07RUeB3D11H+9lAfwcxmrrqLbxcHpikWGAw1FScByUkqWvrgEBPpxqi\n" \ +" ztdXWdqmNqIIjx7gykJUphJCXAM/eBJ5g4PQCmBZNiDKWEu364uF0jJYh4AT6qUDn2FVu6bPIkT\n" \ +" aTB08xKeMOU2H99eCtKRvZGQMZ7hwceNZxVGzsbmMzIBv5dfNeOjnsCdUwbTtKsV8nJgIccZkqw\n" \ +" lJcThDqvJJz8s4zUtLVzpc2vZZKt+qBIkyUKt0V0ONKSe+7g5SCPDr9Kv0tznXP1cNMyQfxnXBC\n" \ +" tqUyuB3gslftPjJLkGWB3u82o/Ij86bf2e7iqRoxyIpWfhpC0JHQ4V/5GlVtJcBt0RPiXif+00w\n" \ +" Ps5BQtNxP4TJP8Ka6rZZJpW37/Kq68ATlPeiiirBQ0HlWR9t9qVbtpEp/dwiY0h5J8Mgbp/h+ta\n" \ +" 4pM7fdKLumn2rxGbKn4BKl4HEtn73ywD7GiL7o28JuulLbKCsqLKUL/tJ7p+oqyIe4c6RGyzU4g\n" \ +" THLNJc3WpCt9gk8A54j3GPcdaZuoosy82V23QpaYpkEIdeIJKUeIAHieXPkTXA11DuassJsCefY\n" \ +" /SvYZN5FiGZU9edRwLDAXJny2mRukoStQBWQOQHjSjg7PYE7ZmzcZb7cG6KK5CZD6txOCcJQvPg\n" \ +" QAQfAn2q6RNOWi1D9J3R5dwlR2xmZPVv9mlI8ByTj59ar09Lm0jUIQl5Y0zAUMrQSPiXfHHpyz4\n" \ +" D1qTRvMQIieQAQXOtllfIDre/X2WqVmI8Qz6D9q0bP9SO37SrSpW8ZUVXw7q+YcKeSgeRyMZ65q\n" \ +" qammvWTalEv1yjOJtaWfh25CBvBOUkHPlxUeHlyq/MiPCitxorSGWG07qG0DASK45xZlx3GJDaH\n" \ +" WljCkLGQR6VGinY2ofIG8Lri2gOi37hxYG3zC+uT2HY6ZDbyFMrAUlwK7pB5HNRcp7nxqpzdN3G\n" \ +" CFQ7NObTa3nApcaSN/suOe4SDw6VK3O4swojsp9WGmxk9fIDrW4UzWkbt2K/v691vjec8YtZUTa\n" \ +" BL+IuMaIjiWWytXQn/wBD608tgtrVC0W2+tOFSFqd9icD6AVnmFFl6n1AhoAmRPdwcfgR4n2H7q\n" \ +" 2Ppi1N2exRojaQlKEBIHkAK7Gmi3MTWaLn6iTeSF+qmaKKK3rSiuedEanQ3I7qQpC0kEEZzXRRR\n" \ +" FjnaRoSVoq/KcYQv9HOr3mHB/qzz3SenhVi0ftAbnNNwLo6G5iQEodUcJd9fJX760ZqLTkHUdsd\n" \ +" hTWEOtuJwQoVl/XGyS7aakOPwGnJcDORujK0DqPH2qJV0cdUzC/0Oi3QTuhddqY84IuFukwnFFK\n" \ +" JDSmlEcwFDGR86ISI1tgtQ4jYaYaTuoSP/udJS1azvFoAZLnbsp4dm/klPQHmKs0faVEWkfEw32\n" \ +" 1f1CFj8q56XZNSwYG5t7fSt46yB5ucimM5L4c643pXWqU5tCteMpRKUfIIH86ipmvnnAUwoQSf2\n" \ +" 3lZ+g/nWEey5yfCtrquBo8Su0+4sQ46pEp1LTSeZUfoPOlnfr67fZKQlK0QkK/VtficV5nrXOkX\n" \ +" XUk9KQHp0gnghI7qPyAp1bOdkCmH2rneQHHxxQjHdb9OvWr2j2c2Didm74VZVVplGFuQXRsc2fO\n" \ +" Qgb1cmsSXQN1JH+TT4D+dPEAAADkK848duMylppISkDGBXrVkoCKKKKIiiqrrbX9m0JARIua1re\n" \ +" dJDMdoArcI58+AA8zVLsO26RqiS9Gsukpct5lHaKbTLaSrd8wFEZ9s0RN6vGRGZktlDqAoHzFKq\n" \ +" JtomzrPOuzGjZvwEBRTJfckttpbUOae9jJ5cBk8R514Wrbo7e489+3aTlvtQGTIkqElsdm2Mkq4\n" \ +" 4zyPKiKf1Hsj09flKdXEQh4/jR3VfMUvJ/2et1ZMOe8keSgFfyqz2LbfJ1M9IZs2kJsx2O0XnEN\n" \ +" yEAhA4ZwcZ58hxr7ZdtkvUS5SbTo2fJMRsuPkPoSG0jzKsDPPhz4HyoipDewC47+FXFWOjYH51Y\n" \ +" bTsAgtrSqc88/jwWrA+QxUlYtujupZ6oNo0nLlSUtqdKEyW04SMZOVYHiKjP8ACUt5/wB3pX/XT\n" \ +" /KiJnWLQ1nsTSURorad39lIFWZKUoThIAHSlNqDbLP0siKu96MnQ0ygSyVyGzvYxnlnB4jga87F\n" \ +" ttlamXJbs2j50xcZvtXUtyEZCfPB5+gyaIm9RSetm3J68RbhJgaSmPM25vtZaviW09knjxIOM8j\n" \ +" y8q7LHtzstwv/AOhrlBftkkudkFOLS43v5xgqSeHHx5daImrRX5QtK0hSTkGiiLMP2ho8wa1iSn\n" \ +" QoxVRQ20fAKClFQ9eIqq7LLJe7vreG7ZZCoZhqD8iZjustjnnwORkY8c+Wa1ZqbStt1PBMa4MId\n" \ +" Rz7wzg+dL8bEbA1vpa7RtK+CkpdWAfXjRFB7UpCNe6Kdm6NnJft1qluKuUJlvdKznPbYH3hzPXJ\n" \ +" PMGqZsk/zc2gf3G5/Cumc3sRsTO92Rcb3uB3XVjP1r4jYfYGwoN76QsYUEurGR5HjREudhUt2BP\n" \ +" 1TMYID0eyuuoJGRvJII+oq96I2iwtVz7rb7ZZWbalyzyJ9wKUjLsrKEkjH4cE8+Jz049bew+wNb\n" \ +" 3Z76N4YO66sZHlzob2H2Bkktb6CRglLqxkeXOiJZbAv9IMj+7X/wB6ag9lGnEaj17CRJA+BhZmy\n" \ +" lK+6EI44PQq3R6E06W9h9gZVvNb6FYxlLqwcfOhvYhYWt7s99G8MK3XVjI68aIo7UxgbR9IajhQ\n" \ +" 7/Du9yiSF3S3tMNrStlkAAt94DPDI4eJFUvYfNetqNYz4xAfjWZx5skZAUnJHD1FMVrYhYWVbzW\n" \ +" +2ojGUOrBx86EbD7A0FBvfRvDCt11YyPI8aIo23zdP6i2e621TaUJiXCfa1IucFPJt5KVnfHRWS\n" \ +" euPPNZ2YadfkNsspUp1aglCU8yTyrTSNh9gbCgjfSFjCgl1YyPI8al9PbItP2WamUywkuJ5KOVE\n" \ +" emeVEVw02ZH9H4YkEqdDYCifE4oqXbaS02lCRhIGBRRF//Z\n" \ +"END:VCARD" |