From ab628527493707667ecacd37e91c83486e15faac Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 9 Mar 2007 15:52:08 +0000 Subject: [PATCH] - Add patch for GNOME bug #415891 (introduce EFlag API). - Add patch for GNOME bug #376991 (refactor password handling). --- evolution-data-server-1.9.92-e-flag.patch | 2163 +++++++++++++++++ ...ution-data-server-1.9.92-e-passwords.patch | 1880 ++++++++++++++ evolution-data-server.spec | 14 +- 3 files changed, 4056 insertions(+), 1 deletion(-) create mode 100644 evolution-data-server-1.9.92-e-flag.patch create mode 100644 evolution-data-server-1.9.92-e-passwords.patch diff --git a/evolution-data-server-1.9.92-e-flag.patch b/evolution-data-server-1.9.92-e-flag.patch new file mode 100644 index 0000000..1acc101 --- /dev/null +++ b/evolution-data-server-1.9.92-e-flag.patch @@ -0,0 +1,2163 @@ +--- /dev/null 2007-03-08 09:20:11.212292094 -0500 ++++ evolution-data-server-1.9.92/libedataserver/e-flag.c 2007-03-08 17:16:18.000000000 -0500 +@@ -0,0 +1,171 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * Copyright (C) 2007 Novell, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of version 2 of the GNU Lesser General Public ++ * License as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++#include "e-flag.h" ++ ++struct _EFlag { ++ GCond *cond; ++ GMutex *mutex; ++ gboolean is_set; ++}; ++ ++/** ++ * e_flag_new: ++ * ++ * Creates a new #EFlag object. It is initially unset. ++ * ++ * Returns: a new #EFlag ++ **/ ++EFlag * ++e_flag_new (void) ++{ ++ EFlag *flag; ++ ++ flag = g_slice_new (EFlag); ++ flag->cond = g_cond_new (); ++ flag->mutex = g_mutex_new (); ++ flag->is_set = FALSE; ++ ++ return flag; ++} ++ ++/** ++ * e_flag_is_set: ++ * @flag: an #EFlag ++ * ++ * Returns the state of @flag. ++ * ++ * Returns: %TRUE if @flag is set ++ **/ ++gboolean ++e_flag_is_set (EFlag *flag) ++{ ++ gboolean is_set; ++ ++ g_return_val_if_fail (flag != NULL, FALSE); ++ ++ g_mutex_lock (flag->mutex); ++ is_set = flag->is_set; ++ g_mutex_unlock (flag->mutex); ++ ++ return is_set; ++} ++ ++/** ++ * e_flag_set: ++ * @flag: an #EFlag ++ * ++ * Sets @flag. All threads waiting on @flag are woken up. Threads that ++ * call e_flag_wait() or e_flag_timed_wait() once @flag is set will not ++ * block at all. ++ **/ ++void ++e_flag_set (EFlag *flag) ++{ ++ g_return_if_fail (flag != NULL); ++ ++ g_mutex_lock (flag->mutex); ++ flag->is_set = TRUE; ++ g_cond_broadcast (flag->cond); ++ g_mutex_unlock (flag->mutex); ++} ++ ++/** ++ * e_flag_clear: ++ * @flag: an #EFlag ++ * ++ * Unsets @flag. Subsequent calls to e_flag_wait() or e_flag_timed_wait() ++ * will block until @flag is set. ++ **/ ++void ++e_flag_clear (EFlag *flag) ++{ ++ g_return_if_fail (flag != NULL); ++ ++ g_mutex_lock (flag->mutex); ++ flag->is_set = FALSE; ++ g_mutex_unlock (flag->mutex); ++} ++ ++/** ++ * e_flag_wait: ++ * @flag: an #EFlag ++ * ++ * Blocks until @flag is set. If @flag is already set, the function returns ++ * immediately. ++ **/ ++void ++e_flag_wait (EFlag *flag) ++{ ++ g_return_if_fail (flag != NULL); ++ ++ g_mutex_lock (flag->mutex); ++ while (!flag->is_set) ++ g_cond_wait (flag->cond, flag->mutex); ++ g_mutex_unlock (flag->mutex); ++} ++ ++/** ++ * e_flag_timed_wait: ++ * @flag: an #EFlag ++ * @abs_time: a #GTimeVal, determining the final time ++ * ++ * Blocks until @flag is set, or until the time specified by @abs_time. ++ * If @flag is already set, the function returns immediately. The return ++ * value indicates the state of @flag after waiting. ++ * ++ * If @abs_time is %NULL, e_flag_timed_wait() acts like e_flag_wait(). ++ * ++ * To easily calculate @abs_time, a combination of g_get_current_time() and ++ * g_time_val_add() can be used. ++ * ++ * Returns: %TRUE if @flag is now set ++ **/ ++gboolean ++e_flag_timed_wait (EFlag *flag, GTimeVal *abs_time) ++{ ++ gboolean is_set; ++ ++ g_return_val_if_fail (flag != NULL, FALSE); ++ ++ g_mutex_lock (flag->mutex); ++ while (!flag->is_set) ++ if (!g_cond_timed_wait (flag->cond, flag->mutex, abs_time)) ++ break; ++ is_set = flag->is_set; ++ g_mutex_unlock (flag->mutex); ++ ++ return is_set; ++} ++ ++/** ++ * e_flag_free: ++ * @flag: an #EFlag ++ * ++ * Destroys @flag. ++ **/ ++void ++e_flag_free (EFlag *flag) ++{ ++ g_return_if_fail (flag != NULL); ++ ++ g_cond_free (flag->cond); ++ g_mutex_free (flag->mutex); ++ g_slice_free (EFlag, flag); ++} +--- /dev/null 2007-03-08 09:20:11.212292094 -0500 ++++ evolution-data-server-1.9.92/libedataserver/e-flag.h 2007-03-08 17:16:18.000000000 -0500 +@@ -0,0 +1,43 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * Copyright (C) 2007 Novell, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of version 2 of the GNU Lesser General Public ++ * License as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef E_FLAG_H ++#define E_FLAG_H ++ ++/* An EFlag is essentially a binary semaphore with a more intuitive interface. ++ * Based on Python's threading.Event class ("EEvent" was already taken). */ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++typedef struct _EFlag EFlag; ++ ++EFlag * e_flag_new (void); ++gboolean e_flag_is_set (EFlag *flag); ++void e_flag_set (EFlag *flag); ++void e_flag_clear (EFlag *flag); ++void e_flag_wait (EFlag *flag); ++gboolean e_flag_timed_wait (EFlag *flag, ++ GTimeVal *abs_time); ++void e_flag_free (EFlag *flag); ++ ++G_END_DECLS ++ ++#endif /* E_FLAG_H */ +--- evolution-data-server-1.9.92/libedataserver/Makefile.in.e-flag 2007-02-26 08:32:13.000000000 -0500 ++++ evolution-data-server-1.9.92/libedataserver/Makefile.in 2007-03-08 17:16:18.000000000 -0500 +@@ -69,7 +69,7 @@ + am_libedataserver_1_2_la_OBJECTS = $(am__objects_1) e-account-list.lo \ + e-account.lo e-categories.lo e-component-listener.lo \ + e-data-server-module.lo e-dbhash.lo e-db3-utils.lo \ +- e-file-cache.lo e-iconv.lo e-iterator.lo e-list.lo \ ++ e-file-cache.lo e-flag.lo e-iconv.lo e-iterator.lo e-list.lo \ + e-list-iterator.lo e-memory.lo e-msgport.lo e-sexp.lo \ + e-source-group.lo e-source-list.lo e-source.lo e-time-utils.lo \ + e-uid.lo e-url.lo e-data-server-util.lo e-trie.lo \ +@@ -420,6 +420,7 @@ + e-dbhash.c \ + e-db3-utils.c \ + e-file-cache.c \ ++ e-flag.c \ + e-iconv.c \ + e-iterator.c \ + e-list.c \ +@@ -459,6 +460,7 @@ + e-db3-utils.h \ + e-dbhash.h \ + e-file-cache.h \ ++ e-flag.h \ + e-iconv.h \ + e-iterator.h \ + e-list.h \ +@@ -577,6 +579,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-db3-utils.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-dbhash.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-file-cache.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-flag.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-iconv.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-iterator.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e-list-iterator.Plo@am__quote@ +--- evolution-data-server-1.9.92/libedataserver/Makefile.am.e-flag 2007-01-03 09:56:27.000000000 -0500 ++++ evolution-data-server-1.9.92/libedataserver/Makefile.am 2007-03-08 17:16:18.000000000 -0500 +@@ -26,6 +26,7 @@ + e-dbhash.c \ + e-db3-utils.c \ + e-file-cache.c \ ++ e-flag.c \ + e-iconv.c \ + e-iterator.c \ + e-list.c \ +@@ -66,6 +67,7 @@ + e-db3-utils.h \ + e-dbhash.h \ + e-file-cache.h \ ++ e-flag.h \ + e-iconv.h \ + e-iterator.h \ + e-list.h \ +--- evolution-data-server-1.9.92/addressbook/backends/file/e-book-backend-file.c.e-flag 2007-01-03 09:56:28.000000000 -0500 ++++ evolution-data-server-1.9.92/addressbook/backends/file/e-book-backend-file.c 2007-03-09 00:22:01.000000000 -0500 +@@ -43,6 +43,7 @@ + #include "libedataserver/e-dbhash.h" + #include "libedataserver/e-db3-utils.h" + #include "libedataserver/e-data-server-util.h" ++#include "libedataserver/e-flag.h" + + #include "libebook/e-contact.h" + +@@ -479,18 +480,15 @@ + + typedef struct { + EBookBackendFile *bf; +- GMutex *mutex; +- GCond *cond; + GThread *thread; +- gboolean stopped; ++ EFlag *running; + } FileBackendSearchClosure; + + static void + closure_destroy (FileBackendSearchClosure *closure) + { + d(printf ("destroying search closure\n")); +- g_mutex_free (closure->mutex); +- g_cond_free (closure->cond); ++ e_flag_free (closure->running); + g_free (closure); + } + +@@ -500,10 +498,8 @@ + FileBackendSearchClosure *closure = g_new (FileBackendSearchClosure, 1); + + closure->bf = bf; +- closure->mutex = g_mutex_new (); +- closure->cond = g_cond_new (); + closure->thread = NULL; +- closure->stopped = FALSE; ++ closure->running = e_flag_new (); + + g_object_set_data_full (G_OBJECT (book_view), "EBookBackendFile.BookView::closure", + closure, (GDestroyNotify)closure_destroy); +@@ -527,7 +523,7 @@ + DB *db; + DBT id_dbt, vcard_dbt; + int db_error; +- gboolean stopped = FALSE, allcontacts; ++ gboolean allcontacts; + + d(printf ("starting initial population of book view\n")); + +@@ -547,9 +543,7 @@ + } + + d(printf ("signalling parent thread\n")); +- g_mutex_lock (closure->mutex); +- g_cond_signal (closure->cond); +- g_mutex_unlock (closure->mutex); ++ e_flag_set (closure->running); + + if (e_book_backend_summary_is_summary_query (bf->priv->summary, query)) { + /* do a summary query */ +@@ -558,11 +552,8 @@ + + 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) ++ if (!e_flag_is_set (closure->running)) + break; + + string_to_dbt (id, &id_dbt); +@@ -595,11 +586,7 @@ + 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) ++ if (!e_flag_is_set (closure->running)) + break; + + /* don't include the version in the list of cards */ +@@ -628,7 +615,7 @@ + + } + +- if (!stopped) ++ if (e_flag_is_set (closure->running)) + e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success); + + /* unref the */ +@@ -646,15 +633,12 @@ + { + FileBackendSearchClosure *closure = init_closure (book_view, E_BOOK_BACKEND_FILE (backend)); + +- g_mutex_lock (closure->mutex); +- + d(printf ("starting book view thread\n")); + closure->thread = g_thread_create (book_view_thread, book_view, TRUE, NULL); + +- g_cond_wait (closure->cond, closure->mutex); ++ e_flag_wait (closure->running); + + /* at this point we know the book view thread is actually running */ +- g_mutex_unlock (closure->mutex); + d(printf ("returning from start_book_view\n")); + } + +@@ -663,14 +647,11 @@ + EDataBookView *book_view) + { + FileBackendSearchClosure *closure = get_closure (book_view); +- gboolean need_join = FALSE; ++ gboolean need_join; + + d(printf ("stopping query\n")); +- g_mutex_lock (closure->mutex); +- if (!closure->stopped) +- need_join = TRUE; +- closure->stopped = TRUE; +- g_mutex_unlock (closure->mutex); ++ need_join = e_flag_is_set (closure->running); ++ e_flag_clear (closure->running); + + if (need_join) + g_thread_join (closure->thread); +--- evolution-data-server-1.9.92/addressbook/backends/groupwise/e-book-backend-groupwise.c.e-flag 2007-01-03 09:56:29.000000000 -0500 ++++ evolution-data-server-1.9.92/addressbook/backends/groupwise/e-book-backend-groupwise.c 2007-03-09 00:22:01.000000000 -0500 +@@ -40,6 +40,7 @@ + #include "libedataserver/e-sexp.h" + #include "libedataserver/e-data-server-util.h" + #include "libedataserver/e-db3-utils.h" ++#include "libedataserver/e-flag.h" + #include "libedataserver/e-url.h" + #include "libebook/e-contact.h" + #include "libedata-book/e-book-backend-sexp.h" +@@ -2070,17 +2071,14 @@ + + typedef struct { + EBookBackendGroupwise *bg; +- GMutex *mutex; +- GCond *cond; + GThread *thread; +- gboolean stopped; ++ EFlag *running; + } GroupwiseBackendSearchClosure; + + static void + closure_destroy (GroupwiseBackendSearchClosure *closure) + { +- g_mutex_free (closure->mutex); +- g_cond_free (closure->cond); ++ e_flag_free (closure->running); + g_free (closure); + } + +@@ -2090,10 +2088,8 @@ + GroupwiseBackendSearchClosure *closure = g_new (GroupwiseBackendSearchClosure, 1); + + closure->bg = bg; +- closure->mutex = g_mutex_new (); +- closure->cond = g_cond_new (); + closure->thread = NULL; +- closure->stopped = FALSE; ++ closure->running = e_flag_new (); + + g_object_set_data_full (G_OBJECT (book_view), "EBookBackendGroupwise.BookView::closure", + closure, (GDestroyNotify)closure_destroy); +@@ -2115,19 +2111,14 @@ + GroupwiseBackendSearchClosure *closure) + { + int i; +- gboolean stopped = FALSE; + + if (enable_debug) + printf ("\nread contacts from cache for the ids found in summary\n"); + for (i = 0; i < ids->len; i ++) { + char *uid = g_ptr_array_index (ids, i); + +- g_mutex_lock (closure->mutex); +- stopped = closure->stopped; +- g_mutex_unlock (closure->mutex); +- +- if (stopped) +- break; ++ if (!e_flag_is_set (closure->running)) ++ break; + + EContact *contact = + e_book_backend_db_cache_get_contact (ebgw->priv->file_db, uid); +@@ -2136,7 +2127,7 @@ + g_object_unref (contact); + } + } +- if (!stopped) ++ if (e_flag_is_set (closure->running)) + e_data_book_view_notify_complete (book_view, + GNOME_Evolution_Addressbook_Success); + } +@@ -2151,7 +2142,6 @@ + const char *query = NULL; + EGwFilter *filter = NULL; + GPtrArray *ids = NULL; +- gboolean stopped = FALSE; + EDataBookView *book_view = data; + GroupwiseBackendSearchClosure *closure = get_closure (book_view); + char *view = NULL; +@@ -2166,9 +2156,7 @@ + if (enable_debug) + printf ("start book view for %s \n", gwb->priv->book_name); + bonobo_object_ref (book_view); +- g_mutex_lock (closure->mutex); +- g_cond_signal (closure->cond); +- g_mutex_unlock (closure->mutex); ++ e_flag_set (closure->running); + + query = e_data_book_view_get_card_query (book_view); + if (enable_debug) +@@ -2200,10 +2188,7 @@ + contacts = e_book_backend_db_cache_get_contacts (gwb->priv->file_db, query); + temp_list = contacts; + for (; contacts != NULL; contacts = g_list_next(contacts)) { +- g_mutex_lock (closure->mutex); +- stopped = closure->stopped; +- g_mutex_unlock (closure->mutex); +- if (stopped) { ++ if (!e_flag_is_set (closure->running)) { + for (;contacts != NULL; contacts = g_list_next (contacts)) + g_object_unref (contacts->data); + break; +@@ -2211,7 +2196,7 @@ + e_data_book_view_notify_update (book_view, E_CONTACT(contacts->data)); + g_object_unref (contacts->data); + } +- if (!stopped) ++ if (e_flag_is_set (closure->running)) + e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success); + if (temp_list) + g_list_free (temp_list); +@@ -2339,10 +2324,7 @@ + temp_list = gw_items; + for (; gw_items != NULL; gw_items = g_list_next(gw_items)) { + +- g_mutex_lock (closure->mutex); +- stopped = closure->stopped; +- g_mutex_unlock (closure->mutex); +- if (stopped) { ++ if (!e_flag_is_set (closure->running)) { + for (;gw_items != NULL; gw_items = g_list_next (gw_items)) + g_object_unref (gw_items->data); + break; +@@ -2363,7 +2345,7 @@ + } + if (temp_list) + g_list_free (temp_list); +- if (!stopped) ++ if (e_flag_is_set (closure->running)) + e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success); + if (filter) + g_object_unref (filter); +@@ -2392,12 +2374,10 @@ + + if (enable_debug) + printf ("\ne_book_backend_groupwise_start_book_view...\n"); +- g_mutex_lock (closure->mutex); + closure->thread = g_thread_create (book_view_thread, book_view, FALSE, NULL); +- g_cond_wait (closure->cond, closure->mutex); ++ e_flag_wait (closure->running); + + /* at this point we know the book view thread is actually running */ +- g_mutex_unlock (closure->mutex); + } + + static void +@@ -2408,10 +2388,7 @@ + + if (enable_debug) + printf ("\ne_book_backend_groupwise_stop_book_view...\n"); +- g_mutex_lock (closure->mutex); +- if (!closure->stopped) +- closure->stopped = TRUE; +- g_mutex_unlock (closure->mutex); ++ e_flag_clear (closure->running); + } + + static void +@@ -2650,11 +2627,8 @@ + if (book_view) { + closure = get_closure (book_view); + bonobo_object_ref (book_view); +- if (closure) { +- g_mutex_lock (closure->mutex); +- g_cond_signal (closure->cond); +- g_mutex_unlock (closure->mutex); +- } ++ if (closure) ++ e_flag_set (closure->running); + } + + while (!done) { +@@ -2799,11 +2773,8 @@ + if (book_view) { + closure = get_closure (book_view); + bonobo_object_ref (book_view); +- if (closure) { +- g_mutex_lock (closure->mutex); +- g_cond_signal (closure->cond); +- g_mutex_unlock (closure->mutex); +- } ++ if (closure) ++ e_flag_set (closure->running); + } + + cache_file_name = e_book_backend_db_cache_get_filename(ebgw->priv->file_db); +@@ -2967,11 +2938,8 @@ + if (book_view) { + closure = get_closure (book_view); + bonobo_object_ref (book_view); +- if (closure){ +- g_mutex_lock (closure->mutex); +- g_cond_signal (closure->cond); +- g_mutex_unlock (closure->mutex); +- } ++ if (closure) ++ e_flag_set (closure->running); + } + + /* update the cache */ +--- evolution-data-server-1.9.92/addressbook/backends/vcf/e-book-backend-vcf.c.e-flag 2007-01-03 09:56:29.000000000 -0500 ++++ evolution-data-server-1.9.92/addressbook/backends/vcf/e-book-backend-vcf.c 2007-03-09 00:22:01.000000000 -0500 +@@ -41,6 +41,7 @@ + #include + + #include "libedataserver/e-data-server-util.h" ++#include "libedataserver/e-flag.h" + + #include "libebook/e-contact.h" + +@@ -427,18 +428,15 @@ + typedef struct { + EBookBackendVCF *bvcf; + EDataBookView *view; +- GMutex *mutex; +- GCond *cond; + GThread *thread; +- gboolean stopped; ++ EFlag *running; + } VCFBackendSearchClosure; + + static void + closure_destroy (VCFBackendSearchClosure *closure) + { + d(printf ("destroying search closure\n")); +- g_mutex_free (closure->mutex); +- g_cond_free (closure->cond); ++ e_flag_free (closure->running); + g_free (closure); + } + +@@ -449,10 +447,8 @@ + + closure->bvcf = bvcf; + closure->view = book_view; +- closure->mutex = g_mutex_new (); +- closure->cond = g_cond_new (); + closure->thread = NULL; +- closure->stopped = FALSE; ++ closure->running = e_flag_new (); + + g_object_set_data_full (G_OBJECT (book_view), "EBookBackendVCF.BookView::closure", + closure, (GDestroyNotify)closure_destroy); +@@ -486,9 +482,7 @@ + e_data_book_view_notify_status_message (book_view, _("Searching...")); + + d(printf ("signalling parent thread\n")); +- g_mutex_lock (closure->mutex); +- g_cond_signal (closure->cond); +- g_mutex_unlock (closure->mutex); ++ e_flag_set (closure->running); + + for (l = closure->bvcf->priv->contact_list; l; l = l->next) { + char *vcard_string = l->data; +@@ -496,11 +490,11 @@ + e_data_book_view_notify_update (closure->view, contact); + g_object_unref (contact); + +- if (closure->stopped) ++ if (!e_flag_is_set (closure->running)) + break; + } + +- if (!closure->stopped) ++ if (e_flag_is_set (closure->running)) + e_data_book_view_notify_complete (closure->view, GNOME_Evolution_Addressbook_Success); + + /* unref the book view */ +@@ -518,15 +512,12 @@ + { + VCFBackendSearchClosure *closure = init_closure (book_view, E_BOOK_BACKEND_VCF (backend)); + +- g_mutex_lock (closure->mutex); +- + d(printf ("starting book view thread\n")); + closure->thread = g_thread_create (book_view_thread, book_view, TRUE, NULL); + +- g_cond_wait (closure->cond, closure->mutex); ++ e_flag_wait (closure->running); + + /* at this point we know the book view thread is actually running */ +- g_mutex_unlock (closure->mutex); + d(printf ("returning from start_book_view\n")); + + } +@@ -536,14 +527,11 @@ + EDataBookView *book_view) + { + VCFBackendSearchClosure *closure = get_closure (book_view); +- gboolean need_join = FALSE; ++ gboolean need_join; + + d(printf ("stopping query\n")); +- g_mutex_lock (closure->mutex); +- if (!closure->stopped) +- need_join = TRUE; +- closure->stopped = TRUE; +- g_mutex_unlock (closure->mutex); ++ need_join = e_flag_is_set (closure->running); ++ e_flag_clear (closure->running); + + if (need_join) + g_thread_join (closure->thread); +--- evolution-data-server-1.9.92/docs/reference/libedataserver/libedataserver-docs.sgml.e-flag 2007-01-03 09:56:22.000000000 -0500 ++++ evolution-data-server-1.9.92/docs/reference/libedataserver/libedataserver-docs.sgml 2007-03-08 17:16:18.000000000 -0500 +@@ -16,6 +16,7 @@ + + + ++ + + + +--- /dev/null 2007-03-08 09:20:11.212292094 -0500 ++++ evolution-data-server-1.9.92/docs/reference/libedataserver/tmpl/e-flag.sgml 2007-03-08 17:16:18.000000000 -0500 +@@ -0,0 +1,89 @@ ++ ++EFlag ++ ++ ++Simple thread synchronization ++ ++ ++ ++An #EFlag is a simple thread synchronization mechanism. It implements a ++thread-safe flag that can be blocked on. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++The EFlag struct is an opaque data structure ++representing a thread-safe flag. It should be accessed only by using ++the following functions. ++ ++ ++ ++ ++ ++ ++ ++ ++@Returns: ++ ++ ++ ++ ++ ++ ++ ++@flag: ++@Returns: ++ ++ ++ ++ ++ ++ ++ ++@flag: ++ ++ ++ ++ ++ ++ ++ ++@flag: ++ ++ ++ ++ ++ ++ ++ ++@flag: ++ ++ ++ ++ ++ ++ ++ ++@flag: ++@abs_time: ++@Returns: ++ ++ ++ ++ ++ ++ ++ ++@flag: ++ ++ +--- evolution-data-server-1.9.92/docs/reference/libedataserver/libedataserver-sections.txt.e-flag 2007-01-03 09:56:22.000000000 -0500 ++++ evolution-data-server-1.9.92/docs/reference/libedataserver/libedataserver-sections.txt 2007-03-08 17:16:18.000000000 -0500 +@@ -83,6 +83,19 @@ + + +
++e-flag ++EFlag ++EFlag ++e_flag_new ++e_flag_is_set ++e_flag_set ++e_flag_clear ++e_flag_wait ++e_flag_timed_wait ++e_flag_free ++
++ ++
+ e-iterator + EIterator + e_iterator_get +--- evolution-data-server-1.9.92/calendar/libecal/e-cal.c.e-flag 2007-03-08 17:16:18.000000000 -0500 ++++ evolution-data-server-1.9.92/calendar/libecal/e-cal.c 2007-03-09 00:22:01.000000000 -0500 +@@ -33,6 +33,7 @@ + #include + + #include ++#include + #include + #include "e-cal-marshal.h" + #include "e-cal-time-util.h" +@@ -49,8 +50,7 @@ + + + typedef struct { +- GMutex *mutex; +- GCond *cond; ++ EFlag *done; + ECalendarStatus status; + + char *uid; +@@ -306,8 +306,7 @@ + { + ECalendarOp *op = g_new0 (ECalendarOp, 1); + +- op->mutex = g_mutex_new (); +- op->cond = g_cond_new (); ++ op->done = e_flag_new (); + + ecal->priv->current_op = op; + +@@ -329,8 +328,7 @@ + e_calendar_free_op (ECalendarOp *op) + { + /* XXX more stuff here */ +- g_cond_free (op->cond); +- g_mutex_free (op->mutex); ++ e_flag_free (op->done); + g_free (op); + } + +@@ -448,14 +446,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->bool = read_only; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -477,14 +471,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (address); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -500,14 +490,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (address); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -523,14 +509,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (attribute); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -546,14 +528,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (capabilities); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -569,13 +547,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -591,13 +565,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -613,14 +583,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->uid = g_strdup (uid); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -636,13 +602,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -658,13 +620,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -680,13 +638,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -702,13 +656,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -725,8 +675,6 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->list = g_list_copy (users); + op->string = g_strdup (object); +@@ -734,9 +682,7 @@ + for (l = op->list; l; l = l->next) + l->data = g_strdup (l->data); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -752,14 +698,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (object); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -775,14 +717,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (object); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -799,17 +737,13 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->list = g_list_copy (objects); + + for (l = op->list; l; l = l->next) + l->data = icalcomponent_new_clone (l->data); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -825,14 +759,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->slist = g_slist_copy (attachments); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -848,15 +778,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->string = g_strdup (object); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); +- ++ e_flag_set (op->done); + } + + static void +@@ -872,15 +797,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->uid = g_strdup (tzid); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); +- ++ e_flag_set (op->done); + } + + static void +@@ -896,13 +816,9 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -919,8 +835,6 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->list = g_list_copy (changes); + +@@ -934,9 +848,7 @@ + l->data = new_ccc; + } + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -953,17 +865,13 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->list = g_list_copy (freebusy); + + for (l = op->list; l; l = l->next) + l->data = e_cal_component_clone (l->data); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static void +@@ -979,14 +887,10 @@ + return; + } + +- g_mutex_lock (op->mutex); +- + op->status = status; + op->query = e_cal_view_new (query, op->listener, ecal); + +- g_cond_signal (op->cond); +- +- g_mutex_unlock (op->mutex); ++ e_flag_set (op->done); + } + + static gboolean +@@ -1722,7 +1626,6 @@ + } + /* start the open operation */ + our_op = e_calendar_new_op (ecal); +- g_mutex_lock (our_op->mutex); + + g_mutex_unlock (priv->mutex); + +@@ -1735,7 +1638,6 @@ + + if (priv->auth_func == NULL) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + priv->load_state = E_CAL_LOAD_NOT_LOADED; + *status = E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; +@@ -1745,7 +1647,6 @@ + username = e_source_get_property (priv->source, "username"); + if (!username) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + priv->load_state = E_CAL_LOAD_NOT_LOADED; + *status = E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; +@@ -1773,7 +1674,6 @@ + + if (!key) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + priv->load_state = E_CAL_LOAD_NOT_LOADED; + *status = E_CALENDAR_STATUS_URI_NOT_LOADED; +@@ -1784,7 +1684,6 @@ + + if (!password) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + priv->load_state = E_CAL_LOAD_NOT_LOADED; + *status = E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; +@@ -1809,7 +1708,6 @@ + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -1823,14 +1721,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + *status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + if (*status == E_CALENDAR_STATUS_OK) { + priv->load_state = E_CAL_LOAD_LOADED; +@@ -1986,8 +1881,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + +@@ -1996,7 +1889,6 @@ + GNOME_Evolution_Calendar_Cal_remove (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2008,14 +1900,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2247,8 +2136,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + /* set it to true so that op does not emit cond signals for all notifications + from the backend */ + our_op->bool = TRUE; +@@ -2261,7 +2148,6 @@ + GNOME_Evolution_Calendar_Cal_isReadOnly (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2273,9 +2159,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + +@@ -2283,7 +2167,6 @@ + *read_only = our_op->bool; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + E_CALENDAR_CHECK_STATUS (status, error); + } +@@ -2326,8 +2209,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + +@@ -2336,7 +2217,6 @@ + GNOME_Evolution_Calendar_Cal_getCalAddress (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2348,14 +2228,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *cal_address = our_op->string; + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2403,8 +2280,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + +@@ -2413,7 +2288,6 @@ + GNOME_Evolution_Calendar_Cal_getAlarmEmailAddress (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2425,15 +2299,12 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *alarm_address = our_op->string; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2476,8 +2347,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + +@@ -2486,7 +2355,6 @@ + GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2498,15 +2366,12 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *ldap_attribute = our_op->string; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2539,8 +2404,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + +@@ -2549,7 +2412,6 @@ + GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2561,15 +2423,12 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + priv->capabilities = our_op->string; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2778,8 +2637,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -2787,7 +2644,6 @@ + GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2799,9 +2655,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + if (status != E_CALENDAR_STATUS_OK) { +@@ -2814,7 +2668,6 @@ + g_free (our_op->string); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2859,15 +2712,12 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_Cal_getAttachmentList (priv->cal, uid, rid ? rid : "", &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2879,9 +2729,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + if (status != E_CALENDAR_STATUS_OK){ +@@ -2891,7 +2739,6 @@ + } + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -2936,8 +2783,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -2945,7 +2790,6 @@ + GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, rid ? rid : "", &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -2957,9 +2801,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + if (status != E_CALENDAR_STATUS_OK){ +@@ -3007,7 +2849,6 @@ + g_free (our_op->string); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -3053,8 +2894,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -3062,7 +2901,6 @@ + GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, "", &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -3074,9 +2912,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + if (status != E_CALENDAR_STATUS_OK){ +@@ -3134,7 +2970,6 @@ + g_free (our_op->string); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -3204,8 +3039,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -3214,7 +3047,6 @@ + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -3226,15 +3058,12 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *changes = our_op->list; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -3304,8 +3133,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -3314,7 +3141,6 @@ + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -3326,15 +3152,12 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *objects = our_op->list; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -3437,8 +3260,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + /* create the CORBA user list to be passed to the backend */ +@@ -3458,7 +3279,6 @@ + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -3470,15 +3290,12 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *freebusy = our_op->list; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4169,8 +3986,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + e_cal_component_get_uid (comp, &uid); +@@ -4180,7 +3995,6 @@ + GNOME_Evolution_Calendar_Cal_discardAlarm (priv->cal, uid, auid, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4192,14 +4006,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4415,8 +4226,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -4424,7 +4233,6 @@ + GNOME_Evolution_Calendar_Cal_createObject (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4436,16 +4244,13 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + if (uid) + *uid = our_op->uid; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4495,8 +4300,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -4504,7 +4307,6 @@ + GNOME_Evolution_Calendar_Cal_modifyObject (priv->cal, icalcomponent_as_ical_string (icalcomp), mod, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4516,14 +4318,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4576,8 +4375,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + +@@ -4586,7 +4383,6 @@ + GNOME_Evolution_Calendar_Cal_removeObject (priv->cal, uid, rid ? rid : "", mod, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4598,14 +4394,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4670,8 +4463,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -4679,7 +4470,6 @@ + GNOME_Evolution_Calendar_Cal_receiveObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4691,14 +4481,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4744,8 +4531,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -4753,7 +4538,6 @@ + GNOME_Evolution_Calendar_Cal_sendObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4765,9 +4549,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *users = our_op->list; +@@ -4788,7 +4570,6 @@ + g_free (our_op->string); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4833,8 +4614,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (priv->mutex); + + /* Check for well known zones and in the cache */ +@@ -4843,7 +4622,6 @@ + /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */ + if (!tzid || !tzid[0]) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + *zone = NULL; +@@ -4861,7 +4639,6 @@ + + if (*zone) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); +@@ -4873,7 +4650,6 @@ + GNOME_Evolution_Calendar_Cal_getTimezone (priv->cal, tzid, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -4885,9 +4661,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + if (status != E_CALENDAR_STATUS_OK){ +@@ -4901,7 +4675,6 @@ + + if (!icalcomp) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4912,7 +4685,6 @@ + icaltimezone_free (*zone, 1); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); +@@ -4922,7 +4694,6 @@ + g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (*zone), *zone); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -4967,15 +4738,12 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (priv->mutex); + + /* Make sure we have a valid component - UTC doesn't, nor do + * we really have to add it */ + if (izone == icaltimezone_get_utc_timezone ()) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); +@@ -4984,7 +4752,6 @@ + icalcomp = icaltimezone_get_component (izone); + if (!icalcomp) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_INVALID_ARG, error); +@@ -4999,7 +4766,6 @@ + GNOME_Evolution_Calendar_Cal_addTimezone (priv->cal, tzobj, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -5011,14 +4777,11 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -5060,8 +4823,6 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (ecal->priv->mutex); + + CORBA_exception_init (&ev); +@@ -5071,7 +4832,6 @@ + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -5083,9 +4843,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + *query = our_op->query; +@@ -5093,7 +4851,6 @@ + bonobo_object_unref (BONOBO_OBJECT (our_op->listener)); + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +@@ -5174,15 +4931,12 @@ + + our_op = e_calendar_new_op (ecal); + +- g_mutex_lock (our_op->mutex); +- + g_mutex_unlock (priv->mutex); + + /* FIXME Adding it to the server to change the tzid */ + icalcomp = icaltimezone_get_component (zone); + if (!icalcomp) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_INVALID_ARG, error); +@@ -5197,7 +4951,6 @@ + GNOME_Evolution_Calendar_Cal_setDefaultTimezone (priv->cal, tzobj, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); +@@ -5209,9 +4962,7 @@ + + CORBA_exception_free (&ev); + +- /* wait for something to happen (both cancellation and a +- successful response will notity us via our cv */ +- g_cond_wait (our_op->cond, our_op->mutex); ++ e_flag_wait (our_op->done); + + status = our_op->status; + +@@ -5223,7 +4974,6 @@ + } + + e_calendar_remove_op (ecal, our_op); +- g_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); diff --git a/evolution-data-server-1.9.92-e-passwords.patch b/evolution-data-server-1.9.92-e-passwords.patch new file mode 100644 index 0000000..3d2bcd7 --- /dev/null +++ b/evolution-data-server-1.9.92-e-passwords.patch @@ -0,0 +1,1880 @@ +--- evolution-data-server-1.9.92/libedataserverui/e-passwords.h.e-passwords 2007-01-03 09:56:25.000000000 -0500 ++++ evolution-data-server-1.9.92/libedataserverui/e-passwords.h 2007-03-08 16:47:27.000000000 -0500 +@@ -28,45 +28,65 @@ + + G_BEGIN_DECLS + +-/* +- initialization is now implicit when you call any of the functions +- below, although this is only correct if the functions are called +- from the main thread. +- +- e_passwords_shutdown should be called at exit time to synch the +- password on-disk storage, and to free up in-memory storage. */ +-void e_passwords_init (void); +- +-void e_passwords_shutdown (void); +-void e_passwords_cancel(void); +-void e_passwords_set_online(int state); +-void e_passwords_remember_password (const char *component, const char *key); +-void e_passwords_add_password (const char *key, const char *passwd); +-char *e_passwords_get_password (const char *component, const char *key); +-void e_passwords_forget_password (const char *component, const char *key); +-void e_passwords_forget_passwords (void); +-void e_passwords_clear_passwords (const char *component); +- ++/** ++ * EPasswordsRememberType: ++ * @E_PASSWORDS_REMEMBER_NEVER: ++ * Do not remember the password. ++ * @E_PASSWORDS_REMEMBER_SESSION: ++ * Remember the password for this session only. ++ * @E_PASSWORDS_REMEMBER_FOREVER: ++ * Remember the password across multiple sessions. ++ * @E_PASSWORDS_REMEMBER_MASK: ++ * Mask value separates the mutually-exclusive values ++ * of the enumeration from the flags. ++ * @E_PASSWORDS_SECRET: ++ * Do not show the password as it's being typed. ++ * @E_PASSWORDS_REPROMPT: ++ * Populate the dialog with the current password (if one exists). ++ * @E_PASSWORDS_ONLINE: ++ * Only prompt the user for a password if we're online. ++ * @E_PASSWORDS_DISABLE_REMEMBER: ++ * Disable the "remember password" option on the dialog. ++ * @E_PASSWORDS_PASSPHRASE: ++ * Ask for a passphrase instead of a password. ++ **/ + typedef enum { + E_PASSWORDS_REMEMBER_NEVER, + E_PASSWORDS_REMEMBER_SESSION, + E_PASSWORDS_REMEMBER_FOREVER, + E_PASSWORDS_REMEMBER_MASK = 0xf, + +- /* option bits */ +- E_PASSWORDS_SECRET = 1<<8, +- E_PASSWORDS_REPROMPT = 1<<9, +- E_PASSWORDS_ONLINE = 1<<10, /* only ask if we're online */ +- E_PASSWORDS_DISABLE_REMEMBER = 1<<11, /* disable the 'remember password' checkbox */ +- E_PASSWORDS_PASSPHRASE = 1<<12, /* We are asking a passphrase */ ++ /* flags */ ++ E_PASSWORDS_SECRET = 1 << 8, ++ E_PASSWORDS_REPROMPT = 1 << 9, ++ E_PASSWORDS_ONLINE = 1 << 10, ++ E_PASSWORDS_DISABLE_REMEMBER = 1 << 11, ++ E_PASSWORDS_PASSPHRASE = 1 << 12, + } EPasswordsRememberType; + +-char * e_passwords_ask_password (const char *title, +- const char*component_name, const char *key, +- const char *prompt, +- EPasswordsRememberType remember_type, +- gboolean *remember, +- GtkWindow *parent); ++#ifndef EDS_DISABLE_DEPRECATED ++void e_passwords_init (void); ++void e_passwords_shutdown (void); ++void e_passwords_cancel (void); ++#endif ++void e_passwords_set_online (gboolean online); ++void e_passwords_remember_password (const gchar *component, ++ const gchar *key); ++void e_passwords_add_password (const gchar *key, ++ const gchar *password); ++gchar * e_passwords_get_password (const gchar *component, ++ const gchar *key); ++void e_passwords_forget_password (const gchar *component, ++ const gchar *key); ++void e_passwords_forget_passwords (void); ++void e_passwords_clear_passwords (const gchar *component); ++gchar * e_passwords_ask_password (const gchar *title, ++ const gchar *component, ++ const gchar *key, ++ const gchar *prompt, ++ EPasswordsRememberType remember_type, ++ gboolean *remember, ++ GtkWindow *parent); + + G_END_DECLS + +--- evolution-data-server-1.9.92/libedataserverui/e-passwords.c.e-passwords 2007-02-09 13:49:32.000000000 -0500 ++++ evolution-data-server-1.9.92/libedataserverui/e-passwords.c 2007-03-08 16:47:27.000000000 -0500 +@@ -23,18 +23,29 @@ + */ + + /* +- * This looks a lot more complicated than it is, and than you'd think +- * it would need to be. There is however, method to the madness. ++ * The threading model was changed in version 1.11. Here's the details. + * +- * The code most cope with being called from any thread at any time, +- * recursively from the main thread, and then serialising every +- * request so that sane and correct values are always returned, and +- * duplicate requests are never made. ++ * We now use a dedicated "dispatcher" thread to process password messages. ++ * The callback functions do not use synchronization guards when accessing ++ * the password store, so those functions must only be called from the ++ * dispatcher thread. + * +- * To this end, every call is marshalled and queued and a dispatch +- * method invoked until that request is satisfied. If mainloop +- * recursion occurs, then the sub-call will necessarily return out of +- * order, but will not be processed out of order. ++ * Message processing behind a visible password dialog is the trickiest ++ * part to get right. We want to, at all costs, avoid repeatedly prompting ++ * the user for the same password. To that end, when the password dialog ++ * for some key 'X' is visible, the dispatcher thread is blocked and ++ * subsequent messages for key 'X' are expedited by redirecting them to a ++ * special "express queue" [1]. ++ * ++ * Once the password dialog is closed, all messages in the express queue ++ * are either (depending on the user's response) cancelled or loaded with ++ * the new password and returned to the sender. The express queue is then ++ * closed so that no new messages can enter, and the dispatcher thread ++ * resumes its normal processing. ++ * ++ * [1] Yes, it's a stupid name, but it's the best I could think of. It's ++ * somewhat analogous to an express lane on a freeway because messages ++ * get through faster. + */ + + #ifdef HAVE_CONFIG_H +@@ -42,159 +53,372 @@ + #endif + + #include +-#include ++#include + #include +-#include +-#include +-#include +-#include +-#include + + #include "e-passwords.h" +-#include "libedataserver/e-msgport.h" ++#include "libedataserver/e-flag.h" + #include "libedataserver/e-url.h" + + #if WITH_GNOME_KEYRING + #include + #endif + +-#ifndef ENABLE_THREADS +-#define ENABLE_THREADS (1) +-#endif +- +-#ifdef ENABLE_THREADS +-#include +- +-static pthread_t main_thread; +-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +-#define LOCK() pthread_mutex_lock(&lock) +-#define UNLOCK() pthread_mutex_unlock(&lock) +-#else +-#define LOCK() +-#define UNLOCK() +-#endif ++#define d(x) + +-#define d(x) x ++typedef struct _EPassMsg EPassMsg; ++typedef struct _EPassDialogData EPassDialogData; ++typedef void (*EPassCallback) (EPassMsg *msg); + + struct _EPassMsg { +- EMsg msg; + +- void (*dispatch)(struct _EPassMsg *); ++ /* The 'expedite' flag indicates that the message ++ * is eligible for entry into the express queue. */ + +- /* input */ +- struct _GtkWindow *parent; +- const char *component; +- const char *key; +- const char *title; +- const char *prompt; +- const char *oldpass; +- guint32 flags; ++ /* dispatching */ ++ EPassCallback callback; ++ gboolean expedite; ++ EFlag *done; ++ ++ /* input/output */ ++ const gchar *component; ++ const gchar *key; ++ gchar *password; ++ gpointer data; ++}; + +- /* output */ +- gboolean *remember; +- char *password; ++struct _EPassDialogData { + +- /* work variables */ +- GtkWidget *entry; +- GtkWidget *check; +- guint ismain:1; +- guint noreply:1; /* supress replies; when calling +- * dispatch functions from others */ ++ /* settings */ ++ GtkWindow *parent; ++ const gchar *title; ++ const gchar *prompt; ++ gint flags; ++ ++ /* input/output */ ++ gboolean remember; ++ gint response; ++ ++ /* synchronization */ ++ EFlag *done; + }; + +-typedef struct _EPassMsg EPassMsg; ++/* Forward Declarations */ ++static void ep_msg_dispatch (EPassMsg *msg); + +-static GHashTable *passwords = NULL; +-static GtkDialog *password_dialog; +-static EDList request_list = E_DLIST_INITIALISER(request_list); +-static int idle_id; +-static int ep_online_state = TRUE; +- +-static char *decode_base64 (char *base64); +-static int base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save); +-static int base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned char *out, int *state, int *save); ++static GThreadPool *dispatcher = NULL; ++static GHashTable *password_cache = NULL; ++static gboolean ep_online_state = TRUE; + +-static gboolean +-ep_idle_dispatch(void *data) ++/* The queue's lock also guards the key. */ ++static const gchar *express_key = NULL; ++static GAsyncQueue *express_queue = NULL; ++ ++#define KEY_FILE_GROUP_PREFIX "Passwords-" ++static GKeyFile *key_file = NULL; ++ ++static gchar * ++ep_key_file_get_filename (void) + { +- EPassMsg *msg; ++ /* XXX It would be nice to someday move this data elsewhere, or else ++ * fully migrate to GNOME Keyring or whatever software supercedes it. ++ * Evolution is one of the few remaining GNOME-2 applications that ++ * still uses the deprecated ~/.gnome2-private directory. */ ++ ++ return g_build_filename (g_get_home_dir (), ++ ".gnome2_private", "Evolution", NULL); ++} + +- /* As soon as a password window is up we stop; it will +- re-invoke us when it has been closed down */ +- LOCK(); +- while (password_dialog == NULL && (msg = (EPassMsg *)e_dlist_remhead(&request_list))) { +- UNLOCK(); ++static gchar * ++ep_key_file_get_group (const gchar *component) ++{ ++ return g_strconcat (KEY_FILE_GROUP_PREFIX, component, NULL); ++} ++ ++static gchar * ++ep_key_file_normalize_key (const gchar *key) ++{ ++ /* XXX Previous code converted all slashes and equal signs in the ++ * key to underscores for use with "gnome-config" functions. While ++ * it may not be necessary to convert slashes for use with GKeyFile, ++ * and an equal sign was most likely never encountered in a key, we ++ * continue to do the same for backward-compatibility. */ ++ ++ gchar *normalized_key, *cp; + +- msg->dispatch(msg); ++ normalized_key = g_strdup (key); ++ for (cp = normalized_key; *cp != '\0'; cp++) ++ if (*cp == '/' || *cp == '=') ++ *cp = '_'; ++ ++ return normalized_key; ++} ++ ++static void ++ep_key_file_load (void) ++{ ++ gchar *filename; ++ GError *error = NULL; + +- LOCK(); ++ filename = ep_key_file_get_filename (); ++ ++ if (!g_file_test (filename, G_FILE_TEST_EXISTS)) ++ goto exit; ++ ++ g_key_file_load_from_file (key_file, filename, ++ G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, ++ &error); ++ ++ if (error != NULL) { ++ g_warning ("%s", error->message); ++ g_error_free (error); + } + +- idle_id = 0; +- UNLOCK(); ++exit: ++ g_free (filename); ++} + +- return FALSE; ++static void ++ep_key_file_save (void) ++{ ++ gchar *contents; ++ gchar *filename; ++ gsize length; ++ GError *error = NULL; ++ ++ filename = ep_key_file_get_filename (); ++ contents = g_key_file_to_data (key_file, &length, NULL); ++ ++ g_file_set_contents (filename, contents, length, &error); ++ ++ if (error != NULL) { ++ g_warning ("%s", error->message); ++ g_error_free (error); ++ } ++ ++ g_free (contents); ++ g_free (filename); + } + +-static EPassMsg * +-ep_msg_new(void (*dispatch)(EPassMsg *)) ++static gchar * ++ep_password_encode (const gchar *password) + { +- EPassMsg *msg; ++ /* XXX The previous Base64 encoding function did not encode the ++ * password's trailing nul byte. This makes decoding the Base64 ++ * string into a nul-terminated password more difficult, but we ++ * continue to do it this way for backward-compatibility. */ ++ ++ gsize length = strlen (password); ++ return g_base64_encode ((const guchar *) password, length); ++} ++ ++static gchar * ++ep_password_decode (const gchar *encoded_password) ++{ ++ /* XXX The previous Base64 encoding function did not encode the ++ * password's trailing nul byte, so we have to append a nul byte ++ * to the decoded data to make it a nul-terminated string. */ ++ ++ gchar *password; ++ gsize length; + +- e_passwords_init(); ++ password = (gchar *) g_base64_decode (encoded_password, &length); ++ password = g_realloc (password, length + 1); ++ password[length] = '\0'; + +- msg = g_malloc0(sizeof(*msg)); +- msg->dispatch = dispatch; +- msg->msg.reply_port = e_msgport_new(); +-#ifdef ENABLE_THREADS +- msg->ismain = pthread_equal(pthread_self(), main_thread); ++ return password; ++} ++ ++static gpointer ++ep_init (gpointer data) ++{ ++ /* Initialize the data structures with unbounded lifetimes. */ ++ ++ dispatcher = g_thread_pool_new ( ++ (GFunc) ep_msg_dispatch, NULL, 1, FALSE, NULL); ++ ++ password_cache = g_hash_table_new_full ( ++ g_str_hash, g_str_equal, g_free, g_free); ++ ++ express_queue = g_async_queue_new (); ++ ++#ifdef WITH_GNOME_KEYRING ++ if (!gnome_keyring_is_available ()) { ++ key_file = g_key_file_new (); ++ ep_key_file_load (); ++ } + #else +- msg->ismain = TRUE; ++ key_file = g_key_file_new (); ++ ep_key_file_load (); + #endif ++ ++ return NULL; ++} ++ ++static EPassMsg * ++ep_msg_new (EPassCallback callback, gboolean expedite) ++{ ++ static GOnce once = G_ONCE_INIT; ++ EPassMsg *msg; ++ ++ g_once (&once, ep_init, NULL); ++ ++ msg = g_slice_new0 (EPassMsg); ++ msg->callback = callback; ++ msg->expedite = expedite; ++ msg->done = e_flag_new (); ++ + return msg; + } + + static void +-ep_msg_free(EPassMsg *msg) ++ep_msg_dispatch (EPassMsg *msg) + { +- e_msgport_destroy(msg->msg.reply_port); +- g_free(msg->password); +- g_free(msg); ++ msg->callback (msg); ++ e_flag_set (msg->done); ++} ++ ++static gboolean ++ep_msg_expedite (EPassMsg *msg) ++{ ++ gboolean success = FALSE; ++ ++ g_async_queue_lock (express_queue); ++ if (express_key != NULL && strcmp (msg->key, express_key) == 0) { ++ g_async_queue_push_unlocked (express_queue, msg); ++ success = TRUE; ++ } ++ g_async_queue_unlock (express_queue); ++ ++ return success; + } + + static void +-ep_msg_send(EPassMsg *msg) ++ep_msg_send (EPassMsg *msg) + { +- int needidle = 0; ++ /* Expedite flag requires a key. */ ++ g_assert (!msg->expedite || msg->key != NULL); + +- LOCK(); +- e_dlist_addtail(&request_list, (EDListNode *)&msg->msg); +- if (!idle_id) { +- if (!msg->ismain) +- idle_id = g_idle_add(ep_idle_dispatch, NULL); ++ if (!(msg->expedite && ep_msg_expedite (msg))) ++ g_thread_pool_push (dispatcher, msg, NULL); ++ ++ e_flag_wait (msg->done); ++} ++ ++static void ++ep_msg_free (EPassMsg *msg) ++{ ++ e_flag_free (msg->done); ++ g_slice_free (EPassMsg, msg); ++} ++ ++static EPassDialogData * ++ep_dialog_data_new (GtkWindow *parent, const gchar *title, ++ const gchar *prompt, gboolean remember, gint flags) ++{ ++ EPassDialogData *data; ++ ++ data = g_slice_new0 (EPassDialogData); ++ data->done = e_flag_new (); ++ ++ data->parent = parent; ++ data->title = title; ++ data->prompt = prompt; ++ data->remember = remember; ++ data->flags = flags; ++ ++ return data; ++} ++ ++static void ++ep_dialog_data_free (EPassDialogData *data) ++{ ++ e_flag_free (data->done); ++ g_slice_free (EPassDialogData, data); ++} ++ ++static gboolean ++ep_dialog_run (EPassMsg *msg) ++{ ++ /* This function must run in the main thread. */ ++ ++ EPassDialogData *data = msg->data; ++ GtkBox *box; ++ GtkWidget *dialog; ++ GtkWidget *entry; ++ GtkWidget *check_button = NULL; ++ gboolean visible; ++ gint remember; ++ ++ visible = !(data->flags & E_PASSWORDS_SECRET); ++ remember = data->flags & E_PASSWORDS_REMEMBER_MASK; ++ ++ /* Create a standard message dialog. */ ++ dialog = gtk_message_dialog_new ( ++ data->parent, 0, GTK_MESSAGE_QUESTION, ++ GTK_BUTTONS_OK_CANCEL, "%s", data->prompt); ++ gtk_window_set_title (GTK_WINDOW (dialog), data->title); ++ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); ++ ++ box = GTK_BOX (GTK_DIALOG (dialog)->vbox); ++ ++ /* Add a GtkEntry for the password. */ ++ entry = gtk_entry_new (); ++ gtk_box_pack_start (box, entry, TRUE, FALSE, 3); ++ gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); ++ gtk_entry_set_visibility (GTK_ENTRY (entry), visible); ++ if (msg->password != NULL) { ++ gtk_entry_set_text (GTK_ENTRY (entry), msg->password); ++ g_free (msg->password); ++ msg->password = NULL; ++ } ++ atk_object_set_description ( ++ gtk_widget_get_accessible (entry), data->prompt); ++ gtk_widget_grab_focus (entry); ++ gtk_widget_show (entry); ++ ++ /* Add a GtkCheckButton for the "remember" option. */ ++ if (remember != E_PASSWORDS_REMEMBER_NEVER) { ++ if (data->flags & E_PASSWORDS_PASSPHRASE) ++ check_button = gtk_check_button_new_with_mnemonic ( ++ (remember == E_PASSWORDS_REMEMBER_FOREVER) ? ++ _("_Remember this passphrase") : ++ _("_Remember this passphrase for the " ++ "remainder of this session")); + else +- needidle = 1; +- } +- UNLOCK(); ++ check_button = gtk_check_button_new_with_mnemonic ( ++ (remember == E_PASSWORDS_REMEMBER_FOREVER) ? ++ _("_Remember this password") : ++ _("_Remember this password for the " ++ "remainder of this session")); ++ gtk_box_pack_start (box, check_button, TRUE, FALSE, 3); ++ gtk_toggle_button_set_active ( ++ GTK_TOGGLE_BUTTON (check_button), data->remember); ++ if (data->flags & E_PASSWORDS_DISABLE_REMEMBER) ++ gtk_widget_set_sensitive (check_button, FALSE); ++ gtk_widget_show (check_button); ++ } ++ ++ /* Run the dialog and collect the results. */ ++ data->response = gtk_dialog_run (GTK_DIALOG (dialog)); ++ msg->password = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); ++ if (check_button != NULL) ++ data->remember = gtk_toggle_button_get_active ( ++ GTK_TOGGLE_BUTTON (check_button)); ++ else ++ data->remember = FALSE; + +- if (msg->ismain) { +- EPassMsg *m; ++ gtk_widget_destroy (dialog); ++ e_flag_set (data->done); + +- if (needidle) +- ep_idle_dispatch(NULL); +- while ((m = (EPassMsg *)e_msgport_get(msg->msg.reply_port)) == NULL) +- g_main_context_iteration(NULL, TRUE); +- g_assert(m == msg); +- } else { +- EMsg *reply_msg = e_msgport_wait(msg->msg.reply_port); +- g_assert(reply_msg == &msg->msg); +- } ++ return FALSE; + } + +-/* the functions that actually do the work */ ++/* The rest of these static functions must run in the dispatcher thread. */ ++ + #if WITH_GNOME_KEYRING + static void +-ep_clear_passwords_keyring(EPassMsg *msg) ++ep_clear_passwords_keyring (EPassMsg *msg) + { + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; +@@ -205,11 +429,8 @@ + + result = gnome_keyring_get_default_keyring_sync (&default_keyring); + if (!default_keyring) { +- if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) { +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); +- return; +- } ++ if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) ++ return; + default_keyring = g_strdup ("default"); + } + +@@ -239,38 +460,44 @@ + } + + g_free (default_keyring); +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); + } + #endif ++ + static void +-ep_clear_passwords_file(EPassMsg *msg) ++ep_clear_passwords_keyfile (EPassMsg *msg) + { +- char *path; +- +- path = g_strdup_printf ("/Evolution/Passwords-%s", msg->component); ++ gchar *group; ++ GError *error = NULL; + +- gnome_config_private_clean_section (path); +- gnome_config_private_sync_file ("/Evolution"); ++ group = ep_key_file_get_group (msg->component); + +- g_free (path); ++ g_key_file_remove_group (key_file, group, &error); ++ if (error == NULL) ++ ep_key_file_save (); ++ else { ++ g_warning ("%s", error->message); ++ g_error_free (error); ++ } + +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++ g_free (group); + } + +-static gboolean +-free_entry (gpointer key, gpointer value, gpointer user_data) ++static void ++ep_clear_passwords (EPassMsg *msg) + { +- g_free (key); +- memset (value, 0, strlen (value)); +- g_free (value); +- return TRUE; ++#if WITH_GNOME_KEYRING ++ if (gnome_keyring_is_available ()) ++ ep_clear_passwords_keyring (msg); ++ else ++ ep_clear_passwords_keyfile (msg); ++#else ++ ep_clear_passwords_keyfile (msg); ++#endif + } + + #if WITH_GNOME_KEYRING + static void +-ep_forget_passwords_keyring(EPassMsg *msg) ++ep_forget_passwords_keyring (EPassMsg *msg) + { + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; +@@ -281,11 +508,8 @@ + + result = gnome_keyring_get_default_keyring_sync (&default_keyring); + if (!default_keyring) { +- if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) { +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); +- return; +- } ++ if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) ++ return; + default_keyring = g_strdup ("default"); + } + d(g_print("Get Default %d\n", result)); +@@ -316,69 +540,54 @@ + g_free (default_keyring); + + /* free up the session passwords */ +- g_hash_table_foreach_remove (passwords, free_entry, NULL); +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++ g_hash_table_remove_all (password_cache); + } + #endif + + static void +-ep_forget_passwords_file(EPassMsg *msg) ++ep_forget_passwords_keyfile (EPassMsg *msg) + { +- void *it; +- char *key; ++ gchar **groups; ++ gsize length, ii; + +- it = gnome_config_private_init_iterator_sections("/Evolution"); +- while ( (it = gnome_config_iterator_next(it, &key, NULL)) ) { +- if (0 == strncmp(key, "Passwords-", 10)) { +- char *section = g_strdup_printf("/Evolution/%s", key); ++ g_hash_table_remove_all (password_cache); + +- gnome_config_private_clean_section (section); +- g_free(section); +- } +- g_free(key); ++ groups = g_key_file_get_groups (key_file, &length); ++ for (ii = 0; ii < length; ii++) { ++ if (!g_str_has_prefix (groups[ii], KEY_FILE_GROUP_PREFIX)) ++ continue; ++ g_key_file_remove_group (key_file, groups[ii], NULL); + } +- +- gnome_config_private_sync_file ("/Evolution"); +- +- /* free up the session passwords */ +- g_hash_table_foreach_remove (passwords, free_entry, NULL); +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++ ep_key_file_save (); ++ g_strfreev (groups); + } + +-static char * +-password_path (const char *component_name, const char *key) ++static void ++ep_forget_passwords (EPassMsg *msg) + { +- char *keycopy, *path; +- int i; +- keycopy = g_strdup (key); +- +- for (i = 0; i < strlen (keycopy); i ++) +- if (keycopy[i] == '/' || keycopy[i] =='=') +- keycopy[i] = '_'; +- +- path = g_strdup_printf ("/Evolution/Passwords-%s/%s", component_name, keycopy); +- +- g_free (keycopy); +- +- return path; ++#if WITH_GNOME_KEYRING ++ if (gnome_keyring_is_available ()) ++ ep_forget_passwords_keyring (msg); ++ else ++ ep_forget_passwords_keyfile (msg); ++#else ++ ep_forget_passwords_keyfile (msg); ++#endif + } + + #if WITH_GNOME_KEYRING + static void +-ep_remember_password_keyring(EPassMsg *msg) ++ep_remember_password_keyring (EPassMsg *msg) + { +- gpointer okey, value; ++ gpointer value; + +- if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) { ++ value = g_hash_table_lookup (password_cache, msg->key); ++ if (value != NULL) { + /* add it to the on-disk cache of passwords */ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + GnomeKeyringResult result; +- EUri *uri = e_uri_new (okey); ++ EUri *uri = e_uri_new (msg->key); + guint32 item_id; + + if (!strcmp (uri->protocol, "ldap") && !uri->user) { +@@ -419,48 +628,48 @@ + + d(g_print("Remember %s: %d/%d\n", msg->key, result, item_id)); + /* now remove it from our session hash */ +- g_hash_table_remove (passwords, msg->key); +- g_free (okey); +- g_free (value); ++ g_hash_table_remove (password_cache, msg->key); + + e_uri_free (uri); + } +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); + } + #endif + + static void +-ep_remember_password_file(EPassMsg *msg) ++ep_remember_password_keyfile (EPassMsg *msg) + { +- gpointer okey, value; +- char *path, *pass64; +- int len, state, save; ++ gchar *group, *key, *password; + +- if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) { +- /* add it to the on-disk cache of passwords */ +- path = password_path (msg->component, okey); ++ password = g_hash_table_lookup (password_cache, msg->key); ++ if (password == NULL) { ++ g_warning ("Password for key \"%s\" not found", msg->key); ++ return; ++ } + +- len = strlen (value); +- pass64 = g_malloc0 ((len + 2) * 4 / 3 + 1); +- state = save = 0; +- base64_encode_close (value, len, FALSE, (guchar *)pass64, &state, &save); +- +- gnome_config_private_set_string (path, pass64); +- g_free (path); +- g_free (pass64); ++ group = ep_key_file_get_group (msg->component); ++ key = ep_key_file_normalize_key (msg->key); ++ password = ep_password_encode (password); ++ ++ g_hash_table_remove (password_cache, msg->key); ++ g_key_file_set_string (key_file, group, key, password); ++ ep_key_file_save (); + +- /* now remove it from our session hash */ +- g_hash_table_remove (passwords, msg->key); +- g_free (okey); +- g_free (value); +- +- gnome_config_private_sync_file ("/Evolution"); +- } ++ g_free (group); ++ g_free (key); ++ g_free (password); ++} + +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++static void ++ep_remember_password (EPassMsg *msg) ++{ ++#if WITH_GNOME_KEYRING ++ if (gnome_keyring_is_available ()) ++ ep_remember_password_keyring (msg); ++ else ++ ep_remember_password_keyfile (msg); ++#else ++ ep_remember_password_keyfile (msg); ++#endif + } + + #if WITH_GNOME_KEYRING +@@ -472,7 +681,6 @@ + GnomeKeyringResult result; + GList *matches = NULL, *tmp; + char *default_keyring = NULL; +- gpointer okey, value; + EUri *uri = e_uri_new (msg->key); + + if (!strcmp (uri->protocol, "ldap") && !uri->user) { +@@ -486,27 +694,17 @@ + uri->user = keycopy; + } + +- if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) { +- g_hash_table_remove (passwords, msg->key); +- memset (value, 0, strlen (value)); +- g_free (okey); +- g_free (value); +- } ++ g_hash_table_remove (password_cache, msg->key); + + if (!uri->host && !uri->user) { + /* No need to remove from keyring for pass phrases */ +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); + return; + } + + result = gnome_keyring_get_default_keyring_sync (&default_keyring); + if (!default_keyring) { +- if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) { +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); +- return; +- } ++ if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) ++ return; + default_keyring = g_strdup ("default"); + } + +@@ -567,35 +765,44 @@ + } + + g_free (default_keyring); +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); + } + #endif + + static void +-ep_forget_password_file (EPassMsg *msg) ++ep_forget_password_keyfile (EPassMsg *msg) + { +- gpointer okey, value; +- char *path; ++ gchar *group, *key; ++ GError *error = NULL; ++ ++ g_hash_table_remove (password_cache, msg->key); + +- if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) { +- g_hash_table_remove (passwords, msg->key); +- memset (value, 0, strlen (value)); +- g_free (okey); +- g_free (value); ++ group = ep_key_file_get_group (msg->component); ++ key = ep_key_file_normalize_key (msg->key); ++ ++ g_key_file_remove_key (key_file, group, key, &error); ++ if (error == NULL) ++ ep_key_file_save (); ++ else { ++ g_warning ("%s", error->message); ++ g_error_free (error); + } + +- /* clear it in the on disk db */ +- path = password_path (msg->component, msg->key); +- gnome_config_private_clean_key (path); +- gnome_config_private_sync_file ("/Evolution"); +- g_free (path); +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++ g_free (group); ++ g_free (key); + } + ++static void ++ep_forget_password (EPassMsg *msg) ++{ ++#if WITH_GNOME_KEYRING ++ if (gnome_keyring_is_available ()) ++ ep_forget_password_keyring (msg); ++ else ++ ep_forget_password_keyfile (msg); ++#else ++ ep_forget_password_keyfile (msg); ++#endif ++} + + #if WITH_GNOME_KEYRING + static void +@@ -605,11 +812,11 @@ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + GnomeKeyringResult result; +- GList *matches = NULL, *tmp; ++ GList *matches = NULL, *tmp; + +- passwd = g_hash_table_lookup (passwords, msg->key); ++ passwd = g_hash_table_lookup (password_cache, msg->key); + if (passwd) { +- msg->password = g_strdup(passwd); ++ msg->password = g_strdup (passwd); + } else { + EUri *uri = e_uri_new (msg->key); + +@@ -683,287 +890,154 @@ + } + + } +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); + } + #endif + + static void +-ep_get_password_file (EPassMsg *msg) ++ep_get_password_keyfile (EPassMsg *msg) + { +- char *path, *passwd; +- char *encoded = NULL; ++ gchar *group, *key, *password; ++ GError *error = NULL; + +- passwd = g_hash_table_lookup (passwords, msg->key); +- if (passwd) { +- msg->password = g_strdup(passwd); +- } else { +- /* not part of the session hash, look it up in the on disk db */ +- path = password_path (msg->component, msg->key); +- encoded = gnome_config_private_get_string_with_default (path, NULL); +- g_free (path); +- if (encoded) { +- msg->password = decode_base64 (encoded); +- g_free (encoded); +- } ++ password = g_hash_table_lookup (password_cache, msg->key); ++ if (password != NULL) { ++ msg->password = g_strdup (password); ++ return; + } + +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); +-} ++ group = ep_key_file_get_group (msg->component); ++ key = ep_key_file_normalize_key (msg->key); + +-static void +-ep_add_password (EPassMsg *msg) +-{ +- gpointer okey, value; +- +- if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) { +- g_hash_table_remove (passwords, msg->key); +- g_free (okey); +- g_free (value); ++ password = g_key_file_get_string (key_file, group, key, &error); ++ if (password != NULL) { ++ msg->password = ep_password_decode (password); ++ g_free (password); ++ } else { ++ g_warning ("%s", error->message); ++ g_error_free (error); + } + +- g_hash_table_insert (passwords, g_strdup (msg->key), g_strdup (msg->oldpass)); +- +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++ g_free (group); ++ g_free (key); + } + +-static void ep_ask_password(EPassMsg *msg); +- + static void +-pass_response(GtkDialog *dialog, int response, void *data) ++ep_get_password (EPassMsg *msg) + { +- EPassMsg *msg = data; +- int type = msg->flags & E_PASSWORDS_REMEMBER_MASK; +- EDList pending = E_DLIST_INITIALISER(pending); +- EPassMsg *mw, *mn; +- +- if (response == GTK_RESPONSE_OK) { +- msg->password = g_strdup(gtk_entry_get_text((GtkEntry *)msg->entry)); +- +- if (type != E_PASSWORDS_REMEMBER_NEVER) { +- int noreply = msg->noreply; +- +- *msg->remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (msg->check)); +- +- msg->noreply = 1; +- +- if (*msg->remember || type == E_PASSWORDS_REMEMBER_FOREVER) { +- msg->oldpass = msg->password; +- ep_add_password(msg); +- } + #if WITH_GNOME_KEYRING +- if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER) { +- if (gnome_keyring_is_available()) +- ep_remember_password_keyring(msg); +- else +- ep_remember_password_file(msg); +- } ++ if (gnome_keyring_is_available ()) ++ ep_get_password_keyring (msg); ++ else ++ ep_get_password_keyfile (msg); + #else +- if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER) +- ep_remember_password_file(msg); +-#endif +- +- msg->noreply = noreply; +- } +- } +- +- gtk_widget_destroy((GtkWidget *)dialog); +- password_dialog = NULL; +- +- /* ok, here things get interesting, we suck up any pending +- * operations on this specific password, and return the same +- * result or ignore other operations */ +- +- LOCK(); +- mw = (EPassMsg *)request_list.head; +- mn = (EPassMsg *)mw->msg.ln.next; +- while (mn) { +-#if WITH_GNOME_KEYRING +- if ((mw->dispatch == (gnome_keyring_is_available() ? ep_forget_password_keyring : ep_forget_password_file) +-#else +- if ((mw->dispatch == ep_forget_password_file ++ ep_get_password_keyfile (msg); + #endif +-#if WITH_GNOME_KEYRING +- || mw->dispatch == (gnome_keyring_is_available() ? ep_get_password_keyring : ep_get_password_file) +-#else +- || mw->dispatch == ep_get_password_file +-#endif +- || mw->dispatch == ep_ask_password) +- && (strcmp(mw->component, msg->component) == 0 +- && strcmp(mw->key, msg->key) == 0)) { +- e_dlist_remove((EDListNode *)mw); +- mw->password = g_strdup(msg->password); +- e_msgport_reply(&mw->msg); +- } +- mw = mn; +- mn = (EPassMsg *)mn->msg.ln.next; +- } +- UNLOCK(); ++} + +- if (!msg->noreply) +- e_msgport_reply(&msg->msg); ++static void ++ep_add_password (EPassMsg *msg) ++{ ++ gchar *key = g_strdup (msg->key); ++ gchar *password = g_strdup (msg->password); + +- ep_idle_dispatch(NULL); ++ g_hash_table_insert (password_cache, key, password); + } + + static void +-ep_ask_password(EPassMsg *msg) ++ep_ask_password (EPassMsg *msg) + { +- GtkWidget *vbox; +- int type = msg->flags & E_PASSWORDS_REMEMBER_MASK; +- guint noreply = msg->noreply; +- AtkObject *a11y; ++ EPassDialogData *data = msg->data; ++ gchar *password; ++ gint remember; ++ ++ /* Open the express queue for this key. This allows us to catch ++ * incoming operations on this key while waiting for the user to ++ * provide a password. Once we have the password, immediately ++ * process any messages in the express queue. */ ++ g_async_queue_lock (express_queue); ++ express_key = msg->key; ++ g_async_queue_unlock (express_queue); ++ ++ if (data->flags & E_PASSWORDS_REPROMPT) ++ ep_get_password (msg); ++ ++ /* Run the password dialog in the main thread. */ ++ g_idle_add ((GSourceFunc) ep_dialog_run, msg); ++ ++ /* Wait for the user to respond. */ ++ e_flag_wait (data->done); ++ ++ /* If the user cancelled the dialog then we need to dispatch ++ * any messages that we trapped in the express queue. */ ++ if (data->response != GTK_RESPONSE_OK) { ++ g_async_queue_lock (express_queue); ++ express_key = NULL; ++ while ((msg = g_async_queue_try_pop_unlocked (express_queue))) ++ ep_msg_dispatch (msg); ++ g_async_queue_unlock (express_queue); ++ return; ++ } + +- msg->noreply = 1; ++ remember = data->flags & E_PASSWORDS_REMEMBER_MASK; + +- /*password_dialog = (GtkDialog *)e_error_new(msg->parent, "mail:ask-session-password", msg->prompt, NULL);*/ +- password_dialog = (GtkDialog *)gtk_message_dialog_new (msg->parent, +- 0, +- GTK_MESSAGE_QUESTION, +- GTK_BUTTONS_OK_CANCEL, +- "%s", msg->prompt); +- gtk_window_set_title(GTK_WINDOW(password_dialog), msg->title); ++ if (remember == E_PASSWORDS_REMEMBER_NEVER) ++ goto cleanup; + +- gtk_widget_ensure_style (GTK_WIDGET (password_dialog)); +- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (password_dialog)->vbox), 0); +- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (password_dialog)->action_area), 12); ++ if (data->remember || remember == E_PASSWORDS_REMEMBER_FOREVER) ++ ep_add_password (msg); + +-#if !GTK_CHECK_VERSION (2,4,0) +- gtk_dialog_set_has_separator(password_dialog, FALSE); +-#endif +- gtk_dialog_set_default_response(password_dialog, GTK_RESPONSE_OK); ++ if (data->remember && remember == E_PASSWORDS_REMEMBER_FOREVER) ++ ep_remember_password (msg); + +- vbox = gtk_vbox_new (FALSE, 12); +- gtk_widget_show (vbox); +- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (password_dialog)->vbox), vbox, TRUE, FALSE, 0); +- gtk_container_set_border_width((GtkContainer *)vbox, 12); +- +- msg->entry = gtk_entry_new (); ++cleanup: + +- a11y = gtk_widget_get_accessible (msg->entry); +- atk_object_set_description (a11y, msg->prompt); +- gtk_entry_set_visibility ((GtkEntry *)msg->entry, !(msg->flags & E_PASSWORDS_SECRET)); +- gtk_entry_set_activates_default((GtkEntry *)msg->entry, TRUE); +- gtk_box_pack_start (GTK_BOX (vbox), msg->entry, TRUE, FALSE, 3); +- gtk_widget_show (msg->entry); +- gtk_widget_grab_focus (msg->entry); +- +- if ((msg->flags & E_PASSWORDS_REPROMPT)) { +-#if WITH_GNOME_KEYRING +- if (gnome_keyring_is_available()) +- ep_get_password_keyring(msg); +- else +- ep_get_password_file(msg); +-#else +- ep_get_password_file(msg); +-#endif +- if (msg->password) { +- gtk_entry_set_text ((GtkEntry *) msg->entry, msg->password); +- g_free (msg->password); +- msg->password = NULL; +- } +- } ++ password = g_strdup (msg->password); + +- /* static password, shouldn't be remembered between sessions, +- but will be remembered within the session beyond our control */ +- if (type != E_PASSWORDS_REMEMBER_NEVER) { +- if (msg->flags & E_PASSWORDS_PASSPHRASE) { +- msg->check = gtk_check_button_new_with_mnemonic(type == E_PASSWORDS_REMEMBER_FOREVER +- ? _("_Remember this passphrase") +- : _("_Remember this passphrase for the remainder of this session")); +- } else { +- msg->check = gtk_check_button_new_with_mnemonic(type == E_PASSWORDS_REMEMBER_FOREVER +- ? _("_Remember this password") +- : _("_Remember this password for the remainder of this session")); +- +- } +- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (msg->check), *msg->remember); +- gtk_box_pack_start (GTK_BOX (vbox), msg->check, TRUE, FALSE, 3); +- if ((msg->flags & E_PASSWORDS_DISABLE_REMEMBER)) +- gtk_widget_set_sensitive(msg->check, FALSE); +- gtk_widget_show (msg->check); ++ /* Close the express queue and process any messages there. */ ++ g_async_queue_lock (express_queue); ++ express_key = NULL; ++ while ((msg = g_async_queue_try_pop_unlocked (express_queue))) { ++ msg->password = g_strdup (password); ++ e_flag_set (msg->done); + } +- +- msg->noreply = noreply; ++ g_async_queue_unlock (express_queue); + +- g_signal_connect(password_dialog, "response", G_CALLBACK (pass_response), msg); +- gtk_widget_show((GtkWidget *)password_dialog); ++ g_free (password); + } + +- + /** + * e_passwords_init: + * +- * Initializes the e_passwords routines. Must be called before any other +- * e_passwords_* function. ++ * This function is here for backward-compatibility. It does nothing. + **/ + void + e_passwords_init (void) + { +- LOCK(); +- +- if (!passwords) { +- /* create the per-session hash table */ +- passwords = g_hash_table_new (g_str_hash, g_str_equal); +-#ifdef ENABLE_THREADS +- main_thread = pthread_self(); +-#endif +- } +- +- UNLOCK(); + } + + /** +- * e_passwords_cancel: +- * +- * Cancel any outstanding password operations and close any dialogues +- * currently being shown. ++ * e_passwords_shutdown: ++ * ++ * This function is here for backward-compatibility. It does nothing. + **/ + void +-e_passwords_cancel(void) ++e_passwords_shutdown (void) + { +- EPassMsg *msg; +- +- LOCK(); +- while ((msg = (EPassMsg *)e_dlist_remhead(&request_list))) +- e_msgport_reply(&msg->msg); +- UNLOCK(); +- +- if (password_dialog) +- gtk_dialog_response(password_dialog,GTK_RESPONSE_CANCEL); + } + + /** +- * e_passwords_shutdown: +- * +- * Cleanup routine to call before exiting. ++ * e_passwords_cancel: ++ * ++ * This function is here for backward-compatibility. It does nothing. + **/ + void +-e_passwords_shutdown (void) ++e_passwords_cancel(void) + { +-#ifdef WITH_GNOME_KEYRING +- /* shouldn't need this really - everything is synchronous */ +- if (!gnome_keyring_is_available()) +- gnome_config_private_sync_file ("/Evolution"); +-#else +- gnome_config_private_sync_file ("/Evolution"); +-#endif +- e_passwords_cancel(); +- +- if (passwords) { +- /* and destroy our per session hash */ +- g_hash_table_foreach_remove (passwords, free_entry, NULL); +- g_hash_table_destroy (passwords); +- passwords = NULL; +- } + } + + /** + * e_passwords_set_online: +- * @state: ++ * @online: + * + * Set the offline-state of the application. This is a work-around + * for having the backends fully offline aware, and returns a +@@ -972,10 +1046,11 @@ + * FIXME: This is not a permanent api, review post 2.0. + **/ + void +-e_passwords_set_online(int state) ++e_passwords_set_online (gboolean online) + { +- ep_online_state = state; +- /* TODO: we could check that a request is open and close it, or maybe who cares */ ++ /* TODO We could check that a request is open and close it, ++ * or maybe who cares */ ++ ep_online_state = online; + } + + /** +@@ -986,150 +1061,137 @@ + void + e_passwords_forget_passwords (void) + { +-#if WITH_GNOME_KEYRING +- EPassMsg *msg = ep_msg_new(gnome_keyring_is_available() ? ep_forget_passwords_keyring : ep_forget_passwords_file); +-#else +- EPassMsg *msg = ep_msg_new(ep_forget_passwords_file); +-#endif +- +- ep_msg_send(msg); +- ep_msg_free(msg); ++ EPassMsg *msg; ++ ++ msg = ep_msg_new (ep_forget_passwords, FALSE); ++ ++ ep_msg_send (msg); ++ ep_msg_free (msg); + } + + /** + * e_passwords_clear_passwords: ++ * @component: component name of the caller + * + * Forgets all disk cached passwords for the component. + **/ + void +-e_passwords_clear_passwords (const char *component_name) ++e_passwords_clear_passwords (const gchar *component) + { +-#if WITH_GNOME_KEYRING +- EPassMsg *msg = ep_msg_new(gnome_keyring_is_available() ? ep_clear_passwords_keyring : ep_clear_passwords_file); +-#else +- EPassMsg *msg = ep_msg_new(ep_clear_passwords_file); +-#endif ++ EPassMsg *msg; ++ ++ g_return_if_fail (component != NULL); + +- msg->component = component_name; +- ep_msg_send(msg); +- ep_msg_free(msg); ++ msg = ep_msg_new (ep_clear_passwords, FALSE); ++ msg->component = component; ++ ++ ep_msg_send (msg); ++ ep_msg_free (msg); + } + + /** + * e_passwords_remember_password: ++ * @component: component name of the caller + * @key: the key + * + * Saves the password associated with @key to disk. + **/ + void +-e_passwords_remember_password (const char *component_name, const char *key) ++e_passwords_remember_password (const gchar *component, const gchar *key) + { + EPassMsg *msg; + +- g_return_if_fail(component_name != NULL); +- g_return_if_fail(key != NULL); ++ g_return_if_fail (component != NULL); ++ g_return_if_fail (key != NULL); + +-#if WITH_GNOME_KEYRING +- msg = ep_msg_new(gnome_keyring_is_available() ? ep_remember_password_keyring : ep_remember_password_file); +-#else +- msg = ep_msg_new(ep_remember_password_file); +-#endif +- msg->component = component_name; ++ msg = ep_msg_new (ep_remember_password, FALSE); ++ msg->component = component; + msg->key = key; + +- ep_msg_send(msg); +- ep_msg_free(msg); ++ ep_msg_send (msg); ++ ep_msg_free (msg); + } + + /** + * e_passwords_forget_password: ++ * @component: component name of the caller + * @key: the key + * + * Forgets the password associated with @key, in memory and on disk. + **/ + void +-e_passwords_forget_password (const char *component_name, const char *key) ++e_passwords_forget_password (const gchar *component, const gchar *key) + { + EPassMsg *msg; + +- g_return_if_fail(component_name != NULL); +- g_return_if_fail(key != NULL); ++ g_return_if_fail (component != NULL); ++ g_return_if_fail (key != NULL); + +-#if WITH_GNOME_KEYRING +- msg = ep_msg_new(gnome_keyring_is_available() ? ep_forget_password_keyring : ep_forget_password_file); +-#else +- msg = ep_msg_new(ep_forget_password_file); +-#endif +- msg->component = component_name; ++ msg = ep_msg_new (ep_forget_password, TRUE); ++ msg->component = component; + msg->key = key; + +- ep_msg_send(msg); +- ep_msg_free(msg); ++ ep_msg_send (msg); ++ ep_msg_free (msg); + } + + /** + * e_passwords_get_password: ++ * @component: component name of the caller + * @key: the key + * + * Return value: the password associated with @key, or %NULL. Caller + * must free the returned password. + **/ + char * +-e_passwords_get_password (const char *component_name, const char *key) ++e_passwords_get_password (const gchar *component, const gchar *key) + { + EPassMsg *msg; +- char *passwd; +- +- g_return_val_if_fail(component_name != NULL, NULL); +- g_return_val_if_fail(key != NULL, NULL); ++ char *password; + +-#if WITH_GNOME_KEYRING +- msg = ep_msg_new(gnome_keyring_is_available() ? ep_get_password_keyring : ep_get_password_file); +-#else +- msg = ep_msg_new(ep_get_password_file); +-#endif ++ g_return_val_if_fail (component != NULL, NULL); ++ g_return_val_if_fail (key != NULL, NULL); + +- msg->component = component_name; ++ msg = ep_msg_new (ep_get_password, TRUE); ++ msg->component = component; + msg->key = key; + +- ep_msg_send(msg); ++ ep_msg_send (msg); ++ password = msg->password; ++ ep_msg_free (msg); + +- passwd = msg->password; +- msg->password = NULL; +- ep_msg_free(msg); +- +- return passwd; ++ return password; + } + + /** + * e_passwords_add_password: + * @key: a key +- * @passwd: the password for @key ++ * @password: the password for @key + * + * This stores the @key/@passwd pair in the current session's password + * hash. + **/ + void +-e_passwords_add_password (const char *key, const char *passwd) ++e_passwords_add_password (const gchar *key, const gchar *password) + { + EPassMsg *msg; + +- g_return_if_fail(key != NULL); +- g_return_if_fail(passwd != NULL); ++ g_return_if_fail (key != NULL); ++ g_return_if_fail (password != NULL); + +- msg = ep_msg_new(ep_add_password); ++ msg = ep_msg_new (ep_add_password, FALSE); + msg->key = key; +- msg->oldpass = passwd; ++ msg->password = g_strdup (password); + +- ep_msg_send(msg); +- ep_msg_free(msg); ++ ep_msg_send (msg); ++ g_free (msg->password); ++ ep_msg_free (msg); + } + + /** + * e_passwords_ask_password: + * @title: title for the password dialog +- * @component_name: the name of the component for which we're storing +- * the password (e.g. Mail, Addressbook, etc.) ++ * @component: component name of the caller + * @key: key to store the password under + * @prompt: prompt string + * @secret: whether or not the password text should be ***ed out +@@ -1146,241 +1208,45 @@ + * return value is non-%NULL and @remember_type is not + * E_PASSWORDS_DO_NOT_REMEMBER. + **/ +-char * +-e_passwords_ask_password (const char *title, const char *component_name, +- const char *key, +- const char *prompt, ++gchar * ++e_passwords_ask_password (const gchar *title, ++ const gchar *component, ++ const gchar *key, ++ const gchar *prompt, + EPasswordsRememberType type, +- gboolean *remember, ++ gboolean *p_remember, + GtkWindow *parent) + { +- char *passwd; +- EPassMsg *msg = ep_msg_new(ep_ask_password); ++ EPassMsg *msg; ++ EPassDialogData *data; ++ gboolean remember; ++ gchar *password; ++ ++ g_return_val_if_fail (title != NULL, NULL); ++ g_return_val_if_fail (component != NULL, NULL); ++ g_return_val_if_fail (key != NULL, NULL); ++ g_return_val_if_fail (prompt != NULL, NULL); + + if ((type & E_PASSWORDS_ONLINE) && !ep_online_state) + return NULL; + +- msg->title = title; +- msg->component = component_name; +- msg->key = key; +- msg->prompt = prompt; +- msg->flags = type; +- msg->remember = remember; +- msg->parent = parent; +- +- ep_msg_send(msg); +- passwd = msg->password; +- msg->password = NULL; +- ep_msg_free(msg); +- +- return passwd; +-} +- +- +- +-static char *base64_alphabet = +-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +- +-static unsigned char camel_mime_base64_rank[256] = { +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, +- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, +- 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, +- 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +-}; +- +-/* call this when finished encoding everything, to +- flush off the last little bit */ +-static int +-base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save) +-{ +- int c1, c2; +- unsigned char *outptr = out; +- +- if (inlen>0) +- outptr += base64_encode_step(in, inlen, break_lines, outptr, state, save); ++ remember = (p_remember != NULL) ? *p_remember : FALSE; ++ data = ep_dialog_data_new (parent, title, prompt, remember, type); + +- c1 = ((unsigned char *)save)[1]; +- c2 = ((unsigned char *)save)[2]; +- +- switch (((char *)save)[0]) { +- case 2: +- outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ]; +- g_assert(outptr[2] != 0); +- goto skip; +- case 1: +- outptr[2] = '='; +- skip: +- outptr[0] = base64_alphabet[ c1 >> 2 ]; +- outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )]; +- outptr[3] = '='; +- outptr += 4; +- break; +- } +- if (break_lines) +- *outptr++ = '\n'; +- +- *save = 0; +- *state = 0; +- +- return outptr-out; +-} +- +-/* +- performs an 'encode step', only encodes blocks of 3 characters to the +- output at a time, saves left-over state in state and save (initialise to +- 0 on first invocation). +-*/ +-static int +-base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned char *out, int *state, int *save) +-{ +- register unsigned char *inptr, *outptr; +- +- if (len<=0) +- return 0; +- +- inptr = in; +- outptr = out; +- +- if (len + ((char *)save)[0] > 2) { +- unsigned char *inend = in+len-2; +- register int c1, c2, c3; +- register int already; +- +- already = *state; +- +- switch (((char *)save)[0]) { +- case 1: c1 = ((unsigned char *)save)[1]; goto skip1; +- case 2: c1 = ((unsigned char *)save)[1]; +- c2 = ((unsigned char *)save)[2]; goto skip2; +- } +- +- /* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */ +- while (inptr < inend) { +- c1 = *inptr++; +- skip1: +- c2 = *inptr++; +- skip2: +- c3 = *inptr++; +- *outptr++ = base64_alphabet[ c1 >> 2 ]; +- *outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ]; +- *outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ]; +- *outptr++ = base64_alphabet[ c3 & 0x3f ]; +- /* this is a bit ugly ... */ +- if (break_lines && (++already)>=19) { +- *outptr++='\n'; +- already = 0; +- } +- } +- +- ((char *)save)[0] = 0; +- len = 2-(inptr-inend); +- *state = already; +- } +- +- if (len>0) { +- register char *saveout; +- +- /* points to the slot for the next char to save */ +- saveout = & (((char *)save)[1]) + ((char *)save)[0]; +- +- /* len can only be 0 1 or 2 */ +- switch(len) { +- case 2: *saveout++ = *inptr++; +- case 1: *saveout++ = *inptr++; +- } +- ((char *)save)[0]+=len; +- } +- +- return outptr-out; +-} +- +- +-/** +- * base64_decode_step: decode a chunk of base64 encoded data +- * @in: input stream +- * @len: max length of data to decode +- * @out: output stream +- * @state: holds the number of bits that are stored in @save +- * @save: leftover bits that have not yet been decoded +- * +- * Decodes a chunk of base64 encoded data +- **/ +-static int +-base64_decode_step(unsigned char *in, int len, unsigned char *out, int *state, unsigned int *save) +-{ +- register unsigned char *inptr, *outptr; +- unsigned char *inend, c; +- register unsigned int v; +- int i; +- +- inend = in+len; +- outptr = out; +- +- /* convert 4 base64 bytes to 3 normal bytes */ +- v=*save; +- i=*state; +- inptr = in; +- while (inptr>16; +- *outptr++ = v>>8; +- *outptr++ = v; +- i=0; +- } +- } +- } ++ msg = ep_msg_new (ep_ask_password, TRUE); ++ msg->component = component; ++ msg->key = key; ++ msg->data = data; + +- *save = v; +- *state = i; ++ ep_msg_send (msg); ++ password = msg->password; ++ remember = data->remember; ++ ep_msg_free (msg); + +- /* quick scan back for '=' on the end somewhere */ +- /* fortunately we can drop 1 output char for each trailing = (upto 2) */ +- i=2; +- while (inptr>in && i) { +- inptr--; +- if (camel_mime_base64_rank[*inptr] != 0xff) { +- if (*inptr == '=') +- outptr--; +- i--; +- } +- } ++ ep_dialog_data_free (data); + +- /* if i!= 0 then there is a truncation error! */ +- return outptr-out; +-} ++ if (p_remember != NULL) ++ *p_remember = remember; + +-static char * +-decode_base64 (char *base64) +-{ +- guchar *plain; +- char *pad = "=="; +- int len, out, state; +- unsigned int save; +- +- len = strlen (base64); +- plain = g_malloc0 (len); +- state = save = 0; +- out = base64_decode_step ((guchar *)base64, len, plain, &state, &save); +- if (len % 4) { +- base64_decode_step ((guchar *)pad, 4 - len % 4, plain + out, +- &state, &save); +- } +- +- return (char *)plain; ++ return password; + } +--- evolution-data-server-1.9.92/libedataserver/e-msgport.h.e-passwords 2007-02-26 01:52:22.000000000 -0500 ++++ evolution-data-server-1.9.92/libedataserver/e-msgport.h 2007-03-08 16:47:27.000000000 -0500 +@@ -54,7 +54,7 @@ + + /* header for any message */ + typedef struct _EMsg { +- EDListNode ln; ++ EDListNode ln; /* deprecated */ + EMsgPort *reply_port; + gint flags; + } EMsg; diff --git a/evolution-data-server.spec b/evolution-data-server.spec index 1847022..a6118d3 100644 --- a/evolution-data-server.spec +++ b/evolution-data-server.spec @@ -26,7 +26,7 @@ Name: evolution-data-server Version: 1.9.92 -Release: 2%{?dist} +Release: 3%{?dist} License: LGPL Group: System Environment/Libraries Summary: Backend data server for Evolution @@ -72,6 +72,12 @@ Patch23: evolution-data-server-1.9.3-e-source-color.patch # GNOME bug #301363 Patch24: evolution-data-server-1.9.92-updated-zoneinfo.patch +# GNOME bug #415891 +Patch25: evolution-data-server-1.9.92-e-flag.patch + +# GNOME bug #376991 +Patch26: evolution-data-server-1.9.92-e-passwords.patch + ### Dependencies ### Requires: GConf2 @@ -164,6 +170,8 @@ evolution-data-server. %patch22 -p1 -b .strftime %patch23 -p1 -b .e-source-color %patch24 -p1 -b .updated-zoneinfo +%patch25 -p1 -b .e-flag +%patch26 -p1 -b .e-passwords mkdir -p krb5-fakeprefix/include mkdir -p krb5-fakeprefix/lib @@ -372,6 +380,10 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/pkgconfig/libexchange-storage-%{eds_api_version}.pc %changelog +* Thu Mar 08 2007 Matthew Barnes - 1.9.92-3.fc7 +- Add patch for GNOME bug #415891 (introduce EFlag API). +- Add patch for GNOME bug #376991 (refactor password handling). + * Tue Mar 06 2007 Matthew Barnes - 1.9.92-2.fc7 - Add patch for GNOME bug #301363 (update timezones).