[evolution-patches] patch for 33919 (other users folders crash)



This fixes up the refcounting issues around the old "pseudofolders" hash
table.
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/shell/ChangeLog,v
retrieving revision 1.1237
diff -u -r1.1237 ChangeLog
--- ChangeLog	14 Apr 2003 22:48:24 -0000	1.1237
+++ ChangeLog	15 Apr 2003 15:19:42 -0000
@@ -1,3 +1,19 @@
+2003-04-15  Dan Winship  <danw ximian com>
+
+	* e-folder.c (e_folder_get_has_subfolders,
+	e_folder_set_has_subfolders): new boolean flag.
+
+	* e-storage.c (EStoragePrivate, impl_finalize, init): Remove the
+	pseudofolders hash
+	(e_storage_async_open_folder): Replace the pseudofolders test with
+	a test of whether the folder has the "has_subfolders" flag set.
+	(e_storage_new_folder): Likewise (for the folder's parent).
+	(e_storage_declare_has_subfolders): Set "has_subfolders" on the
+	folder.
+	(e_storage_get_has_subfolders): Check "has_subfolders" on the
+	folder.
+	Should fix #33919.
+
 2003-04-14  Not Zed  <NotZed Ximian com>
 
 	* glade/e-active-connection-dialog.glade: fix the title of the
Index: e-folder.c
===================================================================
RCS file: /cvs/gnome/evolution/shell/e-folder.c,v
retrieving revision 1.36
diff -u -r1.36 e-folder.c
--- e-folder.c	5 Feb 2003 22:25:15 -0000	1.36
+++ e-folder.c	15 Apr 2003 15:19:43 -0000
@@ -57,6 +57,7 @@
 	unsigned int self_highlight : 1;
 	unsigned int is_stock : 1;
 	unsigned int can_sync_offline : 1;
+	unsigned int has_subfolders : 1;
 
 	/* Custom icon for this folder; if NULL the folder will just use the
 	   icon for its type.  */
@@ -181,6 +182,7 @@
 	priv->self_highlight   = FALSE;
 	priv->is_stock         = FALSE;
 	priv->can_sync_offline = FALSE;
+	priv->has_subfolders   = FALSE;
 	priv->custom_icon_name = NULL;
 
 	folder->priv = priv;
@@ -299,6 +301,14 @@
 	return folder->priv->can_sync_offline;
 }
 
+gboolean
+e_folder_get_has_subfolders (EFolder *folder)
+{
+	g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
+
+	return folder->priv->has_subfolders;
+}
+
 /**
  * e_folder_get_custom_icon:
  * @folder: An EFolder
@@ -440,6 +450,17 @@
 	g_return_if_fail (E_IS_FOLDER (folder));
 
 	folder->priv->can_sync_offline = !! can_sync_offline;
+
+	g_signal_emit (folder, signals[CHANGED], 0);
+}
+
+void
+e_folder_set_has_subfolders (EFolder *folder,
+			     gboolean has_subfolders)
+{
+	g_return_if_fail (E_IS_FOLDER (folder));
+
+	folder->priv->has_subfolders = !! has_subfolders;
 
 	g_signal_emit (folder, signals[CHANGED], 0);
 }
Index: e-folder.h
===================================================================
RCS file: /cvs/gnome/evolution/shell/e-folder.h,v
retrieving revision 1.23
diff -u -r1.23 e-folder.h
--- e-folder.h	17 Sep 2002 19:27:04 -0000	1.23
+++ e-folder.h	15 Apr 2003 15:19:43 -0000
@@ -81,6 +81,7 @@
 gboolean    e_folder_get_highlighted  	  (EFolder *folder);
 gboolean    e_folder_get_is_stock     	  (EFolder *folder);
 gboolean    e_folder_get_can_sync_offline (EFolder *folder);
+gboolean    e_folder_get_has_subfolders   (EFolder *folder);
 const char *e_folder_get_custom_icon_name (EFolder *folder);
 int         e_folder_get_sorting_priority (EFolder *folder);
 
@@ -92,6 +93,7 @@
 void  e_folder_set_child_highlight   (EFolder *folder, gboolean highlighted);
 void  e_folder_set_is_stock          (EFolder *folder, gboolean is_stock);
 void  e_folder_set_can_sync_offline  (EFolder *folder, gboolean can_sync_offline);
+void  e_folder_set_has_subfolders    (EFolder *folder, gboolean has_subfolders);
 void  e_folder_set_custom_icon       (EFolder *folder, const char *icon_name);
 void  e_folder_set_sorting_priority  (EFolder *folder, int sorting_priority);
 
Index: e-storage.c
===================================================================
RCS file: /cvs/gnome/evolution/shell/e-storage.c,v
retrieving revision 1.55
diff -u -r1.55 e-storage.c
--- e-storage.c	14 Mar 2003 19:58:36 -0000	1.55
+++ e-storage.c	15 Apr 2003 15:19:44 -0000
@@ -53,9 +53,6 @@
 	/* The set of folders we have in this storage.  */
 	EFolderTree *folder_tree;
 
-	/* The pseudofolders representing un-filled-in subtrees */
-	GHashTable *pseudofolders;
-
 	/* Internal name of the storage */
 	char *name;
 };
@@ -132,13 +129,6 @@
 /* GObject methods.  */
 
 static void
-free_folder (gpointer path, gpointer folder, gpointer user_data)
-{
-	g_free (path);
-	/* folders will have been freed by e_folder_tree_destroy */
-}
-
-static void
 impl_finalize (GObject *object)
 {
 	EStorage *storage;
@@ -149,10 +139,6 @@
 
 	if (priv->folder_tree != NULL)
 		e_folder_tree_destroy (priv->folder_tree);
-	if (priv->pseudofolders) {
-		g_hash_table_foreach (priv->pseudofolders, free_folder, NULL);
-		g_hash_table_destroy (priv->pseudofolders);
-	}
 
 	g_free (priv->name);
 
@@ -322,7 +308,6 @@
 	priv = g_new (EStoragePrivate, 1);
 
 	priv->folder_tree   = e_folder_tree_new (folder_destroy_notify, NULL);
-	priv->pseudofolders = g_hash_table_new (g_str_hash, g_str_equal);
 	priv->name          = NULL;
 
 	storage->priv = priv;
@@ -494,12 +479,23 @@
 			     EStorageDiscoveryCallback callback,
 			     void *data)
 {
+	EStoragePrivate *priv;
+	EFolder *folder;
+
 	g_return_if_fail (storage != NULL);
 	g_return_if_fail (E_IS_STORAGE (storage));
 	g_return_if_fail (path != NULL);
 	g_return_if_fail (g_path_is_absolute (path));
 
-	if (g_hash_table_lookup (storage->priv->pseudofolders, path) == NULL) {
+	priv = storage->priv;
+
+	folder = e_folder_tree_get_folder (priv->folder_tree, path);
+	if (folder == NULL) {
+		(* callback) (storage, E_STORAGE_NOTFOUND, path, data);
+		return;
+	}
+
+	if (! e_folder_get_has_subfolders (folder)) {
 		(* callback) (storage, E_STORAGE_OK, path, data);
 		return;
 	}
@@ -676,6 +672,24 @@
 /* These functions are used by subclasses to add and remove folders from the
    state stored in the storage object.  */
 
+static void
+remove_subfolders_except (EStorage *storage, const char *path, const char *except)
+{
+	EStoragePrivate *priv;
+	GList *subfolders, *f;
+	const char *folder_path;
+
+	priv = storage->priv;
+
+	subfolders = e_folder_tree_get_subfolders (priv->folder_tree, path);
+	for (f = subfolders; f; f = f->next) {
+		folder_path = f->data;
+		if (!except || strcmp (folder_path, except) != 0)
+			e_storage_removed_folder (storage, folder_path);
+	}
+	g_list_free (subfolders);
+}
+
 gboolean
 e_storage_new_folder (EStorage *storage,
 		      const char *path,
@@ -683,7 +697,7 @@
 {
 	EStoragePrivate *priv;
 	char *parent_path, *p;
-	gpointer stored_path, pseudofolder;
+	EFolder *parent;
 
 	g_return_val_if_fail (storage != NULL, FALSE);
 	g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
@@ -697,17 +711,18 @@
 	if (! e_folder_tree_add (priv->folder_tree, path, e_folder))
 		return FALSE;
 
+	/* If this is the child of a folder that has a pseudo child,
+	 * remove the pseudo child now.
+	 */
 	p = strrchr (path, '/');
 	if (p && p != path)
 		parent_path = g_strndup (path, p - path);
 	else
 		parent_path = g_strdup ("/");
-	if (g_hash_table_lookup_extended (priv->pseudofolders, parent_path,
-					  &stored_path, &pseudofolder) &&
-	    pseudofolder != e_folder) {
-		g_hash_table_remove (priv->pseudofolders, parent_path);
-		g_free (stored_path);		
-		e_storage_removed_folder (storage, e_folder_get_physical_uri (pseudofolder));
+	parent = e_folder_tree_get_folder (priv->folder_tree, parent_path);
+	if (parent && e_folder_get_has_subfolders (parent)) {
+		remove_subfolders_except (storage, parent_path, path);
+		e_folder_set_has_subfolders (parent, FALSE);
 	}
 	g_free (parent_path);
 
@@ -732,9 +747,9 @@
 				  const char *message)
 {
 	EStoragePrivate *priv;
-	GList *subfolders, *f;
-	EFolder *pseudofolder;
+	EFolder *parent, *pseudofolder;
 	char *pseudofolder_path;
+	gboolean ok;
 
 	g_return_val_if_fail (storage != NULL, FALSE);
 	g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
@@ -744,16 +759,13 @@
 
 	priv = storage->priv;
 
-	if (g_hash_table_lookup (priv->pseudofolders, path))
+	parent = e_folder_tree_get_folder (priv->folder_tree, path);
+	if (parent == NULL)
+		return FALSE;
+	if (e_folder_get_has_subfolders (parent))
 		return TRUE;
 
-	subfolders = e_folder_tree_get_subfolders (priv->folder_tree, path);
-	if (subfolders != NULL) {
-		for (f = subfolders; f; f = f->next)
-			e_storage_removed_folder (storage, f->data);
-		g_list_free (subfolders);
-		/* FIXME: close parent */
-	}
+	remove_subfolders_except (storage, path, NULL);
 
 	pseudofolder = e_folder_new (message, "working", "");
 	if (strcmp (path, "/") == 0)
@@ -762,9 +774,15 @@
 		pseudofolder_path = g_strdup_printf ("%s/%s", path, message);
 	e_folder_set_physical_uri (pseudofolder, pseudofolder_path);
 
-	g_hash_table_insert (priv->pseudofolders, g_strdup (path), pseudofolder);
+	ok = e_storage_new_folder (storage, pseudofolder_path, pseudofolder);
+	g_free (pseudofolder_path);
+	if (!ok) {
+		g_object_unref (pseudofolder);
+		return FALSE;
+	}
 
-	return e_storage_new_folder (storage, pseudofolder_path, pseudofolder);
+	e_folder_set_has_subfolders (parent, TRUE);
+	return TRUE;
 }
 
 gboolean
@@ -772,6 +790,7 @@
 			      const char *path)
 {
 	EStoragePrivate *priv;
+	EFolder *folder;
 
 	g_return_val_if_fail (storage != NULL, FALSE);
 	g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
@@ -780,7 +799,9 @@
 
 	priv = storage->priv;
 
-	return g_hash_table_lookup (priv->pseudofolders, path) != NULL;
+	folder = e_folder_tree_get_folder (priv->folder_tree, path);
+
+	return folder && e_folder_get_has_subfolders (folder);
 }
 
 gboolean


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