evolution-data-server r9877 - in branches/camel-gobject: . addressbook addressbook/backends/file addressbook/backends/google addressbook/backends/groupwise addressbook/backends/vcf addressbook/libebook addressbook/libedata-book calendar calendar/backends calendar/backends/caldav calendar/backends/http calendar/backends/weather calendar/libecal camel camel/providers/groupwise camel/providers/imap camel/providers/local camel/providers/pop3 docs/reference/addressbook/libebook/tmpl docs/reference/addressbook/libedata-book docs/reference/addressbook/libedata-book/tmpl docs/reference/calendar/libecal docs/reference/calendar/libecal/tmpl docs/reference/calendar/libedata-cal docs/reference/camel docs/reference/libedataserverui docs/reference/libedataserverui/tmpl libedataserver libedataserverui po servers/exchange servers/exchange/lib servers/groupwise



Author: mbarnes
Date: Tue Jan  6 01:56:50 2009
New Revision: 9877
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=9877&view=rev

Log:
Merge revisions 9745:9876 from trunk.


Added:
   branches/camel-gobject/libedataserverui/e-category-completion.c
      - copied unchanged from r9876, /trunk/libedataserverui/e-category-completion.c
   branches/camel-gobject/libedataserverui/e-category-completion.h
      - copied unchanged from r9876, /trunk/libedataserverui/e-category-completion.h
   branches/camel-gobject/libedataserverui/test-category-completion.c
      - copied unchanged from r9876, /trunk/libedataserverui/test-category-completion.c
Modified:
   branches/camel-gobject/   (props changed)
   branches/camel-gobject/ChangeLog
   branches/camel-gobject/NEWS
   branches/camel-gobject/addressbook/ChangeLog
   branches/camel-gobject/addressbook/backends/file/e-book-backend-file.c
   branches/camel-gobject/addressbook/backends/google/e-book-backend-google.c
   branches/camel-gobject/addressbook/backends/groupwise/e-book-backend-groupwise.c
   branches/camel-gobject/addressbook/backends/vcf/e-book-backend-vcf.c
   branches/camel-gobject/addressbook/libebook/e-contact.c
   branches/camel-gobject/addressbook/libebook/e-contact.h
   branches/camel-gobject/addressbook/libebook/e-vcard.c
   branches/camel-gobject/addressbook/libebook/e-vcard.h
   branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.c
   branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.h
   branches/camel-gobject/addressbook/libedata-book/e-book-backend-sexp.c
   branches/camel-gobject/addressbook/libedata-book/e-book-backend.c
   branches/camel-gobject/addressbook/libedata-book/e-data-book-view.c
   branches/camel-gobject/calendar/ChangeLog
   branches/camel-gobject/calendar/backends/Makefile.am
   branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav-factory.c
   branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav.c
   branches/camel-gobject/calendar/backends/http/e-cal-backend-http.c
   branches/camel-gobject/calendar/backends/weather/Locations.xml.in
   branches/camel-gobject/calendar/backends/weather/Makefile.am
   branches/camel-gobject/calendar/backends/weather/e-cal-backend-weather.c
   branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.c
   branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.h
   branches/camel-gobject/calendar/backends/weather/e-weather-source.c
   branches/camel-gobject/calendar/backends/weather/e-weather-source.h
   branches/camel-gobject/calendar/libecal/e-cal-util.h
   branches/camel-gobject/calendar/libecal/e-cal.c
   branches/camel-gobject/camel/ChangeLog
   branches/camel-gobject/camel/camel-db.c
   branches/camel-gobject/camel/camel-db.h
   branches/camel-gobject/camel/camel-folder-summary.c
   branches/camel-gobject/camel/camel-folder-summary.h
   branches/camel-gobject/camel/camel-folder.c
   branches/camel-gobject/camel/camel-mime-utils.c
   branches/camel-gobject/camel/camel-object.h
   branches/camel-gobject/camel/camel-private.h
   branches/camel-gobject/camel/camel-search-sql-sexp.c
   branches/camel-gobject/camel/camel-store-summary.h
   branches/camel-gobject/camel/camel-store.c
   branches/camel-gobject/camel/camel-store.h
   branches/camel-gobject/camel/camel-utf8.c
   branches/camel-gobject/camel/camel-utf8.h
   branches/camel-gobject/camel/camel-vee-folder.c
   branches/camel-gobject/camel/camel-vee-summary.c
   branches/camel-gobject/camel/camel-vtrash-folder.c
   branches/camel-gobject/camel/providers/groupwise/ChangeLog
   branches/camel-gobject/camel/providers/groupwise/camel-groupwise-folder.c
   branches/camel-gobject/camel/providers/groupwise/camel-groupwise-provider.c
   branches/camel-gobject/camel/providers/groupwise/camel-groupwise-store.c
   branches/camel-gobject/camel/providers/imap/ChangeLog
   branches/camel-gobject/camel/providers/imap/camel-imap-folder.c
   branches/camel-gobject/camel/providers/imap/camel-imap-journal.c
   branches/camel-gobject/camel/providers/imap/camel-imap-store.c
   branches/camel-gobject/camel/providers/imap/camel-imap-summary.c
   branches/camel-gobject/camel/providers/local/camel-local-folder.c
   branches/camel-gobject/camel/providers/pop3/ChangeLog
   branches/camel-gobject/camel/providers/pop3/camel-pop3-store.c
   branches/camel-gobject/configure.in
   branches/camel-gobject/docs/reference/addressbook/libebook/tmpl/e-contact.sgml
   branches/camel-gobject/docs/reference/addressbook/libedata-book/libedata-book-sections.txt
   branches/camel-gobject/docs/reference/addressbook/libedata-book/tmpl/e-book-backend-db-cache.sgml
   branches/camel-gobject/docs/reference/calendar/libecal/libecal-sections.txt
   branches/camel-gobject/docs/reference/calendar/libecal/tmpl/e-cal-util.sgml
   branches/camel-gobject/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt
   branches/camel-gobject/docs/reference/camel/camel-docs.sgml
   branches/camel-gobject/docs/reference/camel/camel-sections.txt
   branches/camel-gobject/docs/reference/libedataserverui/libedataserverui-sections.txt
   branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-data-server-ui-marshal.sgml
   branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-source-selector.sgml
   branches/camel-gobject/evolution-data-server-zip.in
   branches/camel-gobject/libedataserver/e-sexp.c
   branches/camel-gobject/libedataserver/e-source.c
   branches/camel-gobject/libedataserver/e-url.c
   branches/camel-gobject/libedataserverui/ChangeLog
   branches/camel-gobject/libedataserverui/Makefile.am
   branches/camel-gobject/libedataserverui/e-categories-dialog.c
   branches/camel-gobject/libedataserverui/e-contact-store.c
   branches/camel-gobject/libedataserverui/e-data-server-ui-marshal.list
   branches/camel-gobject/libedataserverui/e-source-selector.c
   branches/camel-gobject/libedataserverui/e-source-selector.h
   branches/camel-gobject/po/ChangeLog
   branches/camel-gobject/po/es.po
   branches/camel-gobject/po/hu.po
   branches/camel-gobject/po/it.po
   branches/camel-gobject/po/nb.po
   branches/camel-gobject/po/sl.po
   branches/camel-gobject/servers/exchange/ChangeLog
   branches/camel-gobject/servers/exchange/lib/e2k-autoconfig.c
   branches/camel-gobject/servers/groupwise/ChangeLog
   branches/camel-gobject/servers/groupwise/e-gw-connection.c
   branches/camel-gobject/servers/groupwise/e-gw-item.c

Modified: branches/camel-gobject/NEWS
==============================================================================
--- branches/camel-gobject/NEWS	(original)
+++ branches/camel-gobject/NEWS	Tue Jan  6 01:56:50 2009
@@ -1,3 +1,57 @@
+Evolution-Data-Server 2.25.3 2008-12-15
+---------------------------------------
+
+Bug Fixes:
+	#270376: Skype name field added to the  list of IM information (Sasa Ostrouska)
+	#348299: New files implement category completion (Matthew Barnes)
+	#352287: Share locations and forecast rertieving with libgweather (Milan Crha)
+	#357948: Show preview of the selected image file when choosing new icon (Milan Crha)
+	#435632: (Novell Bugzilla) Don't unref when things aren't reffed (Srinivasa Ragavan)
+	#440265, #447121: (Novell Bugzilla) Fix some stupidity (Srinivasa Ragavan)
+	#451734: Correctly set Blythe, CA URL (Ian Weisser)
+	#503662: Use last '@' in the address part to be the delimiter between user name and server address, not the first one (Milan Crha)
+	#545834: Update mailing list information after full retrieval if necessary (Milan Crha)
+	#552986: Ensure error description is valid UTF-8 text before using it (Milan Crha)
+	#558883: Don't do DB sort from IMAP (Srinivasa Ragavan)
+	#561081: Delete mails for XGWMOVE when mails are moved (Srinivasa Ragavan)
+	#561561: Use a sufficiently large buffer for  strings used as an operand in strftime() (Federic van Starbann)
+	#562228: Always store correct owa_path when validating, without trailing slash and without mailbox name (Milan Crha)
+	#562567: Remember local/remote mode correctly. Also done various cleanups, less debug output and waits for the slave thread only if exists (Milan Crha)
+
+Updated Translations:
+	Kjartan Maraas (nb)
+	Luca Ferretti (it)
+	Gabor Kelemen (hu)
+
+Evolution-Data-Server 2.25.2 2008-12-01
+---------------------------------------
+
+New in 2.25.2
+	Support CalDAV for VTODO and VJOURNAL (Milan Crha)
+
+Bug Fixes:
+       #359745: Support CalDAV for VTODO and VJOURNAL (Milan Crha)
+       #524377: Attachments with localised letters are unrecognised by Outlook (Milan Crha)
+       #527692: CalDAV does not work with Apple CalDAV  (Milan Crha)
+       #531090: Deprecate dead API in camel-object.h (Matthew Barnes)
+       #546637: Mail opened from the "Unread mails" displays empty list (Srinivasa Ragavan)
+       #555979: Evolution does not empty trash on exit (Milan Crha)
+       #556119: Evolution takes a very long time to index newsgroup (Srinivasa Ragavan)
+       #557348: Search folders with "Include threads" do not update reliably (Srinivasa Ragavan)
+       #557818: Centralize ESourceSelector drag-n-drop handling (Matthew Barnes)
+       #558322: Pressing "F2" on a highlighted Task List / Memo List / Address Book / Calendar 
+                should bring up the properties dialog box (Matthew Barnes)
+       #558737: Evolution freezes on trying to store folder (Milan Crha)
+       #558883: Evolution 2.24 is terribly slow with large IMAP folders (Milan Crha) (Srinivasa Ragavan)
+       #559272: Evolution freeze while using a CalDAV calendar (Milan Crha)
+       #560076: Follow-Ups doesn't work in 2.24 (Srinivasa Ragavan)
+       #560185: Support 'getctag' in CalDAV, if available (Milan Crha)
+       #560681: Parsing QUOTED-PRINTABLE vcards probably ignores CHARSET info (Milan Crha)
+       #560981: Result of xpath query is not freed in CalDAV synch loop (Andrew McMillan)
+       #561069: Evolution crashed expunging 48k deleted junk messages (Srinivasa Ragavan)
+       #561466: Changes needed in E-D-S for evolution-mapi (Suman Manjunath)
+       #435964 (bugzilla.novell.com): Crash after switching from offline to online in GW addressbook (Ashish Shrivastava)
+
 Evolution-Data-Server 2.25.1 2008-11-03
 ---------------------------------------
 

Modified: branches/camel-gobject/addressbook/backends/file/e-book-backend-file.c
==============================================================================
--- branches/camel-gobject/addressbook/backends/file/e-book-backend-file.c	(original)
+++ branches/camel-gobject/addressbook/backends/file/e-book-backend-file.c	Tue Jan  6 01:56:50 2009
@@ -172,7 +172,7 @@
 static void
 set_revision (EContact *contact)
 {
-	char time_string[25] = {0};
+	char time_string[100] = {0};
 	const struct tm *tm = NULL;
 	GTimeVal tv;
 

Modified: branches/camel-gobject/addressbook/backends/google/e-book-backend-google.c
==============================================================================
--- branches/camel-gobject/addressbook/backends/google/e-book-backend-google.c	(original)
+++ branches/camel-gobject/addressbook/backends/google/e-book-backend-google.c	Tue Jan  6 01:56:50 2009
@@ -51,11 +51,11 @@
 static EBookBackendSyncStatus e_book_backend_status_from_google_book_error (GoogleBookError error_code);
 
 static EBookBackendSyncStatus
-e_book_backend_google_create_contact (EBookBackendSync *backend,
-                                      EDataBook        *book,
-                                      guint32           opid,
-                                      const char       *vcard_str,
-                                      EContact        **out_contact)
+e_book_backend_google_create_contact (EBookBackendSync 	*backend,
+				      EDataBook		*book,
+				      guint32 		opid,
+				      const char 	*vcard_str,
+				      EContact 		**out_contact)
 {
     EBookBackendGooglePrivate *priv;
     EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
@@ -69,18 +69,18 @@
     *out_contact = NULL;
 
     if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
-        return GNOME_Evolution_Addressbook_OfflineUnavailable;
+	return GNOME_Evolution_Addressbook_OfflineUnavailable;
     }
 
     contact = e_contact_new_from_vcard (vcard_str);
     google_book_add_contact (priv->book, contact, out_contact, &error);
     g_object_unref (contact);
     if (error) {
-        status = e_book_backend_status_from_google_book_error (error->code);
-        __debug__ ("Creating contact failed: %s", error->message);
-        g_clear_error (&error);
-        *out_contact = NULL;
-        return status;
+	status = e_book_backend_status_from_google_book_error (error->code);
+	__debug__ ("Creating contact failed: %s", error->message);
+	g_clear_error (&error);
+	*out_contact = NULL;
+	return status;
     }
 
     return GNOME_Evolution_Addressbook_Success;
@@ -88,10 +88,10 @@
 
 static EBookBackendSyncStatus
 e_book_backend_google_remove_contacts (EBookBackendSync *backend,
-                                       EDataBook        *book,
-                                       guint32           opid,
-                                       GList            *id_list,
-                                       GList           **ids)
+				       EDataBook 	*book,
+				       guint32 		opid,
+				       GList 		*id_list,
+				       GList 		**ids)
 {
     EBookBackendGooglePrivate *priv;
     EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
@@ -103,37 +103,37 @@
     *ids = NULL;
 
     if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
-        return GNOME_Evolution_Addressbook_OfflineUnavailable;
+	return GNOME_Evolution_Addressbook_OfflineUnavailable;
     }
 
     for (id_iter = id_list; id_iter; id_iter = id_iter->next) {
-        GError *error = NULL;
-        const char *uid;
+	GError *error = NULL;
+	const char *uid;
 
-        uid = id_iter->data;
-        google_book_remove_contact (priv->book, uid, &error);
-        if (error) {
-            /* Only last error will be reported */
-            status = e_book_backend_status_from_google_book_error (error->code);
-            __debug__ ("Deleting contact %s failed: %s", uid, error->message);
-            g_clear_error (&error);
-        } else {
-            *ids = g_list_append (*ids, g_strdup (uid));
-        }
+	uid = id_iter->data;
+	google_book_remove_contact (priv->book, uid, &error);
+	if (error) {
+	    /* Only last error will be reported */
+	    status = e_book_backend_status_from_google_book_error (error->code);
+	    __debug__ ("Deleting contact %s failed: %s", uid, error->message);
+	    g_clear_error (&error);
+	} else {
+	    *ids = g_list_append (*ids, g_strdup (uid));
+	}
     }
 
     if (NULL == *ids) {
-        return status;
+	return status;
     }
     return GNOME_Evolution_Addressbook_Success;
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_modify_contact (EBookBackendSync *backend,
-                                      EDataBook        *book,
-                                      guint32           opid,
-                                      const char       *vcard_str,
-                                      EContact        **out_contact)
+e_book_backend_google_modify_contact (EBookBackendSync 	*backend,
+				      EDataBook		*book,
+				      guint32 		opid,
+				      const char 	*vcard_str,
+				      EContact 		**out_contact)
 {
     EBookBackendGooglePrivate *priv;
     EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
@@ -147,29 +147,29 @@
     *out_contact = NULL;
 
     if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
-        return GNOME_Evolution_Addressbook_OfflineUnavailable;
+	return GNOME_Evolution_Addressbook_OfflineUnavailable;
     }
 
     contact = e_contact_new_from_vcard (vcard_str);
     google_book_update_contact (priv->book, contact, out_contact, &error);
     g_object_unref (contact);
     if (error) {
-        status = e_book_backend_status_from_google_book_error (error->code);
-        __debug__ ("Modifying contact failed: %s", error->message);
-        g_clear_error (&error);
-        *out_contact = NULL;
-        return status;
+	status = e_book_backend_status_from_google_book_error (error->code);
+	__debug__ ("Modifying contact failed: %s", error->message);
+	g_clear_error (&error);
+	*out_contact = NULL;
+	return status;
     }
 
     return GNOME_Evolution_Addressbook_Success;
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_get_contact (EBookBackendSync *backend,
-                                   EDataBook        *book,
-                                   guint32           opid,
-                                   const char       *uid,
-                                   char            **vcard_str)
+e_book_backend_google_get_contact (EBookBackendSync 	*backend,
+				   EDataBook 		*book,
+				   guint32 		opid,
+				   const char 		*uid,
+				   char 		**vcard_str)
 {
     EBookBackendGooglePrivate *priv;
     EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
@@ -181,10 +181,10 @@
 
     contact = google_book_get_contact (priv->book, uid, &error);
     if (error) {
-        status = e_book_backend_status_from_google_book_error (error->code);
-        __debug__ ("Getting contact with uid %s failed: %s", uid, error->message);
-        g_clear_error (&error);
-        return status;
+	status = e_book_backend_status_from_google_book_error (error->code);
+	__debug__ ("Getting contact with uid %s failed: %s", uid, error->message);
+	g_clear_error (&error);
+	return status;
     }
     *vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
     g_object_unref (contact);
@@ -194,10 +194,10 @@
 
 static EBookBackendSyncStatus
 e_book_backend_google_get_contact_list (EBookBackendSync *backend,
-                                        EDataBook        *book,
-                                        guint32           opid,
-                                        const char       *query,
-                                        GList           **contacts)
+					EDataBook 	 *book,
+					guint32 	 opid,
+					const char 	 *query,
+					GList 		 **contacts)
 {
     EBookBackendGooglePrivate *priv;
     EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
@@ -212,24 +212,24 @@
 
     all_contacts = google_book_get_all_contacts (priv->book, &error);
     if (error) {
-        status = e_book_backend_status_from_google_book_error (error->code);
-        __debug__ ("Getting all contacts failed: %s", error->message);
-        g_clear_error (&error);
-        return status;
+	status = e_book_backend_status_from_google_book_error (error->code);
+	__debug__ ("Getting all contacts failed: %s", error->message);
+	g_clear_error (&error);
+	return status;
     }
 
     sexp = e_book_backend_sexp_new (query);
     while (all_contacts) {
-        EContact *contact;
+	EContact *contact;
 
-        contact = all_contacts->data;
-        if (e_book_backend_sexp_match_contact (sexp, contact)) {
-            char *vcard_str;
-            vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-            *contacts = g_list_append (*contacts, vcard_str);
-        }
-        g_object_unref (contact);
-        all_contacts = g_list_delete_link (all_contacts, all_contacts);
+	contact = all_contacts->data;
+	if (e_book_backend_sexp_match_contact (sexp, contact)) {
+	    char *vcard_str;
+	    vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+	    *contacts = g_list_append (*contacts, vcard_str);
+	}
+	g_object_unref (contact);
+	all_contacts = g_list_delete_link (all_contacts, all_contacts);
     }
     g_object_unref (sexp);
 
@@ -244,8 +244,8 @@
 
     priv = GET_PRIVATE (user_data);
     for (iter = priv->bookviews; iter; iter = iter->next) {
-        g_object_ref (contact);
-        e_data_book_view_notify_update (E_DATA_BOOK_VIEW (iter->data), contact);
+	g_object_ref (contact);
+	e_data_book_view_notify_update (E_DATA_BOOK_VIEW (iter->data), contact);
     }
 }
 
@@ -257,7 +257,7 @@
 
     priv = GET_PRIVATE (user_data);
     for (iter = priv->bookviews; iter; iter = iter->next) {
-        e_data_book_view_notify_remove (E_DATA_BOOK_VIEW (iter->data), g_strdup (uid));
+	e_data_book_view_notify_remove (E_DATA_BOOK_VIEW (iter->data), g_strdup (uid));
     }
 }
 
@@ -269,8 +269,8 @@
 
     priv = GET_PRIVATE (user_data);
     for (iter = priv->bookviews; iter; iter = iter->next) {
-        g_object_ref (contact);
-        e_data_book_view_notify_update (E_DATA_BOOK_VIEW (iter->data), contact);
+	g_object_ref (contact);
+	e_data_book_view_notify_update (E_DATA_BOOK_VIEW (iter->data), contact);
     }
 }
 
@@ -283,19 +283,19 @@
 
     priv = GET_PRIVATE (user_data);
     if (error) {
-        status = e_book_backend_status_from_google_book_error (error->code);
-        __debug__ ("Book-view query failed: %s", error->message);
-        status = e_book_backend_status_from_google_book_error (error->code);
-        g_clear_error (&error);
+	status = e_book_backend_status_from_google_book_error (error->code);
+	__debug__ ("Book-view query failed: %s", error->message);
+	status = e_book_backend_status_from_google_book_error (error->code);
+	g_clear_error (&error);
     }
     for (iter = priv->bookviews; iter; iter = iter->next) {
-        e_data_book_view_notify_complete (E_DATA_BOOK_VIEW (iter->data), GNOME_Evolution_Addressbook_Success);
+	e_data_book_view_notify_complete (E_DATA_BOOK_VIEW (iter->data), GNOME_Evolution_Addressbook_Success);
     }
 }
 
 static void
 e_book_backend_google_start_book_view (EBookBackend  *backend,
-                                       EDataBookView *bookview)
+				       EDataBookView *bookview)
 {
     EBookBackendGooglePrivate *priv;
     GList *cached_contacts;
@@ -314,18 +314,18 @@
     google_book_set_live_mode (priv->book, TRUE);
     cached_contacts = google_book_get_all_contacts_in_live_mode (priv->book);
     while (cached_contacts) {
-        EContact *contact = cached_contacts->data;
+	EContact *contact = cached_contacts->data;
 
-        e_data_book_view_notify_update (bookview, contact);
-        g_object_unref (contact);
-        cached_contacts = g_list_delete_link (cached_contacts, cached_contacts);
+	e_data_book_view_notify_update (bookview, contact);
+	g_object_unref (contact);
+	cached_contacts = g_list_delete_link (cached_contacts, cached_contacts);
     }
     e_data_book_view_notify_complete (bookview, GNOME_Evolution_Addressbook_Success);
 }
 
 static void
 e_book_backend_google_stop_book_view (EBookBackend  *backend,
-                                      EDataBookView *bookview)
+				      EDataBookView *bookview)
 {
     EBookBackendGooglePrivate *priv;
 
@@ -336,17 +336,17 @@
     e_data_book_view_unref (bookview);
 
     if (NULL == priv->bookviews) {
-        google_book_set_live_mode (priv->book, FALSE);
+	google_book_set_live_mode (priv->book, FALSE);
     }
 }
 
 static EBookBackendSyncStatus
 e_book_backend_google_authenticate_user (EBookBackendSync *backend,
-                                         EDataBook        *book,
-                                         guint32           opid,
-                                         const char       *username,
-                                         const char       *password,
-                                         const char       *auth_method)
+					 EDataBook 	  *book,
+					 guint32 	  opid,
+					 const char 	  *username,
+					 const char 	  *password,
+					 const char 	  *auth_method)
 {
     EBookBackendGooglePrivate *priv;
     EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_Success;
@@ -358,42 +358,42 @@
     priv = GET_PRIVATE (backend);
 
     if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
-        return GNOME_Evolution_Addressbook_Success;
+	return GNOME_Evolution_Addressbook_Success;
     }
 
     if (NULL == username || username[0] == 0) {
-        return GNOME_Evolution_Addressbook_AuthenticationFailed;
+	return GNOME_Evolution_Addressbook_AuthenticationFailed;
     }
 
     g_object_get (G_OBJECT (priv->book),
-                  "username", &book_username,
-                  NULL);
+		  "username", &book_username,
+		  NULL);
 
     match = (0 == strcmp (username, book_username));
     g_free (book_username);
     if (FALSE == match) {
-        g_warning ("Username given when loading source and on authentication did not match!");
-        return GNOME_Evolution_Addressbook_OtherError;
+	g_warning ("Username given when loading source and on authentication did not match!");
+	return GNOME_Evolution_Addressbook_OtherError;
     }
 
     google_book_connect_to_google (priv->book, password, &error);
     if (error) {
-        status = e_book_backend_status_from_google_book_error (error->code);
-        __debug__ ("Authentication failed: %s", error->message);
-        status = e_book_backend_status_from_google_book_error (error->code);
-        g_clear_error (&error);
+	status = e_book_backend_status_from_google_book_error (error->code);
+	__debug__ ("Authentication failed: %s", error->message);
+	status = e_book_backend_status_from_google_book_error (error->code);
+	g_clear_error (&error);
     } else {
-        e_book_backend_notify_writable (E_BOOK_BACKEND (backend), TRUE);
+	e_book_backend_notify_writable (E_BOOK_BACKEND (backend), TRUE);
     }
 
     return status;
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_get_supported_auth_methods (EBookBackendSync *backend,
-                                                  EDataBook        *book,
-                                                  guint32           opid,
-                                                  GList           **methods)
+e_book_backend_google_get_supported_auth_methods (EBookBackendSync 	*backend,
+						  EDataBook 		*book,
+						  guint32 		opid,
+						  GList 		**methods)
 {
     char *auth_method;
 
@@ -405,10 +405,10 @@
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_get_required_fields (EBookBackendSync *backend,
-                                           EDataBook        *book,
-                                           guint32           opid,
-                                           GList           **fields_out)
+e_book_backend_google_get_required_fields (EBookBackendSync 	*backend,
+					   EDataBook 		*book,
+					   guint32 		opid,
+					   GList 		**fields_out)
 {
     __debug__ (G_STRFUNC);
 
@@ -417,36 +417,39 @@
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_get_supported_fields (EBookBackendSync *backend,
-                                            EDataBook        *book,
-                                            guint32           opid,
-                                            GList           **fields_out)
+e_book_backend_google_get_supported_fields (EBookBackendSync 	*backend,
+					    EDataBook 		*book,
+					    guint32 		opid,
+					    GList 		**fields_out)
 {
     const int supported_fields[] =
     {
-        E_CONTACT_FULL_NAME,
-        E_CONTACT_EMAIL_1,
-        E_CONTACT_EMAIL_2,
-        E_CONTACT_EMAIL_3,
-        E_CONTACT_EMAIL_4,
-        E_CONTACT_ADDRESS_LABEL_HOME,
-        E_CONTACT_ADDRESS_LABEL_WORK,
-        E_CONTACT_ADDRESS_LABEL_OTHER,
-        E_CONTACT_PHONE_HOME,
-        E_CONTACT_PHONE_HOME_FAX,
-        E_CONTACT_PHONE_BUSINESS,
-        E_CONTACT_PHONE_BUSINESS_FAX,
-        E_CONTACT_PHONE_MOBILE,
-        E_CONTACT_PHONE_PAGER,
-        E_CONTACT_IM_AIM,
-        E_CONTACT_IM_JABBER,
-        E_CONTACT_IM_YAHOO,
-        E_CONTACT_IM_MSN,
-        E_CONTACT_IM_ICQ,
-        E_CONTACT_ADDRESS,
-        E_CONTACT_ADDRESS_HOME,
-        E_CONTACT_ADDRESS_WORK,
-        E_CONTACT_ADDRESS_OTHER
+	E_CONTACT_FULL_NAME,
+	E_CONTACT_EMAIL_1,
+	E_CONTACT_EMAIL_2,
+	E_CONTACT_EMAIL_3,
+	E_CONTACT_EMAIL_4,
+	E_CONTACT_ADDRESS_LABEL_HOME,
+	E_CONTACT_ADDRESS_LABEL_WORK,
+	E_CONTACT_ADDRESS_LABEL_OTHER,
+	E_CONTACT_PHONE_HOME,
+	E_CONTACT_PHONE_HOME_FAX,
+	E_CONTACT_PHONE_BUSINESS,
+	E_CONTACT_PHONE_BUSINESS_FAX,
+	E_CONTACT_PHONE_MOBILE,
+	E_CONTACT_PHONE_PAGER,
+	E_CONTACT_IM_AIM,
+	E_CONTACT_IM_JABBER,
+	E_CONTACT_IM_YAHOO,
+	E_CONTACT_IM_MSN,
+	E_CONTACT_IM_ICQ,
+	E_CONTACT_IM_SKYPE,
+	E_CONTACT_IM_GADUGADU,
+	E_CONTACT_IM_GROUPWISE,
+	E_CONTACT_ADDRESS,
+	E_CONTACT_ADDRESS_HOME,
+	E_CONTACT_ADDRESS_WORK,
+	E_CONTACT_ADDRESS_OTHER
     };
     GList *fields = NULL;
     int i;
@@ -454,10 +457,10 @@
     __debug__ (G_STRFUNC);
 
     for (i = 0; i < G_N_ELEMENTS (supported_fields); i++) {
-        const char *field_name;
+	const char *field_name;
 
-        field_name = e_contact_field_name (supported_fields[i]);
-        fields = g_list_append (fields, g_strdup (field_name));
+	field_name = e_contact_field_name (supported_fields[i]);
+	fields = g_list_append (fields, g_strdup (field_name));
     }
 
     *fields_out = fields;
@@ -465,20 +468,20 @@
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_get_changes (EBookBackendSync *backend,
-                                   EDataBook        *book,
-                                   guint32           opid,
-                                   const char       *change_id,
-                                   GList           **changes_out)
+e_book_backend_google_get_changes (EBookBackendSync 	*backend,
+				   EDataBook 		*book,
+				   guint32 		opid,
+				   const char 		*change_id,
+				   GList 		**changes_out)
 {
     __debug__ (G_STRFUNC);
     return GNOME_Evolution_Addressbook_OtherError;
 }
 
 static EBookBackendSyncStatus
-e_book_backend_google_remove (EBookBackendSync *backend,
-                              EDataBook        *book,
-                              guint32           opid)
+e_book_backend_google_remove (EBookBackendSync 	*backend,
+			      EDataBook		*book,
+			      guint32 		opid)
 {
     __debug__ (G_STRFUNC);
     return GNOME_Evolution_Addressbook_Success;
@@ -493,8 +496,8 @@
 
 static GNOME_Evolution_Addressbook_CallStatus
 e_book_backend_google_load_source (EBookBackend *backend,
-                                   ESource      *source,
-                                   gboolean      only_if_exists)
+				   ESource 	*source,
+				   gboolean 	only_if_exists)
 {
     EBookBackendGooglePrivate *priv = GET_PRIVATE (backend);
     const char *refresh_interval_str, *use_ssl_str, *use_cache_str;
@@ -503,15 +506,15 @@
     const char *username;
 
     if (priv->book) {
-        g_warning ("Source already loaded!");
-        return GNOME_Evolution_Addressbook_OtherError;
+	g_warning ("Source already loaded!");
+	return GNOME_Evolution_Addressbook_OtherError;
     }
 
     username = e_source_get_property (source, "username");
 
     if (NULL == username || username[0] == '\0') {
-        g_warning ("No or empty username!");
-        return GNOME_Evolution_Addressbook_OtherError;
+	g_warning ("No or empty username!");
+	return GNOME_Evolution_Addressbook_OtherError;
     }
 
     refresh_interval_str = e_source_get_property (source, "refresh-interval");
@@ -519,37 +522,37 @@
     use_cache_str = e_source_get_property (source, "offline_sync");
 
     if (refresh_interval_str) {
-        if (1 != sscanf (refresh_interval_str, "%u", &refresh_interval)) {
-            g_warning ("Could not parse refresh-interval!");
-            refresh_interval = 3600;
-        }
+	if (1 != sscanf (refresh_interval_str, "%u", &refresh_interval)) {
+	    g_warning ("Could not parse refresh-interval!");
+	    refresh_interval = 3600;
+	}
     }
 
     use_ssl = TRUE;
     if (use_ssl_str) {
-        if (0 == g_ascii_strcasecmp (use_ssl_str, "false") || 0 == strcmp (use_ssl_str, "0"))
-            use_ssl = FALSE;
+	if (0 == g_ascii_strcasecmp (use_ssl_str, "false") || 0 == strcmp (use_ssl_str, "0"))
+	    use_ssl = FALSE;
     }
 
     use_cache = TRUE;
     if (use_cache_str) {
-        if (0 == g_ascii_strcasecmp (use_cache_str, "false") || 0 == strcmp (use_cache_str, "0"))
-            use_cache = FALSE;
+	if (0 == g_ascii_strcasecmp (use_cache_str, "false") || 0 == strcmp (use_cache_str, "0"))
+	    use_cache = FALSE;
     }
 
     priv->book = google_book_new (username, use_cache);
 
     g_object_set (G_OBJECT (priv->book),
-                  "refresh-interval", refresh_interval,
-                  "use-ssl", use_ssl,
-                  NULL);
+		  "refresh-interval", refresh_interval,
+		  "use-ssl", use_ssl,
+		  NULL);
     g_object_connect (G_OBJECT (priv->book),
-                      "signal::contact-added", G_CALLBACK (on_google_book_contact_added), backend,
-                      "signal::contact-changed", G_CALLBACK (on_google_book_contact_changed), backend,
-                      "signal::contact-removed", G_CALLBACK (on_google_book_contact_removed), backend,
-                      "signal::sequence-complete", G_CALLBACK (on_google_book_sequence_complete), backend,
-                      "signal::auth-required", G_CALLBACK (on_google_book_auth_required), backend,
-                      NULL);
+		      "signal::contact-added", G_CALLBACK (on_google_book_contact_added), backend,
+		      "signal::contact-changed", G_CALLBACK (on_google_book_contact_changed), backend,
+		      "signal::contact-removed", G_CALLBACK (on_google_book_contact_removed), backend,
+		      "signal::sequence-complete", G_CALLBACK (on_google_book_sequence_complete), backend,
+		      "signal::auth-required", G_CALLBACK (on_google_book_auth_required), backend,
+		      NULL);
 
     __debug__ (G_STRFUNC);
 
@@ -583,19 +586,19 @@
     __debug__ (G_STRFUNC);
 
     if (mode == priv->mode) {
-        return;
+	return;
     }
 
     priv->mode = mode;
 
     if (NULL == priv->book) {
-        return;
+	return;
     }
 
     if (mode == GNOME_Evolution_Addressbook_MODE_REMOTE) {
-        google_book_set_offline_mode (priv->book, FALSE);
+	google_book_set_offline_mode (priv->book, FALSE);
     } else {
-        google_book_set_offline_mode (priv->book, TRUE);
+	google_book_set_offline_mode (priv->book, TRUE);
     }
 }
 
@@ -607,13 +610,13 @@
     __debug__ (G_STRFUNC);
 
     while (priv->bookviews) {
-        e_data_book_view_unref (priv->bookviews->data);
-        priv->bookviews = g_list_delete_link (priv->bookviews,
-                                              priv->bookviews);
+	e_data_book_view_unref (priv->bookviews->data);
+	priv->bookviews = g_list_delete_link (priv->bookviews,
+					      priv->bookviews);
     }
     if (priv->book) {
-        g_object_unref (priv->book);
-        priv->book = NULL;
+	g_object_unref (priv->book);
+	priv->book = NULL;
     }
 
     G_OBJECT_CLASS (e_book_backend_google_parent_class)->dispose (object);
@@ -641,23 +644,23 @@
     g_type_class_add_private (klass, sizeof (EBookBackendGooglePrivate));
 
     /* Set the virtual methods. */
-    backend_class->load_source             = e_book_backend_google_load_source;
-    backend_class->get_static_capabilities = e_book_backend_google_get_static_capabilities;
-    backend_class->start_book_view         = e_book_backend_google_start_book_view;
-    backend_class->stop_book_view          = e_book_backend_google_stop_book_view;
-    backend_class->cancel_operation        = e_book_backend_google_cancel_operation;
-    backend_class->set_mode                = e_book_backend_google_set_mode;
-    sync_class->remove_sync                = e_book_backend_google_remove;
-    sync_class->create_contact_sync        = e_book_backend_google_create_contact;
-    sync_class->remove_contacts_sync       = e_book_backend_google_remove_contacts;
-    sync_class->modify_contact_sync        = e_book_backend_google_modify_contact;
-    sync_class->get_contact_sync           = e_book_backend_google_get_contact;
-    sync_class->get_contact_list_sync      = e_book_backend_google_get_contact_list;
-    sync_class->get_changes_sync           = e_book_backend_google_get_changes;
-    sync_class->authenticate_user_sync     = e_book_backend_google_authenticate_user;
-    sync_class->get_supported_fields_sync  = e_book_backend_google_get_supported_fields;
-    sync_class->get_required_fields_sync   = e_book_backend_google_get_required_fields;
-    sync_class->get_supported_auth_methods_sync  = e_book_backend_google_get_supported_auth_methods;
+    backend_class->load_source			= e_book_backend_google_load_source;
+    backend_class->get_static_capabilities	= e_book_backend_google_get_static_capabilities;
+    backend_class->start_book_view		= e_book_backend_google_start_book_view;
+    backend_class->stop_book_view		= e_book_backend_google_stop_book_view;
+    backend_class->cancel_operation		= e_book_backend_google_cancel_operation;
+    backend_class->set_mode			= e_book_backend_google_set_mode;
+    sync_class->remove_sync			= e_book_backend_google_remove;
+    sync_class->create_contact_sync		= e_book_backend_google_create_contact;
+    sync_class->remove_contacts_sync		= e_book_backend_google_remove_contacts;
+    sync_class->modify_contact_sync		= e_book_backend_google_modify_contact;
+    sync_class->get_contact_sync		= e_book_backend_google_get_contact;
+    sync_class->get_contact_list_sync		= e_book_backend_google_get_contact_list;
+    sync_class->get_changes_sync		= e_book_backend_google_get_changes;
+    sync_class->authenticate_user_sync		= e_book_backend_google_authenticate_user;
+    sync_class->get_supported_fields_sync	= e_book_backend_google_get_supported_fields;
+    sync_class->get_required_fields_sync	= e_book_backend_google_get_required_fields;
+    sync_class->get_supported_auth_methods_sync = e_book_backend_google_get_supported_auth_methods;
 
     object_class->dispose  = e_book_backend_google_dispose;
     object_class->finalize = e_book_backend_google_finalize;

Modified: branches/camel-gobject/addressbook/backends/groupwise/e-book-backend-groupwise.c
==============================================================================
--- branches/camel-gobject/addressbook/backends/groupwise/e-book-backend-groupwise.c	(original)
+++ branches/camel-gobject/addressbook/backends/groupwise/e-book-backend-groupwise.c	Tue Jan  6 01:56:50 2009
@@ -44,6 +44,7 @@
 #include "libedataserver/e-flag.h"
 #include "libedataserver/e-url.h"
 #include "libebook/e-contact.h"
+#include "libebook/e-destination.h"
 #include "libedata-book/e-book-backend-sexp.h"
 #include "libedata-book/e-data-book.h"
 #include "libedata-book/e-data-book-view.h"
@@ -178,6 +179,7 @@
 	GList *yahoo_list = NULL;
 	GList *gadugadu_list = NULL;
 	GList *msn_list = NULL;
+	GList *skype_list = NULL;
 	GList *jabber_list = NULL;
 	GList *groupwise_list = NULL;
 	IMAddress *address;
@@ -204,10 +206,14 @@
 			im_field_id = E_CONTACT_IM_AIM;
 			im_attr_list = &aim_list;
 		}
-		else if ( g_str_equal (address->service, "msn")) {
+		else if (g_str_equal (address->service, "msn")) {
 			im_field_id = E_CONTACT_IM_MSN;
 			im_attr_list = &msn_list;
 		}
+		else if (g_str_equal (address->service, "skype")) {
+			im_field_id = E_CONTACT_IM_SKYPE;
+			im_attr_list = &skype_list;
+		}
 		else if (g_str_equal (address->service, "yahoo")) {
 			im_field_id = E_CONTACT_IM_YAHOO;
 			im_attr_list = &yahoo_list;
@@ -240,6 +246,7 @@
 	e_contact_set_attributes (contact, E_CONTACT_IM_YAHOO, yahoo_list);
 	e_contact_set_attributes (contact, E_CONTACT_IM_GADUGADU, gadugadu_list);
 	e_contact_set_attributes (contact, E_CONTACT_IM_MSN, msn_list);
+	e_contact_set_attributes (contact, E_CONTACT_IM_SKYPE, skype_list);
 	e_contact_set_attributes (contact, E_CONTACT_IM_GROUPWISE, groupwise_list);
 
 	free_attr_list (aim_list);
@@ -248,6 +255,7 @@
 	free_attr_list (yahoo_list);
 	free_attr_list (gadugadu_list);
 	free_attr_list (msn_list);
+	free_attr_list (skype_list);
 	free_attr_list (groupwise_list);
 }
 
@@ -280,6 +288,7 @@
 	append_ims_to_list (&im_list, contact, "gadu-gadu", E_CONTACT_IM_GADUGADU);
 	append_ims_to_list (&im_list, contact, "icq", E_CONTACT_IM_ICQ);
 	append_ims_to_list (&im_list, contact, "msn", E_CONTACT_IM_MSN);
+	append_ims_to_list (&im_list, contact, "skype", E_CONTACT_IM_SKYPE);
 	append_ims_to_list (&im_list, contact, "jabber", E_CONTACT_IM_JABBER);
 	append_ims_to_list (&im_list, contact, "nov", E_CONTACT_IM_GROUPWISE);
 	if (im_list)
@@ -798,7 +807,7 @@
 static void
 set_members_in_gw_item (EGwItem  *item, EContact *contact, EBookBackendGroupwise *egwb)
 {
-  	GList  *members, *temp, *items, *p, *emails_without_ids;
+  	GList  *members, *temp, *dtemp, *items, *p, *emails_without_ids, *dest_without_ids;
 	GList *group_members;
 	char *email;
 	EGwFilter *filter;
@@ -816,10 +825,12 @@
 	filter = e_gw_filter_new ();
 	group_members = NULL;
 	emails_without_ids = NULL;
+	dest_without_ids = NULL;
 
 	for ( ;temp != NULL; temp = g_list_next (temp)) {
 		EVCardAttribute *attr = temp->data;
 		id = email = NULL;
+		EDestination *dest = e_destination_new ();
 
 		for (p = e_vcard_attribute_get_params (attr); p; p = p->next) {
 			EVCardAttributeParam *param = p->data;
@@ -848,13 +859,19 @@
 				email = v ? v->data : NULL;
 			}
 		}
+
+		if (!id && !email)
+			email = e_vcard_attribute_get_value (attr);
 		if (id) {
 			member = g_new0 (EGroupMember , 1);
 			member->id = g_strdup (id);
 			group_members = g_list_append (group_members, member);
 		} else if (email) {
+			e_destination_set_raw (dest, email);
 			e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_EQUAL, "emailList/@primary", email);
 			emails_without_ids = g_list_append (emails_without_ids, g_strdup (email));
+			dest_without_ids = g_list_append (dest_without_ids, dest);
+		
 			count++;
 		}
 	}
@@ -871,8 +888,15 @@
 		temp_item = E_GW_ITEM (items->data);
 		emails = e_gw_item_get_email_list (temp_item);
 		if (emails_without_ids && (ptr = g_list_find_custom (emails_without_ids, emails->data, (GCompareFunc)strcasecmp ))) {
+			int pos = g_list_position (emails_without_ids, ptr);
 			emails_without_ids = g_list_remove_link (emails_without_ids, ptr);
 			g_list_free (ptr);
+
+			ptr = g_list_nth (dest_without_ids, pos);
+			dest_without_ids = g_list_remove_link (dest_without_ids, ptr);
+			g_object_unref (ptr->data);
+			g_list_free (ptr);
+
 			id = g_strdup (e_gw_item_get_id (temp_item));
 			member = g_new0 (EGroupMember , 1);
 			member->id = id;
@@ -890,19 +914,21 @@
 	 */
 
 	temp = emails_without_ids ;
-	for (; temp != NULL; temp = g_list_next (temp)) {
+	dtemp = dest_without_ids;
+	for (; temp != NULL && dtemp != NULL ; temp = g_list_next (temp), dtemp = g_list_next(dtemp)) {
 		EContact *new_contact = e_contact_new ();
 		EGwItem *new_item = e_gw_item_new_empty ();
 		FullName *full_name;
+		EDestination *tdest = (EDestination *)dtemp->data;
 
-		e_contact_set (new_contact,E_CONTACT_FULL_NAME, e_contact_name_from_string (strdup (temp->data)));
-		e_contact_set (new_contact, E_CONTACT_EMAIL_1, strdup (temp->data));
+		e_contact_set (new_contact,E_CONTACT_FULL_NAME, e_contact_name_from_string (strdup (e_destination_get_email(tdest))));
+		e_contact_set (new_contact, E_CONTACT_EMAIL_1, strdup (e_destination_get_email(tdest)));
 		e_contact_set (new_contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (FALSE));
 		e_gw_item_set_item_type (new_item, E_GW_ITEM_TYPE_CONTACT);
 		e_gw_item_set_container_id (new_item, g_strdup(egwb->priv->container_id));
 		full_name = g_new0 (FullName, 1);
 		full_name->name_prefix = NULL;
-		full_name->first_name = g_strdup(temp->data);
+		full_name->first_name = g_strdup(e_destination_get_name(tdest));
 		full_name->middle_name = NULL;
 		full_name->last_name = NULL;
 		full_name->name_suffix = NULL;
@@ -956,6 +982,9 @@
 	g_list_free (members);
 	g_list_foreach (emails_without_ids, (GFunc) g_free, NULL);
 	g_list_free (emails_without_ids);
+	g_list_foreach (dest_without_ids, (GFunc) g_object_unref, NULL);
+	g_list_free (dest_without_ids);
+
 	g_list_free (items);
        	e_gw_item_set_member_list (item, group_members);
 }
@@ -2020,7 +2049,7 @@
 						g_object_unref (contact);
 					}
 					g_ptr_array_free (ids, TRUE);
-					ids->len = 0;
+					ids = NULL;
 				}
 			}
 			else {
@@ -2821,7 +2850,7 @@
 	EContact *contact;
 	EGwFilter *filter;
 	time_t mod_time;
-	char cache_time_string[25], *status_msg;
+	char cache_time_string[100], *status_msg;
 	const struct tm *tm;
 	struct stat buf;
 	char *cache_file_name;
@@ -3454,6 +3483,7 @@
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_YAHOO)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_GADUGADU)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_MSN)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_SKYPE)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_JABBER)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_GROUPWISE)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_WORK)));

Modified: branches/camel-gobject/addressbook/backends/vcf/e-book-backend-vcf.c
==============================================================================
--- branches/camel-gobject/addressbook/backends/vcf/e-book-backend-vcf.c	(original)
+++ branches/camel-gobject/addressbook/backends/vcf/e-book-backend-vcf.c	Tue Jan  6 01:56:50 2009
@@ -216,7 +216,7 @@
 static void
 set_revision (EContact *contact)
 {
-	char time_string[25] = {0};
+	char time_string[100] = {0};
 	const struct tm *tm = NULL;
 	GTimeVal tv;
 

Modified: branches/camel-gobject/addressbook/libebook/e-contact.c
==============================================================================
--- branches/camel-gobject/addressbook/libebook/e-contact.c	(original)
+++ branches/camel-gobject/addressbook/libebook/e-contact.c	Tue Jan  6 01:56:50 2009
@@ -273,7 +273,15 @@
 	/* Geo information */
 	STRUCT_FIELD	(E_CONTACT_GEO,  EVC_GEO, "geo",  N_("Geographic Information"),  FALSE, geo_getter, geo_setter, e_contact_geo_get_type),
 
-	MULTI_LIST_FIELD     (E_CONTACT_TEL,      EVC_TEL,        "phone",      N_("Telephone"),      FALSE)
+	MULTI_LIST_FIELD     (E_CONTACT_TEL,      EVC_TEL,        "phone",      N_("Telephone"),      FALSE),
+
+	ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_HOME_1,  EVC_X_SKYPE,  "im_skype_home_1",  N_("Skype Home Name 1"),         FALSE, "HOME", 0),
+	ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_HOME_2,  EVC_X_SKYPE,  "im_skype_home_2",  N_("Skype Home Name 2"),         FALSE, "HOME", 1),
+	ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_HOME_3,  EVC_X_SKYPE,  "im_skype_home_3",  N_("Skype Home Name 3"),         FALSE, "HOME", 2),
+	ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_WORK_1,  EVC_X_SKYPE,  "im_skype_work_1",  N_("Skype Work Name 1"),         FALSE, "WORK", 0),
+	ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_WORK_2,  EVC_X_SKYPE,  "im_skype_work_2",  N_("Skype Work Name 2"),         FALSE, "WORK", 1),
+	ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_WORK_3,  EVC_X_SKYPE,  "im_skype_work_3",  N_("Skype Work Name 3"),         FALSE, "WORK", 2),
+	MULTI_LIST_FIELD (E_CONTACT_IM_SKYPE,  	  EVC_X_SKYPE,     "im_skype",     N_("Skype Name List"),         FALSE)
 };
 
 #undef LIST_ELEM_STR_FIELD

Modified: branches/camel-gobject/addressbook/libebook/e-contact.h
==============================================================================
--- branches/camel-gobject/addressbook/libebook/e-contact.h	(original)
+++ branches/camel-gobject/addressbook/libebook/e-contact.h	Tue Jan  6 01:56:50 2009
@@ -199,6 +199,14 @@
 
 	E_CONTACT_TEL, /* list of strings */
 
+	E_CONTACT_IM_SKYPE_HOME_1,     /* Synthetic string field */
+	E_CONTACT_IM_SKYPE_HOME_2,     /* Synthetic string field */
+	E_CONTACT_IM_SKYPE_HOME_3,     /* Synthetic string field */
+	E_CONTACT_IM_SKYPE_WORK_1,     /* Synthetic string field */
+	E_CONTACT_IM_SKYPE_WORK_2,     /* Synthetic string field */
+	E_CONTACT_IM_SKYPE_WORK_3,     /* Synthetic string field */
+	E_CONTACT_IM_SKYPE,    	 	/* Multi-valued */
+
 	E_CONTACT_FIELD_LAST,
 	E_CONTACT_FIELD_FIRST        = E_CONTACT_UID,
 

Modified: branches/camel-gobject/addressbook/libebook/e-vcard.c
==============================================================================
--- branches/camel-gobject/addressbook/libebook/e-vcard.c	(original)
+++ branches/camel-gobject/addressbook/libebook/e-vcard.c	Tue Jan  6 01:56:50 2009
@@ -223,7 +223,7 @@
 }
 
 static void
-read_attribute_value (EVCardAttribute *attr, char **p, gboolean quoted_printable)
+read_attribute_value (EVCardAttribute *attr, char **p, gboolean quoted_printable, const char *charset)
 {
 	char *lp = *p;
 	GString *str;
@@ -289,6 +289,16 @@
 		}
 		else if ((*lp == ';') ||
 			 (*lp == ',' && !g_ascii_strcasecmp (attr->name, "CATEGORIES"))) {
+			if (charset) {
+				char *tmp;
+
+				tmp = g_convert (str->str, str->len, "UTF-8", charset, NULL, NULL, NULL);
+				if (tmp) {
+					g_string_assign (str, tmp);
+					g_free (tmp);
+				}
+			}
+
 			e_vcard_attribute_add_value (attr, str->str);
 			g_string_assign (str, "");
 			lp = g_utf8_next_char(lp);
@@ -299,6 +309,16 @@
 		}
 	}
 	if (str) {
+		if (charset) {
+			char *tmp;
+
+			tmp = g_convert (str->str, str->len, "UTF-8", charset, NULL, NULL, NULL);
+			if (tmp) {
+				g_string_assign (str, tmp);
+				g_free (tmp);
+			}
+		}
+
 		e_vcard_attribute_add_value (attr, str->str);
 		g_string_free (str, TRUE);
 	}
@@ -309,7 +329,7 @@
 }
 
 static void
-read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printable)
+read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printable, char **charset)
 {
 	char *lp;
 	GString *str;
@@ -389,6 +409,13 @@
 					*quoted_printable = TRUE;
 					e_vcard_attribute_param_free (param);
 					param = NULL;
+				} else if (param
+				    && !g_ascii_strcasecmp (param->name, "charset")
+				    && g_ascii_strcasecmp (param->values->data, "utf-8") != 0) {
+					g_free (*charset);
+					*charset = g_strdup (param->values->data);
+					e_vcard_attribute_param_free (param);
+					param = NULL;
 				}
 			}
 			else {
@@ -468,6 +495,7 @@
 	GString *str;
 	char *lp;
 	gboolean is_qp = FALSE;
+	char *charset = NULL;
 
 	/* first read in the group/name */
 	str = g_string_new ("");
@@ -533,16 +561,18 @@
 	if (*lp == ';') {
 		/* skip past the ';' */
 		lp = g_utf8_next_char(lp);
-		read_attribute_params (attr, &lp, &is_qp);
+		read_attribute_params (attr, &lp, &is_qp, &charset);
 		if (is_qp)
 			attr->encoding = EVC_ENCODING_RAW;
 	}
 	if (*lp == ':') {
 		/* skip past the ':' */
 		lp = g_utf8_next_char(lp);
-		read_attribute_value (attr, &lp, is_qp);
+		read_attribute_value (attr, &lp, is_qp, charset);
 	}
 
+	g_free (charset);
+
 	*p = lp;
 
 	if (!attr->values)

Modified: branches/camel-gobject/addressbook/libebook/e-vcard.h
==============================================================================
--- branches/camel-gobject/addressbook/libebook/e-vcard.h	(original)
+++ branches/camel-gobject/addressbook/libebook/e-vcard.h	Tue Jan  6 01:56:50 2009
@@ -81,6 +81,7 @@
 #define EVC_X_LIST          	"X-EVOLUTION-LIST"
 #define EVC_X_MANAGER       	"X-EVOLUTION-MANAGER"
 #define EVC_X_MSN           	"X-MSN"
+#define EVC_X_SKYPE           	"X-SKYPE"
 #define EVC_X_RADIO         	"X-EVOLUTION-RADIO"
 #define EVC_X_SPOUSE        	"X-EVOLUTION-SPOUSE"
 #define EVC_X_TELEX         	"X-EVOLUTION-TELEX"
@@ -88,7 +89,7 @@
 #define EVC_X_VIDEO_URL     	"X-EVOLUTION-VIDEO-URL"
 #define EVC_X_WANTS_HTML    	"X-MOZILLA-HTML"
 #define EVC_X_YAHOO         	"X-YAHOO"
-#define EVC_X_GADUGADU        "X-GADUGADU"
+#define EVC_X_GADUGADU          "X-GADUGADU"
 #define EVC_X_GROUPWISE     	"X-GROUPWISE"
 #define EVC_X_BOOK_URI     	"X-EVOLUTION-BOOK-URI"
 

Modified: branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.c
==============================================================================
--- branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.c	(original)
+++ branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.c	Tue Jan  6 01:56:50 2009
@@ -131,8 +131,8 @@
 EContact *
 e_book_backend_db_cache_get_contact (DB *db, const char *uid)
 {
-	DBT        uid_dbt, vcard_dbt;
-	int        db_error;
+	DBT	uid_dbt, vcard_dbt;
+	int	db_error;
 	EContact *contact = NULL;
 
 	g_return_val_if_fail (uid != NULL, NULL);
@@ -163,19 +163,19 @@
  **/
 gboolean
 e_book_backend_db_cache_add_contact (DB *db,
-				   EContact *contact)
+				     EContact *contact)
 {
-	DBT        uid_dbt, vcard_dbt;
-	int        db_error;
-	char       *vcard_str;
+	DBT	uid_dbt, vcard_dbt;
+	int	db_error;
+	char	*vcard_str;
 	const char *uid;
 
 	uid = e_contact_get_const (contact, E_CONTACT_UID);
 	if (!uid) {
 		printf ("no uid\n");
 		printf("name:%s, email:%s\n",
-		       (char*)e_contact_get (contact, E_CONTACT_GIVEN_NAME),
-		       (char*)e_contact_get (contact, E_CONTACT_EMAIL_1));
+			(char*)e_contact_get (contact, E_CONTACT_GIVEN_NAME),
+			(char*)e_contact_get (contact, E_CONTACT_EMAIL_1));
 		return FALSE;
 	}
 	string_to_dbt (uid, &uid_dbt);
@@ -207,11 +207,11 @@
  **/
 gboolean
 e_book_backend_db_cache_remove_contact (DB *db,
-				    const char *uid)
+					const char *uid)
 
 {
-	DBT        uid_dbt;
-	int        db_error;
+	DBT	uid_dbt;
+	int	db_error;
 
 	g_return_val_if_fail (uid != NULL, FALSE);
 
@@ -239,8 +239,8 @@
 gboolean
 e_book_backend_db_cache_check_contact (DB *db, const char *uid)
 {
-	DBT        uid_dbt, vcard_dbt;
-	int        db_error;
+	DBT	uid_dbt, vcard_dbt;
+	int	db_error;
 
 	g_return_val_if_fail (uid != NULL, FALSE);
 
@@ -271,11 +271,11 @@
 GList *
 e_book_backend_db_cache_get_contacts (DB *db, const char *query)
 {
-	DBC        *dbc;
-	DBT        uid_dbt, vcard_dbt;
-	int        db_error;
+	DBC	*dbc;
+	DBT	uid_dbt, vcard_dbt;
+	int	db_error;
 	GList *list = NULL;
-        EBookBackendSExp *sexp = NULL;
+	EBookBackendSExp *sexp = NULL;
 	EContact *contact;
 
 	if (query) {
@@ -315,7 +315,7 @@
 	if (sexp)
 		g_object_unref (sexp);
 
-        return g_list_reverse (list);
+	return g_list_reverse (list);
 }
 
 /**
@@ -381,8 +381,8 @@
 void
 e_book_backend_db_cache_set_populated (DB *db)
 {
-	DBT        uid_dbt, vcard_dbt;
-	int        db_error;
+	DBT	uid_dbt, vcard_dbt;
+	int	db_error;
 
 	string_to_dbt ("populated", &uid_dbt);
 	string_to_dbt ("TRUE", &vcard_dbt);
@@ -404,8 +404,8 @@
 gboolean
 e_book_backend_db_cache_is_populated (DB *db)
 {
-	DBT        uid_dbt, vcard_dbt;
-	int        db_error;
+	DBT	uid_dbt, vcard_dbt;
+	int	db_error;
 
 	string_to_dbt ("populated", &uid_dbt);
 	memset(&vcard_dbt, 0, sizeof(vcard_dbt));
@@ -420,3 +420,40 @@
 		return TRUE;
 	}
 }
+
+void 
+e_book_backend_db_cache_set_time(DB *db, const char *t)
+{
+	DBT uid_dbt, vcard_dbt;
+	int db_error;
+
+	string_to_dbt ("last_update_time", &uid_dbt);
+	string_to_dbt (t, &vcard_dbt);
+
+	db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db->put failed with %d", db_error);
+	}
+}
+
+char *
+e_book_backend_db_cache_get_time (DB *db)
+{
+	DBT uid_dbt, vcard_dbt;
+	int db_error;
+	char *t = NULL;
+
+	string_to_dbt ("last_update_time", &uid_dbt);
+	memset (&vcard_dbt, 0, sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db->get failed with %d", db_error);
+	} else {
+		t = g_strdup (vcard_dbt.data);
+		free (vcard_dbt.data);
+	}
+
+	return t;
+}

Modified: branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.h
==============================================================================
--- branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.h	(original)
+++ branches/camel-gobject/addressbook/libedata-book/e-book-backend-db-cache.h	Tue Jan  6 01:56:50 2009
@@ -25,6 +25,8 @@
 #include <libebook/e-contact.h>
 #include "db.h"
 
+G_BEGIN_DECLS
+
 EContact* e_book_backend_db_cache_get_contact (DB *db, const char *uid);
 void string_to_dbt(const char *str, DBT *dbt);
 char *e_book_backend_db_cache_get_filename(DB *db);
@@ -39,9 +41,8 @@
 void     e_book_backend_db_cache_set_populated (DB *db);
 gboolean e_book_backend_db_cache_is_populated (DB *db);
 GPtrArray* e_book_backend_db_cache_search (DB *db, const char *query);
-
-
-
+void e_book_backend_db_cache_set_time(DB *db, const char *t);
+char * e_book_backend_db_cache_get_time (DB *db); 
 
 G_END_DECLS
 

Modified: branches/camel-gobject/addressbook/libedata-book/e-book-backend-sexp.c
==============================================================================
--- branches/camel-gobject/addressbook/libedata-book/e-book-backend-sexp.c	(original)
+++ branches/camel-gobject/addressbook/libedata-book/e-book-backend-sexp.c	Tue Jan  6 01:56:50 2009
@@ -76,6 +76,13 @@
 }
 
 static gboolean
+compare_im_skype (EContact *contact, const char *str,
+		char *(*compare)(const char*, const char*))
+{
+	return compare_im (contact, str, compare, E_CONTACT_IM_SKYPE);
+}
+
+static gboolean
 compare_im_icq (EContact *contact, const char *str,
 		char *(*compare)(const char*, const char*))
 {
@@ -266,6 +273,7 @@
 	NORMAL_PROP ( E_CONTACT_NOTE, "note"),
 	LIST_PROP ( "im_aim",    compare_im_aim ),
 	LIST_PROP ( "im_msn",    compare_im_msn ),
+	LIST_PROP ( "im_skype",    compare_im_skype ),
 	LIST_PROP ( "im_icq",    compare_im_icq ),
 	LIST_PROP ( "im_jabber", compare_im_jabber ),
 	LIST_PROP ( "im_yahoo",  compare_im_yahoo ),

Modified: branches/camel-gobject/addressbook/libedata-book/e-book-backend.c
==============================================================================
--- branches/camel-gobject/addressbook/libedata-book/e-book-backend.c	(original)
+++ branches/camel-gobject/addressbook/libedata-book/e-book-backend.c	Tue Jan  6 01:56:50 2009
@@ -476,12 +476,21 @@
 	e_book_backend_remove_client (backend, (EDataBook *)where_book_was);
 }
 
-static void
-listener_died_cb (gpointer cnx, gpointer user_data)
+static gboolean
+idle_remove_client (gpointer data)
 {
-	EDataBook *book = E_DATA_BOOK (user_data);
+	EDataBook *book = (EDataBook *) data;
 
 	e_book_backend_remove_client (e_data_book_get_backend (book), book);
+	g_object_unref ((GObject *) book);
+
+	return FALSE;
+}
+static void
+listener_died_cb (gpointer cnx, gpointer user_data)
+{
+	g_object_ref ((GObject *)user_data);
+	g_idle_add (idle_remove_client, user_data);
 }
 
 static void

Modified: branches/camel-gobject/addressbook/libedata-book/e-data-book-view.c
==============================================================================
--- branches/camel-gobject/addressbook/libedata-book/e-data-book-view.c	(original)
+++ branches/camel-gobject/addressbook/libedata-book/e-data-book-view.c	Tue Jan  6 01:56:50 2009
@@ -247,7 +247,6 @@
 
 	id = e_contact_get_const (contact, E_CONTACT_UID);
 	if (!id) {
-		g_object_unref (contact);
 		g_mutex_unlock (book_view->priv->pending_mutex);
 		return;
 	}

Modified: branches/camel-gobject/calendar/backends/Makefile.am
==============================================================================
--- branches/camel-gobject/calendar/backends/Makefile.am	(original)
+++ branches/camel-gobject/calendar/backends/Makefile.am	Tue Jan  6 01:56:50 2009
@@ -1 +1,7 @@
-SUBDIRS = file groupwise http contacts weather caldav google
+if ENABLE_WEATHER
+WEATHER_SUBDIR = weather
+else
+WEATHER_SUBDIR =
+endif
+
+SUBDIRS = file groupwise http contacts $(WEATHER_SUBDIR) caldav google

Modified: branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav-factory.c
==============================================================================
--- branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav-factory.c	(original)
+++ branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav-factory.c	Tue Jan  6 01:56:50 2009
@@ -32,79 +32,92 @@
 #include "e-cal-backend-caldav.h"
 
 typedef struct {
-	   ECalBackendFactory parent_object;
+	ECalBackendFactory parent_object;
 } ECalBackendCalDAVFactory;
 
 typedef struct {
-	   ECalBackendFactoryClass parent_class;
+	ECalBackendFactoryClass parent_class;
 } ECalBackendCalDAVFactoryClass;
 
 static void
-e_cal_backend_caldav_factory_instance_init (ECalBackendCalDAVFactory *factory)
+ecb_caldav_factory_instance_init (ECalBackendCalDAVFactory *factory)
 {
 }
 
 static const char *
 _get_protocol (ECalBackendFactory *factory)
 {
-	   return "caldav";
-}
-
-static ECalBackend*
-_events_new_backend (ECalBackendFactory *factory, ESource *source)
-{
-	   return g_object_new (E_TYPE_CAL_BACKEND_CALDAV,
-					    "source", source,
-					    "kind", ICAL_VEVENT_COMPONENT,
-					    NULL);
-}
-
-static icalcomponent_kind
-_events_get_kind (ECalBackendFactory *factory)
-{
-	   return ICAL_VEVENT_COMPONENT;
-}
-
-static void
-events_backend_factory_class_init (ECalBackendCalDAVFactoryClass *klass)
-{
-	   E_CAL_BACKEND_FACTORY_CLASS (klass)->get_protocol = _get_protocol;
-	   E_CAL_BACKEND_FACTORY_CLASS (klass)->get_kind     = _events_get_kind;
-	   E_CAL_BACKEND_FACTORY_CLASS (klass)->new_backend  = _events_new_backend;
-}
-
-static GType
-events_backend_factory_get_type (GTypeModule *module)
-{
-	   GType type;
-
-	   GTypeInfo info = {
-			 sizeof (ECalBackendCalDAVFactoryClass),
-			 NULL, /* base_class_init */
-			 NULL, /* base_class_finalize */
-			 (GClassInitFunc)  events_backend_factory_class_init,
-			 NULL, /* class_finalize */
-			 NULL, /* class_data */
-			 sizeof (ECalBackend),
-			 0,    /* n_preallocs */
-			 (GInstanceInitFunc) e_cal_backend_caldav_factory_instance_init
-	   };
-
-	   type = g_type_module_register_type (module,
-								    E_TYPE_CAL_BACKEND_FACTORY,
-								    "ECalBackendCalDAVEventsFactory",
-								    &info, 0);
-
-	   return type;
+	return "caldav";
 }
 
+#define declare_functions(_type,_name)						\
+										\
+static ECalBackend*								\
+_new_backend_ ## _type (ECalBackendFactory *factory, ESource *source)		\
+{										\
+	   return g_object_new (E_TYPE_CAL_BACKEND_CALDAV,			\
+				"source", source,				\
+				"kind", ICAL_ ## _type ## _COMPONENT,		\
+				NULL);						\
+}										\
+										\
+static icalcomponent_kind							\
+_get_kind_ ## _type (ECalBackendFactory *factory)				\
+{										\
+	return ICAL_ ## _type ## _COMPONENT;					\
+}										\
+										\
+static void									\
+_backend_factory_class_init_ ## _type (ECalBackendCalDAVFactoryClass *klass)	\
+{										\
+	ECalBackendFactoryClass *bc =  E_CAL_BACKEND_FACTORY_CLASS (klass);	\
+										\
+	g_return_if_fail (bc != NULL);						\
+										\
+	bc->get_protocol = _get_protocol;					\
+	bc->get_kind     = _get_kind_ ## _type;					\
+	bc->new_backend  = _new_backend_ ## _type;				\
+}										\
+										\
+static GType									\
+backend_factory_get_type_ ## _type (GTypeModule *module)			\
+{										\
+	static GType type = 0;							\
+										\
+	GTypeInfo info = {							\
+		sizeof (ECalBackendCalDAVFactoryClass),				\
+		NULL, /* base_class_init */					\
+		NULL, /* base_class_finalize */					\
+		(GClassInitFunc)  _backend_factory_class_init_ ## _type,	\
+		NULL, /* class_finalize */					\
+		NULL, /* class_data */						\
+		sizeof (ECalBackend),						\
+		0,    /* n_preallocs */						\
+		(GInstanceInitFunc) ecb_caldav_factory_instance_init		\
+	   };									\
+										\
+	if (!type) {   								\
+		type = g_type_module_register_type (module,			\
+			E_TYPE_CAL_BACKEND_FACTORY,				\
+			_name,							\
+			&info, 0);						\
+	}									\
+										\
+	return type;								\
+}										\
+
+declare_functions (VEVENT,   "ECalBackendCalDAVEventsFactory");
+declare_functions (VTODO,    "ECalBackendCalDAVTodosFactory");
+declare_functions (VJOURNAL, "ECalBackendCalDAVMemosFactory");
 
-static GType caldav_types[1];
+static GType caldav_types[3];
 
 void
 eds_module_initialize (GTypeModule *module)
 {
-	   caldav_types[0] = events_backend_factory_get_type (module);
+	caldav_types[0] = backend_factory_get_type_VEVENT   (module);
+	caldav_types[1] = backend_factory_get_type_VTODO    (module);
+	caldav_types[2] = backend_factory_get_type_VJOURNAL (module);
 }
 
 void
@@ -115,6 +128,6 @@
 void
 eds_module_list_types (const GType **types, int *num_types)
 {
-	   *types = caldav_types;
-	   *num_types = 1;
+	*types = caldav_types;
+	*num_types = 3;
 }

Modified: branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav.c
==============================================================================
--- branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav.c	(original)
+++ branches/camel-gobject/calendar/backends/caldav/e-cal-backend-caldav.c	Tue Jan  6 01:56:50 2009
@@ -74,9 +74,6 @@
 	/* TRUE after caldav_open */
 	gboolean loaded;
 
-	/* the open status  */
-	ECalBackendSyncStatus ostatus;
-
 	/* lock to protect cache */
 	GMutex *lock;
 
@@ -87,7 +84,7 @@
 	GCond *slave_gone_cond;
 
 	/* BG synch thread */
-	GThread *synch_slave;
+	const GThread *synch_slave; /* just for a reference, whether thread exists */
 	SlaveCommand slave_cmd;
 	GTimeVal refresh_time;
 	gboolean do_synch;
@@ -115,6 +112,10 @@
 	gboolean disposed;
 
 	icaltimezone *default_zone;
+
+	/* support for 'getctag' extension */
+	gboolean ctag_supported;
+	gchar *ctag;
 };
 
 /* ************************************************************************* */
@@ -123,6 +124,7 @@
 #define DEBUG_MESSAGE "message"
 #define DEBUG_MESSAGE_HEADER "message:header"
 #define DEBUG_MESSAGE_BODY "message:body"
+#define DEBUG_SERVER_ITEMS "items"
 
 static gboolean caldav_debug_all = FALSE;
 static GHashTable *caldav_debug_table = NULL;
@@ -151,7 +153,7 @@
 			     debug_key,
 			     debug_value);
 
-	g_debug ("Adding %s to enabled debugging keys", debug_key);
+	d(g_debug ("Adding %s to enabled debugging keys", debug_key));
 }
 
 static gpointer
@@ -164,7 +166,7 @@
 	if (dbg) {
 		const char *ptr;
 
-		g_debug ("Got debug env variable: [%s]", dbg);
+		d(g_debug ("Got debug env variable: [%s]", dbg));
 
 		caldav_debug_table = g_hash_table_new (g_str_hash,
 						       g_str_equal);
@@ -466,7 +468,7 @@
 
 	*online = FALSE;
 
-	if (priv->loaded != TRUE) {
+	if (!priv->loaded) {
 		return GNOME_Evolution_Calendar_OtherError;
 	}
 
@@ -542,13 +544,14 @@
 static char *
 xp_object_get_string (xmlXPathObjectPtr result)
 {
-	char *ret;
+	char *ret = NULL;
 
-	if (result == NULL || result->type != XPATH_STRING) {
-		return NULL;
-	}
+	if (result == NULL)
+		return ret;
 
-	ret = g_strdup ((char *) result->stringval);
+	if (result->type == XPATH_STRING) {
+		ret = g_strdup ((char *) result->stringval);
+	}
 
 	xmlXPathFreeObject (result);
 	return ret;
@@ -559,23 +562,26 @@
 static char *
 xp_object_get_href (xmlXPathObjectPtr result)
 {
-	char *ret;
+	char *ret = NULL;
 	char *val;
 
-	if (result == NULL || result->type != XPATH_STRING) {
-		return NULL;
-	}
+	if (result == NULL)
+		return ret;
 
-	val = (char *) result->stringval;
+	if (result->type == XPATH_STRING) {
+		val = (char *) result->stringval;
 
-	if ((ret = g_strrstr (val, "/")) == NULL) {
-		ret = val;
-	} else {
-		ret++; /* skip the unwanted "/" */
-	}
+		if ((ret = g_strrstr (val, "/")) == NULL) {
+			ret = val;
+		} else {
+			ret++; /* skip the unwanted "/" */
+		}
+
+		ret = g_strdup (ret);
 
-	ret = g_strdup (ret);
-	d(g_debug ("found href: %s", ret));
+		if (caldav_debug_show (DEBUG_SERVER_ITEMS))
+			printf ("CalDAV found href: %s\n", ret);
+	}
 
 	xmlXPathFreeObject (result);
 	return ret;
@@ -585,16 +591,17 @@
 static char *
 xp_object_get_etag (xmlXPathObjectPtr result)
 {
-	char *ret;
+	char *ret = NULL;
 	char *str;
 
-	if (result == NULL || result->type != XPATH_STRING) {
-		return NULL;
-	}
+	if (result == NULL)
+		return ret;
 
-	str = (char *) result->stringval;
+	if (result->type == XPATH_STRING) {
+		str = (char *) result->stringval;
 
-	ret = quote_etag (str);
+		ret = quote_etag (str);
+	}
 
 	xmlXPathFreeObject (result);
 	return ret;
@@ -604,20 +611,20 @@
 xp_object_get_status (xmlXPathObjectPtr result)
 {
 	gboolean res;
-	guint    ret;
-
+	guint    ret = 0;
 
-	if (result == NULL || result->type != XPATH_STRING) {
-		return 0;
-	}
+	if (result == NULL)
+		return ret;
 
-	res = soup_headers_parse_status_line ((char *) result->stringval,
-					      NULL,
-					      &ret,
-					      NULL);
+	if (result->type == XPATH_STRING) {
+		res = soup_headers_parse_status_line ((char *) result->stringval,
+							NULL,
+							&ret,
+							NULL);
 
-	if (res != TRUE) {
-		ret = 0;
+		if (!res) {
+			ret = 0;
+		}
 	}
 
 	xmlXPathFreeObject (result);
@@ -628,13 +635,14 @@
 static int
 xp_object_get_number (xmlXPathObjectPtr result)
 {
-	int ret;
+	int ret = -1;
 
-	if (result == NULL || result->type != XPATH_STRING) {
-		return -1;
-	}
+	if (result == NULL)
+		return ret;
 
-	ret = result->boolval;
+	if (result->type == XPATH_STRING) {
+		ret = result->boolval;
+	}
 
 	xmlXPathFreeObject (result);
 	return ret;
@@ -647,7 +655,8 @@
 #define XPATH_GETETAG_STATUS "string(/D:multistatus/D:response[%d]/D:propstat/D:prop/D:getetag/../../D:status)"
 #define XPATH_GETETAG "string(/D:multistatus/D:response[%d]/D:propstat/D:prop/D:getetag)"
 #define XPATH_CALENDAR_DATA "string(/D:multistatus/D:response[%d]/C:calendar-data)"
-
+#define XPATH_GETCTAG_STATUS "string(/D:multistatus/D:response/D:propstat/D:prop/CS:getctag/../../D:status)"
+#define XPATH_GETCTAG "string(/D:multistatus/D:response/D:propstat/D:prop/CS:getctag)"
 
 typedef struct _CalDAVObject CalDAVObject;
 
@@ -750,6 +759,8 @@
 	}
 
 out:
+	if (result != NULL)
+		xmlXPathFreeObject (result);
 	xmlXPathFreeContext (xpctx);
 	xmlFreeDoc (doc);
 	return res;
@@ -771,7 +782,9 @@
 	cbdav = E_CAL_BACKEND_CALDAV (data);
 	priv = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
 
-	soup_auth_authenticate (auth, priv->username, priv->password);
+	/* do not send same password twice, but keep it for later use */
+	if (!retrying)
+		soup_auth_authenticate (auth, priv->username, priv->password);
 }
 
 static gint
@@ -905,8 +918,8 @@
 
 	priv = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
 
-	/* priv->uri must NOT have trailing slash */
-	uri = g_strconcat (priv->uri, "/" , target, NULL);
+	/* priv->uri *have* trailing slash already */
+	uri = g_strconcat (priv->uri, target, NULL);
 
 	return uri;
 }
@@ -926,6 +939,8 @@
 	/* FIXME: setup text_uri */
 
 	message = soup_message_new (SOUP_METHOD_OPTIONS, priv->uri);
+	if (message == NULL)
+		return GNOME_Evolution_Calendar_NoSuchCal;
 	soup_message_headers_append (message->request_headers,
 				     "User-Agent", "Evolution/" VERSION);
 
@@ -967,6 +982,139 @@
 	return GNOME_Evolution_Calendar_NoSuchCal;
 }
 
+/* returns whether was able to read new ctag from the server's response */
+static gboolean
+parse_getctag_response (SoupMessage *message, gchar **new_ctag)
+{
+	xmlXPathContextPtr xpctx;
+	xmlDocPtr          doc;
+	gboolean           res = FALSE;
+
+	g_return_val_if_fail (message != NULL, FALSE);
+	g_return_val_if_fail (new_ctag != NULL, FALSE);
+
+	doc = xmlReadMemory (message->response_body->data,
+			     message->response_body->length,
+			     "response.xml",
+			     NULL,
+			     0);
+
+	if (doc == NULL) {
+		return FALSE;
+	}
+
+	xpctx = xmlXPathNewContext (doc);
+	xmlXPathRegisterNs (xpctx, (xmlChar *) "D", (xmlChar *) "DAV:");
+	xmlXPathRegisterNs (xpctx, (xmlChar *) "CS", (xmlChar *) "http://calendarserver.org/ns/";);
+
+	if (xp_object_get_status (xpath_eval (xpctx, XPATH_GETCTAG_STATUS)) == 200) {
+		char *txt = xp_object_get_string (xpath_eval (xpctx, XPATH_GETCTAG));
+
+		if (txt && *txt) {
+			int len = strlen (txt);
+
+			if (*txt == '\"' && len > 2 && txt [len - 1] == '\"') {
+				/* dequote */
+				*new_ctag = g_strndup (txt + 1, len - 2);
+			} else {
+				*new_ctag = txt;
+				txt = NULL;
+			}
+
+			res = (*new_ctag) != NULL;
+		}
+
+		g_free (txt);
+	}
+
+	xmlXPathFreeContext (xpctx);
+	xmlFreeDoc (doc);
+
+	return res;
+}
+
+/* Returns whether calendar changed on the server. This works only when server
+   supports 'getctag' extension. */
+static gboolean
+check_calendar_changed_on_server (ECalBackendCalDAV *cbdav)
+{
+	ECalBackendCalDAVPrivate *priv;
+	xmlOutputBufferPtr   	  buf;
+	SoupMessage              *message;
+	xmlDocPtr		  doc;
+	xmlNodePtr           	  root, node;
+	xmlNsPtr		  ns, nsdav;
+	gboolean 		  result = TRUE;
+
+	g_return_val_if_fail (cbdav != NULL, TRUE);
+
+	priv   = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
+
+	/* no support for 'getctag', thus update cache */
+	if (!priv->ctag_supported)
+		return TRUE;
+
+	/* Prepare the soup message */
+	message = soup_message_new ("PROPFIND", priv->uri);
+	if (message == NULL)
+		return FALSE;
+
+	doc = xmlNewDoc ((xmlChar *) "1.0");
+	root = xmlNewNode (NULL, (xmlChar *) "propfind");
+	nsdav = xmlNewNs (root, (xmlChar *) "DAV:", NULL);
+	ns = xmlNewNs (root, (xmlChar *) "http://calendarserver.org/ns/";, (xmlChar *) "CS");
+
+	node = xmlNewTextChild (root, nsdav, (xmlChar *) "prop", NULL);
+	node = xmlNewTextChild (node, nsdav, (xmlChar *) "getctag", NULL);
+	xmlSetNs (node, ns);
+
+	buf = xmlAllocOutputBuffer (NULL);
+	xmlNodeDumpOutput (buf, doc, root, 0, 1, NULL);
+	xmlOutputBufferFlush (buf);
+
+	soup_message_headers_append (message->request_headers,
+				     "User-Agent", "Evolution/" VERSION);
+	soup_message_headers_append (message->request_headers,
+				     "Depth", "0");
+
+	soup_message_set_request (message,
+				  "application/xml",
+				  SOUP_MEMORY_COPY,
+				  (char *) buf->buffer->content,
+				  buf->buffer->use);
+
+	/* Send the request now */
+	send_and_handle_redirection (priv->session, message, NULL);
+
+	/* Clean up the memory */
+	xmlOutputBufferClose (buf);
+	xmlFreeDoc (doc);
+
+	/* Check the result */
+	if (message->status_code != 207) {
+		/* does not support it, but report calendar changed to update cache */
+		priv->ctag_supported = FALSE;
+	} else {
+		char *ctag = NULL;
+
+		if (parse_getctag_response (message, &ctag)) {
+			if (ctag && priv->ctag && g_str_equal (ctag, priv->ctag)) {
+				/* ctag is same, no change in the calendar */
+				result = FALSE;
+				g_free (ctag);
+			} else {
+				g_free (priv->ctag);
+				priv->ctag = ctag;
+			}
+		} else {
+			priv->ctag_supported = FALSE;
+		}
+	}
+
+	g_object_unref (message);
+
+	return result;
+}
 
 static gboolean
 caldav_server_list_objects (ECalBackendCalDAV *cbdav, CalDAVObject **objs, int *len)
@@ -983,6 +1131,10 @@
 	gboolean             result;
 
 	priv = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
+	/* Allocate the soup message */
+	message = soup_message_new ("REPORT", priv->uri);
+	if (message == NULL)
+		return FALSE;
 
 	/* Maybe we should just do a g_strdup_printf here? */
 	/* Prepare request body */
@@ -1002,7 +1154,18 @@
 	xmlSetProp (node, (xmlChar *) "name", (xmlChar *) "VCALENDAR");
 
 	sn = xmlNewTextChild (node, nscd, (xmlChar *) "comp-filter", NULL);
-	xmlSetProp (sn, (xmlChar *) "name", (xmlChar *) "VEVENT");
+	switch (e_cal_backend_get_kind (E_CAL_BACKEND (cbdav))) {
+		default:
+		case ICAL_VEVENT_COMPONENT:
+			xmlSetProp (sn, (xmlChar *) "name", (xmlChar *) "VEVENT");
+			break;
+		case ICAL_VJOURNAL_COMPONENT:
+			xmlSetProp (sn, (xmlChar *) "name", (xmlChar *) "VJOURNAL");
+			break;
+		case ICAL_VTODO_COMPONENT:
+			xmlSetProp (sn, (xmlChar *) "name", (xmlChar *) "VTODO");
+			break;
+	}
 	/* ^^^ add timerange for performance?  */
 
 
@@ -1011,7 +1174,6 @@
 	xmlOutputBufferFlush (buf);
 
 	/* Prepare the soup message */
-	message = soup_message_new ("REPORT", priv->uri);
 	soup_message_headers_append (message->request_headers,
 				     "User-Agent", "Evolution/" VERSION);
 	soup_message_headers_append (message->request_headers,
@@ -1032,7 +1194,9 @@
 
 	/* Check the result */
 	if (message->status_code != 207) {
-		g_warning ("Sever did not response with 207, but with code %d\n", message->status_code);
+		g_warning ("Server did not response with 207, but with code %d (%s)", message->status_code, soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : "Unknown code");
+
+		g_object_unref (message);
 		return FALSE;
 	}
 
@@ -1061,6 +1225,8 @@
 	uri = caldav_generate_uri (cbdav, object->href);
 	message = soup_message_new (SOUP_METHOD_GET, uri);
 	g_free (uri);
+	if (message == NULL)
+		return GNOME_Evolution_Calendar_NoSuchCal;
 
 	soup_message_headers_append (message->request_headers,
 				     "User-Agent", "Evolution/" VERSION);
@@ -1117,6 +1283,8 @@
 	uri = caldav_generate_uri (cbdav, object->href);
 	message = soup_message_new (SOUP_METHOD_PUT, uri);
 	g_free (uri);
+	if (message == NULL)
+		return GNOME_Evolution_Calendar_NoSuchCal;
 
 	soup_message_headers_append (message->request_headers,
 				     "User-Agent", "Evolution/" VERSION);
@@ -1188,6 +1356,8 @@
 	uri = caldav_generate_uri (cbdav, object->href);
 	message = soup_message_new (SOUP_METHOD_DELETE, uri);
 	g_free (uri);
+	if (message == NULL)
+		return GNOME_Evolution_Calendar_NoSuchCal;
 
 	soup_message_headers_append (message->request_headers,
 				     "User-Agent", "Evolution/" VERSION);
@@ -1240,31 +1410,34 @@
 	bkend = E_CAL_BACKEND (cbdav);
 
 	if (kind == ICAL_VCALENDAR_COMPONENT) {
-
 		kind = e_cal_backend_get_kind (bkend);
 		subcomp = icalcomponent_get_first_component (icomp, kind);
 
-		comp = e_cal_component_new ();
-		res = e_cal_component_set_icalcomponent (comp,
+		if (!subcomp) {
+			res = FALSE;
+		} else {
+			comp = e_cal_component_new ();
+			res = e_cal_component_set_icalcomponent (comp,
 						   icalcomponent_new_clone (subcomp));
-		if (res == TRUE) {
-			icaltimezone *zone = icaltimezone_new ();
+			if (res) {
+				icaltimezone *zone = icaltimezone_new ();
 
-			e_cal_component_set_href (comp, object->href);
-			e_cal_component_set_etag (comp, object->etag);
+				e_cal_component_set_href (comp, object->href);
+				e_cal_component_set_etag (comp, object->etag);
 
-			for (subcomp = icalcomponent_get_first_component (icomp, ICAL_VTIMEZONE_COMPONENT);
-			    subcomp;
-			    subcomp = icalcomponent_get_next_component (icomp, ICAL_VTIMEZONE_COMPONENT)) {
-				/* copy timezones of the component to our cache to have it available later */
-				if (icaltimezone_set_component (zone, subcomp))
-					e_cal_backend_cache_put_timezone (priv->cache, zone);
-			}
+				for (subcomp = icalcomponent_get_first_component (icomp, ICAL_VTIMEZONE_COMPONENT);
+				    subcomp;
+				    subcomp = icalcomponent_get_next_component (icomp, ICAL_VTIMEZONE_COMPONENT)) {
+					/* copy timezones of the component to our cache to have it available later */
+					if (icaltimezone_set_component (zone, subcomp))
+						e_cal_backend_cache_put_timezone (priv->cache, zone);
+				}
 
-			icaltimezone_free (zone, TRUE);
-		} else {
-			g_object_unref (comp);
-			comp = NULL;
+				icaltimezone_free (zone, TRUE);
+			} else {
+				g_object_unref (comp);
+				comp = NULL;
+			}
 		}
 	} else {
 		res = FALSE;
@@ -1272,7 +1445,7 @@
 
 	icalcomponent_free (icomp);
 
-	if (res == FALSE) {
+	if (!res) {
 		return res;
 	}
 
@@ -1316,13 +1489,15 @@
 	len    = 0;
 	sobjs  = NULL;
 
+	if (!check_calendar_changed_on_server (cbdav)) {
+		/* no changes on the server, no update required */
+		return;
+	}
+
 	res = caldav_server_list_objects (cbdav, &sobjs, &len);
 
-	if (res == FALSE) {
-		/* FIXME: bloek! */
-		g_warning ("Could not synch server BLehh!");
+	if (!res)
 		return;
-	}
 
 	hindex = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 	cobjs = e_cal_backend_cache_get_components (bcache);
@@ -1365,7 +1540,7 @@
 			res = synchronize_object (cbdav, object, ccomp, &created, &modified);
 		}
 
-		if (res == TRUE) {
+		if (res) {
 			cobjs = g_list_remove (cobjs, ccomp);
 		}
 
@@ -1473,6 +1648,8 @@
 	/* signal we are done */
 	g_cond_signal (priv->slave_gone_cond);
 
+	priv->synch_slave = NULL;
+
 	/* we got killed ... */
 	g_mutex_unlock (priv->lock);
 	return NULL;
@@ -1550,7 +1727,6 @@
 	ECalBackendSyncStatus     result;
 	ECalBackendCalDAVPrivate *priv;
 	ESource                  *source;
-	GThread			 *slave;
 	const char		 *os_val;
 	const char               *uri;
 	gsize                     len;
@@ -1568,14 +1744,13 @@
 	}
 
 	os_val = e_source_get_property (source, "auth");
-
-	if (os_val) {
-		priv->need_auth = TRUE;
-	}
+	priv->need_auth = os_val != NULL;
 
 	os_val = e_source_get_property(source, "ssl");
 	uri = e_cal_backend_get_uri (E_CAL_BACKEND (cbdav));
 
+	g_free (priv->uri);
+	priv->uri = NULL;
 	if (g_str_has_prefix (uri, "caldav://")) {
 		const char *proto;
 
@@ -1586,13 +1761,11 @@
 		}
 
 		priv->uri = g_strconcat (proto, uri + 9, NULL);
-
 	} else {
-
 		priv->uri = g_strdup (uri);
 	}
 
-	/* remove trailing slashes */
+	/* remove trailing slashes... */
 	len = strlen (priv->uri);
 	while (len--) {
 		if (priv->uri[len] == '/') {
@@ -1602,8 +1775,32 @@
 		}
 	}
 
+	/* ...and append exactly one slash */
+	if (priv->uri && *priv->uri) {
+		char *tmp = priv->uri;
+
+		priv->uri = g_strconcat (priv->uri, "/", NULL);
+
+		g_free (tmp);
+	}
+
 	if (priv->cache == NULL) {
-		priv->cache = e_cal_backend_cache_new (priv->uri, E_CAL_SOURCE_TYPE_EVENT);
+		ECalSourceType source_type;
+
+		switch (e_cal_backend_get_kind (E_CAL_BACKEND (cbdav))) {
+			default:
+			case ICAL_VEVENT_COMPONENT:
+				source_type = E_CAL_SOURCE_TYPE_EVENT;
+				break;
+			case ICAL_VTODO_COMPONENT:
+				source_type = E_CAL_SOURCE_TYPE_TODO;
+				break;
+			case ICAL_VJOURNAL_COMPONENT:
+				source_type = E_CAL_SOURCE_TYPE_JOURNAL;
+				break;
+		}
+
+		priv->cache = e_cal_backend_cache_new (priv->uri, source_type);
 
 		if (priv->cache == NULL) {
 			result = GNOME_Evolution_Calendar_OtherError;
@@ -1615,17 +1812,20 @@
 	refresh = e_source_get_property (source, "refresh");
 	priv->refresh_time.tv_sec  = (refresh && atoi (refresh) > 0) ? (60 * atoi (refresh)) : (DEFAULT_REFRESH_TIME);
 
-	priv->slave_cmd = SLAVE_SHOULD_SLEEP;
-	slave = g_thread_create (synch_slave_loop, cbdav, FALSE, NULL);
+	if (!priv->synch_slave) {
+		GThread *slave;
 
-	if (slave == NULL) {
-		g_warning ("Could not create synch slave");
-		result = GNOME_Evolution_Calendar_OtherError;
-	}
+		priv->slave_cmd = SLAVE_SHOULD_SLEEP;
+		slave = g_thread_create (synch_slave_loop, cbdav, FALSE, NULL);
 
-	priv->report_changes = TRUE;
-	priv->synch_slave = slave;
-	priv->loaded = TRUE;
+		if (slave == NULL) {
+			g_warning ("Could not create synch slave");
+			result = GNOME_Evolution_Calendar_OtherError;
+		}
+
+		priv->report_changes = TRUE;
+		priv->synch_slave = slave;
+	}
 out:
 	return result;
 }
@@ -1648,32 +1848,39 @@
 
 	g_mutex_lock (priv->lock);
 
-	if (priv->loaded != TRUE) {
-		priv->ostatus = initialize_backend (cbdav);
+	/* let it decide the 'getctag' extension availability again */
+	g_free (priv->ctag);
+	priv->ctag = NULL;
+	priv->ctag_supported = TRUE;
+
+	if (!priv->loaded) {
+		status = initialize_backend (cbdav);
 	}
 
-	if (priv->ostatus != GNOME_Evolution_Calendar_Success) {
+	if (status != GNOME_Evolution_Calendar_Success) {
 		g_mutex_unlock (priv->lock);
 		return status;
 	}
 
-
-	if (priv->need_auth == TRUE) {
+	if (priv->need_auth) {
 		if ((username == NULL || password == NULL)) {
 			g_mutex_unlock (priv->lock);
 			return GNOME_Evolution_Calendar_AuthenticationRequired;
 		}
 
+		g_free (priv->username);
 		priv->username = g_strdup (username);
+		g_free (priv->password);
 		priv->password = g_strdup (password);
-		priv->need_auth = FALSE;
 	}
 
-	if (! priv->do_offline && priv->mode == CAL_MODE_LOCAL) {
+	if (!priv->do_offline && priv->mode == CAL_MODE_LOCAL) {
 		g_mutex_unlock (priv->lock);
 		return GNOME_Evolution_Calendar_RepositoryOffline;
 	}
 
+	priv->loaded = TRUE;
+
 	if (priv->mode == CAL_MODE_REMOTE) {
 		/* set forward proxy */
 		caldav_set_session_proxy (priv);
@@ -1707,7 +1914,7 @@
 
 	g_mutex_lock (priv->lock);
 
-	if (priv->loaded != TRUE) {
+	if (!priv->loaded) {
 		g_mutex_unlock (priv->lock);
 		return GNOME_Evolution_Calendar_Success;
 	}
@@ -1722,7 +1929,14 @@
 	priv->cache  = NULL;
 	priv->loaded = FALSE;
 	priv->slave_cmd = SLAVE_SHOULD_DIE;
-	g_cond_signal (priv->cond);
+
+	if (priv->synch_slave) {
+		g_cond_signal (priv->cond);
+
+		/* wait until the slave died */
+		g_cond_wait (priv->slave_gone_cond, priv->lock);
+	}
+
 	g_mutex_unlock (priv->lock);
 
 	return GNOME_Evolution_Calendar_Success;
@@ -2099,7 +2313,6 @@
 						   ekind);
 
 	while (scomp) {
-
 		/* Remove components from toplevel here */
 		*objects = g_list_prepend (*objects, scomp);
 		icalcomponent_remove_component (icomp, scomp);
@@ -2307,8 +2520,7 @@
 		return GNOME_Evolution_Calendar_InvalidObject;
 	}
 
-	/* FIXME: use the e_cal_backend_xxx_kind call here */
-	kind = ICAL_VEVENT_COMPONENT;
+	kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
 	status = extract_objects (icomp, kind, &objects);
 
 	if (status != GNOME_Evolution_Calendar_Success) {
@@ -2393,7 +2605,22 @@
 	ECalComponent *comp;
 
  	comp = e_cal_component_new ();
-	e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+
+ 	switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+ 	case ICAL_VEVENT_COMPONENT:
+ 		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+ 		break;
+ 	case ICAL_VTODO_COMPONENT:
+ 		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+ 		break;
+ 	case ICAL_VJOURNAL_COMPONENT:
+ 		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
+ 		break;
+ 	default:
+ 		g_object_unref (comp);
+		return GNOME_Evolution_Calendar_ObjectNotFound;
+ 	}
+
  	*object = e_cal_component_get_as_string (comp);
  	g_object_unref (comp);
 
@@ -2578,7 +2805,7 @@
 	for (iter = list; iter; iter = g_list_next (iter)) {
 		ECalComponent *comp = E_CAL_COMPONENT (iter->data);
 
-		if (do_search == FALSE ||
+		if (!do_search ||
 		    e_cal_backend_sexp_match_comp (sexp, comp, bkend)) {
 			char *str = e_cal_component_get_as_string (comp);
 			*objects = g_list_prepend (*objects, str);
@@ -2629,7 +2856,7 @@
 	for (iter = list; iter; iter = g_list_next (iter)) {
 		ECalComponent *comp = E_CAL_COMPONENT (iter->data);
 
-		if (do_search == FALSE ||
+		if (!do_search ||
 		    e_cal_backend_sexp_match_comp (sexp, comp, bkend)) {
 			char *str = e_cal_component_get_as_string (comp);
 			e_data_cal_view_notify_objects_added_1 (query, str);
@@ -2676,14 +2903,14 @@
 
 static gboolean
 caldav_is_loaded (ECalBackend *backend)
+{
+	ECalBackendCalDAV        *cbdav;
+	ECalBackendCalDAVPrivate *priv;
 
-{	ECalBackendCalDAV        *cbdav;
-ECalBackendCalDAVPrivate *priv;
-
-cbdav = E_CAL_BACKEND_CALDAV (backend);
-priv  = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
+	cbdav = E_CAL_BACKEND_CALDAV (backend);
+	priv  = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
 
-return priv->loaded;
+	return priv->loaded;
 }
 
 static CalMode
@@ -2716,9 +2943,11 @@
 		e_cal_backend_notify_mode (backend,
 					   GNOME_Evolution_Calendar_CalListener_MODE_NOT_SUPPORTED,
 					   cal_mode_to_corba (mode));
+		g_mutex_unlock (priv->lock);
+		return;
 	}
 
-	if (priv->mode == mode || priv->loaded == FALSE) {
+	if (priv->mode == mode || !priv->loaded) {
 		priv->mode = mode;
 		e_cal_backend_notify_mode (backend,
 					   GNOME_Evolution_Calendar_CalListener_MODE_SET,
@@ -2727,6 +2956,8 @@
 		return;
 	}
 
+	priv->mode = mode;
+
 	if (mode == CAL_MODE_REMOTE) {
 		/* Wake up the slave thread */
 		priv->slave_cmd = SLAVE_SHOULD_WORK;
@@ -2793,17 +3024,19 @@
 
 	g_mutex_lock (priv->lock);
 
-	if (priv->disposed == TRUE) {
+	if (priv->disposed) {
 		g_mutex_unlock (priv->lock);
 		return;
 	}
 
 	/* stop the slave  */
 	priv->slave_cmd = SLAVE_SHOULD_DIE;
-	g_cond_signal (priv->cond);
+	if (priv->synch_slave) {
+		g_cond_signal (priv->cond);
 
-	/* wait until the slave died */
-	g_cond_wait (priv->slave_gone_cond, priv->lock);
+		/* wait until the slave died */
+		g_cond_wait (priv->slave_gone_cond, priv->lock);
+	}
 
 	g_object_unref (priv->session);
 
@@ -2831,6 +3064,9 @@
 	cbdav = E_CAL_BACKEND_CALDAV (object);
 	priv = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
 
+	g_free (priv->ctag);
+	priv->ctag = NULL;
+
 	g_mutex_free (priv->lock);
 	g_cond_free (priv->cond);
 	g_cond_free (priv->slave_gone_cond);
@@ -2862,6 +3098,10 @@
 	priv->do_synch = FALSE;
 	priv->loaded   = FALSE;
 
+	/* Thinks the 'getctag' extension is available the first time, but unset it when realizes it isn't. */
+	priv->ctag_supported = TRUE;
+	priv->ctag = NULL;
+
 	priv->lock = g_mutex_new ();
 	priv->cond = g_cond_new ();
 	priv->slave_gone_cond = g_cond_new ();

Modified: branches/camel-gobject/calendar/backends/http/e-cal-backend-http.c
==============================================================================
--- branches/camel-gobject/calendar/backends/http/e-cal-backend-http.c	(original)
+++ branches/camel-gobject/calendar/backends/http/e-cal-backend-http.c	Tue Jan  6 01:56:50 2009
@@ -483,6 +483,11 @@
 
 	/* create message to be sent to server */
 	soup_message = soup_message_new (SOUP_METHOD_GET, priv->uri);
+	if (soup_message == NULL) {
+		priv->is_loading = FALSE;
+		return FALSE;
+	}
+
 	soup_message_headers_append (soup_message->request_headers, "User-Agent",
 				     "Evolution/" VERSION);
 	soup_message_set_flags (soup_message, SOUP_MESSAGE_NO_REDIRECT);

Modified: branches/camel-gobject/calendar/backends/weather/Locations.xml.in
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/Locations.xml.in	(original)
+++ branches/camel-gobject/calendar/backends/weather/Locations.xml.in	Tue Jan  6 01:56:50 2009
@@ -53,7 +53,7 @@
 		<location type="ccf" code="BFL" url="http://www.crh.noaa.gov/data/HNX/CCFHNX";>Bakersfield</location>
 		<location type="ccf" code="CIH" url="http://www.crh.noaa.gov/data/VEF/CCFVEF";>Bishop</location>
 		<location type="ccf" code="BLU" url="http://www.crh.noaa.gov/data/STO/CCFSTO";>Blue Canyon</location>
-		<location type="ccf" code="SLE" url="http://www.crh.noaa.gov/data/PQR/CCFPQR";>Blythe</location>
+		<location type="ccf" code="BLH" url="http://www.crh.noaa.gov/data/PSR/CCFPSR";>Blythe</location>
 		<location type="ccf" code="CEC" url="http://www.crh.noaa.gov/data/EKA/CCFEKA";>Crescent City</location>
 		<location type="ccf" code="DAG" url="http://www.crh.noaa.gov/data/VEF/CCFVEF";>Daggett</location>
 		<location type="ccf" code="FAT" url="http://www.crh.noaa.gov/data/HNX/CCFHNX";>Fresno</location>

Modified: branches/camel-gobject/calendar/backends/weather/Makefile.am
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/Makefile.am	(original)
+++ branches/camel-gobject/calendar/backends/weather/Makefile.am	Tue Jan  6 01:56:50 2009
@@ -13,7 +13,8 @@
 	-DE_DATA_SERVER_PREFIX=\"$(prefix)\"		\
 	-DWEATHER_DATADIR=\""$(weatherdatadir)"\"	\
 	$(EVOLUTION_CALENDAR_CFLAGS)			\
-	$(SOUP_CFLAGS)
+	$(SOUP_CFLAGS)					\
+	$(LIBGWEATHER_CFLAGS)
 
 extension_LTLIBRARIES = libecalbackendweather.la
 
@@ -31,12 +32,15 @@
 	$(top_builddir)/calendar/libecal/libecal-1.2.la				\
 	$(top_builddir)/calendar/libedata-cal/libedata-cal-1.2.la		\
 	$(top_builddir)/libedataserver/libedataserver-1.2.la			\
-	$(top_builddir)/libebackend/libebackend-1.2.la			\
+	$(top_builddir)/libebackend/libebackend-1.2.la				\
 	$(EVOLUTION_CALENDAR_LIBS)						\
-	$(SOUP_LIBS)
+	$(SOUP_LIBS)								\
+	$(LIBGWEATHER_LIBS)
 
-libecalbackendweather_la_LDFLAGS =	\
-	-module -avoid-version $(NO_UNDEFINED)
+libecalbackendweather_la_LDFLAGS =		\
+	-module -avoid-version $(NO_UNDEFINED)	\
+	$(LIBGWEATHER_LIBS)
+	
 
 weatherdata_in_files = Locations.xml.in
 weatherdata_DATA = $(weatherdata_in_files:.xml.in=.xml)

Modified: branches/camel-gobject/calendar/backends/weather/e-cal-backend-weather.c
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/e-cal-backend-weather.c	(original)
+++ branches/camel-gobject/calendar/backends/weather/e-cal-backend-weather.c	Tue Jan  6 01:56:50 2009
@@ -27,11 +27,15 @@
 #include "e-cal-backend-weather.h"
 #include "e-weather-source.h"
 
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include <libgweather/weather.h>
+#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+
 #define WEATHER_UID_EXT "-weather"
 
 static gboolean reload_cb (ECalBackendWeather *cbw);
 static gboolean begin_retrieval_cb (ECalBackendWeather *cbw);
-static ECalComponent* create_weather (ECalBackendWeather *cbw, WeatherForecast *report);
+static ECalComponent* create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_forecast);
 static ECalBackendSyncStatus
 e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, const char *tzobj);
 
@@ -131,16 +135,17 @@
 }
 
 static void
-finished_retrieval_cb (GList *forecasts, ECalBackendWeather *cbw)
+finished_retrieval_cb (WeatherInfo *info, ECalBackendWeather *cbw)
 {
 	ECalBackendWeatherPrivate *priv;
 	ECalComponent *comp;
 	icalcomponent *icomp;
 	GList *l;
+	char *obj;
 
 	priv = cbw->priv;
 
-	if (forecasts == NULL) {
+	if (info == NULL) {
 		e_cal_backend_notify_error (E_CAL_BACKEND (cbw), _("Could not retrieve weather data"));
 		return;
 	}
@@ -167,14 +172,36 @@
 	g_list_free (l);
 	e_file_cache_clean (E_FILE_CACHE (priv->cache));
 
-	for (l = forecasts; l != NULL; l = g_list_next (l)) {
-		char *obj;
-		comp = create_weather (cbw, l->data);
+	comp = create_weather (cbw, info, FALSE);
+	if (comp) {
+		GSList *forecasts;
+
 		e_cal_backend_cache_put_component (priv->cache, comp);
 		icomp = e_cal_component_get_icalcomponent (comp);
 		obj = icalcomponent_as_ical_string (icomp);
 		e_cal_backend_notify_object_created (E_CAL_BACKEND (cbw), obj);
 		g_free (obj);
+
+		forecasts = weather_info_get_forecast_list (info);
+		if (forecasts) {
+			GSList *f;
+
+			/* skip the first one, it's for today, which has been added above */
+			for (f = forecasts->next; f; f = f->next) {
+				WeatherInfo *nfo = f->data;
+
+				if (nfo) {
+					comp = create_weather (cbw, nfo, TRUE);
+					if (comp) {
+						e_cal_backend_cache_put_component (priv->cache, comp);
+						icomp = e_cal_component_get_icalcomponent (comp);
+						obj = icalcomponent_as_ical_string (icomp);
+						e_cal_backend_notify_object_created (E_CAL_BACKEND (cbw), obj);
+						g_free (obj);
+					}
+				}
+			}
+		}
 	}
 
 	priv->is_loading = FALSE;
@@ -210,86 +237,40 @@
 }
 
 static const char*
-getConditions (WeatherForecast *report)
-{
-	switch (report->conditions) {
-		case WEATHER_FAIR:			return _("Fair");
-		case WEATHER_SNOW_SHOWERS:		return _("Snow showers");
-		case WEATHER_SNOW:			return _("Snow");
-		case WEATHER_PARTLY_CLOUDY:		return _("Partly cloudy");
-		case WEATHER_SMOKE:			return _("Smoke");
-		case WEATHER_THUNDERSTORMS:		return _("Thunderstorms");
-		case WEATHER_CLOUDY:			return _("Cloudy");
-		case WEATHER_DRIZZLE:			return _("Drizzle");
-		case WEATHER_SUNNY:			return _("Sunny");
-		case WEATHER_DUST:			return _("Dust");
-		case WEATHER_CLEAR:			return _("Clear");
-		case WEATHER_MOSTLY_CLOUDY:		return _("Mostly cloudy");
-		case WEATHER_WINDY:			return _("Windy");
-		case WEATHER_RAIN_SHOWERS:		return _("Rain showers");
-		case WEATHER_FOGGY:			return _("Foggy");
-		case WEATHER_RAIN_OR_SNOW_MIXED:	return _("Rain/snow mixed");
-		case WEATHER_SLEET:			return _("Sleet");
-		case WEATHER_VERY_HOT_OR_HOT_HUMID:	return _("Very hot/humid");
-		case WEATHER_BLIZZARD:			return _("Blizzard");
-		case WEATHER_FREEZING_RAIN:		return _("Freezing rain");
-		case WEATHER_HAZE:			return _("Haze");
-		case WEATHER_BLOWING_SNOW:		return _("Blowing snow");
-		case WEATHER_FREEZING_DRIZZLE:		return _("Freezing drizzle");
-		case WEATHER_VERY_COLD_WIND_CHILL:	return _("Very cold/wind chill");
-		case WEATHER_RAIN:			return _("Rain");
-		default:				return NULL;
-	}
-}
-
-static const char*
-getCategory (WeatherForecast *report)
+getCategory (WeatherInfo *report)
 {
-	/* Right now this is based on which icons we have available */
-	switch (report->conditions) {
-		case WEATHER_FAIR:			return _("Weather: Sunny");
-		case WEATHER_SNOW_SHOWERS:		return _("Weather: Snow");
-		case WEATHER_SNOW:			return _("Weather: Snow");
-		case WEATHER_PARTLY_CLOUDY:		return _("Weather: Partly Cloudy");
-		case WEATHER_SMOKE:			return _("Weather: Fog");
-		case WEATHER_THUNDERSTORMS:		return _("Weather: Thunderstorms");
-		case WEATHER_CLOUDY:			return _("Weather: Cloudy");
-		case WEATHER_DRIZZLE:			return _("Weather: Rain");
-		case WEATHER_SUNNY:			return _("Weather: Sunny");
-		case WEATHER_DUST:			return _("Weather: Fog");
-		case WEATHER_CLEAR:			return _("Weather: Sunny");
-		case WEATHER_MOSTLY_CLOUDY:		return _("Weather: Cloudy");
-		case WEATHER_WINDY:			return "";
-		case WEATHER_RAIN_SHOWERS:		return _("Weather: Rain");
-		case WEATHER_FOGGY:			return _("Weather: Fog");
-		case WEATHER_RAIN_OR_SNOW_MIXED:	return _("Weather: Rain");
-		case WEATHER_SLEET:			return _("Weather: Rain");
-		case WEATHER_VERY_HOT_OR_HOT_HUMID:	return _("Weather: Sunny");
-		case WEATHER_BLIZZARD:			return _("Weather: Snow");
-		case WEATHER_FREEZING_RAIN:		return _("Weather: Rain");
-		case WEATHER_HAZE:			return _("Weather: Fog");
-		case WEATHER_BLOWING_SNOW:		return _("Weather: Snow");
-		case WEATHER_FREEZING_DRIZZLE:		return _("Weather: Rain");
-		case WEATHER_VERY_COLD_WIND_CHILL:	return "";
-		case WEATHER_RAIN:			return _("Weather: Rain");
-		default:				return NULL;
+	struct {
+		const char *description;
+		const char *icon_name;
+	} categories[] = {
+		{ N_("Weather: Fog"), 		"weather-fog" },
+		{ N_("Weather: Cloudy"), 	"weather-few-clouds" },
+		{ N_("Weather: Cloudy Night"),	"weather-few-clouds-night" },
+		{ N_("Weather: Overcast"),	"weather-overcast" },
+		{ N_("Weather: Showers"), 	"weather-showers" },
+		{ N_("Weather: Snow"), 		"weather-snow" },
+		{ N_("Weather: Sunny"), 	"weather-clear" },
+		{ N_("Weather: Clear Night"), 	"weather-clear-night" },
+		{ N_("Weather: Thunderstorms"), "weather-storm" },
+		{ NULL,				NULL }
+	};
+
+	int i;
+	const char *icon_name = weather_info_get_icon_name (report);
+
+	if (!icon_name)
+		return NULL;
+
+	for (i = 0; categories [i].description; i++) {
+		if (g_str_equal (categories [i].icon_name, icon_name))
+			return _(categories [i].description);
 	}
-}
 
-static float
-ctof (float c)
-{
-	return ((c * 9.0f / 5.0f) + 32.0f);
-}
-
-static float
-cmtoin (float cm)
-{
-	return cm / 2.54f;
+	return NULL;
 }
 
 static ECalComponent*
-create_weather (ECalBackendWeather *cbw, WeatherForecast *report)
+create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_forecast)
 {
 	ECalBackendWeatherPrivate *priv;
 	ECalComponent             *cal_comp;
@@ -297,30 +278,40 @@
 	icalcomponent             *ical_comp;
 	struct icaltimetype        itt;
 	ECalComponentDateTime      dt;
-	const char                *uid;
+	char                	  *uid;
 	GSList                    *text_list = NULL;
 	ECalComponentText         *description;
-	char                      *pop, *snow;
 	ESource                   *source;
 	gboolean                   metric;
-	const char                *format;
+	const char                *tmp;
+	time_t			   update_time;
+	icaltimezone		  *update_zone = NULL;
+	const WeatherLocation     *location;
 
 	g_return_val_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), NULL);
 
+	if (!weather_info_get_value_update (report, &update_time))
+		return NULL;
+
 	priv = cbw->priv;
 
 	source = e_cal_backend_get_source (E_CAL_BACKEND (cbw));
-	format = e_source_get_property (source, "units");
-	if (format == NULL) {
-		format = e_source_get_property (source, "temperature");
-		if (format == NULL)
+	tmp = e_source_get_property (source, "units");
+	if (tmp == NULL) {
+		tmp = e_source_get_property (source, "temperature");
+		if (tmp == NULL)
 			metric = FALSE;
 		else
-			metric = (strcmp (format, "fahrenheit") != 0);
+			metric = (strcmp (tmp, "fahrenheit") != 0);
 	} else {
-		metric = (strcmp (format, "metric") == 0);
+		metric = (strcmp (tmp, "metric") == 0);
 	}
 
+	if (metric)
+		weather_info_to_metric (report);
+	else
+		weather_info_to_imperial (report);
+
 	/* create the component and event object */
 	ical_comp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
 	cal_comp = e_cal_component_new ();
@@ -329,57 +320,87 @@
 	/* set uid */
 	uid = e_cal_component_gen_uid ();
 	e_cal_component_set_uid (cal_comp, uid);
+	g_free (uid);
+
+	/* use timezone of the location to determine date for which this is set */
+	location = weather_info_get_location (report);
+	if (location && location->tz_hint && *location->tz_hint)
+		update_zone = icaltimezone_get_builtin_timezone (location->tz_hint);
+
+	if (!update_zone)
+		update_zone = priv->default_zone;
+
+	/* Set all-day event's date from forecast data - cannot set is_date,
+	   because in that case no timezone conversion is done */
+	itt = icaltime_from_timet_with_zone (update_time, 0, update_zone);
+	itt.hour = 0;
+	itt.minute = 0;
+	itt.second = 0;
+	itt.is_date = 1;
 
-	/* Set all-day event's date from forecast data */
-	itt = icaltime_from_timet (report->date, 1);
 	dt.value = &itt;
-	dt.tzid = NULL;
+	if (update_zone)
+		dt.tzid = icaltimezone_get_tzid (update_zone);
+	else
+		dt.tzid = NULL;
+
 	e_cal_component_set_dtstart (cal_comp, &dt);
 
-	itt = icaltime_from_timet (report->date, 1);
 	icaltime_adjust (&itt, 1, 0, 0, 0);
-	dt.value = &itt;
-	dt.tzid = NULL;
 	/* We have to add 1 day to DTEND, as it is not inclusive. */
 	e_cal_component_set_dtend (cal_comp, &dt);
 
-	/* The summary is the high or high/low temperatures */
-	if (report->high == report->low) {
-		if (metric)
-			comp_summary.value = g_strdup_printf (_("%.1fÂC - %s"), report->high, priv->city);
-		else
-			comp_summary.value = g_strdup_printf (_("%.1fÂF - %s"), ctof (report->high), priv->city);
+	if (is_forecast) {
+		gdouble tmin = 0.0, tmax = 0.0;
+
+		if (weather_info_get_value_temp_min (report, TEMP_UNIT_DEFAULT, &tmin) && 
+		    weather_info_get_value_temp_max (report, TEMP_UNIT_DEFAULT, &tmax) &&
+		    tmin != tmax) {
+			/* because weather_info_get_temp* uses one internal buffer, thus finally
+			   the last value is shown for both, which is obviously wrong */
+			GString *str = g_string_new (priv->city);
+
+			g_string_append (str, " : ");
+			g_string_append (str, weather_info_get_temp_min (report));
+			g_string_append (str, "/");
+			g_string_append (str, weather_info_get_temp_max (report));
+
+			comp_summary.value = g_string_free (str, FALSE);
+		} else {
+			comp_summary.value = g_strdup_printf ("%s : %s", priv->city, weather_info_get_temp (report));
+		}
 	} else {
-		if (metric)
-			comp_summary.value = g_strdup_printf (_("%.1f/%.1fÂC - %s"), report->high, report->low, priv->city);
-		else
-			comp_summary.value = g_strdup_printf (_("%.1f/%.1fÂF - %s"), ctof (report->high), ctof (report->low), priv->city);
+		gdouble tmin = 0.0, tmax = 0.0;
+		/* because weather_info_get_temp* uses one internal buffer, thus finally
+		   the last value is shown for both, which is obviously wrong */
+		GString *str = g_string_new (priv->city);
+
+		g_string_append (str, " : ");
+		if (weather_info_get_value_temp_min (report, TEMP_UNIT_DEFAULT, &tmin) && 
+		    weather_info_get_value_temp_max (report, TEMP_UNIT_DEFAULT, &tmax) &&
+		    tmin != tmax) {
+			g_string_append (str, weather_info_get_temp_min (report));
+			g_string_append (str, "/");
+			g_string_append (str, weather_info_get_temp_max (report));
+		} else {
+			g_string_append (str, weather_info_get_temp (report));
+		}
+
+		comp_summary.value = g_string_free (str, FALSE);
 	}
 	comp_summary.altrep = NULL;
 	e_cal_component_set_summary (cal_comp, &comp_summary);
+	g_free ((char *)comp_summary.value);
+
+	tmp = weather_info_get_forecast (report);
+	comp_summary.value = weather_info_get_weather_summary (report);
 
-	if (report->pop != 0)
-		pop = g_strdup_printf (_("%d%% chance of precipitation\n"), report->pop);
-	else
-		pop = g_strdup ("");
-	if (report->snowhigh == 0)
-		snow = g_strdup ("");
-	else if (report->snowhigh == report->snowlow) {
-		if (metric)
-			snow = g_strdup_printf (_("%.1fcm snow\n"), report->snowhigh);
-		else
-			snow = g_strdup_printf (_("%.1fin snow\n"), cmtoin(report->snowhigh));
-	} else {
-		if (metric)
-			snow = g_strdup_printf (_("%.1f-%.1fcm snow\n"), report->snowlow, report->snowhigh);
-		else
-			snow = g_strdup_printf (_("%.1f-%.1fin snow\n"), cmtoin(report->snowlow), cmtoin(report->snowhigh));
-	}
 	description = g_new0 (ECalComponentText, 1);
-	description->value = g_strdup_printf ("%s\n%s%s", getConditions (report), pop, snow);
+	description->value = g_strconcat (is_forecast ? "" : comp_summary.value, is_forecast ? "" : "\n", tmp ? _("Forecast") : "", tmp ? ":" : "", tmp && !is_forecast ? "\n" : "", tmp ? tmp : "", NULL);
 	description->altrep = "";
 	text_list = g_slist_append (text_list, description);
 	e_cal_component_set_description_list (cal_comp, text_list);
+	g_free ((char *)comp_summary.value);
 
 	/* Set category and visibility */
 	e_cal_component_set_categories (cal_comp, getCategory (report));
@@ -390,9 +411,6 @@
 
 	e_cal_component_commit_sequence (cal_comp);
 
-	g_free (pop);
-	g_free (snow);
-
 	return cal_comp;
 }
 

Modified: branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.c
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.c	(original)
+++ branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.c	Tue Jan  6 01:56:50 2009
@@ -26,18 +26,14 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
 #include <glib/gi18n-lib.h>
 
-#include <gconf/gconf-client.h>
-
-#include "libedataserver/e-xml-utils.h"
-
 #include "e-weather-source-ccf.h"
 
-#define DATA_SIZE 5000
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include <libgweather/weather.h>
+#include <libgweather/gweather-xml.h>
+#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
 
 #ifdef G_OS_WIN32
 
@@ -58,86 +54,98 @@
 #define strtok_r(s,sep,lasts) (*(lasts)=strtok((s),(sep)))
 #endif
 
-static gchar *
-parse_for_url (char *code, char *name, xmlNode *parent)
+struct search_struct
 {
-	xmlNode *child;
-	if (parent->type == XML_ELEMENT_NODE) {
-		if (strcmp ((char*)parent->name, "location") == 0) {
-			child = parent->children;
-			g_assert (child->type == XML_TEXT_NODE);
-			if (strcmp ((char*)child->content, name) == 0) {
-				xmlAttr *attr;
-				gchar *url = NULL;
-				for (attr = parent->properties; attr; attr = attr->next) {
-					if (strcmp ((char*)attr->name, "code") == 0) {
-						if (strcmp ((char*)attr->children->content, code) != 0)
-							return NULL;
-					}
-					if (strcmp ((char*)attr->name, "url") == 0)
-						url = (char*)attr->children->content;
-				}
-				return g_strdup (url);
-			}
-			return NULL;
-		} else {
-			for (child = parent->children; child; child = child->next) {
-				gchar *url = parse_for_url (code, name, child);
-				if (url)
-					return url;
-			}
-		}
+	const char *code;
+	const char *name;
+	gboolean is_old;
+	WeatherLocation *location;
+};
+
+static gboolean
+find_location_func (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *node, gpointer data)
+{
+	WeatherLocation *wl = NULL;
+	struct search_struct *search = (struct search_struct *)data;
+
+	gtk_tree_model_get (model, node, GWEATHER_XML_COL_POINTER, &wl, -1);
+	if (!wl || !wl->name || !wl->code || !search || search->location)
+		return FALSE;
+
+	if (((!strcmp (wl->code, search->code)) || (search->is_old && !strcmp (wl->code + 1, search->code))) &&
+	     (!strcmp (wl->name, search->name))) {
+		search->location = weather_location_clone (wl);
+		return TRUE;
 	}
-	return NULL;
+
+	return FALSE;
 }
 
-static void
-find_station_url (gchar *station, EWeatherSourceCCF *source)
+static WeatherLocation *
+find_location (const gchar *code_name, gboolean is_old)
 {
-	xmlDoc *doc;
-	xmlNode *root;
-	gchar **sstation;
-	gchar *url;
-	gchar *filename;
-
-	sstation = g_strsplit (station, "/", 2);
-
-#ifndef G_OS_WIN32
-	filename = g_strdup (WEATHER_DATADIR "/Locations.xml");
-#else
-	filename = e_util_replace_prefix (E_DATA_SERVER_PREFIX,
-					  e_util_get_prefix (),
-					  WEATHER_DATADIR "/Locations.xml");
-#endif
+	GtkTreeModel *model;
+	gchar **ids;
+	struct search_struct search;
+
+	search.location = NULL;
 
-	doc = e_xml_parse_file (filename);
+	ids = g_strsplit (code_name, "/", 2);
 
-	g_assert (doc != NULL);
+	if (!ids || !ids [0] || !ids [1])
+		goto done;
 
-	root = xmlDocGetRootElement (doc);
+	model = gweather_xml_load_locations ();
+	if (!model)
+		goto done;
 
-	url = parse_for_url (sstation[0], sstation[1], root);
+	search.code = ids [0];
+	search.name = ids [1];
+	search.is_old = is_old;
+	search.location = NULL;
 
-	source->url = g_strdup (url);
-	source->substation = g_strdup (sstation[0]);
+	gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc) find_location_func, &search);
 
-	g_strfreev (sstation);
+	gweather_xml_free_locations (model);
+	g_strfreev (ids);
+
+done:
+	return search.location;
 }
 
 EWeatherSource*
 e_weather_source_ccf_new (const char *uri)
 {
-	/* Our URI is formatted as weather://ccf/AAA[/BBB] - AAA is the 3-letter station
+	/* Old URI is formatted as weather://ccf/AAA[/BBB] - AAA is the 3-letter station
 	 * code for identifying the providing station (subdirectory within the crh data
 	 * repository). BBB is an optional additional station ID for the station within
 	 * the CCF file. If not present, BBB is assumed to be the same station as AAA.
+	 * But the new URI is as weather://code/name, where code is 4-letter code.
+	 * So if got the old URI, then migrate to the new one, if possible.
 	 */
-	EWeatherSourceCCF *source = E_WEATHER_SOURCE_CCF (g_object_new (e_weather_source_ccf_get_type (), NULL));
 
-	find_station_url (strchr (uri, '/') + 1, source);
+	WeatherLocation *wl;
+	EWeatherSourceCCF *source;
+
+	if (!uri)
+		return NULL;
+
+	if (strncmp (uri, "ccf/", 4) == 0)
+		wl = find_location (uri + 4, TRUE);
+	else
+		wl = find_location (uri, FALSE);
+
+	if (!wl)
+		return NULL;
+
+	source = E_WEATHER_SOURCE_CCF (g_object_new (e_weather_source_ccf_get_type (), NULL));
+	source->location = wl;
+	source->info = NULL;
+
 	return E_WEATHER_SOURCE (source);
 }
 
+#if 0
 static GSList*
 tokenize (char *buffer)
 {
@@ -388,74 +396,48 @@
 	g_free (forecasts);
 	g_list_free (fc);
 }
+#endif
 
 static void
-retrieval_done (SoupSession *session, SoupMessage *message, EWeatherSourceCCF *source)
+parse_done (WeatherInfo *info, gpointer data)
 {
-	/* check status code */
-	if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
-		source->done (NULL, source->finished_data);
+	EWeatherSourceCCF *ccfsource = (EWeatherSourceCCF *) data;
+
+	if (!ccfsource)
+		return;
+
+	if (!info || !weather_info_is_valid (info)) {
+		ccfsource->done (NULL, ccfsource->finished_data);
 		return;
 	}
 
-	e_weather_source_ccf_do_parse (source, (char *)message->response_body->data);
+	ccfsource->done (info, ccfsource->finished_data);
 }
 
 static void
 e_weather_source_ccf_parse (EWeatherSource *source, EWeatherSourceFinished done, gpointer data)
 {
 	EWeatherSourceCCF *ccfsource = (EWeatherSourceCCF*) source;
-	SoupMessage *soup_message;
+	WeatherPrefs prefs;
 
 	ccfsource->finished_data = data;
-
 	ccfsource->done = done;
 
-	if (!ccfsource->soup_session) {
-		GConfClient *conf_client;
-		ccfsource->soup_session = soup_session_async_new ();
-
-		/* set the HTTP proxy, if configuration is set to do so */
-		conf_client = gconf_client_get_default ();
-		if (gconf_client_get_bool (conf_client, "/system/http_proxy/use_http_proxy", NULL)) {
-			char *server, *proxy_uri;
-			int port;
-
-			server = gconf_client_get_string (conf_client, "/system/http_proxy/host", NULL);
-			port = gconf_client_get_int (conf_client, "/system/http_proxy/port", NULL);
-
-			if (server && server[0]) {
-				SoupURI *suri;
-				if (gconf_client_get_bool (conf_client, "/system/http_proxy/use_authentication", NULL)) {
-					char *user, *password;
-
-					user = gconf_client_get_string (conf_client,
-									"/system/http_proxy/authentication_user",
-									NULL);
-					password = gconf_client_get_string (conf_client,
-									    "/system/http_proxy/authentication_password",
-									    NULL);
-
-					proxy_uri = g_strdup_printf("http://%s:%s %s:%d", user, password, server, port);
-
-					g_free (user);
-					g_free (password);
-				} else
-					proxy_uri = g_strdup_printf ("http://%s:%d";, server, port);
-
-				suri = soup_uri_new (proxy_uri);
-				g_object_set (G_OBJECT (ccfsource->soup_session), SOUP_SESSION_PROXY_URI, suri, NULL);
-
-				soup_uri_free (suri);
-				g_free (server);
-				g_free (proxy_uri);
-			}
-		}
-		g_object_unref (conf_client);
+	prefs.type = FORECAST_LIST;
+	prefs.radar = FALSE;
+	prefs.radar_custom_url = NULL;
+	prefs.temperature_unit = TEMP_UNIT_CENTIGRADE;
+	prefs.speed_unit = SPEED_UNIT_MS;
+	prefs.pressure_unit = PRESSURE_UNIT_HPA;
+	prefs.distance_unit = DISTANCE_UNIT_METERS;
+
+	if (ccfsource->location && !ccfsource->info) {
+		ccfsource->info = weather_info_new (ccfsource->location, &prefs, parse_done, source);
+		weather_location_free (ccfsource->location);
+		ccfsource->location = NULL;
+	} else {
+		ccfsource->info = weather_info_update (ccfsource->info, &prefs, parse_done, source);
 	}
-
-	soup_message = soup_message_new (SOUP_METHOD_GET, ccfsource->url);
-	soup_session_queue_message (ccfsource->soup_session, soup_message, (SoupSessionCallback) retrieval_done, source);
 }
 
 static void
@@ -471,9 +453,8 @@
 static void
 e_weather_source_ccf_init (EWeatherSourceCCF *source)
 {
-	source->url = NULL;
-	source->substation = NULL;
-	source->soup_session = NULL;
+	source->location = NULL;
+	source->info = NULL;
 }
 
 GType

Modified: branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.h
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.h	(original)
+++ branches/camel-gobject/calendar/backends/weather/e-weather-source-ccf.h	Tue Jan  6 01:56:50 2009
@@ -26,6 +26,10 @@
 #include <libsoup/soup-uri.h>
 #include "e-weather-source.h"
 
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include <libgweather/weather.h>
+#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+
 G_BEGIN_DECLS
 
 #define E_TYPE_WEATHER_SOURCE_CCF            (e_weather_source_ccf_get_type ())
@@ -40,10 +44,10 @@
 struct _EWeatherSourceCCF {
 	EWeatherSource parent;
 
-	char *url;
-	char *substation;
+	WeatherLocation *location;
+	WeatherInfo *info;
+
 	EWeatherSourceFinished done;
-	SoupSession *soup_session;
 	gpointer finished_data;
 };
 

Modified: branches/camel-gobject/calendar/backends/weather/e-weather-source.c
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/e-weather-source.c	(original)
+++ branches/camel-gobject/calendar/backends/weather/e-weather-source.c	Tue Jan  6 01:56:50 2009
@@ -70,7 +70,5 @@
 {
 	const char *base = uri + 10; /* skip weather:// */
 
-	if (strncmp (base, "ccf/", 4) == 0)
-		return e_weather_source_ccf_new (base);
-	return NULL;
+	return e_weather_source_ccf_new (base);
 }

Modified: branches/camel-gobject/calendar/backends/weather/e-weather-source.h
==============================================================================
--- branches/camel-gobject/calendar/backends/weather/e-weather-source.h	(original)
+++ branches/camel-gobject/calendar/backends/weather/e-weather-source.h	Tue Jan  6 01:56:50 2009
@@ -24,6 +24,10 @@
 #include <glib-object.h>
 #include <time.h>
 
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include <libgweather/weather.h>
+#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+
 G_BEGIN_DECLS
 
 typedef enum {
@@ -54,21 +58,7 @@
 	WEATHER_RAIN,
 } WeatherConditions;
 
-typedef struct {
-	/* date, in UTC */
-	time_t date;
-	/* expected conditions */
-	WeatherConditions conditions;
-	/* internal storage is always in celcius and should be
-	 * converted based on the user's current locale setting */
-	float high, low;
-	/* probability of precipitation */
-	int pop;
-	/* snowfall forecast - internal storage in cm */
-	float snowhigh, snowlow;
-} WeatherForecast;
-
-typedef void (*EWeatherSourceFinished)(GList *results, gpointer data);
+typedef void (*EWeatherSourceFinished)(WeatherInfo *result, gpointer data);
 
 #define E_TYPE_WEATHER_SOURCE            (e_weather_source_get_type ())
 #define E_WEATHER_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_WEATHER_SOURCE, EWeatherSource))

Modified: branches/camel-gobject/calendar/libecal/e-cal-util.h
==============================================================================
--- branches/camel-gobject/calendar/libecal/e-cal-util.h	(original)
+++ branches/camel-gobject/calendar/libecal/e-cal-util.h	Tue Jan  6 01:56:50 2009
@@ -115,6 +115,7 @@
 #define CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND       "organizer-must-attend"
 #define CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS "organizer-not-email-address"
 #define CAL_STATIC_CAPABILITY_REMOVE_ALARMS               "remove-alarms"
+#define CAL_STATIC_CAPABILITY_CREATE_MESSAGES             "create-messages"
 #define CAL_STATIC_CAPABILITY_SAVE_SCHEDULES              "save-schedules"
 #define CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK	  "no-conv-to-assign-task"
 #define CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR		  "no-conv-to-recur"

Modified: branches/camel-gobject/calendar/libecal/e-cal.c
==============================================================================
--- branches/camel-gobject/calendar/libecal/e-cal.c	(original)
+++ branches/camel-gobject/calendar/libecal/e-cal.c	Tue Jan  6 01:56:50 2009
@@ -1386,7 +1386,16 @@
 		priv->local_attachment_store =
 			g_filename_to_uri (filename, NULL, NULL);
 		g_free (filename);
+	} else if (g_str_has_prefix (priv->uri, "mapi://")) {
+		gchar *filename = g_build_filename (g_get_home_dir (),
+						    ".evolution/cache/calendar",
+						    mangled_uri,
+						    NULL);
+		priv->local_attachment_store =
+			g_filename_to_uri (filename, NULL, NULL);
+		g_free (filename);
 	}
+
 	g_free (mangled_uri);
 }
 

Modified: branches/camel-gobject/camel/camel-db.c
==============================================================================
--- branches/camel-gobject/camel/camel-db.c	(original)
+++ branches/camel-gobject/camel/camel-db.c	Tue Jan  6 01:56:50 2009
@@ -47,6 +47,8 @@
 
 static GStaticRecMutex trans_lock = G_STATIC_REC_MUTEX_INIT;	
 
+static int write_mir (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex, gboolean delete_old_record);
+
 static int 
 cdb_sql_exec (sqlite3 *db, const char* stmt, CamelException *ex) 
 {
@@ -124,7 +126,6 @@
 		cache = g_strdup ("PRAGMA cache_size=100");
 
 	camel_db_command (cdb, cache, NULL);
-
 	g_free (cache);
 
 	sqlite3_busy_timeout (cdb->db, CAMEL_DB_SLEEP_INTERVAL);
@@ -190,7 +191,8 @@
 {
 	if (!cdb)
 		return -1;
-	g_static_rec_mutex_lock (&trans_lock);
+	if (g_getenv("SQLITE_TRANSLOCK"))
+		g_static_rec_mutex_lock (&trans_lock);
 
 	g_mutex_lock (cdb->lock);
 	return (cdb_sql_exec (cdb->db, "BEGIN", ex));
@@ -207,7 +209,8 @@
 	ret = cdb_sql_exec (cdb->db, "COMMIT", ex);
 	END;
 	g_mutex_unlock (cdb->lock);
-	g_static_rec_mutex_unlock (&trans_lock);
+	if (g_getenv("SQLITE_TRANSLOCK"))
+		g_static_rec_mutex_unlock (&trans_lock);
 
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 	
@@ -221,7 +224,8 @@
 	
 	ret = cdb_sql_exec (cdb->db, "ROLLBACK", ex);
 	g_mutex_unlock (cdb->lock);
-	g_static_rec_mutex_unlock (&trans_lock);	
+	if (g_getenv("SQLITE_TRANSLOCK"))
+		g_static_rec_mutex_unlock (&trans_lock);	
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 	
 	return ret;
@@ -453,7 +457,7 @@
 	if (!cdb)
 		return ret;
 	
-	d(g_print ("\n%s:\n%s \n", __FUNCTION__, stmt));
+	d(g_print ("\n%s:\n%s \n", G_STRFUNC, stmt));
 	g_mutex_lock (cdb->lock);
 
 	START(stmt);
@@ -558,6 +562,53 @@
 	return ret;
 }
 
+struct _db_data_uids_flags {
+	GPtrArray *uids;
+	GPtrArray *flags;
+};
+static int
+read_uids_flags_callback (void *ref, int ncol, char ** cols, char ** name)
+{
+	struct _db_data_uids_flags *data= (struct _db_data_uids_flags *) ref;
+	 
+	int i;
+	for (i = 0; i < ncol; ++i) {
+		if (!strcmp (name [i], "uid"))
+			g_ptr_array_add (data->uids, (char *) (camel_pstring_strdup(cols [i])));
+		else if (!strcmp (name [i], "flags"))
+			g_ptr_array_add (data->flags, GUINT_TO_POINTER(strtoul (cols [i], NULL, 10)));
+	}
+	 
+	 return 0;
+}
+
+int
+camel_db_get_folder_uids_flags (CamelDB *db, char *folder_name, char *sort_by, char *collate, GPtrArray *summary, GHashTable *table, CamelException *ex)
+{
+	 GPtrArray *uids = summary;
+	 GPtrArray *flags = g_ptr_array_new ();
+	 char *sel_query;
+	 int ret;
+	 struct _db_data_uids_flags data;
+	 int i;
+	
+	 data.uids = uids;
+	 data.flags = flags;
+
+
+	 sel_query = sqlite3_mprintf("SELECT uid,flags FROM %Q%s%s%s%s", folder_name, sort_by ? " order by " : "", sort_by ? sort_by: "", (sort_by && collate) ? " collate " : "", (sort_by && collate) ? collate : "");	 
+
+	 ret = camel_db_select (db, sel_query, read_uids_flags_callback, &data, ex);
+	 sqlite3_free (sel_query);
+
+	 for (i=0; i<uids->len; i++) {
+		 g_hash_table_insert (table, uids->pdata[i], flags->pdata[i]);
+	 }
+
+	 g_ptr_array_free (flags, TRUE);
+	 return ret;
+}
+
 static int
 read_uids_callback (void *ref, int ncol, char ** cols, char ** name)
 {
@@ -763,13 +814,29 @@
 	return ret;
 }
 
+
+int 
+camel_db_write_fresh_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex)
+{
+	return write_mir (cdb, folder_name, record, ex, FALSE);
+}
+
+
 int
 camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex)
 {
+	return write_mir (cdb, folder_name, record, ex, TRUE);
+}
+
+static int 
+write_mir (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex, gboolean delete_old_record)
+{
 	int ret;
 	char *del_query;
 	char *ins_query;
 
+	/* FIXME: We should migrate from this DELETE followed by INSERT model to an INSERT OR REPLACE model as pointed out by pvanhoof */
+
 	/* NB: UGLIEST Hack. We can't modify the schema now. We are using msg_security (an unsed one to notify of FLAGGED/Dirty infos */
 
 	ins_query = sqlite3_mprintf ("INSERT INTO %Q VALUES (%Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %ld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q )", 
@@ -783,7 +850,8 @@
 			record->part, record->labels, record->usertags,
 			record->cinfo, record->bdata);
 
-	del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder_name, record->uid);
+	if (delete_old_record)
+			del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder_name, record->uid);
 
 #if 0
 	char *upd_query;
@@ -793,12 +861,14 @@
 	g_free (upd_query);
 #else
 
-	ret = camel_db_add_to_transaction (cdb, del_query, ex);
+	if (delete_old_record)
+			ret = camel_db_add_to_transaction (cdb, del_query, ex);
 	ret = camel_db_add_to_transaction (cdb, ins_query, ex);
 
 #endif
 
-	sqlite3_free (del_query);
+	if (delete_old_record)
+			sqlite3_free (del_query);
 	sqlite3_free (ins_query);
 
 	return ret;
@@ -1149,3 +1219,39 @@
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 	return ret;		
 }
+
+int camel_db_start_in_memory_transactions (CamelDB *cdb, CamelException *ex)
+{
+	int ret;
+	char *cmd = sqlite3_mprintf ("ATTACH DATABASE ':memory:' AS %s", CAMEL_DB_IN_MEMORY_DB);
+
+	ret = camel_db_command (cdb, cmd, ex);
+	sqlite3_free (cmd);
+
+	cmd = sqlite3_mprintf ("CREATE TEMPORARY TABLE %Q (  uid TEXT PRIMARY KEY , flags INTEGER , msg_type INTEGER , read INTEGER , deleted INTEGER , replied INTEGER , important INTEGER , junk INTEGER , attachment INTEGER , msg_security INTEGER , size INTEGER , dsent NUMERIC , dreceived NUMERIC , subject TEXT , mail_from TEXT , mail_to TEXT , mail_cc TEXT , mlist TEXT , followup_flag TEXT , followup_completed_on TEXT , followup_due_by TEXT , part TEXT , labels TEXT , usertags TEXT , cinfo TEXT , bdata TEXT )", CAMEL_DB_IN_MEMORY_TABLE);
+	ret = camel_db_command (cdb, cmd, ex);
+	if (ret != 0 )
+		abort ();
+	sqlite3_free (cmd);
+	
+	return ret;
+}
+
+int camel_db_flush_in_memory_transactions (CamelDB *cdb, const char * folder_name, CamelException *ex)
+{
+	int ret;
+	char *cmd = sqlite3_mprintf ("INSERT INTO %Q SELECT * FROM %Q", folder_name, CAMEL_DB_IN_MEMORY_TABLE);
+
+	ret = camel_db_command (cdb, cmd, ex);
+	sqlite3_free (cmd);
+
+	cmd = sqlite3_mprintf ("DROP TABLE %Q", CAMEL_DB_IN_MEMORY_TABLE);
+	ret = camel_db_command (cdb, cmd, ex);
+	sqlite3_free (cmd);
+
+	cmd = sqlite3_mprintf ("DETACH %Q", CAMEL_DB_IN_MEMORY_DB);
+	ret = camel_db_command (cdb, cmd, ex);
+	sqlite3_free (cmd);
+
+	return ret;
+}

Modified: branches/camel-gobject/camel/camel-db.h
==============================================================================
--- branches/camel-gobject/camel/camel-db.h	(original)
+++ branches/camel-gobject/camel/camel-db.h	Tue Jan  6 01:56:50 2009
@@ -4,8 +4,14 @@
 #define __CAMEL_DB_H
 #include <sqlite3.h>
 #include <glib.h>
+
 #define CAMEL_DB_FILE "folders.db"
 
+/* Hopefully no one will create a folder named EVO_IN_meM_hAnDlE */
+#define CAMEL_DB_IN_MEMORY_TABLE "EVO_IN_meM_hAnDlE.temp" 
+#define CAMEL_DB_IN_MEMORY_DB "EVO_IN_meM_hAnDlE" 
+#define CAMEL_DB_IN_MEMORY_TABLE_LIMIT 100000
+
 #include "camel-exception.h"
 
 typedef struct _CamelDBPrivate CamelDBPrivate;
@@ -132,6 +138,7 @@
 int camel_db_prepare_message_info_table (CamelDB *cdb, const char *folder_name, CamelException *ex);
 
 int camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex);
+int camel_db_write_fresh_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex);
 int camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex);
 int camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex);
 
@@ -156,6 +163,7 @@
 int camel_db_add_to_vfolder_transaction (CamelDB *db, char *folder_name, char *vuid, CamelException *ex);
 
 int camel_db_get_folder_uids (CamelDB *db, char *folder_name, char *sort_by, char *collate, GPtrArray *array, CamelException *ex);
+int camel_db_get_folder_uids_flags (CamelDB *db, char *folder_name, char *sort_by, char *collate, GPtrArray *summary, GHashTable *table, CamelException *ex);
 
 GPtrArray * camel_db_get_folder_junk_uids (CamelDB *db, char *folder_name, CamelException *ex);
 GPtrArray * camel_db_get_folder_deleted_uids (CamelDB *db, char *folder_name, CamelException *ex);
@@ -167,5 +175,9 @@
 int camel_db_set_collate (CamelDB *cdb, const char *col, const char *collate, CamelDBCollate func);
 /* Migration APIS */
 int camel_db_migrate_vfolders_to_14(CamelDB *cdb, const char *folder, CamelException *ex);
+
+int camel_db_start_in_memory_transactions (CamelDB *cdb, CamelException *ex);
+int camel_db_flush_in_memory_transactions (CamelDB *cdb, const char * folder_name, CamelException *ex);
+
 #endif
 

Modified: branches/camel-gobject/camel/camel-folder-summary.c
==============================================================================
--- branches/camel-gobject/camel/camel-folder-summary.c	(original)
+++ branches/camel-gobject/camel/camel-folder-summary.c	Tue Jan  6 01:56:50 2009
@@ -41,6 +41,7 @@
 #include <libedataserver/e-memory.h>
 
 #include "camel-db.h"
+#include "camel-debug.h"
 #include "camel-file-utils.h"
 #include "camel-folder-summary.h"
 #include "camel-folder.h"
@@ -67,6 +68,7 @@
 
 /* Make 5 minutes as default cache drop */
 #define SUMMARY_CACHE_DROP 300
+#define dd(x) if (camel_debug("sync")) x
 
 static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -78,7 +80,6 @@
 /* this should probably be conditional on it existing */
 #define USE_BSEARCH
 
-#define dd(x)
 #define d(x)
 #define io(x)			/* io debug */
 #define w(x)
@@ -128,7 +129,7 @@
 static int		         content_info_save(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
 static void		         content_info_free(CamelFolderSummary *, CamelMessageContentInfo *);
 
-static int save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex);
+static int save_message_infos_to_db (CamelFolderSummary *s, gboolean fresh_mir, CamelException *ex);
 static int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name);
 
 static char *next_uid_string(CamelFolderSummary *s);
@@ -154,6 +155,7 @@
 
 	s->message_info_size = sizeof(CamelMessageInfoBase);
 	s->content_info_size = sizeof(CamelMessageContentInfo);
+	p->flag_cache = g_hash_table_new (g_str_hash, g_str_equal);
 
 	s->message_info_chunks = NULL;
 	s->content_info_chunks = NULL;
@@ -199,7 +201,7 @@
 	CamelFolderSummary *s = (CamelFolderSummary *)obj;
 
 	p = _PRIVATE(obj);
-
+	g_hash_table_destroy (p->flag_cache);
 	if (s->timeout_handle)
 		g_source_remove (s->timeout_handle);
 	//camel_folder_summary_clear(s);
@@ -825,16 +827,17 @@
 	CamelFolderSummary *s = m->summary;
 
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
-	
+	camel_folder_sync (s->folder, FALSE, NULL);
+
 	if (time(NULL) - s->cache_load_time < SUMMARY_CACHE_DROP)
 		return;
 	
-	d(printf("removing cache for  %s %d %p\n", s->folder ? s->folder->full_name : s->summary_path, g_hash_table_size (s->loaded_infos), s->loaded_infos));
+	dd(printf("removing cache for  %s %d %p\n", s->folder ? s->folder->full_name : s->summary_path, g_hash_table_size (s->loaded_infos), s->loaded_infos));
 	/* FIXME[disk-summary] hack. fix it */
 	CAMEL_SUMMARY_LOCK (s, summary_lock);
 	g_hash_table_foreach_remove  (s->loaded_infos, (GHRFunc) remove_item, s);
 	CAMEL_SUMMARY_UNLOCK (s, summary_lock);
-	d(printf("done .. now %d\n",g_hash_table_size (s->loaded_infos)));
+	dd(printf("done .. now %d\n",g_hash_table_size (s->loaded_infos)));
 
 	s->cache_load_time = time(NULL);
 	
@@ -932,14 +935,23 @@
 	printf("\n");
 }
 
+GHashTable *
+camel_folder_summary_get_flag_cache (CamelFolderSummary *summary)
+{
+	struct _CamelFolderSummaryPrivate *p = _PRIVATE(summary);
+	
+	return p->flag_cache;
+}
+
 int
 camel_folder_summary_load_from_db (CamelFolderSummary *s, CamelException *ex)
 {
 	CamelDB *cdb;
 	char *folder_name;
 	int ret = 0;
+	struct _CamelFolderSummaryPrivate *p = _PRIVATE(s);
+
 	/* struct _db_pass_data data; */
-	
 	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
 	s->flags &= ~CAMEL_SUMMARY_DIRTY;
 
@@ -951,7 +963,7 @@
 	folder_name = s->folder->full_name;
 	cdb = s->folder->parent_store->cdb_r;
 
-	ret = camel_db_get_folder_uids (cdb, folder_name, (char *)s->sort_by, (char *)s->collate, s->uids, ex);
+	ret = camel_db_get_folder_uids_flags (cdb, folder_name, (char *)s->sort_by, (char *)s->collate, s->uids, p->flag_cache, ex);
 	/* camel_folder_summary_dump (s); */
 
 #if 0
@@ -1225,23 +1237,20 @@
 	if (fclose (in) != 0)
 		return -1;
 
-
-	camel_db_begin_transaction (cdb, &ex);
-
-	ret = save_message_infos_to_db (s, &ex);
-
-	if (ret != 0) {
-		camel_db_abort_transaction (cdb, &ex);
+	record = (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_to_db (s, &ex));
+	if (!record) {
 		return -1;
 	}
-	camel_db_end_transaction (cdb, &ex);
 
-	record = (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_to_db (s, &ex));
-	if (!record) {
+	ret = save_message_infos_to_db (s, TRUE, &ex);
+
+	if (ret != 0) {
 		return -1;
 	}
 	
+	camel_db_begin_transaction (cdb, &ex);
 	ret = camel_db_write_folder_info_record (cdb, record, &ex);
+	camel_db_end_transaction (cdb, &ex);
 
 	g_free (record->bdata);
 	g_free (record);
@@ -1309,17 +1318,24 @@
 	return 0;
 }
 
+typedef struct {
+	CamelException *ex;
+	gboolean migration;
+	int progress;
+} SaveToDBArgs;
+
 static void
 save_to_db_cb (gpointer key, gpointer value, gpointer data)
 {
-	CamelException *ex = (CamelException *)data;
+	SaveToDBArgs *args = (SaveToDBArgs *) data;
+	CamelException *ex = args->ex;
 	CamelMessageInfoBase *mi = (CamelMessageInfoBase *)value;	
 	CamelFolderSummary *s = (CamelFolderSummary *)mi->summary;
 	char *folder_name = s->folder->full_name;
 	CamelDB *cdb = s->folder->parent_store->cdb_w;
 	CamelMIRecord *mir;
 
-	if (!mi->dirty)
+	if (!args->migration && !mi->dirty)
 		return;
 
 	mir = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_to_db (s, (CamelMessageInfo *)mi);
@@ -1333,22 +1349,44 @@
 		}
 	}
 
-	if (camel_db_write_message_info_record (cdb, folder_name, mir, ex) != 0) {
-		camel_db_camel_mir_free (mir);
-		return;
+	if (!args->migration) {
+			if (camel_db_write_message_info_record (cdb, folder_name, mir, ex) != 0) {
+					camel_db_camel_mir_free (mir);
+					return;
+			}
+	} else {
+			if (camel_db_write_fresh_message_info_record (cdb, CAMEL_DB_IN_MEMORY_TABLE, mir, ex) != 0) {
+					camel_db_camel_mir_free (mir);
+					return;
+			}
+
+			if (args->progress > CAMEL_DB_IN_MEMORY_TABLE_LIMIT) {
+			    g_print ("BULK INsert limit reached \n");
+				camel_db_flush_in_memory_transactions (cdb, folder_name, ex);
+				camel_db_start_in_memory_transactions (cdb, ex);
+				args->progress = 0;
+			} else {
+				args->progress ++;
+			}
 	}
 
 	/* Reset the flags */
 	mi->dirty = FALSE;
+	mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
 	
 	camel_db_camel_mir_free (mir);	
 }
 
 static int
-save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex)
+save_message_infos_to_db (CamelFolderSummary *s, gboolean fresh_mirs, CamelException *ex)
 {
 	CamelDB *cdb = s->folder->parent_store->cdb_w;
 	char *folder_name;
+	SaveToDBArgs args;
+
+	args.ex = ex;
+	args.migration = fresh_mirs;
+	args.progress = 0;
 
 	folder_name = s->folder->full_name;
 	if (camel_db_prepare_message_info_table (cdb, folder_name, ex) != 0) {
@@ -1356,7 +1394,7 @@
 	}
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
 	/* Push MessageInfo-es */
-	g_hash_table_foreach (s->loaded_infos, save_to_db_cb, ex);
+	g_hash_table_foreach (s->loaded_infos, save_to_db_cb, &args);
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 /* FIXME[disk-summary] make sure we free the message infos that are loaded
  * are freed if not used anymore or should we leave that to the timer? */
@@ -1382,11 +1420,11 @@
 	if (!count) 
 		return camel_folder_summary_header_save_to_db (s, ex);
 
-	d(printf("Saving %d/%d dirty records of %s\n", count, g_hash_table_size (s->loaded_infos), s->folder->full_name));
+	dd(printf("Saving %d/%d dirty records of %s\n", count, g_hash_table_size (s->loaded_infos), s->folder->full_name));
 
 	camel_db_begin_transaction (cdb, ex);
 
-	ret = save_message_infos_to_db (s, ex);
+	ret = save_message_infos_to_db (s, FALSE, ex);
 	if (ret != 0) {
 		camel_db_abort_transaction (cdb, ex);
 		/* Failed, so lets reset the flag */
@@ -2078,25 +2116,24 @@
 void
 camel_folder_summary_clear(CamelFolderSummary *s)
 {
-#if 0
-	int i;
+	d(printf ("\ncamel_folder_summary_clearcalled \n"));
+	s->flags &= ~CAMEL_SUMMARY_DIRTY;
 
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
 	if (camel_folder_summary_count(s) == 0) {
 		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 		return;
 	}
+	
+	g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL);
+	g_ptr_array_free (s->uids, TRUE);
+	s->uids = g_ptr_array_new ();
+	s->visible_count = s->deleted_count = s->unread_count = 0;
 
-	for (i=0;i<s->messages->len;i++)
-		camel_message_info_free(s->messages->pdata[i]);
+	g_hash_table_destroy(s->loaded_infos);
+	s->loaded_infos = g_hash_table_new(g_str_hash, g_str_equal);
 
-	g_ptr_array_set_size(s->messages, 0);
-	g_hash_table_destroy(s->messages_uid);
-	s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
-	s->flags |= CAMEL_SUMMARY_DIRTY;
-	s->meta_summary->msg_expunged = TRUE;
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-#endif	
 }
 
 /* FIXME: This is non-sense. Neither an exception is passed,
@@ -3082,7 +3119,7 @@
 message_info_load(CamelFolderSummary *s, FILE *in)
 {
 	CamelMessageInfoBase *mi;
-	guint count;
+	guint32 count;
 	int i;
 	char *subject, *from, *to, *cc, *mlist, *uid;
 

Modified: branches/camel-gobject/camel/camel-folder-summary.h
==============================================================================
--- branches/camel-gobject/camel/camel-folder-summary.h	(original)
+++ branches/camel-gobject/camel/camel-folder-summary.h	Tue Jan  6 01:56:50 2009
@@ -407,6 +407,7 @@
 GPtrArray *camel_folder_summary_array(CamelFolderSummary *summary);
 GHashTable *camel_folder_summary_get_hashtable(CamelFolderSummary *s);
 void camel_folder_summary_free_hashtable (GHashTable *ht);
+GHashTable *camel_folder_summary_get_flag_cache (CamelFolderSummary *summary);
 
 /* basically like strings, but certain keywords can be compressed and de-cased */
 int camel_folder_summary_encode_token(FILE *out, const char *str);

Modified: branches/camel-gobject/camel/camel-folder.c
==============================================================================
--- branches/camel-gobject/camel/camel-folder.c	(original)
+++ branches/camel-gobject/camel/camel-folder.c	Tue Jan  6 01:56:50 2009
@@ -1143,24 +1143,9 @@
 	GPtrArray *array;
 	int i, j, count;
 
-	array = g_ptr_array_new();
+	g_return_val_if_fail(folder->summary != NULL, g_ptr_array_new ());
 
-	g_return_val_if_fail(folder->summary != NULL, array);
-
-	count = camel_folder_summary_count(folder->summary);
-	g_ptr_array_set_size(array, count);
-	for (i = 0, j = 0; i < count; i++) {
-		CamelMessageInfo *info = camel_folder_summary_index(folder->summary, i);
-		
-		if (info) {
-			array->pdata[j++] = (char *)camel_pstring_strdup (camel_message_info_uid (info));
-			camel_message_info_free(info);
-		}
-	}
-	
-	g_ptr_array_set_size (array, j);
-	
-	return array;
+	return camel_folder_summary_array (folder->summary);
 }
 
 

Modified: branches/camel-gobject/camel/camel-mime-utils.c
==============================================================================
--- branches/camel-gobject/camel/camel-mime-utils.c	(original)
+++ branches/camel-gobject/camel/camel-mime-utils.c	Tue Jan  6 01:56:50 2009
@@ -3281,7 +3281,7 @@
 }
 
 static char *
-header_encode_param (const unsigned char *in, gboolean *encoded)
+header_encode_param (const unsigned char *in, gboolean *encoded, gboolean is_filename)
 {
 	const unsigned char *inptr = in;
 	unsigned char *outbuf = NULL;
@@ -3294,11 +3294,34 @@
 	
 	g_return_val_if_fail (in != NULL, NULL);
 
+	if (is_filename) {
+		if (!g_utf8_validate (inptr, -1, NULL)) {
+			GString *buff = g_string_new ("");
+
+			for (; inptr && *inptr; inptr++) {
+				if (*inptr < 32)
+					g_string_append_printf (buff, "%%%02X", (*inptr) & 0xFF);
+				else
+					g_string_append_c (buff, *inptr);
+			}
+
+			outbuf = g_string_free (buff, FALSE);
+			inptr = outbuf;
+		}
+
+		/* do not set encoded flag for file names */
+		str = camel_header_encode_string (inptr);
+		g_free (outbuf);
+
+		return str;
+	}
+
 	/* if we have really broken utf8 passed in, we just treat it as binary data */
 
 	charset = camel_charset_best((char *) in, strlen((char *) in));
-	if (charset == NULL)
+	if (charset == NULL) {
 		return g_strdup((char *) in);
+	}
 
 	if (g_ascii_strcasecmp(charset, "UTF-8") != 0) {
 		if ((outbuf = (unsigned char *) header_convert(charset, "UTF-8", (const char *) in, strlen((char *) in))))
@@ -3322,16 +3345,23 @@
 	str = out->str;
 	g_string_free (out, FALSE);
 	*encoded = TRUE;
-	
+
 	return str;
 }
 
+/* HACK: Set to non-zero when you want the 'filename' and 'name' headers encode in RFC 2047 way,
+   otherwise they will be encoded in the correct RFC 2231 way. It's because Outlook and GMail
+   do not understand the correct standard and refuse attachments with localized name sent
+   from evolution. */
+int camel_header_param_encode_filenames_in_rfc_2047 = 0;
+
 void
 camel_header_param_list_format_append (GString *out, struct _camel_header_param *p)
 {
 	int used = out->len;
 
 	while (p) {
+		gboolean is_filename = camel_header_param_encode_filenames_in_rfc_2047 && (g_ascii_strcasecmp (p->name, "filename") == 0 || g_ascii_strcasecmp (p->name, "name") == 0);
 		gboolean encoded = FALSE;
 		gboolean quote = FALSE;
 		int here = out->len;
@@ -3343,7 +3373,7 @@
 			continue;
 		}
 
-		value = header_encode_param ((unsigned char *) p->value, &encoded);
+		value = header_encode_param ((unsigned char *) p->value, &encoded, is_filename);
 		if (!value) {
 			w(g_warning ("appending parameter %s=%s violates rfc2184", p->name, p->value));
 			value = g_strdup (p->value);
@@ -3360,17 +3390,19 @@
 			quote = ch && *ch;
 		}
 
+		quote = quote || is_filename;
 		nlen = strlen (p->name);
 		vlen = strlen (value);
 
-		if (used + nlen + vlen > CAMEL_FOLD_SIZE - 8) {
+		/* do not fold file names */
+		if (!is_filename && used + nlen + vlen > CAMEL_FOLD_SIZE - 8) {
 			out = g_string_append (out, ";\n\t");
 			here = out->len;
 			used = 0;
 		} else
 			out = g_string_append (out, "; ");
 
-		if (nlen + vlen > CAMEL_FOLD_SIZE - 8) {
+		if (!is_filename && nlen + vlen > CAMEL_FOLD_SIZE - 8) {
 			/* we need to do special rfc2184 parameter wrapping */
 			int maxlen = CAMEL_FOLD_SIZE - (nlen + 8);
 			char *inptr, *inend;

Modified: branches/camel-gobject/camel/camel-object.h
==============================================================================
--- branches/camel-gobject/camel/camel-object.h	(original)
+++ branches/camel-gobject/camel/camel-object.h	Tue Jan  6 01:56:50 2009
@@ -126,9 +126,8 @@
 typedef unsigned int CamelObjectHookID;
 #ifndef CAMEL_DISABLE_DEPRECATED
 typedef struct _CamelObjectMeta CamelObjectMeta;
-#endif /* CAMEL_DISABLE_DEPRECATED */
-
 typedef struct _CamelInterface CamelInterface;
+#endif /* CAMEL_DISABLE_DEPRECATED */
 
 typedef void (*CamelObjectClassInitFunc) (CamelObjectClass *);
 typedef void (*CamelObjectClassFinalizeFunc) (CamelObjectClass *);
@@ -241,10 +240,12 @@
 	int (*state_write)(struct _CamelObject *, FILE *fp);
 };
 
+#ifndef CAMEL_DISABLE_DEPRECATED
 /* an interface is just a class with no instance data */
 struct _CamelInterface {
 	struct _CamelObjectClass type;
 };
+#endif /* CAMEL_DISABLE_DEPRECATED */
 
 #ifndef CAMEL_DISABLE_DEPRECATED
 /* The type system .... it's pretty simple..... */
@@ -319,6 +320,7 @@
 }
 #endif /* CAMEL_DISABLE_DEPRECATED */
 
+#ifndef CAMEL_DISABLE_DEPRECATED
 /* Utility functions, not object specific, but too small to separate */
 typedef struct _CamelIteratorVTable CamelIteratorVTable;
 typedef struct _CamelIterator CamelIterator;
@@ -345,6 +347,7 @@
 const void *camel_iterator_next(void *it, CamelException *ex);
 void camel_iterator_reset(void *it);
 int camel_iterator_length(void *it);
+#endif /* CAMEL_DISABLE_DEPRECATED */
 
 G_END_DECLS
 

Modified: branches/camel-gobject/camel/camel-private.h
==============================================================================
--- branches/camel-gobject/camel/camel-private.h	(original)
+++ branches/camel-gobject/camel/camel-private.h	Tue Jan  6 01:56:50 2009
@@ -128,6 +128,7 @@
 	GMutex *filter_lock;	/* for accessing any of the filtering/indexing stuff, since we share them */
 	GMutex *alloc_lock;	/* for setting up and using allocators */
 	GMutex *ref_lock;	/* for reffing/unreffing messageinfo's ALWAYS obtain before summary_lock */
+	GHashTable *flag_cache;
 };
 
 #define CAMEL_SUMMARY_LOCK(f, l) \

Modified: branches/camel-gobject/camel/camel-search-sql-sexp.c
==============================================================================
--- branches/camel-gobject/camel/camel-search-sql-sexp.c	(original)
+++ branches/camel-gobject/camel/camel-search-sql-sexp.c	Tue Jan  6 01:56:50 2009
@@ -150,8 +150,12 @@
 	
 	if (r1->type == ESEXP_RES_STRING) {
 		r = e_sexp_result_new(f, ESEXP_RES_STRING);
-		r->value.string = g_strdup_printf ("(NOT (%s))",
-						   r1->value.string);
+		/* HACK: Fix and handle completed-on better. */
+		if (strcmp(r1->value.string, "( (usertags LIKE '%completed-on 0%' AND usertags LIKE '%completed-on%') )") == 0)
+			r->value.string = g_strdup ("( (not (usertags LIKE '%completed-on 0%')) AND usertags LIKE '%completed-on%' )");
+		else			
+			r->value.string = g_strdup_printf ("(NOT (%s))",
+							   r1->value.string);
 	}
 	e_sexp_result_free (f, r1);
 
@@ -439,7 +443,7 @@
 	r = e_sexp_result_new(f, ESEXP_RES_STRING);
 	/* Hacks no otherway to fix these really :( */
 	if (strcmp(argv[0]->value.string, "completed-on") == 0)
-		r->value.string = g_strdup_printf("usertags NOT LIKE '%ccompleted-on%c'", '%', '%');
+		r->value.string = g_strdup_printf("(usertags LIKE '%ccompleted-on 0%c' AND usertags LIKE '%ccompleted-on%c')", '%', '%', '%', '%');
 	else if (strcmp(argv[0]->value.string, "follow-up") == 0)
 		r->value.string = g_strdup_printf("usertags NOT LIKE '%cfollow-up%c'", '%', '%');
 	else

Modified: branches/camel-gobject/camel/camel-store-summary.h
==============================================================================
--- branches/camel-gobject/camel/camel-store-summary.h	(original)
+++ branches/camel-gobject/camel/camel-store-summary.h	Tue Jan  6 01:56:50 2009
@@ -57,6 +57,7 @@
 
 	/* not in camle-store.h yet */
 	CAMEL_STORE_INFO_FOLDER_READONLY = 1<<13,
+	CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW = 1<<14,
 
 	CAMEL_STORE_INFO_FOLDER_FLAGGED = 1<<31
 } CamelStoreInfoFlags;

Modified: branches/camel-gobject/camel/camel-store.c
==============================================================================
--- branches/camel-gobject/camel/camel-store.c	(original)
+++ branches/camel-gobject/camel/camel-store.c	Tue Jan  6 01:56:50 2009
@@ -322,6 +322,21 @@
 	}
 
 	if (!folder) {
+
+		if (flags & CAMEL_STORE_IS_MIGRATING) {
+				if ((store->flags & CAMEL_STORE_VTRASH) && strcmp(folder_name, CAMEL_VTRASH_NAME) == 0) {
+						if (store->folders) 
+								camel_object_bag_abort(store->folders, folder_name);
+						return NULL;
+				}
+
+				if ((store->flags & CAMEL_STORE_VJUNK) && strcmp(folder_name, CAMEL_VJUNK_NAME) == 0) {
+						if (store->folders) 
+								camel_object_bag_abort(store->folders, folder_name);
+						return NULL;
+				}
+		}
+
 		if ((store->flags & CAMEL_STORE_VTRASH) && strcmp(folder_name, CAMEL_VTRASH_NAME) == 0) {
 			folder = CS_CLASS(store)->get_trash(store, ex);
 		} else if ((store->flags & CAMEL_STORE_VJUNK) && strcmp(folder_name, CAMEL_VJUNK_NAME) == 0) {

Modified: branches/camel-gobject/camel/camel-store.h
==============================================================================
--- branches/camel-gobject/camel/camel-store.h	(original)
+++ branches/camel-gobject/camel/camel-store.h	Tue Jan  6 01:56:50 2009
@@ -115,6 +115,7 @@
 #define CAMEL_STORE_FILTER_INBOX	(1 << 2)
 #define CAMEL_STORE_VJUNK		(1 << 3)
 #define CAMEL_STORE_PROXY		(1 << 4)
+#define CAMEL_STORE_IS_MIGRATING (1 << 5)
 
 struct _CamelDB;
 
@@ -274,6 +275,7 @@
 						       CamelFolderInfo *info,
 						       CamelException *ex);
 
+#ifndef CAMEL_DISABLE_DEPRECATED
 typedef struct _CamelISubscribe CamelISubscribe;
 struct _CamelISubscribe {
 	CamelInterface iface;
@@ -287,6 +289,7 @@
 gboolean camel_isubscribe_subscribed(CamelStore *store, const char *name);
 void camel_isubscribe_subscribe(CamelStore *store, const char *folder_name, CamelException *ex);
 void camel_isubscribe_unsubscribe(CamelStore *store, const char *folder_name, CamelException *ex);
+#endif /* CAMEL_DISABLE_DEPRECATED */
 
 G_END_DECLS
 

Modified: branches/camel-gobject/camel/camel-utf8.c
==============================================================================
--- branches/camel-gobject/camel/camel-utf8.c	(original)
+++ branches/camel-gobject/camel/camel-utf8.c	Tue Jan  6 01:56:50 2009
@@ -399,3 +399,27 @@
 
 	return out;
 }
+
+/**
+ * camel_utf8_make_valid:
+ * @text: 
+ *
+ * Ensures the returned text will be valid UTF-8 string, with incorrect letters
+ * changed to question marks. Returned pointer should be freed with g_free.
+ **/
+char *
+camel_utf8_make_valid (const char *text)
+{
+	gchar *res = g_strdup (text), *p;
+
+	if (!res)
+		return res;
+
+	p = res;
+	while (!g_utf8_validate (p, -1, (const gchar **) &p)) {
+		/* make all invalid characters appear as question marks */
+		*p = '?';
+	}
+
+	return res;
+}

Modified: branches/camel-gobject/camel/camel-utf8.h
==============================================================================
--- branches/camel-gobject/camel/camel-utf8.h	(original)
+++ branches/camel-gobject/camel/camel-utf8.h	Tue Jan  6 01:56:50 2009
@@ -40,6 +40,9 @@
 char *camel_utf8_ucs2(const char *ptr);
 char *camel_ucs2_utf8(const char *ptr);
 
+/* make valid utf8 string */
+char *camel_utf8_make_valid (const char *text);
+
 G_END_DECLS
 
 #endif /* ! _CAMEL_UTF8_H */

Modified: branches/camel-gobject/camel/camel-vee-folder.c
==============================================================================
--- branches/camel-gobject/camel/camel-vee-folder.c	(original)
+++ branches/camel-gobject/camel/camel-vee-folder.c	Tue Jan  6 01:56:50 2009
@@ -150,7 +150,7 @@
 		camel_vee_folder_construct(vf, parent_store, full, name, flags);
 	}
 
-	d(printf("returning folder %s %p, count = %d\n", name, vf, camel_folder_get_message_count((CamelFolder *)vf)));
+	d(printf("returning folder %s %p, count = %d\n", full, vf, camel_folder_get_message_count((CamelFolder *)vf)));
 
 	if (vf) {
 		tmp = g_strdup_printf("%s/%s.cmeta", ((CamelService *)parent_store)->url->path, full);
@@ -2018,13 +2018,14 @@
 		camel_object_unhook_event((CamelObject *)o, "summary_reloaded", (CamelObjectEventHookFunc) summary_reloaded, data);
 	}
 	
+	/*
 	m = camel_session_thread_msg_new(session, &folder_flags_ops, sizeof(*m));
 	m->sub = summary->folder;
 	g_object_ref((CamelObject *)summary->folder);
 	m->vf = vf;
 	g_object_ref((CamelObject *)vf);
 	camel_session_thread_queue(session, &m->msg, 0);
-	
+	*/
 }
 
 /* vfolder base implementaitons */
@@ -2065,8 +2066,16 @@
 	}
 
 	/* Recreate the table when the query changes, only if we are not setting it first */
-	if (vf->expression)
+	if (vf->expression) {
+		CamelFolderSummary *s = ((CamelFolder *)vf)->summary;
+		camel_folder_summary_clear (s);
 		camel_db_recreate_vfolder (((CamelFolder *) vf)->parent_store->cdb_w, ((CamelFolder *) vf)->full_name, NULL);
+		s->junk_count = 0;
+		s->deleted_count = 0; 
+		s->unread_count = 0;
+		s->visible_count = 0;
+		s->junk_not_deleted_count = 0;
+	}
 
 
 	g_free(vf->expression);
@@ -2091,6 +2100,94 @@
 	CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
 }
 
+/* This entire code will be useless, since we sync the counts always. */
+static int
+vf_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args)
+{
+	CamelFolder *folder = (CamelFolder *)object;
+	int i;
+	guint32 tag;
+	int unread = -1, deleted = 0, junked = 0, visible = 0, count = -1, junked_not_deleted = -1;
+
+	for (i=0;i<args->argc;i++) {
+		CamelArgGet *arg = &args->argv[i];
+
+		tag = arg->tag;
+
+		/* NB: this is a copy of camel-folder.c with the unread count logic altered.
+		   makes sure its still atomically calculated */
+		switch (tag & CAMEL_ARG_TAG) {
+		case CAMEL_FOLDER_ARG_UNREAD:
+		case CAMEL_FOLDER_ARG_DELETED:
+		case CAMEL_FOLDER_ARG_JUNKED:
+		case CAMEL_FOLDER_ARG_JUNKED_NOT_DELETED:	
+		case CAMEL_FOLDER_ARG_VISIBLE:
+			
+			/* This is so we can get the values atomically, and also so we can calculate them only once */
+			if (unread == -1) {
+				int j;
+				CamelMessageInfoBase *info;
+				CamelVeeMessageInfo *vinfo;
+
+				unread = deleted = visible = junked = junked_not_deleted = 0;
+				count = camel_folder_summary_count(folder->summary);
+				for (j=0; j<count; j++) {
+					if ((info = (CamelMessageInfoBase *) camel_folder_summary_index(folder->summary, j))) {
+						guint32 flags;
+
+						vinfo = (CamelVeeMessageInfo *) info;
+						flags = vinfo->old_flags;// ? vinfo->old_flags : camel_message_info_flags(info);
+
+						if ((flags & (CAMEL_MESSAGE_SEEN)) == 0)
+							unread++;
+						if (flags & CAMEL_MESSAGE_DELETED)
+							deleted++;
+						if (flags & CAMEL_MESSAGE_JUNK) {
+							junked++;
+								if (! (flags & CAMEL_MESSAGE_DELETED))
+									junked_not_deleted++;						
+						}
+						if ((flags & (CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0)
+							visible++;
+						camel_message_info_free(info);
+					}
+				}
+			}
+
+			switch (tag & CAMEL_ARG_TAG) {
+			case CAMEL_FOLDER_ARG_UNREAD:
+				count = unread == -1 ? 0 : unread;
+				break;
+			case CAMEL_FOLDER_ARG_DELETED:
+				count = deleted == -1 ? 0 : deleted;
+				break;
+			case CAMEL_FOLDER_ARG_JUNKED:
+				count = junked == -1 ? 0 : junked;
+				break;
+			case CAMEL_FOLDER_ARG_JUNKED_NOT_DELETED:
+				count = junked_not_deleted == -1 ? 0 : junked_not_deleted;
+				break;				
+			case CAMEL_FOLDER_ARG_VISIBLE:
+				count = visible == -1 ? 0 : visible;
+				break;
+			}
+			folder->summary->unread_count = unread == -1 ? 0 : unread;
+			folder->summary->deleted_count = deleted == -1 ? 0 : deleted;
+			junked = folder->summary->junk_count = junked == -1 ? 0 : junked;
+			folder->summary->junk_not_deleted_count = junked_not_deleted == -1 ? 0 : junked_not_deleted;
+			folder->summary->visible_count = visible == -1 ? 0 : visible;			
+			*arg->ca_int = count;
+			break;
+		default:
+			continue;
+		}
+
+		arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
+	}
+
+	return ((CamelObjectClass *)camel_vee_folder_parent)->getv(object, ex, args);
+}
+
 static void
 camel_vee_folder_class_init (CamelVeeFolderClass *klass)
 {
@@ -2098,6 +2195,8 @@
 
 	camel_vee_folder_parent = CAMEL_FOLDER_CLASS(g_type_class_peek (camel_folder_get_type ()));
 
+	((CamelObjectClass *)klass)->getv = vf_getv; 
+
 	folder_class->refresh_info = vee_refresh_info;
 	folder_class->sync = vee_sync;
 	folder_class->expunge = vee_expunge;

Modified: branches/camel-gobject/camel/camel-vee-summary.c
==============================================================================
--- branches/camel-gobject/camel/camel-vee-summary.c	(original)
+++ branches/camel-gobject/camel/camel-vee-summary.c	Tue Jan  6 01:56:50 2009
@@ -42,7 +42,7 @@
 #define d(x)
 
 static CamelFolderSummaryClass *camel_vee_summary_parent;
-const char *unread_str = " (and\n  \n     (match-all (not (system-flag  \"Seen\")))\n    \n  )\n; (match-threads \"all\"  (and\n  \n     (match-all (not (system-flag  \"Seen\")))\n    \n  )\n)\n;";
+const char *unread_str = " (and\n  \n     (match-all (not (system-flag  \"Seen\")))\n    \n  )\n;  (or\n  \n     (match-all (not (system-flag  \"Seen\")))\n    \n  )\n; (match-threads \"all\"  (and\n  \n     (match-all (not (system-flag  \"Seen\")))\n    \n  )\n)\n;  (match-threads \"all\"  (or\n  \n     (match-all (not (system-flag  \"Seen\")))\n    \n  )\n)\n;";
 
 static void
 vee_message_info_free(CamelFolderSummary *s, CamelMessageInfo *info)
@@ -176,20 +176,33 @@
 {
 	int res = FALSE;
 	CamelVeeFolder *vf = (CamelVeeFolder *)mi->summary->folder;
-	const char *exp = g_getenv("CAMEL_VFOLDER_UNREAD_EXP");
+	static char *exp = NULL;
+	static only_once = FALSE;
 	gboolean hacked_unread_folder = FALSE;
+	char *meta = NULL;
 
 	/* HACK: Ugliest of all hacks. Its virtually not possible now
 	 * to maintain counts and the non matching uids of unread vfolder here.
 	 * So, I hardcode unread vfolder expression and hack it. */
+	if (!only_once) {
+		exp =  g_getenv("CAMEL_VFOLDER_UNREAD_EXP") ? g_strcompress(g_getenv("CAMEL_VFOLDER_UNREAD_EXP")) : NULL;
+		only_once = TRUE;
+	}
+
 	if (!exp || !*exp)
-		exp = unread_str;
+		exp = g_strcompress(unread_str);
+
 	if (camel_debug("vfolderexp"))
 		printf("Expression for vfolder '%s' is '%s'\n", mi->summary->folder->full_name, g_strescape(vf->expression, ""));
 
 	if (strstr(exp, vf->expression) &&  (vf->flags & CAMEL_STORE_VEE_FOLDER_SPECIAL) == 0)
 		hacked_unread_folder = TRUE;
 
+	meta = camel_object_meta_get (mi->summary->folder, "vfolder:unread");
+	if (!hacked_unread_folder && meta && strcmp (meta, "true") == 0)
+		hacked_unread_folder = TRUE;
+	g_free(meta);
+
 	if (mi->uid) {
 		guint32 old_visible, old_unread, old_deleted, old_junked, old_junked_not_deleted;
 		guint32 visible, unread, deleted, junked, junked_not_deleted;
@@ -418,7 +431,7 @@
 {
 	CamelVeeMessageInfo *mi;
 	char *vuid;
-
+	GHashTable * fcache;
 	vuid = g_malloc(strlen(uid)+9);
 	memcpy(vuid, hash, 8);
 	strcpy(vuid+8, uid);
@@ -441,6 +454,8 @@
 
 	mi = (CamelVeeMessageInfo *)camel_message_info_new(&s->summary);
 	mi->summary = summary;
+	fcache = camel_folder_summary_get_flag_cache(summary);
+	mi->old_flags = GPOINTER_TO_UINT(g_hash_table_lookup (fcache, uid));
 	/* We would do lazy loading of flags, when the folders are loaded to memory through folder_reloaded signal */
 	g_object_ref (summary);
 	mi->info.uid = (char *) camel_pstring_strdup (vuid);

Modified: branches/camel-gobject/camel/camel-vtrash-folder.c
==============================================================================
--- branches/camel-gobject/camel/camel-vtrash-folder.c	(original)
+++ branches/camel-gobject/camel/camel-vtrash-folder.c	Tue Jan  6 01:56:50 2009
@@ -151,7 +151,7 @@
 						guint32 flags;
 
 						vinfo = (CamelVeeMessageInfo *) info;
-						flags = vinfo->old_flags ? vinfo->old_flags : camel_message_info_flags(info);
+						flags = vinfo->old_flags;// ? vinfo->old_flags : camel_message_info_flags(info);
 
 						if ((flags & (CAMEL_MESSAGE_SEEN)) == 0)
 							unread++;

Modified: branches/camel-gobject/camel/providers/groupwise/camel-groupwise-folder.c
==============================================================================
--- branches/camel-gobject/camel/providers/groupwise/camel-groupwise-folder.c	(original)
+++ branches/camel-gobject/camel/providers/groupwise/camel-groupwise-folder.c	Tue Jan  6 01:56:50 2009
@@ -229,8 +229,11 @@
 		time_t actual_time;
 		int offset = 0;
 		dtstring = e_gw_item_get_creation_date (item);
-		time = e_gw_connection_get_date_from_string (dtstring);
-		actual_time = camel_header_decode_date (ctime(&time), NULL);
+		if (dtstring) {
+				time = e_gw_connection_get_date_from_string (dtstring);
+				actual_time = camel_header_decode_date (ctime(&time), NULL);
+		} else
+				actual_time = (time_t) 0;
 		camel_mime_message_set_date (msg, actual_time, offset);
 	}
 }
@@ -922,7 +925,13 @@
 	done = FALSE;
 	m->slist = NULL;
 
-	while (!done && !camel_application_is_exiting) {
+	while (!done) {
+
+		if (camel_application_is_exiting) {
+				CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
+				return ;
+		}
+
 		item_list = NULL;
 		status = e_gw_connection_get_all_mail_uids (m->cnc, m->container_id, cursor, FALSE, READ_CURSOR_MAX_IDS, position, &item_list);
 		if (status != E_GW_CONNECTION_STATUS_OK) {
@@ -1191,10 +1200,6 @@
 		if (gw_store->current_folder != folder) {
 			gw_store->current_folder = folder;
 		}
-
-		if (list) {
-			gw_update_cache (folder, list, ex, FALSE);
-		}
 		
 		if (check_all && !is_proxy) {
 				EGwContainer *container;
@@ -1205,8 +1210,15 @@
 
 				if (camel_folder_summary_count (folder->summary) == e_gw_container_get_total_count (container))
 						check_all = FALSE;
+
+				folder->summary->unread_count = e_gw_container_get_unread_count (container);
+				folder->summary->visible_count = e_gw_container_get_total_count (container);
 				g_object_unref (container);
 		}
+
+		if (list) {
+			gw_update_cache (folder, list, ex, FALSE);
+		}
 	}
 
 
@@ -1270,7 +1282,7 @@
 
 	int folder_needs_caching;
 
-	camel_object_get (folder, NULL, CAMEL_OFFLINE_FOLDER_ARG_SYNC_OFFLINE, &folder_needs_caching, NULL);
+	camel_object_get (folder, NULL, CAMEL_OFFLINE_FOLDER_SYNC_OFFLINE, &folder_needs_caching, NULL);
 
 	changes = camel_folder_change_info_new ();
 	container_id = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name));
@@ -1343,6 +1355,8 @@
 				mi->info.content->type = camel_content_type_new ("multipart", "mixed");	
 			}
 
+			mi->info.flags = 0;
+
 			if (type == E_GW_ITEM_TYPE_APPOINTMENT || type == E_GW_ITEM_TYPE_TASK || type == E_GW_ITEM_TYPE_NOTE)
 				camel_message_info_set_user_flag ((CamelMessageInfo*)mi, "$has_cal", TRUE);
 		}
@@ -1359,16 +1373,12 @@
 
 		item_status = e_gw_item_get_item_status (item);
 		if (item_status & E_GW_ITEM_STAT_READ)
-			status_flags |= CAMEL_MESSAGE_SEEN;
+			mi->info.flags |= CAMEL_MESSAGE_SEEN;
 		else 
 			mi->info.flags &= ~CAMEL_MESSAGE_SEEN;
 
 		if (item_status & E_GW_ITEM_STAT_REPLIED)
-			status_flags |= CAMEL_MESSAGE_ANSWERED;
-		if (exists) 
-			mi->info.flags |= status_flags;
-		else 
-			mi->info.flags = status_flags;
+			mi->info.flags |= CAMEL_MESSAGE_ANSWERED;
 
 		priority = e_gw_item_get_priority (item);
 		if (priority && !(g_ascii_strcasecmp (priority,"High"))) {
@@ -1449,12 +1459,17 @@
 				time_t time;
 				time_t actual_time;
 				temp_date = e_gw_item_get_creation_date (item);
-				time = e_gw_connection_get_date_from_string (temp_date);
-				actual_time = camel_header_decode_date (ctime(&time), NULL);
+				if (temp_date) {
+						/* Creation date can be returned as null for auto-generated meetings */
+						time = e_gw_connection_get_date_from_string (temp_date);
+						actual_time = camel_header_decode_date (ctime(&time), NULL);
+				} else
+					actual_time = (time_t) 0;
 				mi->info.date_sent = mi->info.date_received = actual_time;
 			}
 		}
 
+		mi->info.dirty = TRUE;
 		if (exists) {
 			camel_folder_change_info_change_uid (changes, mi->info.uid);
 			camel_message_info_free (pmi);
@@ -1462,12 +1477,7 @@
 			mi->info.uid = camel_pstring_strdup (e_gw_item_get_id(item));
 			mi->info.size = e_gw_item_get_mail_size (item);	
 			mi->info.subject = camel_pstring_strdup(e_gw_item_get_subject(item));
-			mi->info.dirty = TRUE;
 			
-			folder->summary->visible_count ++;
-			if (!(mi->info.flags & CAMEL_MESSAGE_SEEN))
-					folder->summary->unread_count ++;
-
 			camel_folder_summary_add (folder->summary,(CamelMessageInfo *)mi);
 			camel_folder_change_info_add_uid (changes, mi->info.uid);
 			camel_folder_change_info_recent_uid (changes, mi->info.uid);
@@ -1670,8 +1680,11 @@
 				time_t time;
 				time_t actual_time;
 				temp_date = e_gw_item_get_creation_date (item);
-				time = e_gw_connection_get_date_from_string (temp_date);
-				actual_time = camel_header_decode_date (ctime(&time), NULL);
+				if (temp_date) {
+						time = e_gw_connection_get_date_from_string (temp_date);
+						actual_time = camel_header_decode_date (ctime(&time), NULL);
+				} else
+						actual_time = (time_t) 0;
 				mi->info.date_sent = mi->info.date_received = actual_time;
 			}
 		}
@@ -1780,7 +1793,7 @@
 									gsize len_iter = 0;
 									char *temp = NULL;
 	
-									temp = g_base64_decode(t_attach, &len_iter);
+									temp = (char *) g_base64_decode(t_attach, &len_iter);
 									gstr = g_string_append_len (gstr, temp, len_iter);
 									g_free (temp);
 									len += len_iter;
@@ -1924,7 +1937,7 @@
 								gsize len_iter = 0;
 								char *temp = NULL;
 
-								temp = g_base64_decode(t_attach, &len_iter);
+								temp = (char *) g_base64_decode(t_attach, &len_iter);
 								gstr = g_string_append_len (gstr, temp, len_iter);
 								g_free (temp);
 								len += len_iter;
@@ -2686,7 +2699,21 @@
 	g_string_append_printf (gstr, "UID:%s\n",e_gw_item_get_icalid (item));
 	g_string_append_printf (gstr, "DTSTART:%s\n",e_gw_item_get_start_date (item));
 	g_string_append_printf (gstr, "SUMMARY:%s\n", e_gw_item_get_subject (item));
-	g_string_append_printf (gstr, "DESCRIPTION:%s\n", e_gw_item_get_message (item));
+
+	temp = e_gw_item_get_message (item);
+	if (temp) {
+		g_string_append(gstr, "DESCRIPTION:");
+		while (*temp) {
+			if (*temp == '\n')
+				g_string_append(gstr, "\\n");
+			else
+				g_string_append_c(gstr, *temp);
+			temp++;
+		}
+		g_string_append(gstr, "\n");	
+	}
+	temp = NULL;
+
 	g_string_append_printf (gstr, "DTSTAMP:%s\n", e_gw_item_get_creation_date (item));
 	g_string_append_printf (gstr, "X-GWMESSAGEID:%s\n", e_gw_item_get_id (item));
 	g_string_append_printf (gstr, "X-GWSHOW-AS:BUSY\n");
@@ -2741,6 +2768,7 @@
 	EGwItemOrganizer *org = NULL;
 	GString *gstr = g_string_new (NULL);
 	char **tmp = NULL;
+	const char *temp = NULL;
 
 	tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
 
@@ -2750,7 +2778,21 @@
 	g_string_append_printf (gstr, "UID:%s\n",e_gw_item_get_icalid (item));
 	g_string_append_printf (gstr, "DTSTART:%s\n",e_gw_item_get_start_date (item));
 	g_string_append_printf (gstr, "SUMMARY:%s\n", e_gw_item_get_subject (item));
-	g_string_append_printf (gstr, "DESCRIPTION:%s\n", e_gw_item_get_message (item));
+
+	temp = e_gw_item_get_message (item);
+	if (temp) {
+		g_string_append(gstr, "DESCRIPTION:");
+		while (*temp) {
+			if (*temp == '\n')
+				g_string_append(gstr, "\\n");
+			else
+				g_string_append_c(gstr, *temp);
+			temp++;
+		}
+		g_string_append(gstr, "\n");	
+	}
+	temp = NULL;
+
 	g_string_append_printf (gstr, "DTSTAMP:%s\n", e_gw_item_get_creation_date (item));
 	g_string_append_printf (gstr, "X-GWMESSAGEID:%s\n", e_gw_item_get_id (item));
 	g_string_append_printf (gstr, "X-GWRECORDID:%s\n", tmp[0]);

Modified: branches/camel-gobject/camel/providers/groupwise/camel-groupwise-provider.c
==============================================================================
--- branches/camel-gobject/camel/providers/groupwise/camel-groupwise-provider.c	(original)
+++ branches/camel-gobject/camel/providers/groupwise/camel-groupwise-provider.c	Tue Jan  6 01:56:50 2009
@@ -73,7 +73,7 @@
 	  N_("SOAP Settings") },
 
 	{ CAMEL_PROVIDER_CONF_ENTRY, "soap_port", NULL,
-	  N_("Post Office Agent SOAP Port:"), "7191" },
+	  N_("Post Office Agent SOAP _Port:"), "7191" },
 
 	{ CAMEL_PROVIDER_CONF_HIDDEN, "auth-domain", NULL,
 	  NULL, "Groupwise" },

Modified: branches/camel-gobject/camel/providers/groupwise/camel-groupwise-store.c
==============================================================================
--- branches/camel-gobject/camel/providers/groupwise/camel-groupwise-store.c	(original)
+++ branches/camel-gobject/camel/providers/groupwise/camel-groupwise-store.c	Tue Jan  6 01:56:50 2009
@@ -1430,6 +1430,17 @@
 		return NULL;
 }
 
+static gboolean
+groupwise_can_refresh_folder (CamelStore *store, CamelFolderInfo *info, CamelException *ex)
+{
+	gboolean res;
+
+	res = CAMEL_STORE_CLASS(parent_class)->can_refresh_folder (store, info, ex) ||
+	      (camel_url_get_param (((CamelService *)store)->url, "check_all") != NULL);
+
+	return res;
+}
+
 /*
  * Function to check if we are both connected and are _actually_
  * online. Based on an equivalient function in IMAP
@@ -1498,6 +1509,7 @@
 	camel_store_class->get_folder_info = groupwise_get_folder_info;
 	camel_store_class->free_folder_info = camel_store_free_folder_info_full;
 	camel_store_class->get_trash = groupwise_get_trash;
+	camel_store_class->can_refresh_folder = groupwise_can_refresh_folder;
 }
 
 
@@ -1597,3 +1609,4 @@
 	
 	return camel_groupwise_store_type;
 }
+

Modified: branches/camel-gobject/camel/providers/imap/camel-imap-folder.c
==============================================================================
--- branches/camel-gobject/camel/providers/imap/camel-imap-folder.c	(original)
+++ branches/camel-gobject/camel/providers/imap/camel-imap-folder.c	Tue Jan  6 01:56:50 2009
@@ -473,6 +473,7 @@
 			break; }
 			/* imap args */
 		case CAMEL_IMAP_FOLDER_ARG_CHECK_FOLDER:
+			/* The internal value has precedence before the one stored in the summary. */
 			*arg->ca_int = ((CamelImapFolder *)object)->check_folder;
 			break;
 			/* CamelObject args */
@@ -514,8 +515,27 @@
 		switch (tag & CAMEL_ARG_TAG) {
 		case CAMEL_IMAP_FOLDER_ARG_CHECK_FOLDER:
 			if (((CamelImapFolder *)object)->check_folder != arg->ca_int) {
+				CamelFolder *folder = (CamelFolder *)object;
+
 				((CamelImapFolder *)object)->check_folder = arg->ca_int;
 				save = 1;
+
+				/* store both to the summary and to folder cmeta, to have this value restored correctly next time folder is fully loaded */
+				if (folder->parent_store && CAMEL_IS_IMAP_STORE (folder->parent_store)) {
+					CamelStoreInfo *si;
+					CamelStoreSummary *sm = CAMEL_STORE_SUMMARY (((CamelImapStore *)(folder->parent_store))->summary);
+
+					si = camel_store_summary_path (sm, folder->full_name);
+					if (si) {
+						if ((si->flags & CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW) != 0 ? 1 : 0 != (arg->ca_int) ? 1 : 0) {
+							si->flags = (si->flags & (~CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW)) | ((arg->ca_int) ? CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW : 0);
+							camel_store_summary_touch (sm);
+							camel_store_summary_save (sm);
+						}
+
+						camel_store_summary_info_free (sm, si);
+					}
+				}
 			}
 			break;
 		default:
@@ -1587,6 +1607,8 @@
 
 	camel_folder_summary_save_to_db (folder->summary, ex);
 	uids = camel_db_get_folder_deleted_uids (folder->parent_store->cdb_r, folder->full_name, ex);
+	if (!uids)
+		return;
 
 	if (CAMEL_OFFLINE_STORE (store)->state == CAMEL_OFFLINE_STORE_NETWORK_AVAIL)
 		imap_expunge_uids_online (folder, uids, ex);
@@ -2254,12 +2276,12 @@
 			if (response)
 				handle_copyuid_copy_user_tags (response, source, destination);
 			camel_imap_response_free (store, response);
+		}
 
-			if (!camel_exception_is_set(ex) && delete_originals) {
-				for (i=last;i<uid;i++)
-					camel_folder_delete_message(source, uids->pdata[i]);
-				last = uid;
-			}
+		if (!camel_exception_is_set(ex) && delete_originals) {
+			for (i=last;i<uid;i++)
+				camel_folder_delete_message(source, uids->pdata[i]);
+			last = uid;
 		}
 		g_free (uidset);
 	}
@@ -2899,12 +2921,29 @@
 		 && retry < 2
 		 && camel_exception_get_id(ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE);
 
-done:	/* FIXME, this shouldn't be done this way. */
-	if (msg)
+done:
+	if (msg) {
+		/* FIXME, this shouldn't be done this way. */
 		camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", store->base_url);
+
+		if (!mi->info.mlist || !*mi->info.mlist) {
+			/* update mailing list information, if necessary */
+			char *mlist = camel_header_raw_check_mailing_list (&(CAMEL_MIME_PART (msg)->headers));
+
+			if (mlist) {
+				if (mi->info.mlist)
+					camel_pstring_free (mi->info.mlist);
+				mi->info.mlist = camel_pstring_add (mlist, TRUE);
+				mi->info.dirty = TRUE;
+
+				if (mi->info.summary)
+					camel_folder_summary_touch (mi->info.summary);
+			}
+		}
+	}
 fail:
 	camel_message_info_free(&mi->info);
-	
+
 	return msg;
 }
 

Modified: branches/camel-gobject/camel/providers/imap/camel-imap-journal.c
==============================================================================
--- branches/camel-gobject/camel/providers/imap/camel-imap-journal.c	(original)
+++ branches/camel-gobject/camel/providers/imap/camel-imap-journal.c	Tue Jan  6 01:56:50 2009
@@ -160,6 +160,25 @@
 }
 
 static GPtrArray *
+copy_uids_array (GPtrArray *array)
+{
+	GPtrArray *res;
+	guint i, sz;
+
+	if (!array)
+		return NULL;
+
+	sz = array->len;
+	res = g_ptr_array_sized_new (sz);
+
+	for (i = 0; i < sz; i++) {
+		g_ptr_array_add (res, g_strdup (g_ptr_array_index (array, i)));
+	}
+
+	return res;
+}
+
+static GPtrArray *
 decode_uids (FILE *file)
 {
 	GPtrArray *uids;
@@ -413,20 +432,20 @@
 		{
 			GPtrArray *uids = va_arg (ap, GPtrArray *);
 			
-			entry->uids = uids;
+			entry->uids = copy_uids_array (uids);
 			break;
 		}
 		case CAMEL_IMAP_JOURNAL_ENTRY_APPEND:
 		{
 			char *uid = va_arg (ap, char *);
-			entry->append_uid = uid;
+			entry->append_uid = g_strdup (uid);
 			break;
 		}
 		case CAMEL_IMAP_JOURNAL_ENTRY_TRANSFER:
 		{
 			CamelFolder *dest = va_arg (ap, CamelFolder *);
 			
-			entry->uids = va_arg (ap, GPtrArray *);
+			entry->uids = copy_uids_array (va_arg (ap, GPtrArray *));
 			entry->move = va_arg (ap, gboolean);
 			entry->dest_folder_name = g_strdup (dest->full_name);
 			break;

Modified: branches/camel-gobject/camel/providers/imap/camel-imap-store.c
==============================================================================
--- branches/camel-gobject/camel/providers/imap/camel-imap-store.c	(original)
+++ branches/camel-gobject/camel/providers/imap/camel-imap-store.c	Tue Jan  6 01:56:50 2009
@@ -2385,7 +2385,7 @@
 	if (si == NULL)
 		return NULL;
 
-	newflags = (si->info.flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) | (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
+	newflags = (si->info.flags & (CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW)) | (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
 	if (si->info.flags != newflags) {
 		si->info.flags = newflags;
 		camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
@@ -3074,12 +3074,19 @@
 	      (camel_url_get_param (((CamelService *)store)->url, "check_all") != NULL) ||
 	      (camel_url_get_param (((CamelService *)store)->url, "check_lsub") != NULL && (info->flags & CAMEL_FOLDER_SUBSCRIBED) != 0);
 
-	if (!res && !camel_exception_is_set (ex)) {
-		CamelFolder *folder;
+	if (!res && !camel_exception_is_set (ex) && CAMEL_IS_IMAP_STORE (store)) {
+		CamelStoreInfo *si;
+		CamelStoreSummary *sm = CAMEL_STORE_SUMMARY (((CamelImapStore *)(store))->summary);
 
-		folder = camel_store_get_folder (store, info->full_name, 0, ex);
-		if (folder && CAMEL_IS_IMAP_FOLDER (folder))
-			res = CAMEL_IMAP_FOLDER (folder)->check_folder;
+		if (!sm)
+			return FALSE;
+
+		si = camel_store_summary_path (sm, info->full_name);
+		if (si) {
+			res = (si->flags & CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW) != 0 ? TRUE : FALSE;
+
+			camel_store_summary_info_free (sm, si);
+		}
 	}
 
 	return res;

Modified: branches/camel-gobject/camel/providers/imap/camel-imap-summary.c
==============================================================================
--- branches/camel-gobject/camel/providers/imap/camel-imap-summary.c	(original)
+++ branches/camel-gobject/camel/providers/imap/camel-imap-summary.c	Tue Jan  6 01:56:50 2009
@@ -163,6 +163,22 @@
 	return (a1 < a1) ? -1 : (a1 > a2) ? 1 : 0;
 }
 
+static int
+uid_compare (const void *va, const void *vb)
+{
+	const char **sa = (const char **)va, **sb = (const char **)vb;
+	unsigned long a, b;
+
+	a = strtoul (*sa, NULL, 10);
+	b = strtoul (*sb, NULL, 10);
+	if (a < b)
+		return -1;
+	else if (a == b)
+		return 0;
+	else
+		return 1;
+}
+
 /**
  * camel_imap_summary_new:
  * @folder: Parent folder.
@@ -181,7 +197,8 @@
 	camel_exception_init (&ex);
 
 	summary->folder = folder;
-	if (folder) {
+	/* Don't do DB sort. Its pretty slow to load */
+	if (folder && 0) {
 		camel_db_set_collate (folder->parent_store->cdb_r, "uid", "imap_uid_sort", (CamelDBCollate)sort_uid_cmp);
 		summary->sort_by = "uid";
 		summary->collate = "imap_uid_sort";
@@ -199,6 +216,8 @@
 		camel_exception_clear (&ex);
 	}
 
+	g_ptr_array_sort (summary->uids, (GCompareFunc) uid_compare); 
+
 	return summary;
 }
 

Modified: branches/camel-gobject/camel/providers/local/camel-local-folder.c
==============================================================================
--- branches/camel-gobject/camel/providers/local/camel-local-folder.c	(original)
+++ branches/camel-gobject/camel/providers/local/camel-local-folder.c	Tue Jan  6 01:56:50 2009
@@ -290,7 +290,7 @@
 	}
 
 	folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf, lf->summary_path, lf->folder_path, lf->index);
-	if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, NULL) == -1) {
+	if (!(flags & CAMEL_STORE_IS_MIGRATING) && camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, NULL) == -1) {
 		/* ? */
 		if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == 0) {
 			/* we sync here so that any hard work setting up the folder isn't lost */

Modified: branches/camel-gobject/camel/providers/pop3/camel-pop3-store.c
==============================================================================
--- branches/camel-gobject/camel/providers/pop3/camel-pop3-store.c	(original)
+++ branches/camel-gobject/camel/providers/pop3/camel-pop3-store.c	Tue Jan  6 01:56:50 2009
@@ -50,6 +50,7 @@
 #include "camel-tcp-stream-raw.h"
 #include "camel-tcp-stream.h"
 #include "camel-url.h"
+#include "camel-utf8.h"
 
 #ifdef HAVE_SSL
 #include "camel-tcp-stream-ssl.h"
@@ -610,7 +611,9 @@
 		
 		/* we only re-prompt if we failed to authenticate, any other error and we just abort */
 		if (status == 0 && camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE) {
-			errbuf = g_markup_printf_escaped ("%s\n\n", camel_exception_get_description (ex));
+			char *tmp = camel_utf8_make_valid (camel_exception_get_description (ex));
+			errbuf = g_markup_printf_escaped ("%s\n\n", tmp);
+			g_free (tmp);
 			camel_exception_clear (ex);
 
 			camel_session_forget_password (session, service, NULL, "password", ex);

Modified: branches/camel-gobject/configure.in
==============================================================================
--- branches/camel-gobject/configure.in	(original)
+++ branches/camel-gobject/configure.in	Tue Jan  6 01:56:50 2009
@@ -4,7 +4,7 @@
 # Evolution-Data-Server version */
 m4_define([eds_major_version], [2])
 m4_define([eds_minor_version], [25])
-m4_define([eds_micro_version], [2])
+m4_define([eds_micro_version], [4])
 
 m4_define([eds_version],
           [eds_major_version.eds_minor_version.eds_micro_version])
@@ -32,6 +32,7 @@
 m4_define([libsoup_minimum_version], [2.3.0])
 m4_define([gnome_keyring_minimum_version], [2.20.1])
 m4_define([sqlite_minimum_version], [3.5])
+m4_define([gweather_minimum_version], [2.25.4])
 
 dnl *************************************************************************************************
 dnl Base Version
@@ -1000,6 +1001,28 @@
 msg_calendar=$enable_calendar
 
 dnl **************************************************
+dnl Weather calendar backend support
+dnl **************************************************
+AC_MSG_CHECKING(if we should build the weather calendar backend)
+AC_ARG_WITH([weather], 
+  [AS_HELP_STRING([--with-weather], [Build the weather calendar backend (default=yes)])],
+  [use_gweather=$withval], 
+  [use_gweather=yes])
+if test $enable_calendar = no; then
+	use_gweather="no (calendar support is disabled)"
+fi
+AC_MSG_RESULT($use_gweather)
+
+if test $use_gweather = yes; then
+	PKG_CHECK_MODULES([LIBGWEATHER], 
+	   [gweather >= gweather_minimum_version],
+	   [], 
+	   [AC_MSG_ERROR([The weather calendar backend requires GWeather >= gweather_minimum_version. Alternatively, you may specify --without-weather as a configure option to avoid building the backend.])])
+fi
+
+AM_CONDITIONAL(ENABLE_WEATHER, test $use_gweather = yes)
+
+dnl **************************************************
 dnl NNTP support.
 dnl **************************************************
 AC_ARG_ENABLE(nntp, 
@@ -1624,8 +1647,10 @@
 gladedir="$privdatadir/glade"
 AC_SUBST(gladedir)
 
-weatherdatadir="$privdatadir/weather"
-AC_SUBST(weatherdatadir)
+if test $use_gweather = yes; then
+	weatherdatadir="$privdatadir/weather"
+	AC_SUBST(weatherdatadir)
+fi
 
 dnl separate camel from e-d-s?  or should it be under the same spot?  same for now.
 camel_providerdir='${libdir}'/evolution-data-server-$API_VERSION/camel-providers
@@ -1776,6 +1801,7 @@
 echo "
 	evolution-data-server has been configured as follows:
 	Calendar:         $msg_calendar
+	Weather calendar: $use_gweather
 	Mail Directory:   $system_mail_dir, $system_mail_perm
 	LDAP support:     $msg_ldap"
 if test "$msg_nntp" = "yes"; then

Modified: branches/camel-gobject/docs/reference/addressbook/libebook/tmpl/e-contact.sgml
==============================================================================
--- branches/camel-gobject/docs/reference/addressbook/libebook/tmpl/e-contact.sgml	(original)
+++ branches/camel-gobject/docs/reference/addressbook/libebook/tmpl/e-contact.sgml	Tue Jan  6 01:56:50 2009
@@ -433,6 +433,41 @@
 
 </para>
 
+<!-- ##### ARG EContact:im-skype ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG EContact:im-skype-home-1 ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG EContact:im-skype-home-2 ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG EContact:im-skype-home-3 ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG EContact:im-skype-work-1 ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG EContact:im-skype-work-2 ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG EContact:im-skype-work-3 ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG EContact:im-yahoo ##### -->
 <para>
 
@@ -736,6 +771,13 @@
 @E_CONTACT_IM_GADUGADU: 
 @E_CONTACT_GEO: 
 @E_CONTACT_TEL: 
+ E_CONTACT_IM_SKYPE_HOME_1: 
+ E_CONTACT_IM_SKYPE_HOME_2: 
+ E_CONTACT_IM_SKYPE_HOME_3: 
+ E_CONTACT_IM_SKYPE_WORK_1: 
+ E_CONTACT_IM_SKYPE_WORK_2: 
+ E_CONTACT_IM_SKYPE_WORK_3: 
+ E_CONTACT_IM_SKYPE: 
 @E_CONTACT_FIELD_LAST: 
 @E_CONTACT_FIELD_FIRST: 
 @E_CONTACT_LAST_SIMPLE_STRING: 

Modified: branches/camel-gobject/docs/reference/addressbook/libedata-book/libedata-book-sections.txt
==============================================================================
--- branches/camel-gobject/docs/reference/addressbook/libedata-book/libedata-book-sections.txt	(original)
+++ branches/camel-gobject/docs/reference/addressbook/libedata-book/libedata-book-sections.txt	Tue Jan  6 01:56:50 2009
@@ -296,4 +296,6 @@
 e_book_backend_db_cache_set_populated
 e_book_backend_db_cache_is_populated
 e_book_backend_db_cache_search
+e_book_backend_db_cache_set_time
+e_book_backend_db_cache_get_time
 </SECTION>

Modified: branches/camel-gobject/docs/reference/addressbook/libedata-book/tmpl/e-book-backend-db-cache.sgml
==============================================================================
--- branches/camel-gobject/docs/reference/addressbook/libedata-book/tmpl/e-book-backend-db-cache.sgml	(original)
+++ branches/camel-gobject/docs/reference/addressbook/libedata-book/tmpl/e-book-backend-db-cache.sgml	Tue Jan  6 01:56:50 2009
@@ -130,3 +130,21 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION e_book_backend_db_cache_set_time ##### -->
+<para>
+
+</para>
+
+ db: 
+ t: 
+
+
+<!-- ##### FUNCTION e_book_backend_db_cache_get_time ##### -->
+<para>
+
+</para>
+
+ db: 
+ Returns: 
+
+

Modified: branches/camel-gobject/docs/reference/calendar/libecal/libecal-sections.txt
==============================================================================
--- branches/camel-gobject/docs/reference/calendar/libecal/libecal-sections.txt	(original)
+++ branches/camel-gobject/docs/reference/calendar/libecal/libecal-sections.txt	Tue Jan  6 01:56:50 2009
@@ -370,6 +370,7 @@
 CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND
 CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS
 CAL_STATIC_CAPABILITY_REMOVE_ALARMS
+CAL_STATIC_CAPABILITY_CREATE_MESSAGES
 CAL_STATIC_CAPABILITY_SAVE_SCHEDULES
 CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK
 CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR

Modified: branches/camel-gobject/docs/reference/calendar/libecal/tmpl/e-cal-util.sgml
==============================================================================
--- branches/camel-gobject/docs/reference/calendar/libecal/tmpl/e-cal-util.sgml	(original)
+++ branches/camel-gobject/docs/reference/calendar/libecal/tmpl/e-cal-util.sgml	Tue Jan  6 01:56:50 2009
@@ -327,6 +327,13 @@
 
 
 
+<!-- ##### MACRO CAL_STATIC_CAPABILITY_CREATE_MESSAGES ##### -->
+<para>
+
+</para>
+
+
+
 <!-- ##### MACRO CAL_STATIC_CAPABILITY_SAVE_SCHEDULES ##### -->
 <para>
 

Modified: branches/camel-gobject/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt
==============================================================================
--- branches/camel-gobject/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt	(original)
+++ branches/camel-gobject/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt	Tue Jan  6 01:56:50 2009
@@ -159,7 +159,6 @@
 e_cal_backend_get_free_busy
 e_cal_backend_internal_get_default_timezone
 e_cal_backend_internal_get_timezone
-e_cal_backend_last_client_gone
 e_cal_backend_set_notification_proxy
 e_cal_backend_notify_object_created
 e_cal_backend_notify_object_modified

Modified: branches/camel-gobject/docs/reference/camel/camel-docs.sgml
==============================================================================
--- branches/camel-gobject/docs/reference/camel/camel-docs.sgml	(original)
+++ branches/camel-gobject/docs/reference/camel/camel-docs.sgml	Tue Jan  6 01:56:50 2009
@@ -87,6 +87,7 @@
 <!ENTITY CamelSASLPlain SYSTEM "xml/camel-sasl-plain.xml">
 <!ENTITY CamelSASLPOPb4SMTP SYSTEM "xml/camel-sasl-popb4smtp.xml">
 <!ENTITY CamelSearchSQL SYSTEM "xml/camel-search-sql.xml">
+<!ENTITY CamelSearchSQLSexp SYSTEM "xml/camel-search-sql-sexp.xml">
 <!ENTITY CamelService SYSTEM "xml/camel-service.xml">
 <!ENTITY CamelSession SYSTEM "xml/camel-session.xml">
 <!ENTITY CamelSMIMEContext SYSTEM "xml/camel-smime-context.xml">
@@ -303,6 +304,7 @@
       &CamelMsgPort;
       &CamelNetUtils;
       &CamelSearchSQL;
+      &CamelSearchSQLSexp;
       &CamelStringUtils;
       &CamelTrie;
       &CamelUIDCache;

Modified: branches/camel-gobject/docs/reference/camel/camel-sections.txt
==============================================================================
--- branches/camel-gobject/docs/reference/camel/camel-sections.txt	(original)
+++ branches/camel-gobject/docs/reference/camel/camel-sections.txt	Tue Jan  6 01:56:50 2009
@@ -204,6 +204,7 @@
 CamelFIRecord
 CamelDBSelectCB
 camel_db_open
+camel_db_clone
 camel_db_close
 camel_db_command
 camel_db_transaction_command
@@ -216,6 +217,7 @@
 camel_db_delete_folder
 camel_db_delete_uid
 camel_db_delete_uids
+camel_db_delete_vuids
 camel_db_create_folders_table
 camel_db_select
 camel_db_write_folder_info_record
@@ -231,6 +233,7 @@
 camel_db_count_visible_message_info
 camel_db_count_visible_unread_message_info
 camel_db_count_junk_not_deleted_message_info
+camel_db_count_message_info
 camel_db_camel_mir_free
 camel_db_create_vfolder
 camel_db_recreate_vfolder
@@ -247,6 +250,8 @@
 camel_db_get_column_name
 camel_db_set_collate
 camel_db_migrate_vfolders_to_14
+<SUBSECTION Private>
+CamelDBPrivate
 </SECTION>
 
 <SECTION>
@@ -405,6 +410,7 @@
 camel_folder_search_by_expression
 camel_folder_search_by_uids
 camel_folder_search_free
+camel_folder_count_by_expression
 camel_folder_get_message_info
 camel_folder_free_message_info
 camel_folder_ref_message_info
@@ -456,6 +462,7 @@
 camel_folder_search_set_body_index
 camel_folder_search_execute_expression
 camel_folder_search_search
+camel_folder_search_count
 camel_folder_search_free_result
 <SUBSECTION Standard>
 CAMEL_FOLDER_SEARCH
@@ -498,6 +505,7 @@
 camel_folder_summary_header_save_to_db
 camel_folder_summary_touch
 camel_folder_summary_add
+camel_folder_summary_peek_info
 camel_folder_summary_get_changed
 camel_folder_summary_cache_size
 camel_folder_summary_reload_from_db
@@ -524,6 +532,8 @@
 camel_folder_summary_uid_from_index
 camel_folder_summary_check_uid
 camel_folder_summary_array
+camel_folder_summary_get_hashtable
+camel_folder_summary_free_hashtable
 camel_folder_summary_encode_token
 camel_folder_summary_decode_token
 camel_flag_get
@@ -1299,7 +1309,6 @@
 camel_interface_cast
 camel_interface_is
 camel_object_new
-camel_object_new_name
 camel_object_ref
 camel_object_unref
 camel_object_hook_event
@@ -1577,6 +1586,11 @@
 </SECTION>
 
 <SECTION>
+<FILE>camel-search-sql-sexp</FILE>
+camel_sexp_to_sql_sexp
+</SECTION>
+
+<SECTION>
 <FILE>camel-seekable-stream</FILE>
 <TITLE>CamelSeekableStream</TITLE>
 CamelSeekableStream
@@ -2096,6 +2110,8 @@
 camel_vee_folder_set_folders
 camel_vee_folder_rebuild_folder
 camel_vee_folder_set_expression
+camel_vee_folder_mask_event_folder_changed
+camel_vee_folder_unmask_event_folder_changed
 camel_vee_folder_hash_folder
 camel_vee_folder_sync_headers
 <SUBSECTION Standard>
@@ -3405,6 +3421,12 @@
 CamelArgV
 CamelArgGet
 CamelArgGetV
+ca_object
+ca_int
+ca_double
+ca_str
+ca_ptr
+CAMEL_ARGV_MAX
 camel_argv_start
 camel_argv_end
 camel_argv_build

Modified: branches/camel-gobject/docs/reference/libedataserverui/libedataserverui-sections.txt
==============================================================================
--- branches/camel-gobject/docs/reference/libedataserverui/libedataserverui-sections.txt	(original)
+++ branches/camel-gobject/docs/reference/libedataserverui/libedataserverui-sections.txt	Tue Jan  6 01:56:50 2009
@@ -257,6 +257,7 @@
 e_source_selector_show_selection
 e_source_selector_selection_shown
 e_source_selector_set_select_new
+e_source_selector_edit_primary_selection
 e_source_selector_peek_primary_selection
 e_source_selector_set_primary_selection
 e_source_selector_get_primary_source_group
@@ -312,6 +313,7 @@
 
 <SECTION>
 <FILE>e-data-server-ui-marshal</FILE>
+e_data_server_ui_marshal_BOOLEAN__BOXED_OBJECT_FLAGS_UINT
 e_data_server_ui_marshal_BOOLEAN__OBJECT_BOXED
 </SECTION>
 

Modified: branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-data-server-ui-marshal.sgml
==============================================================================
--- branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-data-server-ui-marshal.sgml	(original)
+++ branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-data-server-ui-marshal.sgml	Tue Jan  6 01:56:50 2009
@@ -17,6 +17,19 @@
 <!-- ##### SECTION Stability_Level ##### -->
 
 
+<!-- ##### FUNCTION e_data_server_ui_marshal_BOOLEAN__BOXED_OBJECT_FLAGS_UINT ##### -->
+<para>
+
+</para>
+
+ closure: 
+ return_value: 
+ n_param_values: 
+ param_values: 
+ invocation_hint: 
+ marshal_data: 
+
+
 <!-- ##### FUNCTION e_data_server_ui_marshal_BOOLEAN__OBJECT_BOXED ##### -->
 <para>
 

Modified: branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-source-selector.sgml
==============================================================================
--- branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-source-selector.sgml	(original)
+++ branches/camel-gobject/docs/reference/libedataserverui/tmpl/e-source-selector.sgml	Tue Jan  6 01:56:50 2009
@@ -23,6 +23,18 @@
 </para>
 
 
+<!-- ##### SIGNAL ESourceSelector::data-dropped ##### -->
+<para>
+
+</para>
+
+ esourceselector: the object which received the signal.
+ arg1: 
+ arg2: 
+ arg3: 
+ arg4: 
+ Returns: 
+
 <!-- ##### SIGNAL ESourceSelector::popup-event ##### -->
 <para>
 
@@ -142,6 +154,14 @@
 @state: 
 
 
+<!-- ##### FUNCTION e_source_selector_edit_primary_selection ##### -->
+<para>
+
+</para>
+
+ selector: 
+
+
 <!-- ##### FUNCTION e_source_selector_peek_primary_selection ##### -->
 <para>
 

Modified: branches/camel-gobject/evolution-data-server-zip.in
==============================================================================
--- branches/camel-gobject/evolution-data-server-zip.in	(original)
+++ branches/camel-gobject/evolution-data-server-zip.in	Tue Jan  6 01:56:50 2009
@@ -19,12 +19,14 @@
 LIBEXCHANGE_STORAGE_CURRENT_MINUS_AGE=`expr @LIBEXCHANGE_STORAGE_CURRENT@ - @LIBEXCHANGE_STORAGE_AGE `
 LIBGDATA_CURRENT_MINUS_AGE=`expr @LIBGDATA_CURRENT@ - @LIBGDATA_AGE `
 LIBGDATA_GOOGLE_CURRENT_MINUS_AGE=`expr @LIBGDATA_GOOGLE_CURRENT@ - @LIBGDATA_GOOGLE_AGE `
+LIBEBACKEND_CURRENT_MINUS_AGE=`expr @LIBEBACKEND_CURRENT@ - @LIBEBACKEND_AGE `
 
 cd @prefix@
 rm $ZIP
 zip $ZIP -@ <<EOF
 bin/libcamel-1.2-$LIBCAMEL_CURRENT_MINUS_AGE.dll
 bin/libcamel-provider-1.2-$LIBCAMEL_CURRENT_MINUS_AGE.dll
+bin/libebackend-1.2-$LIBEBACKEND_CURRENT_MINUS_AGE.dll
 bin/libebook-1.2-$LIBEBOOK_CURRENT_MINUS_AGE.dll
 bin/libecal-1.2-$LIBECAL_CURRENT_MINUS_AGE.dll
 bin/libedata-book-1.2-$LIBEDATABOOK_CURRENT_MINUS_AGE.dll
@@ -90,34 +92,9 @@
 lib/libexchange-storage-1.2.dll.a
 lib/libgdata-1.2.dll.a
 lib/libgdata-google-1.2.dll.a
-lib/pkgconfig/camel-1.2.pc
-lib/pkgconfig/camel-provider-1.2.pc
-lib/pkgconfig/evolution-data-server-1.2.pc
-lib/pkgconfig/libebook-1.2.pc
-lib/pkgconfig/libecal-1.2.pc
-lib/pkgconfig/libedata-book-1.2.pc
-lib/pkgconfig/libedata-cal-1.2.pc
-lib/pkgconfig/libedataserver-1.2.pc
-lib/pkgconfig/libedataserverui-1.2.pc
-lib/pkgconfig/libegroupwise-1.2.pc
-lib/pkgconfig/libexchange-storage-1.2.pc
-lib/pkgconfig/libgdata-1.2.pc
-lib/pkgconfig/libgdata-google-1.2.pc
-include/evolution-data-server- BASE_VERSION@/camel
-include/evolution-data-server- BASE_VERSION@/exchange
-include/evolution-data-server- BASE_VERSION@/google
-include/evolution-data-server- BASE_VERSION@/groupwise
-include/evolution-data-server- BASE_VERSION@/libebook
-include/evolution-data-server- BASE_VERSION@/libecal
-include/evolution-data-server- BASE_VERSION@/libedata-book
-include/evolution-data-server- BASE_VERSION@/libedata-cal
-include/evolution-data-server- BASE_VERSION@/libedataserver
-include/evolution-data-server- BASE_VERSION@/libedataserverui
-include/evolution-data-server- BASE_VERSION@/libical
-share/gtk-doc/html/libebook
-share/gtk-doc/html/libecal
-share/gtk-doc/html/libedata-cal
-share/gtk-doc/html/libedataserver
+lib/pkgconfig
+include/evolution-data-server- BASE_VERSION@
+share/gtk-doc
 share/idl/evolution-data-server-1.2/Evolution-DataServer-Addressbook.idl
 share/idl/evolution-data-server-1.2/Evolution-DataServer-Calendar.idl
 share/idl/evolution-data-server-1.2/Evolution-DataServer.idl

Modified: branches/camel-gobject/libedataserver/e-sexp.c
==============================================================================
--- branches/camel-gobject/libedataserver/e-sexp.c	(original)
+++ branches/camel-gobject/libedataserver/e-sexp.c	Tue Jan  6 01:56:50 2009
@@ -706,7 +706,7 @@
 		r->value.time = t->value.time;
 		break;
 	case ESEXP_TERM_IFUNC:
-		if (t->value.func.sym->f.ifunc)
+		if (t->value.func.sym && t->value.func.sym->f.ifunc)
 			r = t->value.func.sym->f.ifunc(f, t->value.func.termcount, t->value.func.terms, t->value.func.sym->data);
 		break;
 	case ESEXP_TERM_FUNC:

Modified: branches/camel-gobject/libedataserver/e-source.c
==============================================================================
--- branches/camel-gobject/libedataserver/e-source.c	(original)
+++ branches/camel-gobject/libedataserver/e-source.c	Tue Jan  6 01:56:50 2009
@@ -537,6 +537,7 @@
 
 }
 
+#ifndef EDS_DISABLE_DEPRECATED
 void
 e_source_set_color (ESource *source,
 		    guint32 color)
@@ -556,6 +557,7 @@
 
 	e_source_set_color_spec (source, NULL);
 }
+#endif
 
 /**
  * e_source_set_color_spec:
@@ -646,6 +648,7 @@
 }
 
 
+#ifndef EDS_DISABLE_DEPRECATED
 /**
  * e_source_get_color:
  * @source: An ESource
@@ -679,6 +682,7 @@
 
 	return TRUE;
 }
+#endif
 
 char *
 e_source_get_uri (ESource *source)
@@ -791,7 +795,7 @@
 }
 
 /**
- * e_source_compare:
+ * e_source_equal:
  * @a: An ESource
  * @b: Another ESource
  *

Modified: branches/camel-gobject/libedataserver/e-url.c
==============================================================================
--- branches/camel-gobject/libedataserver/e-url.c	(original)
+++ branches/camel-gobject/libedataserver/e-url.c	Tue Jan  6 01:56:50 2009
@@ -180,6 +180,16 @@
 		slash = uri_string + strcspn (uri_string, "/#");
 		at = strchr (uri_string, '@');
 		if (at && at < slash) {
+			const char *at2;
+			/* this is for cases where username contains '@' at it, like:
+			   http://user domain com@server.addr.com/path
+			   We skip all at-s before the slash here. */
+
+			while (at2 = strchr (at + 1, '@'), at2 && at2 < slash) {
+				at = at2;
+			}
+		}
+		if (at && at < slash) {
 			colon = strchr (uri_string, ':');
 			if (colon && colon < at) {
 				uri->passwd = g_strndup (colon + 1, at - colon - 1);

Modified: branches/camel-gobject/libedataserverui/Makefile.am
==============================================================================
--- branches/camel-gobject/libedataserverui/Makefile.am	(original)
+++ branches/camel-gobject/libedataserverui/Makefile.am	Tue Jan  6 01:56:50 2009
@@ -12,6 +12,7 @@
 
 lib_LTLIBRARIES = libedataserverui-1.2.la
 noinst_PROGRAMS = 			\
+	test-category-completion		\
 	test-source-combo-box		\
 	test-source-selector		\
 	test-contact-store		\
@@ -20,6 +21,7 @@
 libedataserverui_1_2_la_SOURCES =	\
 	$(MARSHAL_GENERATED)		\
 	e-categories-dialog.c		\
+	e-category-completion.c		\
 	e-destination-store.c		\
 	e-book-auth-util.c		\
 	e-contact-store.c		\
@@ -48,6 +50,7 @@
 
 libedataserveruiinclude_HEADERS =	\
 	e-categories-dialog.h		\
+	e-category-completion.h		\
 	e-destination-store.h		\
 	e-book-auth-util.h		\
 	e-contact-store.h		\
@@ -65,6 +68,12 @@
 	e-cell-renderer-color.h
 
 # Test programs
+test_category_completion_SOURCES = test-category-completion.c
+test_category_completion_LDADD = 					\
+	libedataserverui-1.2.la 				\
+	$(top_builddir)/libedataserver/libedataserver-1.2.la	\
+	$(E_DATA_SERVER_UI_LIBS)
+
 test_source_selector_SOURCES = test-source-selector.c
 test_source_selector_LDADD = 					\
 	libedataserverui-1.2.la 				\

Modified: branches/camel-gobject/libedataserverui/e-categories-dialog.c
==============================================================================
--- branches/camel-gobject/libedataserverui/e-categories-dialog.c	(original)
+++ branches/camel-gobject/libedataserverui/e-categories-dialog.c	Tue Jan  6 01:56:50 2009
@@ -28,6 +28,7 @@
 #include "libedataserver/e-categories.h"
 #include "libedataserver/libedataserver-private.h"
 #include "e-categories-dialog.h"
+#include "e-category-completion.h"
 
 enum {
 	COLUMN_ACTIVE,
@@ -59,6 +60,25 @@
 	GtkWidget *category_icon;
 } CategoryPropertiesDialog;
 
+static void
+update_preview (GtkFileChooser *chooser, gpointer user_data)
+{
+	GtkImage *image;
+	char *filename;
+
+	g_return_if_fail (chooser != NULL);
+
+	image = GTK_IMAGE (gtk_file_chooser_get_preview_widget (chooser));
+	g_return_if_fail (image != NULL);
+
+	filename = gtk_file_chooser_get_preview_filename (chooser);
+
+	gtk_image_set_from_file (image, filename);
+	gtk_file_chooser_set_preview_widget_active (chooser, filename != NULL);
+
+	g_free (filename);
+}
+
 static CategoryPropertiesDialog *
 load_properties_dialog (ECategoriesDialog *parent)
 {
@@ -86,6 +106,21 @@
 	prop_dialog->category_name = glade_xml_get_widget (prop_dialog->gui, "category-name");
 	prop_dialog->category_icon = glade_xml_get_widget (prop_dialog->gui, "category-icon");
 
+	if (prop_dialog->category_icon) {
+		GtkFileChooser *chooser = GTK_FILE_CHOOSER (prop_dialog->category_icon);
+
+		if (chooser) {
+			GtkWidget *image = gtk_image_new ();
+
+			gtk_widget_show (image);
+
+			gtk_file_chooser_set_preview_widget (chooser, image);
+			gtk_file_chooser_set_preview_widget_active (chooser, TRUE);
+
+			g_signal_connect (G_OBJECT (chooser), "update-preview", (GCallback) update_preview, NULL);
+		}
+	}
+
 	return prop_dialog;
 }
 
@@ -110,6 +145,70 @@
 G_DEFINE_TYPE (ECategoriesDialog, e_categories_dialog, GTK_TYPE_DIALOG)
 
 static void
+categories_dialog_build_model (ECategoriesDialog *dialog)
+{
+	GtkTreeView *tree_view;
+	GtkListStore *store;
+	GList *list, *iter;
+
+	store = gtk_list_store_new (
+		N_COLUMNS, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+
+	gtk_tree_sortable_set_sort_column_id (
+		GTK_TREE_SORTABLE (store),
+		COLUMN_CATEGORY, GTK_SORT_ASCENDING);
+
+	list = e_categories_get_list ();
+	for (iter = list; iter != NULL; iter = iter->next) {
+		const gchar *category_name = iter->data;
+		const gchar *filename;
+		GdkPixbuf *pixbuf = NULL;
+		GtkTreeIter iter;
+		gboolean active;
+
+		/* Only add user-visible categories. */
+		if (!e_categories_is_searchable (category_name))
+			continue;
+
+		active = (g_hash_table_lookup (
+			dialog->priv->selected_categories,
+			category_name) != NULL);
+
+		filename = e_categories_get_icon_file_for (category_name);
+		if (filename != NULL)
+			pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+
+		gtk_list_store_append (store, &iter);
+
+		gtk_list_store_set (
+			store, &iter,
+			COLUMN_ACTIVE, active,
+			COLUMN_ICON, pixbuf,
+			COLUMN_CATEGORY, category_name,
+			-1);
+
+		if (pixbuf != NULL)
+			g_object_unref (pixbuf);
+	}
+
+	tree_view = GTK_TREE_VIEW (dialog->priv->categories_list);
+	gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
+
+	/* This has to be reset everytime we install a new model. */
+	gtk_tree_view_set_search_column (tree_view, COLUMN_CATEGORY);
+
+	g_list_free (list);
+	g_object_unref (store);
+}
+
+static void
+categories_dialog_listener_cb (gpointer useless_pointer,
+                               ECategoriesDialog *dialog)
+{
+	categories_dialog_build_model (dialog);
+}
+
+static void
 e_categories_dialog_dispose (GObject *object)
 {
 	ECategoriesDialogPrivate *priv = E_CATEGORIES_DIALOG (object)->priv;
@@ -132,6 +231,9 @@
 {
 	ECategoriesDialogPrivate *priv = E_CATEGORIES_DIALOG (object)->priv;
 
+	e_categories_unregister_change_listener (
+		G_CALLBACK (categories_dialog_listener_cb), object);
+
 	g_free (priv);
 	E_CATEGORIES_DIALOG (object)->priv = NULL;
 
@@ -155,7 +257,7 @@
 	GString **str = user_data;
 
 	if (strlen ((*str)->str) > 0)
-		*str = g_string_append (*str, ",");
+		*str = g_string_append (*str, ", ");
 
 	*str = g_string_append (*str, (const char *) key);
 }
@@ -247,7 +349,6 @@
 		if (gtk_dialog_run (GTK_DIALOG (prop_dialog->the_dialog)) == GTK_RESPONSE_OK) {
 			const char *category_name;
 			char *correct_category_name;
-			GtkTreeIter iter;
 
 			category_name = gtk_entry_get_text (GTK_ENTRY (prop_dialog->category_name));
 			correct_category_name = check_category_name (category_name);
@@ -266,27 +367,12 @@
 				g_free (correct_category_name);
 			} else {
 				gchar *category_icon;
-				GdkPixbuf *icon = NULL;
-				GtkListStore *list_store = GTK_LIST_STORE (
-								gtk_tree_view_get_model (GTK_TREE_VIEW (prop_dialog->parent->priv->categories_list)));
 
 				category_icon = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (prop_dialog->category_icon));
-				if (category_icon)
-					icon = gdk_pixbuf_new_from_file (category_icon, NULL);
 
 				e_categories_add (correct_category_name, NULL, category_icon, TRUE);
 
-				gtk_list_store_append (list_store, &iter);
-				gtk_list_store_set (list_store, &iter,
-						    COLUMN_ACTIVE, FALSE,
-						    COLUMN_ICON, icon,
-						    COLUMN_CATEGORY,correct_category_name,
-						    -1);
-
-				if (icon)
-					g_object_unref (icon);
-				if (category_icon)
-					g_free (category_icon);
+				g_free (category_icon);
 				g_free (correct_category_name);
 
 				break;
@@ -376,17 +462,15 @@
 
 	gtk_tree_model_get (model, &iter, COLUMN_CATEGORY, &category_name, -1);
 	e_categories_remove (category_name);
-	gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 }
 
 static void
 e_categories_dialog_init (ECategoriesDialog *dialog)
 {
 	ECategoriesDialogPrivate *priv;
-	GList *cat_list;
 	GtkCellRenderer *renderer;
+	GtkEntryCompletion *completion;
 	GtkTreeViewColumn *column;
-	GtkListStore *model;
 	GtkWidget *main_widget;
 	char *gladefile;
 
@@ -412,6 +496,10 @@
 	priv->categories_entry = glade_xml_get_widget (priv->gui, "entry-categories");
 	priv->categories_list = glade_xml_get_widget (priv->gui, "categories-list");
 
+	completion = e_category_completion_new ();
+	gtk_entry_set_completion (GTK_ENTRY (priv->categories_entry), completion);
+	g_object_unref (completion);
+
 	priv->new_button = glade_xml_get_widget (priv->gui, "button-new");
 	g_signal_connect (G_OBJECT (priv->new_button), "clicked", G_CALLBACK (new_button_clicked_cb), dialog);
 	priv->edit_button = glade_xml_get_widget (priv->gui, "button-edit");
@@ -425,37 +513,6 @@
 	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
 	gtk_window_set_title (GTK_WINDOW (dialog), _("Categories"));
 
-	/* set up the categories list */
-	model = gtk_list_store_new (
-		N_COLUMNS, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING);
-	gtk_tree_sortable_set_sort_column_id (
-		GTK_TREE_SORTABLE (model),
-		COLUMN_CATEGORY, GTK_SORT_ASCENDING);
-	cat_list = e_categories_get_list ();
-	while (cat_list != NULL) {
-		GtkTreeIter iter;
-
-		/* only add categories that are user-visible */
-		if (e_categories_is_searchable ((const char *) cat_list->data)) {
-			const gchar *icon_file;
-			GdkPixbuf *icon = NULL;
-			icon_file = e_categories_get_icon_file_for ((const char *) cat_list->data);
-			if (icon_file)
-				icon = gdk_pixbuf_new_from_file (icon_file, NULL);
-			gtk_list_store_append (model, &iter);
-			gtk_list_store_set (model, &iter,
-					    COLUMN_ACTIVE, FALSE,
-					    COLUMN_ICON,   icon,
-					    COLUMN_CATEGORY,  cat_list->data,
-					    -1);
-			if (icon)
-				g_object_unref (icon);
-		}
-
-		cat_list = g_list_remove (cat_list, cat_list->data);
-	}
-	gtk_tree_view_set_model (GTK_TREE_VIEW (priv->categories_list), GTK_TREE_MODEL (model));
-
 	renderer = gtk_cell_renderer_toggle_new ();
 	g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (category_toggled_cb), dialog);
 	column = gtk_tree_view_column_new_with_attributes ("?", renderer,
@@ -472,8 +529,10 @@
 							   "text", COLUMN_CATEGORY, NULL);
 	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->categories_list), column);
 
-	/* free memory */
-	g_object_unref (model);
+	categories_dialog_build_model (dialog);
+
+	e_categories_register_change_listener (
+		G_CALLBACK (categories_dialog_listener_cb), dialog);
 }
 
 /**

Modified: branches/camel-gobject/libedataserverui/e-contact-store.c
==============================================================================
--- branches/camel-gobject/libedataserverui/e-contact-store.c	(original)
+++ branches/camel-gobject/libedataserverui/e-contact-store.c	Tue Jan  6 01:56:50 2009
@@ -372,6 +372,8 @@
 	GPtrArray     *contacts;
 	gint           i;
 
+	g_return_val_if_fail (find_uid != NULL, -1);
+
 	source_index = find_contact_source_by_view (contact_store, find_view);
 	if (source_index < 0)
 		return -1;
@@ -387,7 +389,7 @@
 		EContact    *contact = g_ptr_array_index (contacts, i);
 		const gchar *uid     = e_contact_get_const (contact, E_CONTACT_UID);
 
-		if (!strcmp (find_uid, uid))
+		if (uid && !strcmp (find_uid, uid))
 			return i;
 	}
 

Modified: branches/camel-gobject/libedataserverui/e-data-server-ui-marshal.list
==============================================================================
--- branches/camel-gobject/libedataserverui/e-data-server-ui-marshal.list	(original)
+++ branches/camel-gobject/libedataserverui/e-data-server-ui-marshal.list	Tue Jan  6 01:56:50 2009
@@ -1 +1,2 @@
 BOOLEAN:OBJECT,BOXED
+BOOLEAN:BOXED,OBJECT,FLAGS,UINT

Modified: branches/camel-gobject/libedataserverui/e-source-selector.c
==============================================================================
--- branches/camel-gobject/libedataserverui/e-source-selector.c	(original)
+++ branches/camel-gobject/libedataserverui/e-source-selector.c	Tue Jan  6 01:56:50 2009
@@ -68,12 +68,11 @@
 	SELECTION_CHANGED,
 	PRIMARY_SELECTION_CHANGED,
 	POPUP_EVENT,
+	DATA_DROPPED,
 	NUM_SIGNALS
 };
 static unsigned int signals[NUM_SIGNALS] = { 0 };
 
-static gboolean selector_popup_menu (GtkWidget *widget);
-
 G_DEFINE_TYPE (ESourceSelector, e_source_selector, GTK_TYPE_TREE_VIEW)
 
 /* Selection management.  */
@@ -673,18 +672,6 @@
 }
 
 static gboolean
-selector_popup_menu (GtkWidget *widget)
-{
-	ESourceSelector *selector = E_SOURCE_SELECTOR (widget);
-	ESource *source;
-	gboolean res = FALSE;
-
-	source = e_source_selector_peek_primary_selection (selector);
-	g_signal_emit (selector, signals[POPUP_EVENT], 0, source, NULL, &res);
-	return res;
-}
-
-static gboolean
 selector_button_press_event (GtkWidget *widget, GdkEventButton *event, ESourceSelector *selector)
 {
 	ESourceSelectorPrivate *priv = selector->priv;
@@ -827,6 +814,161 @@
 	G_OBJECT_CLASS (e_source_selector_parent_class)->finalize (object);
 }
 
+static void
+source_selector_drag_leave (GtkWidget *widget,
+                            GdkDragContext *context,
+                            guint time_)
+{
+	GtkTreeView *tree_view;
+	GtkTreeViewDropPosition pos;
+
+	tree_view = GTK_TREE_VIEW (widget);
+	pos = GTK_TREE_VIEW_DROP_BEFORE;
+
+	gtk_tree_view_set_drag_dest_row (tree_view, NULL, pos);
+}
+
+static gboolean
+source_selector_drag_motion (GtkWidget *widget,
+                             GdkDragContext *context,
+                             gint x,
+                             gint y,
+                             guint time_)
+{
+	GtkTreeView *tree_view;
+	GtkTreeModel *model;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+	GtkTreeViewDropPosition pos;
+	GdkDragAction action = 0;
+	gpointer object = NULL;
+
+	tree_view = GTK_TREE_VIEW (widget);
+	model = gtk_tree_view_get_model (tree_view);
+
+	if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
+		goto exit;
+
+	if (!gtk_tree_model_get_iter (model, &iter, path))
+		goto exit;
+
+	gtk_tree_model_get (model, &iter, 0, &object, -1);
+
+	if (E_IS_SOURCE_GROUP (object) || e_source_get_readonly (object))
+		goto exit;
+
+	pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
+	gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
+
+	if (context->actions & GDK_ACTION_MOVE)
+		action = GDK_ACTION_MOVE;
+	else
+		action = context->suggested_action;
+
+exit:
+	if (path != NULL)
+		gtk_tree_path_free (path);
+
+	if (object != NULL)
+		g_object_unref (object);
+
+	gdk_drag_status (context, action, time_);
+
+	return TRUE;
+}
+
+static gboolean
+source_selector_drag_drop (GtkWidget *widget,
+                           GdkDragContext *context,
+                           gint x,
+                           gint y,
+                           guint time_)
+{
+	GtkTreeView *tree_view;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gboolean drop_zone;
+	gboolean valid;
+	gpointer object;
+
+	tree_view = GTK_TREE_VIEW (widget);
+	model = gtk_tree_view_get_model (tree_view);
+
+	if (!gtk_tree_view_get_path_at_pos (
+		tree_view, x, y, &path, NULL, NULL, NULL))
+		return FALSE;
+
+	valid = gtk_tree_model_get_iter (model, &iter, path);
+	gtk_tree_path_free (path);
+	g_return_val_if_fail (valid, FALSE);
+
+	gtk_tree_model_get (model, &iter, 0, &object, -1);
+	drop_zone = E_IS_SOURCE (object);
+	g_object_unref (object);
+
+	return drop_zone;
+}
+
+static void
+source_selector_drag_data_received (GtkWidget *widget,
+                                    GdkDragContext *context,
+                                    gint x,
+                                    gint y,
+                                    GtkSelectionData *selection_data,
+                                    guint info,
+                                    guint time_)
+{
+	GtkTreeView *tree_view;
+	GtkTreeModel *model;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+	gpointer object = NULL;
+	gboolean delete;
+	gboolean success = FALSE;
+
+	tree_view = GTK_TREE_VIEW (widget);
+	model = gtk_tree_view_get_model (tree_view);
+	delete = (context->action == GDK_ACTION_MOVE);
+
+	if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
+		goto exit;
+
+	if (!gtk_tree_model_get_iter (model, &iter, path))
+		goto exit;
+
+	gtk_tree_model_get (model, &iter, 0, &object, -1);
+
+	if (!E_IS_SOURCE (object) || e_source_get_readonly (object))
+		goto exit;
+
+	g_signal_emit (
+		widget, signals[DATA_DROPPED], 0, selection_data,
+		object, context->action, info, &success);
+
+exit:
+	if (path != NULL)
+		gtk_tree_path_free (path);
+
+	if (object != NULL)
+		g_object_unref (object);
+
+	gtk_drag_finish (context, success, delete, time_);
+}
+
+static gboolean
+source_selector_popup_menu (GtkWidget *widget)
+{
+	ESourceSelector *selector;
+	ESource *source;
+	gboolean res = FALSE;
+
+	selector = E_SOURCE_SELECTOR (widget);
+	source = e_source_selector_peek_primary_selection (selector);
+	g_signal_emit (selector, signals[POPUP_EVENT], 0, source, NULL, &res);
+
+	return res;
+}
 
 /* Initialization.  */
 static gboolean
@@ -854,7 +996,11 @@
 	object_class->finalize = source_selector_finalize;
 
 	widget_class = GTK_WIDGET_CLASS (class);
-	widget_class->popup_menu = selector_popup_menu;
+	widget_class->drag_leave = source_selector_drag_leave;
+	widget_class->drag_motion = source_selector_drag_motion;
+	widget_class->drag_drop = source_selector_drag_drop;
+	widget_class->drag_data_received = source_selector_drag_data_received;
+	widget_class->popup_menu = source_selector_popup_menu;
 
 	g_object_class_install_property (
 		object_class,
@@ -893,6 +1039,18 @@
 			      e_data_server_ui_marshal_BOOLEAN__OBJECT_BOXED,
 			      G_TYPE_BOOLEAN, 2, G_TYPE_OBJECT,
 			      GDK_TYPE_EVENT|G_SIGNAL_TYPE_STATIC_SCOPE);
+	signals[DATA_DROPPED] =
+		g_signal_new ("data_dropped",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ESourceSelectorClass, data_dropped),
+			      NULL, NULL,
+			      e_data_server_ui_marshal_BOOLEAN__BOXED_OBJECT_FLAGS_UINT,
+			      G_TYPE_BOOLEAN, 4,
+			      GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
+			      E_TYPE_SOURCE,
+			      GDK_TYPE_DRAG_ACTION,
+			      G_TYPE_UINT);
 }
 
 static gboolean

Modified: branches/camel-gobject/libedataserverui/e-source-selector.h
==============================================================================
--- branches/camel-gobject/libedataserverui/e-source-selector.h	(original)
+++ branches/camel-gobject/libedataserverui/e-source-selector.h	Tue Jan  6 01:56:50 2009
@@ -49,9 +49,21 @@
 struct _ESourceSelectorClass {
 	GtkTreeViewClass parent_class;
 
-	void (* selection_changed) (ESourceSelector *selector);
-	void (* primary_selection_changed) (ESourceSelector *selector);
-	gboolean (*popup_event)(ESourceSelector *selector, ESource *primary, GdkEventButton *event);
+	void		(*selection_changed)	(ESourceSelector *selector);
+	void		(*primary_selection_changed)
+						(ESourceSelector *selector);
+	gboolean	(*popup_event)		(ESourceSelector *selector,
+						 ESource *primary,
+						 GdkEventButton *event);
+	gboolean	(*data_dropped)		(ESourceSelector *selector,
+						 GtkSelectionData *data,
+						 ESource *destination,
+						 GdkDragAction action,
+						 guint target_info);
+
+	gpointer padding1;
+	gpointer padding2;
+	gpointer padding3;
 };
 
 

Modified: branches/camel-gobject/servers/exchange/lib/e2k-autoconfig.c
==============================================================================
--- branches/camel-gobject/servers/exchange/lib/e2k-autoconfig.c	(original)
+++ branches/camel-gobject/servers/exchange/lib/e2k-autoconfig.c	Tue Jan  6 01:56:50 2009
@@ -1516,6 +1516,8 @@
 	}
 
 	if (*result == E2K_AUTOCONFIG_OK) {
+		int len;
+
 		*result = e2k_autoconfig_check_global_catalog (ac, &op);
 		e2k_operation_free (&op);
 
@@ -1524,6 +1526,13 @@
 		path = g_strdup (euri->path + 1);
 		e2k_uri_free (euri);
 
+		/* no slash at the end of path */
+		len = strlen (path);
+		while (len && path [len - 1] == '/') {
+			path [len - 1] = '\0';
+			len--;
+		}
+
 		/* change a mailbox only if not set by the caller */
 		if (!exchange_params->mailbox || !*exchange_params->mailbox) {
 			mailbox = strrchr (path, '/');
@@ -1536,6 +1545,12 @@
 
 			g_free (exchange_params->mailbox);
 			exchange_params->mailbox  = g_strdup (mailbox);
+		} else {
+			/* always strip the mailbox part from the path */
+			char *slash = strrchr (path, '/');
+
+			if (slash)
+				*slash = '\0';
 		}
 
 		exchange_params->owa_path = g_strdup_printf ("%s%s", "/", path);

Modified: branches/camel-gobject/servers/groupwise/e-gw-connection.c
==============================================================================
--- branches/camel-gobject/servers/groupwise/e-gw-connection.c	(original)
+++ branches/camel-gobject/servers/groupwise/e-gw-connection.c	Tue Jan  6 01:56:50 2009
@@ -840,7 +840,7 @@
 		}
 
 		e_gw_message_write_string_parameter (msg, "uid", NULL, uid);
-		e_gw_message_write_string_parameter (msg, "view", NULL, "count");
+		e_gw_message_write_string_parameter (msg, "view", NULL, "count unreadCount");
 		e_gw_message_write_footer (msg);
 
 		/* send message to server */
@@ -1813,39 +1813,41 @@
 static time_t
 timet_from_string (const char *str)
 {
-	struct tm date;
-        int len, i;
+		struct tm date;
+		int len, i;
 
-        g_return_val_if_fail (str != NULL, -1);
+		g_return_val_if_fail (str != NULL, -1);
 
-	/* yyyymmdd[Thhmmss[Z]] */
-        len = strlen (str);
+		/* yyyymmdd[Thhmmss[Z]] */
+		len = strlen (str);
 
-        if (!(len == 8 || len == 15 || len == 16))
-                return -1;
-
-        for (i = 0; i < len; i++)
-                if (!((i != 8 && i != 15 && isdigit (str[i]))
-                      || (i == 8 && str[i] == 'T')
-                      || (i == 15 && str[i] == 'Z')))
-                        return -1;
+		if (!(len == 8 || len == 15 || len == 16))
+				return -1;
+
+		for (i = 0; i < len; i++)
+				if (!((i != 8 && i != 15 && isdigit (str[i]))
+										|| (i == 8 && str[i] == 'T')
+										|| (i == 15 && str[i] == 'Z')))
+						return -1;
 
 #define digit_at(x,y) (x[y] - '0')
 
-	date.tm_year = digit_at (str, 0) * 1000
-                + digit_at (str, 1) * 100
-                + digit_at (str, 2) * 10
-                + digit_at (str, 3) -1900;
-        date.tm_mon = digit_at (str, 4) * 10 + digit_at (str, 5) -1;
-        date.tm_mday = digit_at (str, 6) * 10 + digit_at (str, 7);
-        if (len > 8) {
-                date.tm_hour = digit_at (str, 9) * 10 + digit_at (str, 10);
-                date.tm_min  = digit_at (str, 11) * 10 + digit_at (str, 12);
-                date.tm_sec  = digit_at (str, 13) * 10 + digit_at (str, 14);
-        } else
-		date.tm_hour = date.tm_min = date.tm_sec = 0;
+		date.tm_year = digit_at (str, 0) * 1000
+				+ digit_at (str, 1) * 100
+				+ digit_at (str, 2) * 10
+				+ digit_at (str, 3) -1900;
+		date.tm_mon = digit_at (str, 4) * 10 + digit_at (str, 5) -1;
+		date.tm_mday = digit_at (str, 6) * 10 + digit_at (str, 7);
+		if (len > 8) {
+				date.tm_hour = digit_at (str, 9) * 10 + digit_at (str, 10);
+				date.tm_min  = digit_at (str, 11) * 10 + digit_at (str, 12);
+				date.tm_sec  = digit_at (str, 13) * 10 + digit_at (str, 14);
+		} else
+				date.tm_hour = date.tm_min = date.tm_sec = 0;
+
+		date.tm_wday = date.tm_yday = date.tm_isdst = 0;
 
-	return mktime (&date);
+		return mktime (&date);
 }
 
 char *
@@ -2770,7 +2772,7 @@
 
 	if (buffer && buf_length && atoi (buf_length) > 0) {
 		gsize len = atoi (buf_length) ;
-		*attachment = g_base64_decode (buffer,&len) ;
+		*attachment = (char *) g_base64_decode (buffer,&len) ;
 		*attach_length = len ;
 	} else {
 		*attachment = NULL;

Modified: branches/camel-gobject/servers/groupwise/e-gw-item.c
==============================================================================
--- branches/camel-gobject/servers/groupwise/e-gw-item.c	(original)
+++ branches/camel-gobject/servers/groupwise/e-gw-item.c	Tue Jan  6 01:56:50 2009
@@ -307,6 +307,11 @@
 			priv->classification = NULL;
 		}
 
+		if (priv->security) {
+			g_free (priv->security);
+			priv->security = NULL;
+		}
+
 		if (priv->accept_level) {
 			g_free (priv->accept_level);
 			priv->accept_level = NULL;



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