[evolution-patches] fix for addressbook db corruption crash



If for any reason a db entry gets partially overwritten and is left in a
bad state (where the data is trashed but the db still thinks there's a
value there), e-d-s can get really unstable.  The trouble is all the
code assumes there's a UID in the EContact that is created from the
vcard, and if that vcard attribute has been trashed and is missing,
e-d-s crashes.

So, this fix parses the vcard, and if there's no UID set on the contact
it sets it to be the same as the db key (which it should always be.)

This has the added benefit (over ignoring the corrupted entry) of having
the corrupted entry show up in the addressbook view, so you can
edit/fix/delete it.

Fixes Michael's crash from last night.

Chris
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/addressbook/ChangeLog,v
retrieving revision 1.113
diff -u -r1.113 ChangeLog
--- ChangeLog	31 Mar 2004 22:42:26 -0000	1.113
+++ ChangeLog	1 Apr 2004 19:12:15 -0000
@@ -1,3 +1,29 @@
+2004-04-01  Chris Toshok  <toshok ximian com>
+
+	* backends/file/e-book-backend-file.c (create_contact): new
+	function, for use when creating a contact from the db.  all the
+	libedata-book machinery depends on the contact having a UID, so if
+	it doesn't have one (i.e. it's been corrupted), set it to be the
+	uid we pass in (the db key).
+	(build_summary): use create_contact
+	(e_book_backend_file_start_book_view): same.
+	(e_book_backend_file_get_changes): same.
+	(e_book_backend_file_upgrade_db): same.
+	(e_book_backend_file_load_source): add lots more g_warning spew in
+	the event the load fails.
+
+2004-03-31  Chris Toshok  <toshok ximian com>
+
+	* libebook/e-contact.c (e_contact_get_first_attr): ignore the
+	attribute's group.
+	(e_contact_set_property): same.
+	(e_contact_find_attribute_with_types): same.
+	(e_contact_get_property): same.
+	(e_contact_get_attributes): same.
+
+	* libebook/e-vcard.c (e_vcard_to_string_vcard_30): ignore the
+	attribute's group when looking for VERSION attributes.
+
 2004-03-30  Chris Toshok  <toshok ximian com>
  
 	[ backend portion of fix for #51977 ]
Index: backends/file/e-book-backend-file.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/addressbook/backends/file/e-book-backend-file.c,v
retrieving revision 1.13
diff -u -r1.13 e-book-backend-file.c
--- backends/file/e-book-backend-file.c	13 Mar 2004 22:40:45 -0000	1.13
+++ backends/file/e-book-backend-file.c	1 Apr 2004 19:12:15 -0000
@@ -60,6 +60,16 @@
 	dbt->size = strlen (str) + 1;
 }
 
+static EContact*
+create_contact (char *uid, const char *vcard)
+{
+	EContact *contact = e_contact_new_from_vcard (vcard);
+	if (!e_contact_get_const (contact, E_CONTACT_UID))
+		e_contact_set (contact, E_CONTACT_UID, uid);
+
+	return contact;
+}
+
 static void
 build_summary (EBookBackendFilePrivate *bfpriv)
 {
@@ -84,7 +94,7 @@
 		/* don't include the version in the list of cards */
 		if (id_dbt.size != strlen(E_BOOK_BACKEND_FILE_VERSION_NAME) + 1
 		    || strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
-			EContact *contact = e_contact_new_from_vcard (vcard_dbt.data);
+			EContact *contact = create_contact (id_dbt.data, vcard_dbt.data);
 			e_book_backend_summary_add_contact (bfpriv->summary, contact);
 			g_object_unref (contact);
 		}
@@ -454,7 +464,8 @@
 			db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
 
 			if (db_error == 0) {
-				EContact *contact = e_contact_new_from_vcard (vcard_dbt.data);
+				EContact *contact = create_contact (id_dbt.data, vcard_dbt.data);
+				/* notify_update will check if it matches for us */
 				e_data_book_view_notify_update (book_view, contact);
 				g_object_unref (contact);
 			}
@@ -483,9 +494,7 @@
 
 			/* don't include the version in the list of cards */
 			if (strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
-				char *vcard_string = vcard_dbt.data;
-				EContact *contact = e_contact_new_from_vcard (vcard_string);
-
+				EContact *contact = create_contact (id_dbt.data, vcard_dbt.data);
 				/* notify_update will check if it matches for us */
 				e_data_book_view_notify_update (book_view, contact);
 				g_object_unref (contact);
@@ -627,7 +636,8 @@
 				 * and can change without the rest of the
 				 * card changing 
 				 */
-				contact = e_contact_new_from_vcard (vcard_dbt.data);
+				contact = create_contact (id_dbt.data, vcard_dbt.data);
+
 #if notyet
 				g_object_set (card, "last_use", NULL, "use_score", 0.0, NULL);
 #endif
@@ -793,7 +803,7 @@
 			    || strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
 				EContact *contact;
 
-				contact = e_contact_new_from_vcard (vcard_dbt.data);
+				contact = create_contact (id_dbt.data, vcard_dbt.data);
 
 				/* the cards we're looking for are
 				   created with a normal id dbt, but
@@ -893,20 +903,26 @@
 	g_free (uri);
 
 	db_error = e_db3_utils_maybe_recover (filename);
-	if (db_error != 0)
+	if (db_error != 0) {
+		g_warning ("db recovery failed with %d", db_error);
 		return GNOME_Evolution_Addressbook_OtherError;
+	}
 
 	db_error = db_create (&db, NULL, 0);
-	if (db_error != 0)
+	if (db_error != 0) {
+		g_warning ("db_create failed with %d", db_error);
 		return GNOME_Evolution_Addressbook_OtherError;
+	}
 
 	db_error = db->open (db, NULL, filename, NULL, DB_HASH, 0, 0666);
 
 	if (db_error == DB_OLD_VERSION) {
 		db_error = e_db3_utils_upgrade_format (filename);
 
-		if (db_error != 0)
+		if (db_error != 0) {
+			g_warning ("db format upgrade failed with %d", db_error);
 			return GNOME_Evolution_Addressbook_OtherError;
+		}
 
 		db_error = db->open (db, NULL, filename, NULL, DB_HASH, 0, 0666);
 	}
@@ -933,8 +949,10 @@
 			}
 
 			db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_CREATE, 0666);
-
-			if (db_error == 0) {
+			if (db_error != 0) {
+				g_warning ("db->open (... DB_CREATE ...) failed with %d", db_error);
+			}
+			else {
 				EContact *contact;
 
 				contact = do_create(bf, XIMIAN_VCARD);
@@ -954,6 +972,7 @@
 	if (!e_book_backend_file_maybe_upgrade_db (bf)) {
 		db->close (db, 0);
 		bf->priv->file_db = NULL;
+		g_warning ("e_book_backend_file_maybe_upgrade_db failed");
 		return GNOME_Evolution_Addressbook_OtherError;
 	}
 
@@ -965,6 +984,7 @@
 	if (stat (bf->priv->filename, &sb) == -1) {
 		db->close (db, 0);
 		bf->priv->file_db = NULL;
+		g_warning ("stat(%s) failed", bf->priv->filename);
 		return GNOME_Evolution_Addressbook_OtherError;
 	}
 	db_mtime = sb.st_mtime;


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