From cbfab681c1576d4de27d48fbd6b4b7780670494a Mon Sep 17 00:00:00 2001 From: Chris Toshok Date: Wed, 22 Oct 2003 20:50:36 +0000 Subject: use the synchronous api for this. simplifies it a bunch. 2003-10-21 Chris Toshok * tools/evolution-addressbook-abuse.c: use the synchronous api for this. simplifies it a bunch. 2003-10-21 Chris Toshok * backend/pas/pas-book.c (impl_GNOME_Evolution_Addressbook_Book_remove): we can ill afford bad debug spew. (view_listener_died_cb): implement. (impl_GNOME_Evolution_Addressbook_Book_getBookView): hook up an ORBit_small connection listener on the view's listener. (pas_book_respond_create): use e_contact_get_const instead of e_contact_get here. fixes a leak. * backend/pas/pas-book-view.c (impl_GNOME_Evolution_Addressbook_BookView_stop): implement, call pas_backend_stop_book_view. (pas_book_view_get_listener): return the book view's listener. (pas_book_view_class_init): fill in epv->stop. (pas_book_view_init): use a #define for THRESHOLD_MAX instead of the constant. * backend/pas/pas-book-view.h: add prototype for pas_book_view_get_listener. * backend/pas/pas-backend.c (pas_backend_stop_book_view): implement. (pas_backend_remove_book_view): implement. * backend/pas/pas-backend.h: add prototype for stop_book_view and remove_book_view. * backend/pas/pas-backend-vcf.c (load_file): pass in the fd and use fdopen here. (foreach_build_list): don't creat EContacts here, because we'll just be converting them back to vcards anyway. (save_file): use char*'s instead of EContacts, and split entries with 2 blank lines. Also, hold the lock over the entire function. (do_create): hold the lock around uid generation and touching the hash table. (pas_backend_vcf_process_remove_contacts): same. (pas_backend_vcf_process_modify_contact): same. (pas_backend_vcf_stop_book_view): new function, but leave unimplemented for now. (pas_backend_vcf_load_uri): the uri contains the directory name, not the filename. (pas_backend_vcf_dispose): grab the lock here just for sanity's sake. Also reorder things a bit, and free the hashtable and mutex. (pas_backend_vcf_init): init the mutex. * backend/pas/pas-backend-summary.c (pas_backend_summary_add_contact): don't unref the contact here. * backend/pas/pas-backend-ldap.c (pas_backend_ldap_process_stop_book_view): new function, but leave unimplemented for now. * backend/pas/pas-backend-file.c (build_summary): use an EContact for this call. (do_summary_query): nuke, the contents of this has been moved to start_book_view. (pas_backend_file_search_timeout): same. (pas_backend_file_search): same. (pas_backend_file_start_book_view): glom everything into here involving searching. This function could (and should) be renamed and reused from both this function and _get_contact_list. (pas_backend_file_stop_book_view): new function. (pas_backend_file_class_init): fill in backend->stop_book_view. * backend/pas/Makefile.am (LDAP_BACKEND): libpasldap.a -> libpasldap.la (noinst_LTLIBRARIES): *.a -> *.la. (libpas_la_SOURCES): same. (libpasfile_la_SOURCES): same. (libpasvcf_la_SOURCES): same. (libpasldap_la_SOURCES): same. * backend/idl/addressbook.idl: add BookView::stop. * backend/ebook/e-vcard.c (read_attribute_value): fix GString related leaks. (read_attribute_params): same. (parse): don't leak the EVCardAttributes corresponding to BEGIN/END:vCard. (free_gstring): new function (e_vcard_attribute_remove_values): free the decoded_values list, using free_gstring. * backend/ebook/e-book.c (e_book_response_get_book_view): ref the listener here. * backend/ebook/e-book-view.h: add prototype for e_book_view_stop. * backend/ebook/e-book-view.c (e_book_view_stop): new function. * backend/ebook/e-book-async.c (_get_book_view_response_dtor): unref the book view. svn path=/trunk/; revision=23000 --- addressbook/ChangeLog | 105 ++++++++- addressbook/backend/ebook/e-book-async.c | 1 + addressbook/backend/ebook/e-book-view.c | 12 +- addressbook/backend/ebook/e-book.c | 3 +- addressbook/backend/ebook/e-contact.h | 4 + addressbook/backend/ebook/e-vcard.c | 34 ++- addressbook/backend/idl/addressbook.idl | 1 + addressbook/backend/pas/Makefile.am | 17 +- addressbook/backend/pas/pas-backend-file.c | 288 ++++++++++++------------ addressbook/backend/pas/pas-backend-ldap.c | 8 + addressbook/backend/pas/pas-backend-summary.c | 2 - addressbook/backend/pas/pas-backend-vcf.c | 95 +++++--- addressbook/backend/pas/pas-backend.c | 23 ++ addressbook/backend/pas/pas-backend.h | 6 + addressbook/backend/pas/pas-book-view.c | 20 +- addressbook/backend/pas/pas-book-view.h | 1 + addressbook/backend/pas/pas-book.c | 14 +- addressbook/tools/evolution-addressbook-abuse.c | 76 ++----- 18 files changed, 451 insertions(+), 259 deletions(-) diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index c56e281549..f6f6e05455 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -19,6 +19,107 @@ "evolution:button_label" property on the component for use in the shell. +2003-10-21 Chris Toshok + + * tools/evolution-addressbook-abuse.c: use the synchronous api for + this. simplifies it a bunch. + +2003-10-21 Chris Toshok + + * backend/pas/pas-book.c + (impl_GNOME_Evolution_Addressbook_Book_remove): we can ill afford + bad debug spew. + (view_listener_died_cb): implement. + (impl_GNOME_Evolution_Addressbook_Book_getBookView): hook up an + ORBit_small connection listener on the view's listener. + (pas_book_respond_create): use e_contact_get_const instead of + e_contact_get here. fixes a leak. + + * backend/pas/pas-book-view.c + (impl_GNOME_Evolution_Addressbook_BookView_stop): implement, call + pas_backend_stop_book_view. + (pas_book_view_get_listener): return the book view's listener. + (pas_book_view_class_init): fill in epv->stop. + (pas_book_view_init): use a #define for THRESHOLD_MAX instead of + the constant. + + * backend/pas/pas-book-view.h: add prototype for + pas_book_view_get_listener. + + * backend/pas/pas-backend.c (pas_backend_stop_book_view): + implement. + (pas_backend_remove_book_view): implement. + + * backend/pas/pas-backend.h: add prototype for stop_book_view and + remove_book_view. + + * backend/pas/pas-backend-vcf.c (load_file): pass in the fd and + use fdopen here. + (foreach_build_list): don't creat EContacts here, because we'll + just be converting them back to vcards anyway. + (save_file): use char*'s instead of EContacts, and split entries + with 2 blank lines. Also, hold the lock over the entire function. + (do_create): hold the lock around uid generation and touching the + hash table. + (pas_backend_vcf_process_remove_contacts): same. + (pas_backend_vcf_process_modify_contact): same. + (pas_backend_vcf_stop_book_view): new function, but leave + unimplemented for now. + (pas_backend_vcf_load_uri): the uri contains the directory name, + not the filename. + (pas_backend_vcf_dispose): grab the lock here just for sanity's + sake. Also reorder things a bit, and free the hashtable and + mutex. + (pas_backend_vcf_init): init the mutex. + + * backend/pas/pas-backend-summary.c + (pas_backend_summary_add_contact): don't unref the contact here. + + * backend/pas/pas-backend-ldap.c + (pas_backend_ldap_process_stop_book_view): new function, but leave + unimplemented for now. + + * backend/pas/pas-backend-file.c (build_summary): use an EContact + for this call. + (do_summary_query): nuke, the contents of this has been moved to + start_book_view. + (pas_backend_file_search_timeout): same. + (pas_backend_file_search): same. + (pas_backend_file_start_book_view): glom everything into here + involving searching. This function could (and should) be renamed + and reused from both this function and _get_contact_list. + (pas_backend_file_stop_book_view): new function. + (pas_backend_file_class_init): fill in backend->stop_book_view. + + * backend/pas/Makefile.am (LDAP_BACKEND): libpasldap.a -> + libpasldap.la + (noinst_LTLIBRARIES): *.a -> *.la. + (libpas_la_SOURCES): same. + (libpasfile_la_SOURCES): same. + (libpasvcf_la_SOURCES): same. + (libpasldap_la_SOURCES): same. + + * backend/idl/addressbook.idl: add BookView::stop. + + * backend/ebook/e-vcard.c (read_attribute_value): fix GString + related leaks. + (read_attribute_params): same. + (parse): don't leak the EVCardAttributes corresponding to + BEGIN/END:vCard. + (free_gstring): new function + (e_vcard_attribute_remove_values): free the decoded_values list, + using free_gstring. + + * backend/ebook/e-book.c (e_book_response_get_book_view): ref the + listener here. + + * backend/ebook/e-book-view.h: add prototype for e_book_view_stop. + + * backend/ebook/e-book-view.c (e_book_view_stop): new function. + + * backend/ebook/e-book-async.c (_get_book_view_response_dtor): + unref the book view. + 2003-10-20 Dan Winship * backend/pas/pas-book-view.c: Queue up removes and modifies as @@ -80,10 +181,6 @@ * backend/ebook/e-contact.c (photo_getter): s/malloc/g_malloc/ - * backend/ebook/tests/ebook/Makefile.am: - * backend/ebook/tests/vcard/Makefile.am: Make these automake-1.7 - compliant - 2003-10-20 JP Rosevear * backend/pas/pas-backend-vcf.c (pas_backend_vcf_search): compiler diff --git a/addressbook/backend/ebook/e-book-async.c b/addressbook/backend/ebook/e-book-async.c index 2ccc565eb9..d21f22a739 100644 --- a/addressbook/backend/ebook/e-book-async.c +++ b/addressbook/backend/ebook/e-book-async.c @@ -969,6 +969,7 @@ _get_book_view_response_dtor (EBookMsg *msg) GetBookViewResponse *resp = (GetBookViewResponse*)msg; g_object_unref (resp->book); + g_object_unref (resp->book_view); g_free (resp); } diff --git a/addressbook/backend/ebook/e-book-view.c b/addressbook/backend/ebook/e-book-view.c index e8468e35de..c36e87967c 100644 --- a/addressbook/backend/ebook/e-book-view.c +++ b/addressbook/backend/ebook/e-book-view.c @@ -204,9 +204,17 @@ e_book_view_start (EBookView *book_view) void e_book_view_stop (EBookView *book_view) { + CORBA_Environment ev; + g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view)); - if (book_view->priv->listener) - e_book_view_listener_stop (book_view->priv->listener); + + CORBA_exception_init (&ev); + + GNOME_Evolution_Addressbook_BookView_stop (book_view->priv->corba_book_view, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("corba exception._major = %d\n", ev._major); + } } static void diff --git a/addressbook/backend/ebook/e-book.c b/addressbook/backend/ebook/e-book.c index 3883cd4b15..c84b4c3f83 100644 --- a/addressbook/backend/ebook/e-book.c +++ b/addressbook/backend/ebook/e-book.c @@ -1027,6 +1027,8 @@ e_book_response_get_book_view (EBook *book, op->status = status; op->view = e_book_view_new (corba_book_view, op->listener); + bonobo_object_ref(BONOBO_OBJECT(op->listener)); + pthread_cond_signal (&op->cond); e_mutex_unlock (op->mutex); @@ -1677,7 +1679,6 @@ e_book_load_uri (EBook *book, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - e_book_clear_op (book, our_op); CORBA_exception_free (&ev); diff --git a/addressbook/backend/ebook/e-contact.h b/addressbook/backend/ebook/e-contact.h index 8de02caa5f..21c0256ca9 100644 --- a/addressbook/backend/ebook/e-contact.h +++ b/addressbook/backend/ebook/e-contact.h @@ -127,6 +127,10 @@ typedef enum { E_CONTACT_BIRTH_DATE, /* structured field (EContactDate) */ E_CONTACT_ANNIVERSARY, /* structured field (EContactDate) */ + /* Security Fields */ + E_CONTACT_X509_CERT, /* string field */ + E_CONTACT_X509_CERT_SHA1_FINGERPRINT, /* string field */ + E_CONTACT_FIELD_LAST, /* useful constants */ diff --git a/addressbook/backend/ebook/e-vcard.c b/addressbook/backend/ebook/e-vcard.c index 7ea1d9da84..5207d0fefe 100644 --- a/addressbook/backend/ebook/e-vcard.c +++ b/addressbook/backend/ebook/e-vcard.c @@ -252,8 +252,8 @@ read_attribute_value (EVCardAttribute *attr, char **p, gboolean quoted_printable lp = g_utf8_next_char(lp); } else if (*lp == ';') { - e_vcard_attribute_add_value (attr, g_string_free (str, FALSE)); - str = g_string_new (""); + e_vcard_attribute_add_value (attr, str->str); + g_string_assign (str, ""); lp = g_utf8_next_char(lp); } else { @@ -261,8 +261,10 @@ read_attribute_value (EVCardAttribute *attr, char **p, gboolean quoted_printable lp = g_utf8_next_char(lp); } } - if (str) - e_vcard_attribute_add_value (attr, g_string_free (str, FALSE)); + if (str) { + e_vcard_attribute_add_value (attr, str->str); + g_string_free (str, TRUE); + } if (*lp == '\r') { lp = g_utf8_next_char (lp); /* \n */ @@ -290,7 +292,7 @@ read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printab if (*lp == '=') { if (str->len > 0) { param = e_vcard_attribute_param_new (str->str); - str = g_string_assign (str, ""); + g_string_assign (str, ""); lp = g_utf8_next_char (lp); } else { @@ -311,7 +313,7 @@ read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printab if (param) { if (str->len > 0) { e_vcard_attribute_param_add_value (param, str->str); - str = g_string_assign (str, ""); + g_string_assign (str, ""); if (!colon) lp = g_utf8_next_char (lp); } @@ -354,7 +356,7 @@ read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printab param = e_vcard_attribute_param_new (param_name); e_vcard_attribute_param_add_value (param, str->str); } - str = g_string_assign (str, ""); + g_string_assign (str, ""); if (!colon) lp = g_utf8_next_char (lp); } @@ -376,7 +378,7 @@ read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printab } else { g_warning ("invalid character found in parameter spec"); - str = g_string_assign (str, ""); + g_string_assign (str, ""); skip_until (&lp, ":;"); } } @@ -514,6 +516,8 @@ parse (EVCard *evc, const char *str) if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "begin")) { g_warning ("vcard began without a BEGIN:VCARD\n"); } + if (attr) + e_vcard_attribute_free (attr); while (*p) { EVCardAttribute *next_attr = read_attribute (&p); @@ -529,6 +533,9 @@ parse (EVCard *evc, const char *str) g_warning ("vcard ended without END:VCARD\n"); } + if (attr && !g_ascii_strcasecmp (attr->name, "end")) + e_vcard_attribute_free (attr); + g_free (buf); } @@ -712,7 +719,8 @@ e_vcard_to_string_vcard_30 (EVCard *evc) attr_str = g_string_append (attr_str, CRLF); - str = g_string_append (str, g_string_free (attr_str, FALSE)); + str = g_string_append (str, attr_str->str); + g_string_free (attr_str, TRUE); } str = g_string_append (str, "END:vCard"); @@ -925,11 +933,19 @@ e_vcard_attribute_add_values (EVCardAttribute *attr, va_end (ap); } +static void +free_gstring (GString *str) +{ + g_string_free (str, TRUE); +} + void e_vcard_attribute_remove_values (EVCardAttribute *attr) { g_list_foreach (attr->values, (GFunc)g_free, NULL); g_list_free (attr->values); + g_list_foreach (attr->decoded_values, (GFunc)free_gstring, NULL); + g_list_free (attr->decoded_values); attr->values = NULL; } diff --git a/addressbook/backend/idl/addressbook.idl b/addressbook/backend/idl/addressbook.idl index 1ad3a62dd9..bfdbae6882 100644 --- a/addressbook/backend/idl/addressbook.idl +++ b/addressbook/backend/idl/addressbook.idl @@ -80,6 +80,7 @@ module Addressbook { interface BookView : Bonobo::Unknown { oneway void start (); + oneway void stop (); }; interface Book : Bonobo::Unknown { diff --git a/addressbook/backend/pas/Makefile.am b/addressbook/backend/pas/Makefile.am index b602a21512..6217456006 100644 --- a/addressbook/backend/pas/Makefile.am +++ b/addressbook/backend/pas/Makefile.am @@ -35,14 +35,14 @@ LDAP_BACKEND_FILES = \ pas-backend-ldap.h if ENABLE_LDAP -LDAP_BACKEND = libpasldap.a +LDAP_BACKEND = libpasldap.la endif ldapschemadir = $(privdatadir) ldapschema_DATA= $(LDAP_SCHEMA) -privlib_LIBRARIES = libpas.a -noinst_LIBRARIES = libpasfile.a libpasvcf.a $(LDAP_BACKEND) +privlib_LTLIBRARIES = libpas.la +noinst_LTLIBRARIES = libpasfile.la libpasvcf.la $(LDAP_BACKEND) pasincludedir = $(privincludedir)/pas @@ -57,33 +57,34 @@ pasinclude_HEADERS = \ pas-backend-sync.h \ pas-types.h -libpas_a_SOURCES = \ +libpas_la_SOURCES = \ $(pasinclude_HEADERS) \ $(CORBA_SOURCE_C) \ pas-book-factory.c \ pas-book-view.c \ pas-book.c \ pas-backend-card-sexp.c \ - pas-backend-file.c \ pas-backend.c \ pas-backend-summary.c \ pas-backend-sync.c \ pas-marshal.c \ ximian-vcard.h -libpasfile_a_SOURCES = \ +libpasfile_la_SOURCES = \ pas-backend-file.c \ pas-backend-file.h -libpasvcf_a_SOURCES = \ +libpasvcf_la_SOURCES = \ pas-backend-vcf.c \ pas-backend-vcf.h if ENABLE_LDAP -libpasldap_a_SOURCES = \ +libpasldap_la_SOURCES = \ $(LDAP_BACKEND_FILES) endif +libpas_la_LIBADD = libpasfile.la libpasvcf.la $(LDAP_BACKEND) $(DB3_LDADD) + MARSHAL_GENERATED = pas-marshal.c pas-marshal.h @EVO_MARSHAL_RULE@ diff --git a/addressbook/backend/pas/pas-backend-file.c b/addressbook/backend/pas/pas-backend-file.c index 06923d7b08..923c7e907d 100644 --- a/addressbook/backend/pas/pas-backend-file.c +++ b/addressbook/backend/pas/pas-backend-file.c @@ -90,8 +90,9 @@ build_summary (PASBackendFilePrivate *bfpriv) /* 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)) { - - pas_backend_summary_add_contact (bfpriv->summary, vcard_dbt.data); + EContact *contact = e_contact_new_from_vcard (vcard_dbt.data); + pas_backend_summary_add_contact (bfpriv->summary, contact); + g_object_unref (contact); } db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); @@ -99,52 +100,6 @@ build_summary (PASBackendFilePrivate *bfpriv) } } -static void -do_summary_query (PASBackendFile *bf, - PASBookView *view) -{ - GPtrArray *ids = pas_backend_summary_search (bf->priv->summary, pas_book_view_get_card_query (view)); - int db_error = 0; - 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); - -#if SUMMARY_STORES_ENOUGH_INFO - /* this is disabled for the time being because lists - can have more than 3 email addresses and the - summary only stores 3. */ - - 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 - string_to_dbt (id, &id_dbt); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - - db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); - - if (db_error == 0) - pas_book_view_notify_update (view, vcard_dbt.data); -#if SUMMARY_STORES_ENOUGH_INFO - } -#endif - } - - g_ptr_array_free (ids, TRUE); - - pas_book_view_notify_complete (view, GNOME_Evolution_Addressbook_Success); -} - static char * pas_backend_file_create_unique_id (void) { @@ -155,105 +110,6 @@ pas_backend_file_create_unique_id (void) return g_strdup_printf (PAS_ID_PREFIX "%08lX%08X", time(NULL), c++); } -typedef struct { - PASBackendFile *bf; - PASBook *book; - PASBookView *view; - DBC *dbc; - - gboolean done_first; -} FileBackendSearchClosure; - -static void -free_search_closure (FileBackendSearchClosure *closure) -{ - g_free (closure); -} - -static gboolean -pas_backend_file_search_timeout (gpointer data) -{ - FileBackendSearchClosure *closure = data; - int db_error = 0; - DBT id_dbt, vcard_dbt; - int file_version_name_len; - DBC *dbc = closure->dbc; - - file_version_name_len = strlen (PAS_BACKEND_FILE_VERSION_NAME); - - memset (&id_dbt, 0, sizeof (id_dbt)); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - - if (closure->done_first) { - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); - } - else { - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST); - closure->done_first = TRUE; - } - - while (db_error == 0) { - - /* 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); - - /* 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); - } - - dbc->c_close (dbc); - - if (db_error != DB_NOTFOUND) { - g_warning ("pas_backend_file_search: error building list\n"); - free_search_closure (closure); - } - - pas_book_view_notify_complete (closure->view, GNOME_Evolution_Addressbook_Success); - - free_search_closure (closure); - - return FALSE; -} - - -static void -pas_backend_file_search (PASBackendFile *bf, - PASBookView *book_view) -{ - const char *query = pas_book_view_get_card_query (book_view); - - 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...")); - - 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->view = book_view; - closure->bf = bf; - - db_error = db->cursor (db, NULL, &closure->dbc, 0); - - if (db_error != 0) { - g_warning ("pas_backend_file_search: error building list\n"); - } else { - g_idle_add (pas_backend_file_search_timeout, closure); - } - } -} - static EContact * do_create(PASBackendFile *bf, const char *vcard_req) @@ -509,11 +365,146 @@ pas_backend_file_get_contact_list (PASBackendSync *backend, : GNOME_Evolution_Addressbook_Success; } +typedef struct { + GMutex *mutex; + gboolean stopped; +} FileBackendSearchClosure; + static void pas_backend_file_start_book_view (PASBackend *backend, PASBookView *book_view) { - pas_backend_file_search (PAS_BACKEND_FILE (backend), book_view); + FileBackendSearchClosure *closure = g_new0 (FileBackendSearchClosure, 1); + PASBackendFile *bf = PAS_BACKEND_FILE (backend); + const char *query; + DB *db; + DBT id_dbt, vcard_dbt; + int db_error; + gboolean stopped = FALSE; + + printf ("starting initial population of book view\n"); + + /* ref the book view because it'll be removed and unrefed + when/if it's stopped */ + g_object_ref (book_view); + + db = bf->priv->file_db; + query = pas_book_view_get_card_query (book_view); + + closure->mutex = g_mutex_new(); + closure->stopped = FALSE; + g_object_set_data (G_OBJECT (book_view), "PASBackendFile.BookView::closure", closure); + + 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...")); + + if (pas_backend_summary_is_summary_query (bf->priv->summary, query)) { + /* do a summary query */ + GPtrArray *ids = pas_backend_summary_search (bf->priv->summary, pas_book_view_get_card_query (book_view)); + int i; + + for (i = 0; i < ids->len; i ++) { + char *id = g_ptr_array_index (ids, i); + + g_mutex_lock (closure->mutex); + stopped = closure->stopped; + g_mutex_unlock (closure->mutex); + + if (stopped) { + g_mutex_free (closure->mutex); + g_free (closure); + break; + } + + string_to_dbt (id, &id_dbt); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); + + db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); + + if (db_error == 0) { + EContact *contact = e_contact_new_from_vcard (vcard_dbt.data); + pas_book_view_notify_update (book_view, contact); + g_object_unref (contact); + } + } + + g_ptr_array_free (ids, TRUE); + } + else { + /* iterate over the db and do the query there */ + DBC *dbc; + + memset (&id_dbt, 0, sizeof (id_dbt)); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); + + db_error = db->cursor (db, NULL, &dbc, 0); + + db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST); + while (db_error == 0) { + + g_mutex_lock (closure->mutex); + stopped = closure->stopped; + g_mutex_unlock (closure->mutex); + + if (stopped) { + g_mutex_free (closure->mutex); + g_free (closure); + break; + } + + /* 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); + + /* notify_update will check if it matches for us */ + pas_book_view_notify_update (book_view, contact); + g_object_unref (contact); + } + + db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); + } + + dbc->c_close (dbc); + + if (db_error != DB_NOTFOUND) + g_warning ("pas_backend_file_search: error building list\n"); + + } + + g_mutex_lock (closure->mutex); + stopped = closure->stopped; + g_mutex_unlock (closure->mutex); + if (!stopped) + pas_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success); + + g_mutex_free (closure->mutex); + g_free (closure); + + g_object_set_data (G_OBJECT (book_view), "PASBackendFile.BookView::closure", NULL); + + /* unref the */ + g_object_unref (book_view); + + printf ("finished initial population of book view\n"); +} + +static void +pas_backend_file_stop_book_view (PASBackend *backend, + PASBookView *book_view) +{ + FileBackendSearchClosure *closure = g_object_get_data (G_OBJECT (book_view), "PASBackendFile.BookView::closure"); + if (!closure) { + printf ("book view is already done populating\n"); + return; + } + + printf ("stopping book view!\n"); + g_mutex_lock (closure->mutex); + closure->stopped = TRUE; + g_mutex_lock (closure->mutex); } typedef struct { @@ -1108,6 +1099,7 @@ pas_backend_file_class_init (PASBackendFileClass *klass) 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->stop_book_view = pas_backend_file_stop_book_view; backend_class->cancel_operation = pas_backend_file_cancel_operation; sync_class->remove_sync = pas_backend_file_remove; diff --git a/addressbook/backend/pas/pas-backend-ldap.c b/addressbook/backend/pas/pas-backend-ldap.c index 9c44e9983f..d4aa4ea82d 100644 --- a/addressbook/backend/pas/pas-backend-ldap.c +++ b/addressbook/backend/pas/pas-backend-ldap.c @@ -2819,6 +2819,13 @@ pas_backend_ldap_process_start_book_view (PASBackend *backend, pas_backend_ldap_search (bl, NULL /* XXX ugh */, view); } +static void +pas_backend_ldap_process_stop_book_view (PASBackend *backend, + PASBookView *view) +{ + /* FIXME we don't stop them... */ +} + static void pas_backend_ldap_process_get_changes (PASBackend *backend, PASBook *book, @@ -3146,6 +3153,7 @@ pas_backend_ldap_class_init (PASBackendLDAPClass *klass) 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->stop_book_view = pas_backend_ldap_process_stop_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; diff --git a/addressbook/backend/pas/pas-backend-summary.c b/addressbook/backend/pas/pas-backend-summary.c index 15f12cebc1..268a0c7062 100644 --- a/addressbook/backend/pas/pas-backend-summary.c +++ b/addressbook/backend/pas/pas-backend-summary.c @@ -711,8 +711,6 @@ pas_backend_summary_add_contact (PASBackendSummary *summary, EContact *contact) 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 (contact); - #ifdef SUMMARY_STATS summary->priv->size += sizeof (PASBackendSummaryItem); summary->priv->size += new_item->id ? strlen (new_item->id) : 0; diff --git a/addressbook/backend/pas/pas-backend-vcf.c b/addressbook/backend/pas/pas-backend-vcf.c index 3765fd978e..e82fe04f56 100644 --- a/addressbook/backend/pas/pas-backend-vcf.c +++ b/addressbook/backend/pas/pas-backend-vcf.c @@ -36,6 +36,7 @@ typedef struct _PASBackendVCFSearchContext PASBackendVCFSearchContext; struct _PASBackendVCFPrivate { char *uri; char *filename; + GMutex *mutex; GHashTable *contacts; gboolean dirty; int flush_timeout_tag; @@ -122,13 +123,13 @@ insert_contact (PASBackendVCF *vcf, char *vcard) } static void -load_file (PASBackendVCF *vcf) +load_file (PASBackendVCF *vcf, int fd) { FILE *fp; GString *str; char buf[1024]; - fp = fopen (vcf->priv->filename, "r"); + fp = fdopen (fd, "r"); if (!fp) { g_warning ("failed to open `%s' for reading", vcf->priv->filename); return; @@ -160,30 +161,32 @@ load_file (PASBackendVCF *vcf) static void foreach_build_list (char *id, char *vcard_string, GList **list) { - *list = g_list_append (*list, e_contact_new_from_vcard (vcard_string)); + *list = g_list_append (*list, vcard_string); } static gboolean save_file (PASBackendVCF *vcf) { - GList *contacts = NULL; + GList *vcards = NULL; GList *l; char *new_path; int fd, rv; - g_hash_table_foreach (vcf->priv->contacts, (GHFunc)foreach_build_list, &contacts); + g_warning ("PASBackendVCF flushing file to disk"); + + g_mutex_lock (vcf->priv->mutex); + g_hash_table_foreach (vcf->priv->contacts, (GHFunc)foreach_build_list, &vcards); 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); + for (l = vcards; l; l = l->next) { + char *vcard_str = l->data; 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"); @@ -192,8 +195,8 @@ save_file (PASBackendVCF *vcf) return FALSE; } - rv = write (fd, "\r\n", 2); - if (rv < 2) { + rv = write (fd, "\r\n\r\n", 4); + if (rv < 4) { /* XXX */ g_warning ("write failed. we need to handle short writes\n"); close (fd); @@ -208,12 +211,13 @@ save_file (PASBackendVCF *vcf) return FALSE; } - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); + g_list_free (vcards); g_free (new_path); vcf->priv->dirty = FALSE; + g_mutex_unlock (vcf->priv->mutex); + return TRUE; } @@ -245,6 +249,10 @@ do_create(PASBackendVCF *bvcf, EContact *contact; char *vcard; + /* at the very least we need the unique_id generation to be + protected by the lock, even if the actual vcard parsing + isn't. */ + g_mutex_lock (bvcf->priv->mutex); id = pas_backend_vcf_create_unique_id (); contact = e_contact_new_from_vcard (vcard_req); @@ -261,6 +269,8 @@ do_create(PASBackendVCF *bvcf, vcf_flush_file, bvcf); } + g_mutex_unlock (bvcf->priv->mutex); + return contact; } @@ -292,8 +302,13 @@ pas_backend_vcf_process_remove_contacts (PASBackendSync *backend, /* FIXME: make this handle bulk deletes like the file backend does */ PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); char *id = id_list->data; + gboolean success; + + g_mutex_lock (bvcf->priv->mutex); + success = g_hash_table_remove (bvcf->priv->contacts, id); - if (!g_hash_table_remove (bvcf->priv->contacts, id)) { + if (!success) { + g_mutex_unlock (bvcf->priv->mutex); return GNOME_Evolution_Addressbook_ContactNotFound; } else { @@ -301,6 +316,7 @@ pas_backend_vcf_process_remove_contacts (PASBackendSync *backend, if (!bvcf->priv->flush_timeout_tag) bvcf->priv->flush_timeout_tag = g_timeout_add (FILE_FLUSH_TIMEOUT, vcf_flush_file, bvcf); + g_mutex_unlock (bvcf->priv->mutex); *ids = g_list_append (*ids, id); @@ -317,16 +333,26 @@ pas_backend_vcf_process_modify_contact (PASBackendSync *backend, PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); char *old_id, *old_vcard_string; const char *id; + gboolean success; /* 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)) { + g_mutex_lock (bvcf->priv->mutex); + success = g_hash_table_lookup_extended (bvcf->priv->contacts, id, (gpointer)&old_id, (gpointer)&old_vcard_string); + + if (!success) { + g_mutex_unlock (bvcf->priv->mutex); return GNOME_Evolution_Addressbook_ContactNotFound; } else { g_hash_table_insert (bvcf->priv->contacts, old_id, g_strdup (vcard)); + 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); + g_mutex_unlock (bvcf->priv->mutex); g_free (old_vcard_string); @@ -400,6 +426,13 @@ pas_backend_vcf_start_book_view (PASBackend *backend, pas_backend_vcf_search (PAS_BACKEND_VCF (backend), book_view); } +static void +pas_backend_vcf_stop_book_view (PASBackend *backend, + PASBookView *book_view) +{ + /* XXX nothing here yet, and there should be. */ +} + static char * pas_backend_vcf_extract_path_from_uri (const char *uri) { @@ -443,16 +476,17 @@ pas_backend_vcf_load_uri (PASBackend *backend, gboolean only_if_exists) { PASBackendVCF *bvcf = PAS_BACKEND_VCF (backend); - char *filename; + char *dirname; 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); + dirname = pas_backend_vcf_extract_path_from_uri (uri); + bvcf->priv->filename = g_build_filename (dirname, "addressbook.vcf", NULL); - fd = open (filename, O_RDWR); + fd = open (bvcf->priv->filename, O_RDWR); bvcf->priv->contacts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); @@ -460,10 +494,10 @@ pas_backend_vcf_load_uri (PASBackend *backend, if (fd != -1) { writable = TRUE; } else { - fd = open (filename, O_RDONLY); + fd = open (bvcf->priv->filename, O_RDONLY); if (fd == -1) { - fd = open (filename, O_CREAT, 0666); + fd = open (bvcf->priv->filename, O_CREAT, 0666); if (fd != -1 && !only_if_exists) { EContact *contact; @@ -485,8 +519,7 @@ pas_backend_vcf_load_uri (PASBackend *backend, return GNOME_Evolution_Addressbook_OtherError; } - close (fd); /* XXX ugh */ - load_file (bvcf); + load_file (bvcf, fd); pas_backend_set_is_loaded (backend, TRUE); pas_backend_set_is_writable (backend, writable); @@ -546,17 +579,25 @@ pas_backend_vcf_dispose (GObject *object) if (bvcf->priv) { - if (bvcf->priv->dirty) - save_file (bvcf); + g_mutex_lock (bvcf->priv->mutex); if (bvcf->priv->flush_timeout_tag) { g_source_remove (bvcf->priv->flush_timeout_tag); bvcf->priv->flush_timeout_tag = 0; } + if (bvcf->priv->dirty) + save_file (bvcf); + + g_hash_table_destroy (bvcf->priv->contacts); + g_free (bvcf->priv->uri); g_free (bvcf->priv->filename); + g_mutex_unlock (bvcf->priv->mutex); + + g_mutex_free (bvcf->priv->mutex); + g_free (bvcf->priv); bvcf->priv = NULL; } @@ -580,6 +621,7 @@ pas_backend_vcf_class_init (PASBackendVCFClass *klass) 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->stop_book_view = pas_backend_vcf_stop_book_view; backend_class->cancel_operation = pas_backend_vcf_cancel_operation; sync_class->create_contact_sync = pas_backend_vcf_process_create_contact; @@ -598,8 +640,9 @@ pas_backend_vcf_init (PASBackendVCF *backend) { PASBackendVCFPrivate *priv; - priv = g_new0 (PASBackendVCFPrivate, 1); - priv->uri = NULL; + priv = g_new0 (PASBackendVCFPrivate, 1); + priv->uri = NULL; + priv->mutex = g_mutex_new(); backend->priv = priv; } diff --git a/addressbook/backend/pas/pas-backend.c b/addressbook/backend/pas/pas-backend.c index 076565de07..5b559940d1 100644 --- a/addressbook/backend/pas/pas-backend.c +++ b/addressbook/backend/pas/pas-backend.c @@ -200,6 +200,18 @@ pas_backend_start_book_view (PASBackend *backend, (* PAS_BACKEND_GET_CLASS (backend)->start_book_view) (backend, book_view); } +void +pas_backend_stop_book_view (PASBackend *backend, + PASBookView *book_view) +{ + 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)->stop_book_view); + + (* PAS_BACKEND_GET_CLASS (backend)->stop_book_view) (backend, book_view); +} + void pas_backend_get_changes (PASBackend *backend, PASBook *book, @@ -308,6 +320,17 @@ pas_backend_add_book_view (PASBackend *backend, g_mutex_unlock (backend->priv->views_mutex); } +void +pas_backend_remove_book_view (PASBackend *backend, + PASBookView *view) +{ + g_mutex_lock (backend->priv->views_mutex); + + e_list_remove (backend->priv->views, view); + + g_mutex_unlock (backend->priv->views_mutex); +} + /** * pas_backend_add_client: * @backend: An addressbook backend. diff --git a/addressbook/backend/pas/pas-backend.h b/addressbook/backend/pas/pas-backend.h index 41f6542213..b71d438441 100644 --- a/addressbook/backend/pas/pas-backend.h +++ b/addressbook/backend/pas/pas-backend.h @@ -58,6 +58,7 @@ struct _PASBackendClass { 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 (*stop_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); @@ -134,10 +135,15 @@ GNOME_Evolution_Addressbook_CallStatus pas_backend_cancel_operation (PASBackend void pas_backend_start_book_view (PASBackend *backend, PASBookView *view); +void pas_backend_stop_book_view (PASBackend *backend, + PASBookView *view); void pas_backend_add_book_view (PASBackend *backend, PASBookView *view); +void pas_backend_remove_book_view (PASBackend *backend, + PASBookView *view); + EList *pas_backend_get_book_views (PASBackend *backend); void pas_backend_notify_update (PASBackend *backend, diff --git a/addressbook/backend/pas/pas-book-view.c b/addressbook/backend/pas/pas-book-view.c index 712997d258..afdfb1dacb 100644 --- a/addressbook/backend/pas/pas-book-view.c +++ b/addressbook/backend/pas/pas-book-view.c @@ -19,6 +19,8 @@ struct _PASBookViewPrivate { GNOME_Evolution_Addressbook_BookViewListener listener; #define INITIAL_THRESHOLD 20 +#define THRESHOLD_MAX 3000 + GMutex *pending_mutex; CORBA_sequence_GNOME_Evolution_Addressbook_VCard adds; @@ -339,6 +341,15 @@ impl_GNOME_Evolution_Addressbook_BookView_start (PortableServer_Servant servant, pas_backend_start_book_view (pas_book_view_get_backend (view), view); } +static void +impl_GNOME_Evolution_Addressbook_BookView_stop (PortableServer_Servant servant, + CORBA_Environment *ev) +{ + PASBookView *view = PAS_BOOK_VIEW (bonobo_object (servant)); + + pas_backend_stop_book_view (pas_book_view_get_backend (view), view); +} + /** * pas_book_view_get_card_query */ @@ -363,6 +374,12 @@ pas_book_view_get_backend (PASBookView *book_view) return book_view->priv->backend; } +GNOME_Evolution_Addressbook_BookViewListener +pas_book_view_get_listener (PASBookView *book_view) +{ + return book_view->priv->listener; +} + /** * pas_book_view_new: */ @@ -423,6 +440,7 @@ pas_book_view_class_init (PASBookViewClass *klass) epv = &klass->epv; epv->start = impl_GNOME_Evolution_Addressbook_BookView_start; + epv->stop = impl_GNOME_Evolution_Addressbook_BookView_stop; } @@ -434,7 +452,7 @@ pas_book_view_init (PASBookView *book_view) book_view->priv->pending_mutex = g_mutex_new(); book_view->priv->next_threshold = INITIAL_THRESHOLD; - book_view->priv->threshold_max = 3000; + book_view->priv->threshold_max = THRESHOLD_MAX; book_view->priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); diff --git a/addressbook/backend/pas/pas-book-view.h b/addressbook/backend/pas/pas-book-view.h index 0cacab6bf0..3b292d11db 100644 --- a/addressbook/backend/pas/pas-book-view.h +++ b/addressbook/backend/pas/pas-book-view.h @@ -48,6 +48,7 @@ PASBookView *pas_book_view_new (PASBackend *b 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); +GNOME_Evolution_Addressbook_BookViewListener pas_book_view_get_listener (PASBookView *book_view); void pas_book_view_notify_update (PASBookView *book_view, EContact *contact); diff --git a/addressbook/backend/pas/pas-book.c b/addressbook/backend/pas/pas-book.c index 7b6e0c9a2b..08078887b6 100644 --- a/addressbook/backend/pas/pas-book.c +++ b/addressbook/backend/pas/pas-book.c @@ -42,7 +42,7 @@ impl_GNOME_Evolution_Addressbook_Book_remove (PortableServer_Servant servant, { PASBook *book = PAS_BOOK (bonobo_object (servant)); - printf ("impl_GNOME_Evolution_Addressbook_Book_open\n"); + printf ("impl_GNOME_Evolution_Addressbook_Book_remove\n"); pas_backend_remove (pas_book_get_backend (book), book); } @@ -121,6 +121,15 @@ impl_GNOME_Evolution_Addressbook_Book_modifyContact (PortableServer_Servant serv pas_backend_modify_contact (pas_book_get_backend (book), book, vcard); } +static void +view_listener_died_cb (gpointer cnx, gpointer user_data) +{ + PASBookView *book_view = PAS_BOOK_VIEW (user_data); + + pas_backend_stop_book_view (pas_book_view_get_backend (book_view), book_view); + pas_backend_remove_book_view (pas_book_view_get_backend (book_view), book_view); +} + static void impl_GNOME_Evolution_Addressbook_Book_getBookView (PortableServer_Servant servant, const GNOME_Evolution_Addressbook_BookViewListener listener, @@ -154,6 +163,7 @@ impl_GNOME_Evolution_Addressbook_Book_getBookView (PortableServer_Servant servan return; } + ORBit_small_listen_for_broken (pas_book_view_get_listener (view), G_CALLBACK (view_listener_died_cb), view); pas_backend_add_book_view (backend, view); @@ -298,7 +308,7 @@ pas_book_respond_create (PASBook *book, GNOME_Evolution_Addressbook_BookListener_notifyContactCreated ( book->priv->listener, status, - e_contact_get (contact, E_CONTACT_UID), &ev); + e_contact_get_const (contact, E_CONTACT_UID), &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("pas_book_respond_create: Exception " diff --git a/addressbook/tools/evolution-addressbook-abuse.c b/addressbook/tools/evolution-addressbook-abuse.c index 7801ed7e9d..3446e15938 100644 --- a/addressbook/tools/evolution-addressbook-abuse.c +++ b/addressbook/tools/evolution-addressbook-abuse.c @@ -2,15 +2,12 @@ #include -#include #include -#include +#include #include -static int contacts_to_add_total = 1000; -static int contacts_to_add = 50; -static int call_count = 0; +#define CONTACTS_TO_ADD 2000 static gchar * make_random_string (void) @@ -53,58 +50,12 @@ make_random_vcard (void) return vcard; } -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -static void -add_cb (EBook *book, EBookStatus status, const char *id, gpointer closure) -{ - switch (status) { - case E_BOOK_ERROR_OK: - --contacts_to_add_total; - g_message ("succesful add! (%d remaining)", contacts_to_add_total); - if (contacts_to_add_total <= 0) - g_main_loop_quit (NULL); - break; - default: - g_message ("something went wrong..."); - g_main_loop_quit (NULL); - break; - } -} - -static void -use_addressbook (EBook *book, EBookStatus status, gpointer closure) -{ - gint i; - - if (book == NULL || status != E_BOOK_ERROR_OK) - g_error (_("Error loading default addressbook.")); - - for (i = 0; i < contacts_to_add; ++i) { - gchar *vcard = make_random_vcard (); - EContact *contact = e_contact_new_from_vcard (vcard); - g_message ("adding %d", i); - e_book_async_add_contact (book, contact, add_cb, NULL); - g_free (vcard); - g_object_unref (contact); - } - - g_object_unref (book); -} - -static gint -abuse_timeout (gpointer foo) -{ - e_book_async_get_default_addressbook (use_addressbook, NULL); - - ++call_count; - g_message ("timeout!"); - return call_count < contacts_to_add_total / contacts_to_add; -} - int main (int argc, char *argv[]) { + EBook *book; + int i; + if (getenv ("ABUSE_THE_WOMBAT") == NULL) { g_print ("You probably don't want to use this program.\n" "It isn't very nice.\n"); @@ -119,9 +70,22 @@ main (int argc, char *argv[]) GNOME_PROGRAM_STANDARD_PROPERTIES, NULL); - g_timeout_add (20, abuse_timeout, NULL); + if (!e_book_get_default_addressbook (&book, NULL)) { + g_warning ("couldn't open addressbook"); + exit (1); + } - bonobo_main (); + for (i = 0; i < CONTACTS_TO_ADD; ++i) { + gchar *vcard = make_random_vcard (); + EContact *contact = e_contact_new_from_vcard (vcard); + g_message ("adding %d", i); + if (!e_book_add_contact (book, contact, NULL)) { + g_warning ("something went wrong..."); + exit (1); + } + g_free (vcard); + g_object_unref (contact); + } return 0; } -- cgit v1.2.3