evolution-data-server r8728 - in branches/camel-db-summary: . camel camel/providers/imap libedataserver libedataserverui po



Author: sragavan
Date: Mon May  5 03:19:52 2008
New Revision: 8728
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=8728&view=rev

Log:
Merge branch 'master' into new_summary


Modified:
   branches/camel-db-summary/ChangeLog
   branches/camel-db-summary/camel/ChangeLog
   branches/camel-db-summary/camel/camel-folder-summary.c
   branches/camel-db-summary/camel/camel-session.c
   branches/camel-db-summary/camel/camel-session.h
   branches/camel-db-summary/camel/providers/imap/ChangeLog
   branches/camel-db-summary/camel/providers/imap/camel-imap-folder.c
   branches/camel-db-summary/configure.in
   branches/camel-db-summary/libedataserver/e-categories.c
   branches/camel-db-summary/libedataserver/e-categories.h
   branches/camel-db-summary/libedataserverui/ChangeLog
   branches/camel-db-summary/libedataserverui/e-passwords.c
   branches/camel-db-summary/po/ChangeLog
   branches/camel-db-summary/po/he.po

Modified: branches/camel-db-summary/camel/camel-folder-summary.c
==============================================================================
--- branches/camel-db-summary/camel/camel-folder-summary.c	(original)
+++ branches/camel-db-summary/camel/camel-folder-summary.c	Mon May  5 03:19:52 2008
@@ -527,7 +527,7 @@
 	if (ci == NULL)
 		return NULL;
 
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) {
+	if (camel_file_util_decode_uint32(in, &count) == -1) {
 		camel_folder_summary_content_info_free (s, ci);
 		return NULL;
 	}
@@ -1872,7 +1872,7 @@
 	camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.hi);
 	camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.lo);
 
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
+	if (camel_file_util_decode_uint32(in, &count) == -1)
 		goto error;
 
 	if (count > 0) {
@@ -1884,7 +1884,7 @@
 		}
 	}
 
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
+	if (camel_file_util_decode_uint32(in, &count) == -1)
 		goto error;
 
 	for (i=0;i<count;i++) {
@@ -1895,7 +1895,7 @@
 		g_free(name);
 	}
 
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
+	if (camel_file_util_decode_uint32(in, &count) == -1)
 		goto error;
 
 	for (i=0;i<count;i++) {
@@ -2049,7 +2049,8 @@
 	ct = camel_content_type_new(type, subtype);
 	g_free(type);		/* can this be removed? */
 	g_free(subtype);
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
+	
+	if (camel_file_util_decode_uint32(in, &count) == -1)
 		goto error;
 
 	for (i = 0; i < count; i++) {

Modified: branches/camel-db-summary/camel/camel-session.c
==============================================================================
--- branches/camel-db-summary/camel/camel-session.c	(original)
+++ branches/camel-db-summary/camel/camel-session.c	Mon May  5 03:19:52 2008
@@ -536,12 +536,13 @@
 	CS_CLASS(m->session)->thread_status(m->session, m, what, pc);
 }
 
-static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size)
+static void *
+session_thread_msg_new (CamelSession *session,
+                        CamelSessionThreadOps *ops,
+                        unsigned int size)
 {
 	CamelSessionThreadMsg *m;
 
-	g_assert(size >= sizeof(*m));
-
 	m = g_malloc0(size);
 	m->ops = ops;
 	m->session = session;
@@ -556,9 +557,12 @@
 	return m;
 }
 
-static void session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg)
+static void
+session_thread_msg_free (CamelSession *session,
+                         CamelSessionThreadMsg *msg)
 {
-	g_assert(msg->ops != NULL);
+	g_return_if_fail (CAMEL_IS_SESSION (session));
+	g_return_if_fail (msg != NULL && msg->ops != NULL);
 
 	d(printf("free message %p session %p\n", msg, session));
 
@@ -578,7 +582,8 @@
 }
 
 static void
-session_thread_proxy(CamelSessionThreadMsg *msg, CamelSession *session)
+session_thread_proxy (CamelSessionThreadMsg *msg,
+                      CamelSession *session)
 {
 	if (msg->ops->receive) {
 		CamelOperation *oldop;
@@ -591,7 +596,10 @@
 	camel_session_thread_msg_free(session, msg);
 }
 
-static int session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags)
+static int
+session_thread_queue (CamelSession *session,
+                      CamelSessionThreadMsg *msg,
+                      int flags)
 {
 	GThreadPool *thread_pool;
 	int id;
@@ -612,7 +620,9 @@
 	return id;
 }
 
-static void session_thread_wait(CamelSession *session, int id)
+static void
+session_thread_wait (CamelSession *session,
+                     int id)
 {
 	int wait;
 
@@ -627,7 +637,11 @@
 	} while (wait);
 }
 
-static void session_thread_status(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc)
+static void
+session_thread_status (CamelSession *session,
+                       CamelSessionThreadMsg *msg,
+                       const char *text,
+                       int pc)
 {
 }
 
@@ -646,13 +660,15 @@
  * Returns a new #CamelSessionThreadMsg
  **/
 void *
-camel_session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size)
-{
-	g_assert(CAMEL_IS_SESSION(session));
-	g_assert(ops != NULL);
-	g_assert(size >= sizeof(CamelSessionThreadMsg));
+camel_session_thread_msg_new (CamelSession *session,
+                              CamelSessionThreadOps *ops,
+                              unsigned int size)
+{
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+	g_return_val_if_fail (ops != NULL, NULL);
+	g_return_val_if_fail (size >= sizeof (CamelSessionThreadMsg), NULL);
 
-	return CS_CLASS (session)->thread_msg_new(session, ops, size);
+	return CS_CLASS (session)->thread_msg_new (session, ops, size);
 }
 
 /**
@@ -664,13 +680,13 @@
  * msg_new, and must nto have been submitted to any queue function.
  **/
 void
-camel_session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg)
+camel_session_thread_msg_free (CamelSession *session,
+                               CamelSessionThreadMsg *msg)
 {
-	g_assert(CAMEL_IS_SESSION(session));
-	g_assert(msg != NULL);
-	g_assert(msg->ops != NULL);
+	g_return_if_fail (CAMEL_IS_SESSION (session));
+	g_return_if_fail (msg != NULL && msg->ops != NULL);
 
-	CS_CLASS (session)->thread_msg_free(session, msg);
+	CS_CLASS (session)->thread_msg_free (session, msg);
 }
 
 /**
@@ -686,12 +702,14 @@
  * Returns the id of the operation queued
  **/
 int
-camel_session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags)
+camel_session_thread_queue (CamelSession *session,
+                            CamelSessionThreadMsg *msg,
+                            int flags)
 {
-	g_assert(CAMEL_IS_SESSION(session));
-	g_assert(msg != NULL);
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), -1);
+	g_return_val_if_fail (msg != NULL, -1);
 
-	return CS_CLASS (session)->thread_queue(session, msg, flags);
+	return CS_CLASS (session)->thread_queue (session, msg, flags);
 }
 
 /**
@@ -702,14 +720,15 @@
  * Wait on an operation to complete (by id).
  **/
 void
-camel_session_thread_wait(CamelSession *session, int id)
+camel_session_thread_wait (CamelSession *session,
+                           int id)
 {
-	g_assert(CAMEL_IS_SESSION(session));
+	g_return_if_fail (CAMEL_IS_SESSION (session));
 
 	if (id == -1)
 		return;
 
-	CS_CLASS (session)->thread_wait(session, id);
+	CS_CLASS (session)->thread_wait (session, id);
 }
 
 /**
@@ -723,7 +742,7 @@
 gboolean
 camel_session_check_junk (CamelSession *session)
 {
-	g_assert(CAMEL_IS_SESSION(session));
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
 
 	return session->check_junk;
 }
@@ -736,9 +755,10 @@
  * Set check_junk flag, if set, incoming mail will be checked for being junk.
  **/
 void
-camel_session_set_check_junk (CamelSession *session, gboolean check_junk)
+camel_session_set_check_junk (CamelSession *session,
+                              gboolean check_junk)
 {
-	g_assert(CAMEL_IS_SESSION(session));
+	g_return_if_fail (CAMEL_IS_SESSION (session));
 
 	session->check_junk = check_junk;
 }
@@ -746,24 +766,30 @@
 gboolean
 camel_session_get_network_state (CamelSession *session)
 {
-	g_return_val_if_fail (CAMEL_IS_SESSION(session), FALSE);
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
 
 	return session->network_state;
 }
 
 void
-camel_session_set_network_state (CamelSession *session, gboolean network_state)
+camel_session_set_network_state (CamelSession *session,
+                                 gboolean network_state)
 {
-	g_return_if_fail (CAMEL_IS_SESSION(session));
+	g_return_if_fail (CAMEL_IS_SESSION (session));
 
 	session->network_state = network_state;
 }
 
 void
-camel_session_set_junk_headers (CamelSession *session, const char **headers, const char **values, int len)
+camel_session_set_junk_headers (CamelSession *session,
+                                const char **headers,
+                                const char **values,
+                                int len)
 {
 	int i;
 
+	g_return_if_fail (CAMEL_IS_SESSION (session));
+
 	if (session->priv->junk_headers) {
 		g_hash_table_remove_all (session->priv->junk_headers);
 		g_hash_table_destroy (session->priv->junk_headers);
@@ -779,5 +805,7 @@
 const GHashTable *
 camel_session_get_junk_headers (CamelSession *session)
 {
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+
 	return session->priv->junk_headers;
 }

Modified: branches/camel-db-summary/camel/camel-session.h
==============================================================================
--- branches/camel-db-summary/camel/camel-session.h	(original)
+++ branches/camel-db-summary/camel/camel-session.h	Mon May  5 03:19:52 2008
@@ -103,12 +103,22 @@
 						  CamelException *ex);
 
 	/* mechanism for creating and maintaining multiple threads of control */
-	void *(*thread_msg_new)(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size);
-	void (*thread_msg_free)(CamelSession *session, CamelSessionThreadMsg *msg);
-	int (*thread_queue)(CamelSession *session, CamelSessionThreadMsg *msg, int flags);
-	void (*thread_wait)(CamelSession *session, int id);
-	void (*thread_status)(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc);
-	gboolean (*lookup_addressbook) (CamelSession *session, const char *name);
+	void *          (*thread_msg_new)    (CamelSession *session,
+					      CamelSessionThreadOps *ops,
+					      unsigned int size);
+	void            (*thread_msg_free)   (CamelSession *session,
+					      CamelSessionThreadMsg *msg);
+	int             (*thread_queue)      (CamelSession *session,
+					      CamelSessionThreadMsg *msg,
+					      int flags);
+	void            (*thread_wait)       (CamelSession *session,
+					      int id);
+	void            (*thread_status)     (CamelSession *session,
+					      CamelSessionThreadMsg *msg,
+					      const char *text,
+					      int pc);
+	gboolean        (*lookup_addressbook)(CamelSession *session,
+					      const char *name);
 } CamelSessionClass;
 
 
@@ -131,9 +141,11 @@
 						     CamelException *ex);
 
 #define camel_session_get_store(session, url_string, ex) \
-	((CamelStore *) camel_session_get_service_connected (session, url_string, CAMEL_PROVIDER_STORE, ex))
+	((CamelStore *) camel_session_get_service_connected \
+	(session, url_string, CAMEL_PROVIDER_STORE, ex))
 #define camel_session_get_transport(session, url_string, ex) \
-	((CamelTransport *) camel_session_get_service_connected (session, url_string, CAMEL_PROVIDER_TRANSPORT, ex))
+	((CamelTransport *) camel_session_get_service_connected \
+	(session, url_string, CAMEL_PROVIDER_TRANSPORT, ex))
 
 char *             camel_session_get_storage_path   (CamelSession *session,
 						     CamelService *service,
@@ -156,7 +168,7 @@
 						     const char *prompt,
 						     gboolean cancel);
 
-char *		   camel_session_build_password_prompt
+char *             camel_session_build_password_prompt
 						    (const char *type,
 						     const char *user,
 						     const char *host);
@@ -169,9 +181,9 @@
 						     const char *type,
 						     CamelException *ex);
 
-gboolean  camel_session_check_junk               (CamelSession *session);
-void      camel_session_set_check_junk           (CamelSession *session,
-						  gboolean      check_junk);
+gboolean           camel_session_check_junk         (CamelSession *session);
+void               camel_session_set_check_junk     (CamelSession *session,
+						     gboolean check_junk);
 
 struct _CamelSessionThreadOps {
 	void (*receive)(CamelSession *session, struct _CamelSessionThreadMsg *m);
@@ -192,15 +204,26 @@
 	/* user fields follow */
 };
 
-void *camel_session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size);
-void camel_session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg);
-int camel_session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags);
-void camel_session_thread_wait(CamelSession *session, int id);
-gboolean camel_session_get_network_state (CamelSession *session);
-void camel_session_set_network_state (CamelSession *session, gboolean network_state);
-const GHashTable * camel_session_get_junk_headers (CamelSession *session);
-void camel_session_set_junk_headers (CamelSession *session, const char **headers, const char **values, int len);
-gboolean camel_session_lookup_addressbook (CamelSession *session, const char *name);
+void *             camel_session_thread_msg_new     (CamelSession *session,
+						     CamelSessionThreadOps *ops,
+						     unsigned int size);
+void               camel_session_thread_msg_free    (CamelSession *session,
+						     CamelSessionThreadMsg *msg);
+int                camel_session_thread_queue       (CamelSession *session,
+						     CamelSessionThreadMsg *msg,
+						     int flags);
+void               camel_session_thread_wait        (CamelSession *session,
+						     int id);
+gboolean           camel_session_get_network_state  (CamelSession *session);
+void               camel_session_set_network_state  (CamelSession *session,
+						     gboolean network_state);
+const GHashTable * camel_session_get_junk_headers   (CamelSession *session);
+void               camel_session_set_junk_headers   (CamelSession *session,
+						     const char **headers,
+						     const char **values,
+						     int len);
+gboolean           camel_session_lookup_addressbook (CamelSession *session,
+						     const char *name);
 
 G_END_DECLS
 

Modified: branches/camel-db-summary/camel/providers/imap/camel-imap-folder.c
==============================================================================
--- branches/camel-db-summary/camel/providers/imap/camel-imap-folder.c	(original)
+++ branches/camel-db-summary/camel/providers/imap/camel-imap-folder.c	Mon May  5 03:19:52 2008
@@ -1847,6 +1847,10 @@
 	if (!destset++)
 		goto lose;
 
+	/* first do NOOP on the destination folder, so server has enough time to propagate our copy command there */
+	camel_imap_response_free (CAMEL_IMAP_STORE (destination->parent_store),
+				  camel_imap_command (CAMEL_IMAP_STORE (destination->parent_store), destination, NULL, "NOOP"));
+
 	camel_exception_init (&ex);
 	/* refresh folder's summary first, we copied messages there on the server,
 	   but do not know about it in a local summary */
@@ -1898,6 +1902,39 @@
 	g_warning ("Bad COPYUID response from server");
 }
 
+/* returns whether any of messages from uidset has set any user tag or not */
+static gboolean
+any_has_user_tag (CamelFolder *source, char *uidset)
+{
+	GPtrArray *src;
+
+	g_return_val_if_fail (source != NULL && uidset != NULL, FALSE);
+
+	src = imap_uid_set_to_array (source->summary, uidset);
+	if (src) {
+		gboolean have = FALSE;
+		int i;
+
+		CAMEL_IMAP_FOLDER_REC_LOCK (source, cache_lock);
+		for (i = 0; i < src->len && !have; i++) {
+			CamelMessageInfo *mi = camel_folder_get_message_info (source, src->pdata[i]);
+
+			if (mi) {
+				have = camel_message_info_user_tags (mi) != NULL;
+
+				camel_folder_free_message_info (source, mi);
+			}
+		}
+		CAMEL_IMAP_FOLDER_REC_UNLOCK (source, cache_lock);
+
+		imap_uid_array_free (src);
+
+		return have;
+	}
+
+	return FALSE;
+}
+
 static void
 do_copy (CamelFolder *source, GPtrArray *uids,
 	 CamelFolder *destination, int delete_originals, CamelException *ex)
@@ -1910,9 +1947,10 @@
 	while (uid < uids->len && !camel_exception_is_set (ex)) {
 		uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid);
 
-		if ((store->capabilities & IMAP_CAPABILITY_XGWMOVE) && delete_originals) {
+		/* use XGWMOVE only when none of the moving messages has set any user tag */
+		if ((store->capabilities & IMAP_CAPABILITY_XGWMOVE) != 0 && delete_originals && !any_has_user_tag (source, uidset)) {
 			response = camel_imap_command (store, source, ex, "UID XGWMOVE %s %F", uidset, destination->full_name);
-			/* TODO: EXPUNGE returns??? */
+			/* returns only 'A00012 OK UID XGWMOVE completed' '* 2 XGWMOVE' so nothing useful */
 			camel_imap_response_free (store, response);
 		} else {
 			response = camel_imap_command (store, source, ex, "UID COPY %s %F", uidset, destination->full_name);

Modified: branches/camel-db-summary/configure.in
==============================================================================
--- branches/camel-db-summary/configure.in	(original)
+++ branches/camel-db-summary/configure.in	Mon May  5 03:19:52 2008
@@ -22,6 +22,7 @@
 m4_define([libgnome_minimum_version], [2.0.0])          # XXX Just a Guess
 m4_define([libxml_minimum_version], [2.0.0])            # XXX Just a Guess
 m4_define([libsoup_minimum_version], [2.3.0])
+m4_define([gnome_keyring_minimum_version], [2.20.1])
 
 dnl *************************************************************************************************
 dnl Base Version
@@ -453,7 +454,7 @@
   with_nss_libs="$withval")
 
 if test "x${enable_gnome_keyring}" = "xyes"; then
-	PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1, with_gnome_keyring="yes", with_gnome_keyring="no");
+	PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1 >= gnome_keyring_minimum_version, with_gnome_keyring="yes", with_gnome_keyring="no");
 	if test "x$with_gnome_keyring" = "xyes"; then
 		AC_DEFINE(WITH_GNOME_KEYRING, 1, [Gnome Keyring available])	
 		GNOME_KEYRING_REQUIREMENT="gnome-keyring-1"

Modified: branches/camel-db-summary/libedataserver/e-categories.c
==============================================================================
--- branches/camel-db-summary/libedataserver/e-categories.c	(original)
+++ branches/camel-db-summary/libedataserver/e-categories.c	Mon May  5 03:19:52 2008
@@ -66,10 +66,55 @@
 	{ NULL }
 };
 
+/* ------------------------------------------------------------------------- */
+
+typedef struct {
+	GObject object;
+} EChangedListener;
+
+typedef struct {
+	GObjectClass parent_class;
+
+	void (* changed) (void);
+} EChangedListenerClass;
+
+static GType e_changed_listener_get_type (void);
+
+enum {
+	CHANGED,
+	LAST_SIGNAL
+};
+
+static guint changed_listener_signals[LAST_SIGNAL];
+
+static void
+e_changed_listener_class_init (EChangedListenerClass *klass)
+{
+	changed_listener_signals[CHANGED] =
+		g_signal_new ("changed",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (EChangedListenerClass, changed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+}
+
+static void
+e_changed_listener_init (EChangedListener *changed)
+{
+}
+
+G_DEFINE_TYPE (EChangedListener, e_changed_listener, G_TYPE_OBJECT);
+
+/* ------------------------------------------------------------------------- */
+
 static gboolean initialized = FALSE;
 static GHashTable *categories_table = NULL;
 static gboolean save_is_pending = FALSE;
 static guint idle_id = 0;
+static EChangedListener *listeners = NULL;
+static gboolean changed = FALSE;
 
 static gchar *
 build_categories_filename (void)
@@ -179,6 +224,10 @@
 	g_free (filename);
 	save_is_pending = FALSE;
 
+	if (changed)
+		g_signal_emit_by_name (listeners, "changed");
+
+	changed = FALSE;
 exit:
 	idle_id = 0;
 	return FALSE;
@@ -380,6 +429,11 @@
 		categories_table = NULL;
 	}
 
+	if (listeners != NULL) {
+		g_object_unref (listeners);
+		listeners = NULL;
+	}
+
 	initialized = FALSE;
 }
 
@@ -397,6 +451,8 @@
 		g_str_hash, g_str_equal, g_free,
 		(GDestroyNotify) free_category_info);
 
+	listeners = g_object_new (e_changed_listener_get_type (), NULL);
+
 	g_atexit (finalize_categories);
 
 	n_added = load_categories ();
@@ -479,6 +535,7 @@
 
 	g_hash_table_insert (categories_table, g_strdup (category), cat_info);
 
+	changed = TRUE;
 	save_categories ();
 }
 
@@ -496,8 +553,10 @@
 	if (!initialized)
 		initialize_categories ();
 
-	if (g_hash_table_remove (categories_table, category))
+	if (g_hash_table_remove (categories_table, category)) {
+		changed = TRUE;
 		save_categories ();
+	}
 }
 
 /**
@@ -571,6 +630,7 @@
 
 	g_free (cat_info->color);
 	cat_info->color = g_strdup (color);
+	changed = TRUE;
 	save_categories ();
 }
 #endif /* EDS_DISABLE_DEPRECATED */
@@ -622,6 +682,7 @@
 
 	g_free (cat_info->icon_file);
 	cat_info->icon_file = g_strdup (icon_file);
+	changed = TRUE;
 	save_categories ();
 }
 
@@ -649,3 +710,36 @@
 
 	return cat_info->searchable;
 }
+
+/**
+ * e_categories_register_change_listener:
+ * @listener: the callback to be called on any category change.
+ * @user_data: used data passed to the @listener when called.
+ *
+ * Registers callback to be called on change of any category.
+ * Pair listener and user_data is used to distinguish between listeners.
+ * Listeners can be unregistered with @e_categories_unregister_change_listener.
+ **/
+void
+e_categories_register_change_listener (GCallback listener, gpointer user_data)
+{
+	if (!initialized)
+		initialize_categories ();
+
+	g_signal_connect (listeners, "changed", listener, user_data);
+}
+
+/**
+ * e_categories_unregister_change_listener:
+ * @listener: Callback to be removed.
+ * @user_data: User data as passed with call to @e_categories_register_change_listener.
+ *
+ * Removes previously registered callback from the list of listeners on changes.
+ * If it was not registered, then does nothing.
+ **/
+void
+e_categories_unregister_change_listener (GCallback listener, gpointer user_data)
+{
+	if (initialized)
+		g_signal_handlers_disconnect_by_func (listeners, listener, user_data);
+}

Modified: branches/camel-db-summary/libedataserver/e-categories.h
==============================================================================
--- branches/camel-db-summary/libedataserver/e-categories.h	(original)
+++ branches/camel-db-summary/libedataserver/e-categories.h	Mon May  5 03:19:52 2008
@@ -20,6 +20,7 @@
 #ifndef __E_CATEGORIES__
 #define __E_CATEGORIES__
 
+#include <glib-object.h>
 #include <glib/glist.h>
 #include <glib/gmacros.h>
 
@@ -41,6 +42,9 @@
 void        e_categories_set_icon_file_for (const char *category, const char *icon_file);
 gboolean    e_categories_is_searchable (const char *category);
 
+void e_categories_register_change_listener   (GCallback listener, gpointer user_data);
+void e_categories_unregister_change_listener (GCallback listener, gpointer user_data);
+
 G_END_DECLS
 
 #endif

Modified: branches/camel-db-summary/libedataserverui/e-passwords.c
==============================================================================
--- branches/camel-db-summary/libedataserverui/e-passwords.c	(original)
+++ branches/camel-db-summary/libedataserverui/e-passwords.c	Mon May  5 03:19:52 2008
@@ -73,6 +73,7 @@
 	/* output */
 	gboolean *remember;
 	gchar *password;
+	GError *error;
 
 	/* work variables */
 	GtkWidget *entry;
@@ -176,6 +177,21 @@
 }
 
 #ifdef WITH_GNOME_KEYRING
+
+/* XXX Unfortunately, gnome-keyring doesn't use GErrors. */
+#define EP_KEYRING_ERROR	(ep_keyring_error_domain ())
+
+static GQuark
+ep_keyring_error_domain (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("ep-keyring-error-quark");
+
+	return quark;
+}
+
 static EUri *
 ep_keyring_uri_new (const gchar *string)
 {
@@ -243,7 +259,8 @@
 static gboolean
 ep_keyring_delete_passwords (const gchar *user,
                              const gchar *server,
-                             GList *passwords)
+                             GList *passwords,
+                             GError **error)
 {
 	while (passwords != NULL) {
 		GnomeKeyringFound *found = passwords->data;
@@ -257,7 +274,8 @@
 
 		result = gnome_keyring_item_delete_sync (NULL, found->item_id);
 		if (result != GNOME_KEYRING_RESULT_OK) {
-			g_warning (
+			g_set_error (
+				error, EP_KEYRING_ERROR, result,
 				"Unable to delete password in "
 				"keyring (Keyring reports: %s)",
 				gnome_keyring_result_to_message (result));
@@ -274,7 +292,8 @@
 ep_keyring_insert_password (const gchar *user,
                             const gchar *server,
                             const gchar *display_name,
-                            const gchar *password)
+                            const gchar *password,
+                            GError **error)
 {
 	GnomeKeyringAttributeList *attributes;
 	GnomeKeyringResult result;
@@ -299,7 +318,8 @@
 		NULL, GNOME_KEYRING_ITEM_NETWORK_PASSWORD,
 		display_name, attributes, password, TRUE, &item_id);
 	if (result != GNOME_KEYRING_RESULT_OK) {
-		g_warning (
+		g_set_error (
+			error, EP_KEYRING_ERROR, result,
 			"Unable to create password in "
 			"keyring (Keyring reports: %s)",
 			gnome_keyring_result_to_message (result));
@@ -312,7 +332,8 @@
 
 static GList *
 ep_keyring_lookup_passwords (const gchar *user,
-                             const gchar *server)
+                             const gchar *server,
+                             GError **error)
 {
 	GnomeKeyringAttributeList *attributes;
 	GnomeKeyringResult result;
@@ -331,7 +352,8 @@
 	result = gnome_keyring_find_items_sync (
 		GNOME_KEYRING_ITEM_NETWORK_PASSWORD, attributes, &passwords);
 	if (result != GNOME_KEYRING_RESULT_OK) {
-		g_warning (
+		g_set_error (
+			error, EP_KEYRING_ERROR, result,
 			"Unable to find password(s) in "
 			"keyring (Keyring reports: %s)",
 			gnome_keyring_result_to_message (result));
@@ -412,6 +434,13 @@
 static void
 ep_msg_free (EPassMsg *msg)
 {
+	/* XXX We really should be passing this back to the caller, but
+	 *     doing so will require breaking the password API. */
+	if (msg->error != NULL) {
+		g_warning ("%s", msg->error->message);
+		g_error_free (msg->error);
+	}
+
 	e_flag_free (msg->done);
 	g_free (msg->password);
 	g_free (msg);
@@ -447,13 +476,23 @@
 ep_clear_passwords_keyring (EPassMsg *msg)
 {
 	GList *passwords;
+	GError *error = NULL;
 
 	/* Find all Evolution passwords and delete them. */
-	passwords = ep_keyring_lookup_passwords (NULL, NULL);
+	passwords = ep_keyring_lookup_passwords (NULL, NULL, &error);
 	if (passwords != NULL) {
-		ep_keyring_delete_passwords (NULL, NULL, passwords);
+		ep_keyring_delete_passwords (NULL, NULL, passwords, &error);
 		gnome_keyring_found_list_free (passwords);
 	}
+
+	/* Not finding the requested key is acceptable, but we still
+	 * want to leave an informational message on the terminal. */
+	if (g_error_matches (error, EP_KEYRING_ERROR, GNOME_KEYRING_RESULT_NO_MATCH)) {
+		g_message ("%s", error->message);
+		g_error_free (error);
+
+	} else if (error != NULL)
+		g_propagate_error (&msg->error, error);
 }
 #endif
 
@@ -474,11 +513,8 @@
                 g_message ("%s", error->message);
                 g_error_free (error);
 
-	/* Issue a warning if anything else goes wrong. */
-	} else if (error != NULL) {
-		g_warning ("%s", error->message);
-		g_error_free (error);
-	}
+	} else if (error != NULL)
+		g_propagate_error (&msg->error, error);
 
 	g_free (group);
 }
@@ -504,13 +540,18 @@
 ep_forget_passwords_keyring (EPassMsg *msg)
 {
 	GList *passwords;
+	GError *error = NULL;
 
 	/* Find all Evolution passwords and delete them. */
-	passwords = ep_keyring_lookup_passwords (NULL, NULL);
+	passwords = ep_keyring_lookup_passwords (NULL, NULL, &error);
 	if (passwords != NULL) {
-		ep_keyring_delete_passwords (NULL, NULL, passwords);
+		ep_keyring_delete_passwords (NULL, NULL, passwords, &error);
 		gnome_keyring_found_list_free (passwords);
+
 	}
+
+	if (error != NULL)
+		g_propagate_error (&msg->error, error);
 }
 #endif
 
@@ -569,6 +610,7 @@
 {
 	gchar *password;
 	EUri *uri;
+	GError *error = NULL;
 
 	password = g_hash_table_lookup (password_cache, msg->key);
 	if (password == NULL) {
@@ -581,9 +623,12 @@
 
 	/* Only remove the password from the session hash
 	 * if the keyring insertion was successful. */
-	if (ep_keyring_insert_password (uri->user, uri->host, msg->key, password))
+	if (ep_keyring_insert_password (uri->user, uri->host, msg->key, password, &error))
 		g_hash_table_remove (password_cache, msg->key);
 
+	if (error != NULL)
+		g_propagate_error (&msg->error, error);
+
 	e_uri_free (uri);
 }
 #endif
@@ -634,17 +679,21 @@
 {
 	GList *passwords;
 	EUri *uri;
+	GError *error = NULL;
 
 	uri = ep_keyring_uri_new (msg->key);
 	g_return_if_fail (uri != NULL);
 
 	/* Find all Evolution passwords matching the URI and delete them. */
-	passwords = ep_keyring_lookup_passwords (uri->user, uri->host);
+	passwords = ep_keyring_lookup_passwords (uri->user, uri->host, &error);
 	if (passwords != NULL) {
-		ep_keyring_delete_passwords (uri->user, uri->host, passwords);
+		ep_keyring_delete_passwords (uri->user, uri->host, passwords, &error);
 		gnome_keyring_found_list_free (passwords);
 	}
 
+	if (error != NULL)
+		g_propagate_error (&msg->error, error);
+
 	e_uri_free (uri);
 }
 #endif
@@ -672,11 +721,8 @@
                 g_message ("%s", error->message);
                 g_error_free (error);
 
-	/* Issue a warning if anything else goes wrong. */
-	} else if (error != NULL) {
-		g_warning ("%s", error->message);
-		g_error_free (error);
-	}
+	} else if (error != NULL)
+		g_propagate_error (&msg->error, error);
 
 	g_free (group);
 	g_free (key);
@@ -706,12 +752,13 @@
 {
 	GList *passwords;
 	EUri *uri;
+	GError *error = NULL;
 
 	uri = ep_keyring_uri_new (msg->key);
 	g_return_if_fail (uri != NULL);
 
 	/* Find the first Evolution password that matches the URI. */
-	passwords = ep_keyring_lookup_passwords (uri->user, uri->host);
+	passwords = ep_keyring_lookup_passwords (uri->user, uri->host, &error);
 	if (passwords != NULL) {
 		GList *iter = passwords;
 
@@ -729,6 +776,15 @@
 		gnome_keyring_found_list_free (passwords);
 	}
 
+	/* Not finding the requested key is acceptable, but we still
+	 * want to leave an informational message on the terminal. */
+	if (g_error_matches (error, EP_KEYRING_ERROR, GNOME_KEYRING_RESULT_NO_MATCH)) {
+		g_message ("%s", error->message);
+		g_error_free (error);
+
+	} else if (error != NULL)
+		g_propagate_error (&msg->error, error);
+
 	e_uri_free (uri);
 }
 #endif
@@ -758,16 +814,40 @@
                 g_message ("%s", error->message);
                 g_error_free (error);
 
-	/* Issue a warning if anything else goes wrong. */
-	} else if (error != NULL) {
-		g_warning ("%s", error->message);
-		g_error_free (error);
-	}
+	} else if (error != NULL)
+		g_propagate_error (&msg->error, error);
 
 	g_free (group);
 	g_free (key);
 }
 
+#ifdef WITH_GNOME_KEYRING
+static void
+ep_keyring_migrate_from_keyfile (EPassMsg *msg)
+{
+	/* Fetch the password from the keyfile. */
+	ep_get_password_keyfile (msg);
+	if (msg->password == NULL)
+		return;
+
+	/* Add it to the in-memory cache. */
+	g_hash_table_insert (
+		password_cache, g_strdup (msg->key),
+		g_strdup (msg->password));
+
+	/* Remember it in the keyring. */
+	ep_remember_password_keyring (msg);
+
+	/* Remove it from the in-memory cache. */
+	g_hash_table_remove (password_cache, msg->key);
+
+	/* Remove it from the keyfile only if the keyring
+	 * insertion was successful. */
+	if (msg->error == NULL)
+		ep_forget_password_keyfile (msg);
+}
+#endif
+
 static void
 ep_get_password (EPassMsg *msg)
 {
@@ -775,14 +855,19 @@
 
 	/* Check the in-memory cache first. */
 	password = g_hash_table_lookup (password_cache, msg->key);
-	if (password != NULL)
+	if (password != NULL) {
 		msg->password = g_strdup (password);
 
 #ifdef WITH_GNOME_KEYRING
-	else if (gnome_keyring_is_available ())
+	} else if (gnome_keyring_is_available ()) {
 		ep_get_password_keyring (msg);
+
+		/* Try looking for the password in the keyfile.
+		 * If we find it, migrate it to the keyring. */
+		if (msg->password == NULL && msg->error == NULL)
+			ep_keyring_migrate_from_keyfile (msg);
 #endif
-	else
+	} else
 		ep_get_password_keyfile (msg);
 
 	if (!msg->noreply)
@@ -1043,15 +1128,10 @@
 			(GDestroyNotify) g_free);
 		main_thread = g_thread_self ();
 
-#ifdef WITH_GNOME_KEYRING
-		if (!gnome_keyring_is_available ()) {
-			key_file = g_key_file_new ();
-			ep_key_file_load ();
-		}
-#else
+		/* Load the keyfile even if we're using the keyring.
+		 * We might be able to extract passwords from it. */
 		key_file = g_key_file_new ();
 		ep_key_file_load ();
-#endif
 	}
 
 	G_UNLOCK (passwords);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]