evolution-scalix r121 - in trunk: . addressbook camel m4



Author: psuwalski
Date: Thu Apr  9 06:15:08 2009
New Revision: 121
URL: http://svn.gnome.org/viewvc/evolution-scalix?rev=121&view=rev

Log:
Many changes for Evolution 2.24:
* camel-imap4 is no longer being maintained as a source.
* manually synchronized code with latest camel-imap4 code in e-d-s trunk.
* allow building against 2.24.
* adjust to *db* summary methods.
* this is highly unstable at the moment. Individual fixes to come. 


Modified:
   trunk/addressbook/e-book-backend-scalix-factory.c
   trunk/camel/camel-scalix-command.c
   trunk/camel/camel-scalix-command.h
   trunk/camel/camel-scalix-engine.c
   trunk/camel/camel-scalix-engine.h
   trunk/camel/camel-scalix-folder.c
   trunk/camel/camel-scalix-folder.h
   trunk/camel/camel-scalix-journal.c
   trunk/camel/camel-scalix-journal.h
   trunk/camel/camel-scalix-provider.c
   trunk/camel/camel-scalix-store.c
   trunk/camel/camel-scalix-summary.c
   trunk/camel/camel-scalix-utils.c
   trunk/camel/camel-scalix-utils.h
   trunk/configure.in
   trunk/m4/intltool.m4

Modified: trunk/addressbook/e-book-backend-scalix-factory.c
==============================================================================
--- trunk/addressbook/e-book-backend-scalix-factory.c	(original)
+++ trunk/addressbook/e-book-backend-scalix-factory.c	Thu Apr  9 06:15:08 2009
@@ -22,8 +22,17 @@
 #include <config.h>
 #endif
 
+#include <libescalix/scalix-version.h>
+
 #include <glib-object.h>
+
+#if EAPI_CHECK_VERSION (2, 24)
+/* This header moved with Evolution 2.24 */
+#include <libebackend/e-data-server-module.h>
+#else
 #include <libedataserver/e-data-server-module.h>
+#endif
+
 #include <libedata-book/e-book-backend-factory.h>
 
 #include <libescalix/scalix.h>

Modified: trunk/camel/camel-scalix-command.c
==============================================================================
--- trunk/camel/camel-scalix-command.c	(original)
+++ trunk/camel/camel-scalix-command.c	Thu Apr  9 06:15:08 2009
@@ -26,19 +26,18 @@
 #include <string.h>
 #include <errno.h>
 
-#include <camel/camel-stream-null.h>
-#include <camel/camel-stream-filter.h>
-#include <camel/camel-mime-filter-crlf.h>
+#include <glib/gi18n-lib.h>
+
 #include <camel/camel-debug.h>
-#include <camel/camel-i18n.h>
+#include <camel/camel-mime-filter-crlf.h>
+#include <camel/camel-stream-filter.h>
+#include <camel/camel-stream-null.h>
 
-#include "camel-scalix-stream.h"
+#include "camel-scalix-command.h"
 #include "camel-scalix-engine.h"
 #include "camel-scalix-folder.h"
 #include "camel-scalix-specials.h"
-
-#include "camel-scalix-command.h"
-
+#include "camel-scalix-stream.h"
 
 #define d(x) (camel_debug ("scalix:command") ? (x) : 0)
 
@@ -123,6 +122,8 @@
 {
 	CamelSCALIXCommandPart *part;
 	CamelSCALIXLiteral *literal;
+	register const char *inptr;
+	const char *start;
 	
 	switch (scalix_string_get_type (string)) {
 	case SCALIX_STRING_ATOM:
@@ -131,8 +132,25 @@
 		break;
 	case SCALIX_STRING_QSTRING:
 		/* we need to quote the string */
-		/* FIXME: need to escape stuff */
-		g_string_append_printf (str, "\"%s\"", string);
+		g_string_append_c (str, '"');
+
+		inptr = string;
+		while (*inptr) {
+			start = string;
+			while (*inptr && *inptr != '\\' && *inptr != '"')
+				inptr++;
+
+			if (inptr > start)
+				g_string_append_len (str, start, inptr - start);
+
+			if (*inptr != '\0') {
+				g_string_append_c (str, '\\');
+				g_string_append_c (str, *inptr);
+				inptr++;
+			}
+		}
+
+		g_string_append_c (str, '"');
 		break;
 	case SCALIX_STRING_LITERAL:
 		if (engine->capa & CAMEL_SCALIX_CAPABILITY_LITERALPLUS) {
@@ -294,15 +312,20 @@
 	g_string_free (str, FALSE);
 	
 	ic = g_new0 (CamelSCALIXCommand, 1);
-	((EDListNode *) ic)->next = NULL;
-	((EDListNode *) ic)->prev = NULL;
+	((CamelDListNode *) ic)->next = NULL;
+	((CamelDListNode *) ic)->prev = NULL;
 	ic->untagged = g_hash_table_new (g_str_hash, g_str_equal);
 	ic->status = CAMEL_SCALIX_COMMAND_QUEUED;
+	ic->result = CAMEL_SCALIX_RESULT_NONE;
 	ic->resp_codes = g_ptr_array_new ();
 	ic->engine = engine;
 	ic->ref_count = 1;
 	ic->parts = parts;
 	ic->part = parts;
+	ic->reset = NULL;
+	ic->plus = NULL;
+	ic->tag = NULL;
+	ic->id = -1;
 	
 	camel_exception_init (&ic->ex);
 	
@@ -496,6 +519,7 @@
 	if (camel_debug ("scalix:command")) {
 		int sending = ic->part != ic->parts;
 		unsigned char *eoln, *eob;
+		size_t ret;
 		
 		linebuf = ic->part->buffer;
 		eob = linebuf + ic->part->buflen;
@@ -509,8 +533,8 @@
 				eoln++;
 			
 			if (sending)
-				fwrite ("sending: ", 1, 10, stderr);
-			fwrite (linebuf, 1, eoln - linebuf, stderr);
+				ret = fwrite ("sending: ", 1, 10, stderr);
+			ret = fwrite (linebuf, 1, eoln - linebuf, stderr);
 			
 			linebuf = eoln + 1;
 			sending = 1;
@@ -668,6 +692,9 @@
 	for (i = 0; i < ic->resp_codes->len; i++)
 		camel_scalix_resp_code_free (ic->resp_codes->pdata[i]);
 	g_ptr_array_set_size (ic->resp_codes, 0);
+
+	if (ic->reset && ic->user_data)
+		ic->reset (ic, ic->user_data);
 	
 	ic->status = CAMEL_SCALIX_COMMAND_QUEUED;
 	ic->result = CAMEL_SCALIX_RESULT_NONE;

Modified: trunk/camel/camel-scalix-command.h
==============================================================================
--- trunk/camel/camel-scalix-command.h	(original)
+++ trunk/camel/camel-scalix-command.h	Thu Apr  9 06:15:08 2009
@@ -25,10 +25,9 @@
 
 #include <glib.h>
 
-#include <libedataserver/e-msgport.h>
-
 #include <camel/camel-stream.h>
 #include <camel/camel-exception.h>
+#include <camel/camel-list-utils.h>
 #include <camel/camel-data-wrapper.h>
 
 #ifdef __cplusplus
@@ -54,6 +53,8 @@
 					    struct _camel_scalix_token_t *token,
 					    CamelException *ex);
 
+typedef void (* CamelSCALIXCommandReset) (CamelSCALIXCommand *ic, void *user_data);
+
 enum {
 	CAMEL_SCALIX_LITERAL_STRING,
 	CAMEL_SCALIX_LITERAL_STREAM,
@@ -92,7 +93,7 @@
 };
 
 struct _CamelSCALIXCommand {
-	EDListNode node;
+	CamelDListNode node;
 	
 	struct _CamelSCALIXEngine *engine;
 	
@@ -119,6 +120,7 @@
 	
 	/* '+' callback/data */
 	CamelSCALIXPlusCallback plus;
+	CamelSCALIXCommandReset reset;
 	void *user_data;
 };
 

Modified: trunk/camel/camel-scalix-engine.c
==============================================================================
--- trunk/camel/camel-scalix-engine.c	(original)
+++ trunk/camel/camel-scalix-engine.c	Thu Apr  9 06:15:08 2009
@@ -29,19 +29,18 @@
 #include <ctype.h>
 #include <errno.h>
 
+#include <glib/gi18n-lib.h>
+
 #include <camel/camel-sasl.h>
 #include <camel/camel-stream-buffer.h>
-#include <camel/camel-i18n.h>
 
-#include "camel-scalix-summary.h"
 #include "camel-scalix-command.h"
-#include "camel-scalix-stream.h"
+#include "camel-scalix-engine.h"
 #include "camel-scalix-folder.h"
+#include "camel-scalix-stream.h"
+#include "camel-scalix-summary.h"
 #include "camel-scalix-utils.h"
 
-#include "camel-scalix-engine.h"
-
-
 #define d(x) x
 
 
@@ -49,6 +48,9 @@
 static void camel_scalix_engine_init (CamelSCALIXEngine *engine, CamelSCALIXEngineClass *klass);
 static void camel_scalix_engine_finalize (CamelObject *object);
 
+static int parse_xgwextensions (CamelSCALIXEngine *engine, CamelSCALIXCommand *ic, guint32 index,
+				camel_scalix_token_t *token, CamelException *ex);
+
 
 static CamelObjectClass *parent_class = NULL;
 
@@ -115,14 +117,14 @@
 	
 	engine->folder = NULL;
 	
-	e_dlist_init (&engine->queue);
+	camel_dlist_init (&engine->queue);
 }
 
 static void
 camel_scalix_engine_finalize (CamelObject *object)
 {
 	CamelSCALIXEngine *engine = (CamelSCALIXEngine *) object;
-	EDListNode *node;
+	CamelDListNode *node;
 	
 	if (engine->istream)
 		camel_object_unref (engine->istream);
@@ -140,7 +142,7 @@
 	if (engine->folder)
 		camel_object_unref (engine->folder);
 	
-	while ((node = e_dlist_remhead (&engine->queue))) {
+	while ((node = camel_dlist_remhead (&engine->queue))) {
 		node->next = NULL;
 		node->prev = NULL;
 		
@@ -226,18 +228,37 @@
 	
  exception:
 	
-	engine->state = CAMEL_SCALIX_ENGINE_DISCONNECTED;
-	
-	camel_object_unref (engine->istream);
-	engine->istream = NULL;
-	camel_object_unref (engine->ostream);
-	engine->ostream = NULL;
+	camel_scalix_engine_disconnect (engine);
 	
 	return -1;
 }
 
 
 /**
+ * camel_scalix_engine_disconnect:
+ * @engine: SCALIX engine
+ *
+ * Closes the engine's connection to the IMAP4 server and sets state
+ * to #CAMEL_SCALIX_ENGINE_DISCONNECTED.
+ **/
+void
+camel_scalix_engine_disconnect (CamelSCALIXEngine *engine)
+{
+	engine->state = CAMEL_SCALIX_ENGINE_DISCONNECTED;
+
+	if (engine->istream) {
+		camel_object_unref (engine->istream);
+		engine->istream = NULL;
+	}
+
+	if (engine->ostream) {
+		camel_object_unref (engine->ostream);
+		engine->ostream = NULL;
+	}
+}
+
+
+/**
  * camel_scalix_engine_capability:
  * @engine: SCALIX engine
  * @ex: exception
@@ -264,6 +285,22 @@
 	
 	camel_scalix_command_unref (ic);
 	
+	if (retval == -1 || !(engine->capa & CAMEL_SCALIX_CAPABILITY_XGWEXTENSIONS))
+		return retval;
+
+	ic = camel_scalix_engine_prequeue (engine, NULL, "XGWEXTENSIONS\r\n");
+	camel_scalix_command_register_untagged (ic, "XGWEXTENSIONS", parse_xgwextensions);
+
+	while ((id = camel_scalix_engine_iterate (engine)) < ic->id && id != -1)
+		;
+
+	if (id == -1 || ic->status != CAMEL_SCALIX_COMMAND_COMPLETE) {
+		camel_exception_xfer (ex, &ic->ex);
+		retval = -1;
+	}
+
+	camel_scalix_command_unref (ic);
+
 	return retval;
 }
 
@@ -448,9 +485,49 @@
 	{ "IDLE",          CAMEL_SCALIX_CAPABILITY_IDLE          }, /* rfc2177 */
 	{ "MULTIAPPEND",   CAMEL_SCALIX_CAPABILITY_MULTIAPPEND   }, /* rfc3502 */
 	{ "UNSELECT",      CAMEL_SCALIX_CAPABILITY_UNSELECT      },
+	{ "XGWEXTENSIONS", CAMEL_SCALIX_CAPABILITY_XGWEXTENSIONS }, /* GroupWise extensions */
 	{ NULL,            0                                    }
 };
 
+static struct {
+	const char *name;
+	guint32 flag;
+} scalix_xgwextensions[] = {
+	{ "XGWMOVE",       CAMEL_SCALIX_CAPABILITY_XGWMOVE       }, /* GroupWise MOVE command */
+	{ NULL,            0                                    }
+};
+
+static int
+parse_xgwextensions (CamelSCALIXEngine *engine, CamelSCALIXCommand *ic, guint32 index, camel_scalix_token_t *token, CamelException *ex)
+{
+	int i;
+
+	if (camel_scalix_engine_next_token (engine, token, ex) == -1)
+		return -1;
+
+	while (token->token == CAMEL_SCALIX_TOKEN_ATOM) {
+		for (i = 0; scalix_xgwextensions[i].name; i++) {
+			if (!g_ascii_strcasecmp (scalix_xgwextensions[i].name, token->v.atom))
+				engine->capa |= scalix_xgwextensions[i].flag;
+		}
+
+		if (camel_scalix_engine_next_token (engine, token, ex) == -1)
+			return -1;
+	}
+
+	if (token->token != '\n') {
+		d(fprintf (stderr, "expected '\\n' at the end of the XGWEXTENSIONS response\n"));
+		goto unexpected;
+	}
+
+	return 0;
+
+ unexpected:
+
+	camel_scalix_utils_set_unexpected_token_error (ex, engine, token);
+
+	return -1;
+}
 
 static gboolean
 auth_free (gpointer key, gpointer value, gpointer user_data)
@@ -699,8 +776,7 @@
 }
 
 
-/**
- * 
+/*
  * resp-text-code  = "ALERT" /
  *                   "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
  *                   capability-data / "PARSE" /
@@ -709,7 +785,7 @@
  *                   "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
  *                   "UNSEEN" SP nz-number /
  *                   atom [SP 1*<any TEXT-CHAR except "]">]
- **/
+ */
 
 static struct {
 	const char *name;
@@ -1175,7 +1251,7 @@
 		/* NOTE: these can be over-ridden by a registered untagged response handler */
 		if (!strcmp ("EXISTS", token->v.atom)) {
 			camel_scalix_summary_set_exists (folder->summary, v);
-		} else if (!strcmp ("EXPUNGE", token->v.atom)) {
+		} else if (!strcmp ("EXPUNGE", token->v.atom) || !strcmp ("XGWMOVE", token->v.atom)) {
 			camel_scalix_summary_expunge (folder->summary, (int) v);
 		} else if (!strcmp ("RECENT", token->v.atom)) {
 			camel_scalix_summary_set_recent (folder->summary, v);
@@ -1261,9 +1337,8 @@
 	ic = (CamelSCALIXCommand *) engine->queue.head;
 	cmd = (const char *) ic->parts->buffer;
 
-	if (!ic->folder || ic->folder == engine->folder ||
-	    !cmd || !strncmp (cmd, "SELECT ", 7) || 
-	    !strncmp (cmd, "EXAMINE ", 8)) {
+	if (!ic->folder || ic->folder == engine->folder || !cmd ||
+	    !strncmp (cmd, "SELECT ", 7) || !strncmp (cmd, "EXAMINE ", 8)) {
 		/* no need to pre-queue a SELECT */
 		return;
 	}
@@ -1273,7 +1348,6 @@
 					   (CamelFolder *) ic->folder, 
 					   "SELECT %F\r\n", 
 					   ic->folder);
-	
 	ic->user_data = engine;
 	
 	camel_scalix_command_unref (ic);
@@ -1303,20 +1377,21 @@
 	} else if (!strncmp (cmd, "CLOSE", 5)) {
 		if (ic->result == CAMEL_SCALIX_RESULT_OK) {
 			engine->state = CAMEL_SCALIX_ENGINE_AUTHENTICATED;
+#if 0
 			if (engine->folder) {
 				camel_object_unref (engine->folder);
 				engine->folder = NULL;
 			}
+#endif
 		}
 	} else if (!strncmp (cmd, "LOGOUT", 6)) {
 		engine->state = CAMEL_SCALIX_ENGINE_DISCONNECTED;
-		
+#if 0		
 		if (engine->folder) {
 			camel_object_unref (engine->folder);
 			engine->folder = NULL;
 		}
-		
-		
+#endif		
 	}
 	
 	return retval;
@@ -1340,14 +1415,16 @@
 {
 	CamelSCALIXCommand *ic, *nic;
 	GPtrArray *resp_codes;
+	int retries = 0;
 	int retval = -1;
 	
-	if (e_dlist_empty (&engine->queue))
+	if (camel_dlist_empty (&engine->queue))
 		return 0;
 	
-	/* This sucks... it would be nicer if we didn't have to check the stream's disconnected status */
+ retry:
+	/* FIXME: it would be nicer if we didn't have to check the stream's disconnected status */
 	if ((engine->state == CAMEL_SCALIX_ENGINE_DISCONNECTED || 
-	     ! engine->istream || engine->istream->disconnected) && !engine->reconnecting) {
+	     !engine->istream || engine->istream->disconnected) && !engine->reconnecting) {
 		CamelException rex;
 		gboolean connected;
 	
@@ -1362,42 +1439,21 @@
 		
 		if (!connected) {
 			/* pop the first command and act as tho it failed (which, technically, it did...) */
-			ic = (CamelSCALIXCommand *) e_dlist_remhead (&engine->queue);
+			ic = (CamelSCALIXCommand *) camel_dlist_remhead (&engine->queue);
 			ic->status = CAMEL_SCALIX_COMMAND_ERROR;
 			camel_exception_xfer (&ic->ex, &rex);
 			camel_scalix_command_unref (ic);
-			
-			/* FIXME: in a perfect world, if the connect failure was due to the user cancelling the
-			 * passwd dialog, we'd either send a LOGOUT command here -or- we'd leave the connection
-			 * open but in the PREAUTH state that we'd later be able to handle if the user queued
-			 * more commands on the engine. */
-			engine->state = CAMEL_SCALIX_ENGINE_DISCONNECTED;
-			if (engine->istream != NULL) {
-				camel_object_unref (engine->istream);
-				engine->istream = NULL;
-			}
-
-			if (engine->ostream != NULL) {
-				camel_object_unref (engine->ostream);
-				engine->ostream = NULL;
-			}
-			
 			return -1;
 		}
 	}
 	
+	/* check to see if we need to pre-queue a SELECT, if so do it */
 	engine_prequeue_folder_select (engine);
 		
-	engine->current = ic = (CamelSCALIXCommand *) e_dlist_remhead (&engine->queue);
-
-	if (ic == NULL) {
-		g_print ("ic == NULL\n");
-		return -1;
-	}
-
+	engine->current = ic = (CamelSCALIXCommand *) camel_dlist_remhead (&engine->queue);
 	ic->status = CAMEL_SCALIX_COMMAND_ACTIVE;
 
-	if (scalix_process_command (engine, ic) != -1) {
+	if ((retval = scalix_process_command (engine, ic)) != -1) {
 		if (engine_state_change (engine, ic) == -1) {
 			/* This can ONLY happen if @ic was the pre-queued SELECT command
 			 * and it got a NO or BAD response.
@@ -1408,7 +1464,7 @@
 			 * over to @nic and pretend we just processed @nic.
 			 **/
 			
-			nic = (CamelSCALIXCommand *) e_dlist_remhead (&engine->queue);
+			nic = (CamelSCALIXCommand *) camel_dlist_remhead (&engine->queue);
 			
 			nic->status = ic->status;
 			nic->result = ic->result;
@@ -1423,6 +1479,17 @@
 		}
 		
 		retval = ic->id;
+	} else if (!engine->reconnecting && retries < 3) {
+		/* put @ic back in the queue and retry */
+		camel_dlist_addhead (&engine->queue, (CamelDListNode *) ic);
+		camel_scalix_command_reset (ic);
+		retries++;
+		goto retry;
+	} else {
+		camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+				      _("Failed to send command to IMAP server %s: %s"),
+				      engine->url->host, errno ? g_strerror (errno) :
+				      _("service unavailable"));
 	}
 	
 	camel_scalix_command_unref (ic);
@@ -1456,7 +1523,7 @@
 	va_end (args);
 	
 	ic->id = engine->nextid++;
-	e_dlist_addtail (&engine->queue, (EDListNode *) ic);
+	camel_dlist_addtail (&engine->queue, (CamelDListNode *) ic);
 	camel_scalix_command_ref (ic);
 	
 	return ic;
@@ -1487,15 +1554,15 @@
 	ic = camel_scalix_command_newv (engine, (CamelSCALIXFolder *) folder, format, args);
 	va_end (args);
 	
-	if (e_dlist_empty (&engine->queue)) {
-		e_dlist_addtail (&engine->queue, (EDListNode *) ic);
+	if (camel_dlist_empty (&engine->queue)) {
+		camel_dlist_addtail (&engine->queue, (CamelDListNode *) ic);
 		ic->id = engine->nextid++;
 	} else {
 		CamelSCALIXCommand *nic;
-		EDListNode *node;
+		CamelDListNode *node;
 		
-		node = (EDListNode *) ic;
-		e_dlist_addhead (&engine->queue, node);
+		node = (CamelDListNode *) ic;
+		camel_dlist_addhead (&engine->queue, node);
 		nic = (CamelSCALIXCommand *) node->next;
 		ic->id = nic->id - 1;
 		
@@ -1526,12 +1593,12 @@
 void
 camel_scalix_engine_dequeue (CamelSCALIXEngine *engine, CamelSCALIXCommand *ic)
 {
-	EDListNode *node = (EDListNode *) ic;
+	CamelDListNode *node = (CamelDListNode *) ic;
 	
 	if (node->next == NULL && node->prev == NULL)
 		return;
 	
-	e_dlist_remove (node);
+	camel_dlist_remove (node);
 	node->next = NULL;
 	node->prev = NULL;
 	
@@ -1549,7 +1616,7 @@
  * failure and updates the engine state to DISCONNECTED if the stream
  * gets disconencted.
  *
- * Returns 0 on success or -1 on fail.
+ * Returns %0 on success or %-1 on fail.
  **/
 int
 camel_scalix_engine_next_token (CamelSCALIXEngine *engine, camel_scalix_token_t *token, CamelException *ex)
@@ -1557,7 +1624,7 @@
 	if (camel_scalix_stream_next_token (engine->istream, token) == -1) {
 		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
 				      _("Server %s unexpectedly disconnected: %s"),
-				      engine->url->host, errno ? g_strerror (errno) : _("Unknown"));
+				      engine->url->host, errno ? g_strerror (errno) : _("Unknown error"));
 		
 		engine->state = CAMEL_SCALIX_ENGINE_DISCONNECTED;
 		
@@ -1596,7 +1663,7 @@
 			if (retval == -1) {
 				camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
 						      _("Server %s unexpectedly disconnected: %s"),
-						      engine->url->host, errno ? g_strerror (errno) : _("Unknown"));
+						      engine->url->host, errno ? g_strerror (errno) : _("Unknown error"));
 				
 				engine->state = CAMEL_SCALIX_ENGINE_DISCONNECTED;
 				
@@ -1641,7 +1708,7 @@
 	if (retval == -1) {
 		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
 				      _("Server %s unexpectedly disconnected: %s"),
-				      engine->url->host, errno ? g_strerror (errno) : _("Unknown"));
+				      engine->url->host, errno ? g_strerror (errno) : _("Unknown error"));
 		
 		if (linebuf != NULL)
 			g_byte_array_free (linebuf, TRUE);
@@ -1697,7 +1764,7 @@
 	if (retval == -1) {
 		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
 				      _("Server %s unexpectedly disconnected: %s"),
-				      engine->url->host, errno ? g_strerror (errno) : _("Unknown"));
+				      engine->url->host, errno ? g_strerror (errno) : _("Unknown error"));
 		
 		if (literalbuf != NULL)
 			g_byte_array_free (literalbuf, TRUE);

Modified: trunk/camel/camel-scalix-engine.h
==============================================================================
--- trunk/camel/camel-scalix-engine.h	(original)
+++ trunk/camel/camel-scalix-engine.h	Thu Apr  9 06:15:08 2009
@@ -28,11 +28,10 @@
 
 #include <glib.h>
 
-#include <libedataserver/e-msgport.h>
-
 #include <camel/camel-stream.h>
 #include <camel/camel-folder.h>
 #include <camel/camel-session.h>
+#include <camel/camel-list-utils.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -83,6 +82,9 @@
 	CAMEL_SCALIX_CAPABILITY_MULTIAPPEND      = (1 << 11),
 	CAMEL_SCALIX_CAPABILITY_UNSELECT         = (1 << 12),
 	
+	CAMEL_SCALIX_CAPABILITY_XGWEXTENSIONS    = (1 << 16),
+        CAMEL_SCALIX_CAPABILITY_XGWMOVE          = (1 << 17),
+
 	//CAMEL_SCALIX_CAPABILITY_XSCALIX_1     = (1 << 16),
 	//CAMEL_SCALIX_CAPABILITY_XSCALIX_2     = (1 << 17),
 	
@@ -190,7 +192,7 @@
 	
 	struct _CamelSCALIXFolder *folder;    /* currently selected folder */
 	
-	EDList queue;                          /* queue of waiting commands */
+	CamelDList queue;                     /* queue of waiting commands */
 	struct _CamelSCALIXCommand *current;
 };
 
@@ -208,6 +210,8 @@
 /* returns 0 on success or -1 on error */
 int camel_scalix_engine_take_stream (CamelSCALIXEngine *engine, CamelStream *stream, CamelException *ex);
 
+void camel_scalix_engine_disconnect (CamelSCALIXEngine *engine);
+
 int camel_scalix_engine_capability (CamelSCALIXEngine *engine, CamelException *ex);
 int camel_scalix_engine_namespace (CamelSCALIXEngine *engine, CamelException *ex);
 

Modified: trunk/camel/camel-scalix-folder.c
==============================================================================
--- trunk/camel/camel-scalix-folder.c	(original)
+++ trunk/camel/camel-scalix-folder.c	Thu Apr  9 06:15:08 2009
@@ -21,9 +21,6 @@
 #include <config.h>
 #endif
 
-#include <glib.h>
-#include <glib/gstdio.h>
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,15 +32,17 @@
 #include <errno.h>
 #include <time.h>
 
-#include <camel/camel-utf8.h>
-#include <camel-private.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <camel/camel-private.h>
 #include <camel/camel-file-utils.h>
-#include <camel/camel-mime-message.h>
-#include <camel/camel-stream-mem.h>
 #include <camel/camel-stream-filter.h>
 #include <camel/camel-mime-filter-crlf.h>
+#include <camel/camel-mime-message.h>
 #include <camel/camel-multipart.h>
-#include <camel/camel-i18n.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-utf8.h>
 
 #include "camel-scalix-utils.h"
 #include "camel-scalix-store.h"
@@ -99,15 +98,18 @@
                                          GPtrArray * uids, CamelException * ex);
 static void scalix_search_free (CamelFolder * folder, GPtrArray * uids);
 static void scalix_rename (CamelFolder * folder, const char *new);
+/*
+static char* scalix_get_filename (CamelFolder *folder, const char *uid, CamelException *ex);
+*/
 
 static CamelOfflineFolderClass *parent_class = NULL;
 
 static GSList *scalix_folder_props = NULL;
 
 static CamelProperty scalix_prop_list[] = {
-    {CAMEL_SCALIX_FOLDER_ENABLE_MLIST, "mlist_info",
-     N_
-     ("Enable mailing-list detection required for some filter and search folder rules")},
+	{ CAMEL_SCALIX_FOLDER_ENABLE_MLIST, "mlist_info", N_("Enable mailing-list detection required for some filter and search folder rules") },
+	{ CAMEL_SCALIX_FOLDER_EXPIRE_ACCESS, "expire-access", N_("Expire cached messages that haven't been read in X seconds") },
+	{ CAMEL_SCALIX_FOLDER_EXPIRE_AGE, "expire-age", N_("Expire cached messages older than X seconds") },
 };
 
 CamelType
@@ -165,6 +167,9 @@
     folder_class->search_by_uids = scalix_search_by_uids;
     folder_class->search_free = scalix_search_free;
     folder_class->rename = scalix_rename;
+    /*
+    folder_class->get_filename = scalix_get_filename;
+    */
 }
 
 static void
@@ -192,8 +197,7 @@
 
     camel_object_unref (folder->search);
 
-    if (folder->cache)
-        camel_object_unref (folder->cache);
+    camel_object_unref (folder->cache);
 
     if (folder->journal) {
         camel_offline_journal_write (folder->journal, NULL);
@@ -204,79 +208,104 @@
     g_free (folder->cachedir);
 }
 
-static int
-scalix_getv (CamelObject * object, CamelException * ex, CamelArgGetV * args)
+/*
+static char*
+scalix_get_filename (CamelFolder *folder, const char *uid, CamelException *ex)
 {
-    CamelArgGetV props;
-    int i, count = 0;
-    guint32 tag;
-
-    for (i = 0; i < args->argc; i++) {
-        CamelArgGet *arg = &args->argv[i];
-
-        tag = arg->tag;
-
-        switch (tag & CAMEL_ARG_TAG) {
-        case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES:
-        case CAMEL_FOLDER_ARG_PROPERTIES:
-            props.argc = 1;
-            props.argv[0] = *arg;
-            ((CamelObjectClass *) parent_class)->getv (object, ex, &props);
-            *arg->ca_ptr =
-                g_slist_concat (*arg->ca_ptr,
-                                g_slist_copy (scalix_folder_props));
-            break;
-        case CAMEL_SCALIX_FOLDER_ARG_ENABLE_MLIST:
-            *arg->ca_int = ((CamelSCALIXFolder *) object)->enable_mlist;
-            break;
-        case CAMEL_SCALIX_FOLDER_ARG_NEED_SYNCH:
-            *arg->ca_int = ((CamelSCALIXFolder *) object)->need_synch;
-            break;
-        default:
-            count++;
-            continue;
-        }
-
-        arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
-    }
-
-    if (count)
-        return ((CamelObjectClass *) parent_class)->getv (object, ex, args);
+    CamelSCALIXFolder *scalix_folder = (CamelSCALIXFolder *) folder;
 
-    return 0;
+    return camel_data_cache_get_filename (scalix_folder->cache, "cache", uid, ex);
 }
+*/
 
 static int
-scalix_setv (CamelObject * object, CamelException * ex, CamelArgV * args)
+scalix_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
 {
-    CamelSCALIXFolder *folder = (CamelSCALIXFolder *) object;
-    gboolean save = FALSE;
-    guint32 tag;
-    int i;
+	CamelSCALIXFolder *folder = (CamelSCALIXFolder *) object;
+	CamelArgGetV props;
+	int i, count = 0;
+	guint32 tag;
+
+	for (i = 0; i < args->argc; i++) {
+		CamelArgGet *arg = &args->argv[i];
+
+		tag = arg->tag;
+
+		switch (tag & CAMEL_ARG_TAG) {
+		case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES:
+		case CAMEL_FOLDER_ARG_PROPERTIES:
+			props.argc = 1;
+			props.argv[0] = *arg;
+			((CamelObjectClass *) parent_class)->getv (object, ex, &props);
+			*arg->ca_ptr = g_slist_concat (*arg->ca_ptr, g_slist_copy (scalix_folder_props));
+			break;
+		case CAMEL_SCALIX_FOLDER_ARG_ENABLE_MLIST:
+			*arg->ca_int = folder->enable_mlist;
+			break;
+		case CAMEL_SCALIX_FOLDER_ARG_EXPIRE_ACCESS:
+			*arg->ca_int = folder->cache->expire_access;
+			break;
+		case CAMEL_SCALIX_FOLDER_ARG_EXPIRE_AGE:
+			*arg->ca_int = folder->cache->expire_age;
+			break;
+		default:
+			count++;
+			continue;
+		}
 
-    for (i = 0; i < args->argc; i++) {
-        CamelArg *arg = &args->argv[i];
+		arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
+	}
 
-        tag = arg->tag;
+	if (count)
+		return ((CamelObjectClass *) parent_class)->getv (object, ex, args);
 
-        switch (tag & CAMEL_ARG_TAG) {
-        case CAMEL_SCALIX_FOLDER_ARG_ENABLE_MLIST:
-            if (folder->enable_mlist != arg->ca_int) {
-                folder->enable_mlist = arg->ca_int;
-                save = TRUE;
-            }
-            break;
-        default:
-            continue;
-        }
+	return 0;
+}
 
-        arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
-    }
+static int
+scalix_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
+{
+	CamelSCALIXFolder *folder = (CamelSCALIXFolder *) object;
+	CamelDataCache *cache = folder->cache;
+	gboolean save = FALSE;
+	guint32 tag;
+	int i;
+
+	for (i = 0; i < args->argc; i++) {
+		CamelArg *arg = &args->argv[i];
+
+		tag = arg->tag;
+
+		switch (tag & CAMEL_ARG_TAG) {
+		case CAMEL_SCALIX_FOLDER_ARG_ENABLE_MLIST:
+			if (folder->enable_mlist != arg->ca_int) {
+				folder->enable_mlist = arg->ca_int;
+				save = TRUE;
+			}
+			break;
+		case CAMEL_SCALIX_FOLDER_ARG_EXPIRE_ACCESS:
+			if (cache->expire_access != (time_t) arg->ca_int) {
+				camel_data_cache_set_expire_access (cache, (time_t) arg->ca_int);
+				save = TRUE;
+			}
+			break;
+		case CAMEL_SCALIX_FOLDER_ARG_EXPIRE_AGE:
+			if (cache->expire_age != (time_t) arg->ca_int) {
+				camel_data_cache_set_expire_age (cache, (time_t) arg->ca_int);
+				save = TRUE;
+			}
+			break;
+		default:
+			continue;
+		}
 
-    if (save)
-        camel_object_state_write (object);
+		arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
+	}
 
-    return ((CamelObjectClass *) parent_class)->setv (object, ex, args);
+	if (save)
+		camel_object_state_write (object);
+
+	return ((CamelObjectClass *) parent_class)->setv (object, ex, args);
 }
 
 static char *
@@ -425,7 +454,6 @@
     folder->summary = camel_scalix_summary_new (folder);
     scalix_folder->cachedir =
         scalix_store_build_filename (store, folder->full_name);
-    
     g_mkdir_with_parents (scalix_folder->cachedir, 0777);
 
     scalix_folder->cache =
@@ -445,7 +473,7 @@
 
     if (camel_object_state_read (folder) == -1) {
         /* set our defaults */
-        scalix_folder->enable_mlist = TRUE;
+        scalix_folder->enable_mlist = FALSE;
     }
 
     if (!g_ascii_strcasecmp (full_name, "INBOX")) {
@@ -453,9 +481,7 @@
             folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
         if (camel_url_get_param (((CamelService *) store)->url, "filter_junk"))
             folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK;
-    } else
-        if (!camel_url_get_param
-            (((CamelService *) store)->url, "filter_junk_inbox")) {
+    } else if (!camel_url_get_param (((CamelService *) store)->url, "filter_junk_inbox")) {
         if (camel_url_get_param (((CamelService *) store)->url, "filter_junk"))
             folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK;
     }
@@ -554,7 +580,7 @@
             /* FIXME: would be good to save the NO reason into the err message */
             camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
                                   _
-                                  ("Cannot sync flags to folder `%s': Unknown"),
+                                  ("Cannot sync flags to folder `%s': Unknown error"),
                                   folder->full_name);
             retval = -1;
             break;
@@ -587,8 +613,10 @@
     int retval = 0;
     int i, j;
 
+#if 0
     if (folder->permanent_flags == 0)
         return 0;
+#endif
 
     on_set = g_ptr_array_new ();
     off_set = g_ptr_array_new ();
@@ -648,20 +676,18 @@
 static void
 scalix_sync (CamelFolder * folder, gboolean expunge, CamelException * ex)
 {
-    CamelSCALIXEngine *engine =
-        ((CamelSCALIXStore *) folder->parent_store)->engine;
-    CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
-    CamelSCALIXMessageInfo *iinfo;
-    CamelMessageInfo *info;
-    CamelSCALIXCommand *ic;
-    flags_diff_t diff;
-    GPtrArray *sync;
-    int id, max, i;
-    int retval;
-
-    if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
-        return;
+	CamelSCALIXEngine *engine = ((CamelSCALIXStore *) folder->parent_store)->engine;
+	CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
+	CamelSCALIXMessageInfo *iinfo;
+	CamelMessageInfo *info;
+	CamelSCALIXCommand *ic;
+	flags_diff_t diff;
+	GPtrArray *sync;
+	int id, max, i;
+	int retval;
 
+	if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
+		return;
 
 #if EAPI_CHECK_VERSION (2, 10)
 	CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock);
@@ -669,82 +695,77 @@
 	CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock);
 #endif
 
+	/* gather a list of changes to sync to the server */
+	if (folder->permanent_flags) {
+		sync = g_ptr_array_new ();
+		max = camel_folder_summary_count (folder->summary);
+		for (i = 0; i < max; i++) {
+			iinfo = (CamelSCALIXMessageInfo *) (info = camel_folder_summary_index (folder->summary, i));
+			if (iinfo->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
+				camel_scalix_flags_diff (&diff, iinfo->server_flags, iinfo->info.flags);
+				diff.changed &= folder->permanent_flags;
+
+				/* weed out flag changes that we can't sync to the server */
+				if (!diff.changed)
+					camel_message_info_free (info);
+				else
+					g_ptr_array_add (sync, info);
+			} else {
+				camel_message_info_free (info);
+			}
+		}
+
+		if (sync->len > 0) {
+			retval = scalix_sync_changes (folder, sync, ex);
+
+			for (i = 0; i < sync->len; i++)
+				camel_message_info_free (sync->pdata[i]);
+
+			g_ptr_array_free (sync, TRUE);
+
+			if (retval == -1)
+				goto done;
+		} else {
+			g_ptr_array_free (sync, TRUE);
+		}
+	}
+
+	if (expunge && !((CamelSCALIXFolder *) folder)->read_only) {
+		ic = camel_scalix_engine_queue (engine, folder, "EXPUNGE\r\n");
+		while ((id = camel_scalix_engine_iterate (engine)) < ic->id && id != -1)
+			;
+
+		switch (ic->result) {
+		case CAMEL_SCALIX_RESULT_OK:
+			camel_scalix_summary_flush_updates (folder->summary, ex);
+			break;
+		case CAMEL_SCALIX_RESULT_NO:
+			/* FIXME: would be good to save the NO reason into the err message */
+			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+			                      _("Cannot expunge folder `%s': Unknown error"),
+			                      folder->full_name);
+			break;
+		case CAMEL_SCALIX_RESULT_BAD:
+			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+			                      _("Cannot expunge folder `%s': Bad command"),
+			                      folder->full_name);
+			break;
+		}
+
+		camel_scalix_command_unref (ic);
+	} else {
+		camel_scalix_summary_flush_updates (folder->summary, ex);
+	}
 
-    /* gather a list of changes to sync to the server */
-    sync = g_ptr_array_new ();
-    max = camel_folder_summary_count (folder->summary);
-    for (i = 0; i < max; i++) {
-        iinfo = (CamelSCALIXMessageInfo *) (info =
-                                            camel_folder_summary_index (folder->
-                                                                        summary,
-                                                                        i));
-        if (iinfo->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
-            camel_scalix_flags_diff (&diff, iinfo->server_flags,
-                                     iinfo->info.flags);
-            diff.changed &= folder->permanent_flags;
+	camel_folder_summary_save (folder->summary);
 
-            /* weed out flag changes that we can't sync to the server */
-            if (!diff.changed)
-                camel_message_info_free (info);
-            else
-                g_ptr_array_add (sync, info);
-        } else {
-            camel_message_info_free (info);
-        }
-    }
-
-    if (sync->len > 0) {
-        retval = scalix_sync_changes (folder, sync, ex);
-
-        for (i = 0; i < sync->len; i++)
-            camel_message_info_free (sync->pdata[i]);
-
-        g_ptr_array_free (sync, TRUE);
-
-        if (retval == -1)
-            goto done;
-    } else {
-        g_ptr_array_free (sync, TRUE);
-    }
-
-    if (expunge) {
-        ic = camel_scalix_engine_queue (engine, folder, "EXPUNGE\r\n");
-        while ((id = camel_scalix_engine_iterate (engine)) < ic->id
-               && id != -1) ;
-
-        switch (ic->result) {
-        case CAMEL_SCALIX_RESULT_OK:
-            camel_scalix_summary_flush_updates (folder->summary, ex);
-            break;
-        case CAMEL_SCALIX_RESULT_NO:
-            /* FIXME: would be good to save the NO reason into the err message */
-            camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-                                  _("Cannot expunge folder `%s': Unknown"),
-                                  folder->full_name);
-            break;
-        case CAMEL_SCALIX_RESULT_BAD:
-            camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-                                  _("Cannot expunge folder `%s': Bad command"),
-                                  folder->full_name);
-            break;
-        }
-
-        camel_scalix_command_unref (ic);
-    } else {
-        camel_scalix_summary_flush_updates (folder->summary, ex);
-    }
-
-    camel_folder_summary_save (folder->summary);
-
-  done:
+done:
 
 #if EAPI_CHECK_VERSION (2, 10)
 	CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
 #else
 	CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock);
 #endif
-
-
 }
 
 static void
@@ -778,6 +799,7 @@
     scalix_sync (folder, TRUE, ex);
 }
 
+    extern int camel_application_is_exiting;
 static void
 scalix_refresh_info (CamelFolder * folder, CamelException * ex)
 {
@@ -796,7 +818,7 @@
     int id;
     int i;
 
-    if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
+    if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL || camel_application_is_exiting)
         return;
 
 
@@ -1186,6 +1208,13 @@
     if (appended_uid)
         *appended_uid = NULL;
 
+    if (((CamelSCALIXFolder *) folder)->read_only) {
+        camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+                              _("Cannot append message to folder '%s': Folder is read-only"),
+                              folder->full_name);
+        return;
+    }
+
     if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
         camel_scalix_journal_append ((CamelSCALIXJournal *) scalix_folder->
                                      journal, message, info, appended_uid, ex);

Modified: trunk/camel/camel-scalix-folder.h
==============================================================================
--- trunk/camel/camel-scalix-folder.h	(original)
+++ trunk/camel/camel-scalix-folder.h	Thu Apr  9 06:15:08 2009
@@ -47,14 +47,18 @@
 enum {
 	CAMEL_SCALIX_FOLDER_ARG_ENABLE_MLIST = CAMEL_OFFLINE_FOLDER_ARG_LAST,
 	CAMEL_SCALIX_FOLDER_ARG_NEED_SYNCH,
-	CAMEL_SCALIX_FOLDER_ARG_FREE_BUSY,
+	//CAMEL_SCALIX_FOLDER_ARG_FREE_BUSY,
+	CAMEL_SCALIX_FOLDER_ARG_EXPIRE_ACCESS,
+	CAMEL_SCALIX_FOLDER_ARG_EXPIRE_AGE, 
 	CAMEL_SCALIX_FOLDER_ARG_LAST = CAMEL_OFFLINE_FOLDER_ARG_LAST + 0x100
 };
 
 enum {
 	CAMEL_SCALIX_FOLDER_ENABLE_MLIST = CAMEL_SCALIX_FOLDER_ARG_ENABLE_MLIST | CAMEL_ARG_BOO,
+	CAMEL_SCALIX_FOLDER_EXPIRE_ACCESS = CAMEL_SCALIX_FOLDER_ARG_EXPIRE_ACCESS | CAMEL_ARG_INT,
+	CAMEL_SCALIX_FOLDER_EXPIRE_AGE = CAMEL_SCALIX_FOLDER_ARG_EXPIRE_AGE | CAMEL_ARG_INT,
 	CAMEL_SCALIX_FOLDER_NEED_SYNCH = CAMEL_SCALIX_FOLDER_ARG_NEED_SYNCH | CAMEL_ARG_BOO,
-	CAMEL_SCALIX_FOLDER_FREE_BUSY = CAMEL_SCALIX_FOLDER_ARG_FREE_BUSY | CAMEL_ARG_BOO
+	//CAMEL_SCALIX_FOLDER_FREE_BUSY = CAMEL_SCALIX_FOLDER_ARG_FREE_BUSY | CAMEL_ARG_BOO
 };
 
 struct _CamelSCALIXFolder {
@@ -72,6 +76,7 @@
 	guint32 uidnext;
 	guint32 flags;
 	
+	unsigned int read_only:1;
 	unsigned int enable_mlist:1;
 	unsigned int is_special:1;
 	unsigned int is_trash:1;

Modified: trunk/camel/camel-scalix-journal.c
==============================================================================
--- trunk/camel/camel-scalix-journal.c	(original)
+++ trunk/camel/camel-scalix-journal.c	Thu Apr  9 06:15:08 2009
@@ -51,10 +51,10 @@
 static void camel_scalix_journal_init (CamelSCALIXJournal *journal, CamelSCALIXJournalClass *klass);
 static void camel_scalix_journal_finalize (CamelObject *object);
 
-static void scalix_entry_free (CamelOfflineJournal *journal, EDListNode *entry);
-static EDListNode *scalix_entry_load (CamelOfflineJournal *journal, FILE *in);
-static int scalix_entry_write (CamelOfflineJournal *journal, EDListNode *entry, FILE *out);
-static int scalix_entry_play (CamelOfflineJournal *journal, EDListNode *entry, CamelException *ex);
+static void scalix_entry_free (CamelOfflineJournal *journal, CamelDListNode *entry);
+static CamelDListNode *scalix_entry_load (CamelOfflineJournal *journal, FILE *in);
+static int scalix_entry_write (CamelOfflineJournal *journal, CamelDListNode *entry, FILE *out);
+static int scalix_entry_play (CamelOfflineJournal *journal, CamelDListNode *entry, CamelException *ex);
 
 
 static CamelOfflineJournalClass *parent_class = NULL;
@@ -112,7 +112,7 @@
 }
 
 static void
-scalix_entry_free (CamelOfflineJournal *journal, EDListNode *entry)
+scalix_entry_free (CamelOfflineJournal *journal, CamelDListNode *entry)
 {
 	CamelSCALIXJournalEntry *scalix_entry = (CamelSCALIXJournalEntry *) entry;
 	
@@ -120,7 +120,7 @@
 	g_free (scalix_entry);
 }
 
-static EDListNode *
+static CamelDListNode *
 scalix_entry_load (CamelOfflineJournal *journal, FILE *in)
 {
 	CamelSCALIXJournalEntry *entry;
@@ -140,7 +140,7 @@
 		goto exception;
 	}
 	
-	return (EDListNode *) entry;
+	return (CamelDListNode *) entry;
 	
  exception:
 	
@@ -158,7 +158,7 @@
 }
 
 static int
-scalix_entry_write (CamelOfflineJournal *journal, EDListNode *entry, FILE *out)
+scalix_entry_write (CamelOfflineJournal *journal, CamelDListNode *entry, FILE *out)
 {
 	CamelSCALIXJournalEntry *scalix_entry = (CamelSCALIXJournalEntry *) entry;
 	
@@ -260,7 +260,7 @@
 }
 
 static int
-scalix_entry_play (CamelOfflineJournal *journal, EDListNode *entry, CamelException *ex)
+scalix_entry_play (CamelOfflineJournal *journal, CamelDListNode *entry, CamelException *ex)
 {
 	CamelSCALIXJournalEntry *scalix_entry = (CamelSCALIXJournalEntry *) entry;
 	
@@ -348,7 +348,7 @@
 	entry->type = CAMEL_SCALIX_JOURNAL_ENTRY_APPEND;
 	entry->v.append_uid = uid;
 	
-	e_dlist_addtail (&journal->queue, (EDListNode *) entry);
+	camel_dlist_addtail (&journal->queue, (CamelDListNode *) entry);
 	
 	info = camel_folder_summary_info_new_from_message (folder->summary, message);
 	info->uid = g_strdup (uid);

Modified: trunk/camel/camel-scalix-journal.h
==============================================================================
--- trunk/camel/camel-scalix-journal.h	(original)
+++ trunk/camel/camel-scalix-journal.h	Thu Apr  9 06:15:08 2009
@@ -31,11 +31,21 @@
 #include <camel/camel-offline-journal.h>
 #include <camel/camel-mime-message.h>
 
+#include <libescalix/scalix-version.h>
+
+
 #ifdef __cplusplus
 extern "C" {
 #pragma }
 #endif /* __cplusplus */
 
+#if !EAPI_CHECK_VERSION (2, 24)
+/* In Evolution 2.24, EDListNode deprecated in favour of code-wise identical
+   CamelDListNode. GNOME bug #545877. */
+#define CamelDListNode EDListNode
+#define camel_dlist_addtail e_dlist_addtail
+#endif
+
 #define CAMEL_TYPE_SCALIX_JOURNAL            (camel_scalix_journal_get_type ())
 #define CAMEL_SCALIX_JOURNAL(obj)            (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_SCALIX_JOURNAL, CamelSCALIXJournal))
 #define CAMEL_SCALIX_JOURNAL_CLASS(klass)    (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_SCALIX_JOURNAL, CamelSCALIXJournalClass))
@@ -54,7 +64,7 @@
 };
 
 struct _CamelSCALIXJournalEntry {
-	EDListNode node;
+	CamelDListNode node;
 	
 	int type;
 	

Modified: trunk/camel/camel-scalix-provider.c
==============================================================================
--- trunk/camel/camel-scalix-provider.c	(original)
+++ trunk/camel/camel-scalix-provider.c	Thu Apr  9 06:15:08 2009
@@ -88,7 +88,6 @@
 	guint hash = 0;
 	
 	add_hash (&hash, u->user);
-	add_hash (&hash, u->authmech);
 	add_hash (&hash, u->host);
 	hash ^= u->port;
 	
@@ -118,7 +117,6 @@
 	
 	return check_equal (u1->protocol, u2->protocol)
 		&& check_equal (u1->user, u2->user)
-		&& check_equal (u1->authmech, u2->authmech)
 		&& check_equal (u1->host, u2->host)
 		&& u1->port == u2->port;
 }

Modified: trunk/camel/camel-scalix-store.c
==============================================================================
--- trunk/camel/camel-scalix-store.c	(original)
+++ trunk/camel/camel-scalix-store.c	Thu Apr  9 06:15:08 2009
@@ -449,6 +449,14 @@
 
 	camel_scalix_command_unref (ic);
 
+	if (camel_tcp_stream_ssl_enable_ssl ((CamelTcpStreamSSL *) tcp_stream) == -1) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+		                      _("Failed to connect to IMAP server %s in secure mode: %s"),
+		                      service->url->host, _("TLS negotiations failed"));
+		camel_scalix_engine_disconnect (engine);
+		return FALSE;
+	}
+
 	return TRUE;
 #else
 	camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
@@ -1799,7 +1807,7 @@
 		g_free (list);
 	}
 	
-	fi = camel_folder_info_build (array, top, '/', TRUE);
+	fi = camel_scalix_build_folder_info_tree (array, top);
 	
 	camel_url_free (url);
 	

Modified: trunk/camel/camel-scalix-summary.c
==============================================================================
--- trunk/camel/camel-scalix-summary.c	(original)
+++ trunk/camel/camel-scalix-summary.c	Thu Apr  9 06:15:08 2009
@@ -39,6 +39,7 @@
 #include <camel/camel-string-utils.h>
 #include <camel/camel-offline-journal.h>
 #include <camel/camel-i18n.h>
+#include <camel/camel-db.h>
 
 #include "camel-scalix-store.h"
 #include "camel-scalix-engine.h"
@@ -54,6 +55,11 @@
 
 #define CAMEL_SCALIX_SUMMARY_VERSION  3
 
+#define IMAP_SAVE_INCREMENT 1024
+
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+#define EXTRACT_DIGIT(val) if (*part) part++; val=strtoul (part, &part, 10);
+
 static void camel_scalix_summary_class_init (CamelSCALIXSummaryClass *klass);
 static void camel_scalix_summary_init (CamelSCALIXSummary *summary, CamelSCALIXSummaryClass *klass);
 static void camel_scalix_summary_finalize (CamelObject *object);
@@ -67,6 +73,13 @@
 static CamelMessageContentInfo *scalix_content_info_load (CamelFolderSummary *summary, FILE *in);
 static int scalix_content_info_save (CamelFolderSummary *summary, FILE *out, CamelMessageContentInfo *info);
 
+static int scalix_summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static CamelFIRecord *scalix_summary_header_to_db (CamelFolderSummary *s, CamelException *ex);
+static CamelMIRecord *scalix_message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info);
+static CamelMessageInfo *scalix_message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
+static int scalix_content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
+static CamelMessageContentInfo *scalix_content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
+
 static CamelFolderSummaryClass *parent_class = NULL;
 
 static const char *scalix_message_info_get_user_tag (const CamelMessageInfo *mi, const char *tag);
@@ -108,9 +121,15 @@
 	summary_class->content_info_load = scalix_content_info_load;
 	summary_class->content_info_save = scalix_content_info_save;
 
+	summary_class->summary_header_from_db = scalix_summary_header_from_db;
+	summary_class->summary_header_to_db = scalix_summary_header_to_db;
+	summary_class->message_info_from_db = scalix_message_info_from_db;
+	summary_class->message_info_to_db = scalix_message_info_to_db;
+	summary_class->content_info_from_db = scalix_content_info_from_db;
+	summary_class->content_info_to_db = scalix_content_info_to_db;
+
 	summary_class->info_user_tag = scalix_message_info_get_user_tag;
 	summary_class->info_set_user_tag = scalix_message_info_set_user_tag;
-
 }
 
 static void
@@ -124,8 +143,6 @@
 	folder_summary->message_info_size = sizeof (CamelSCALIXMessageInfo);
 	folder_summary->content_info_size = sizeof (CamelSCALIXMessageContentInfo);
 	
-	((CamelFolderSummary *) summary)->flags |= CAMEL_SCALIX_SUMMARY_HAVE_MLIST;
-	
 	summary->update_flags = TRUE;
 	summary->uidvalidity_changed = FALSE;
 }
@@ -149,6 +166,34 @@
 }
 
 static int
+scalix_summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir)
+{
+	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) s;
+	char* part;
+
+	if (parent_class->summary_header_from_db (s, mir) == -1)
+		return -1;
+
+	part = mir->bdata;
+
+	if (part) {
+		EXTRACT_FIRST_DIGIT (scalix_summary->version)
+	}
+
+	if (part) {
+		EXTRACT_DIGIT (scalix_summary->uidvalidity)
+	}
+
+	if (scalix_summary->version > CAMEL_SCALIX_SUMMARY_VERSION) {
+		g_warning("Unknown SCALIX summary version\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
 scalix_header_load (CamelFolderSummary *summary, FILE *fin)
 {
 	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) summary;
@@ -184,6 +229,20 @@
 	return 0;
 }
 
+static CamelFIRecord *
+scalix_summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) s;
+	struct _CamelFIRecord *fir;
+
+	fir = parent_class->summary_header_to_db (s, ex);
+	if (!fir)
+		return NULL;
+	fir->bdata = g_strdup_printf ("%d %u", CAMEL_SCALIX_SUMMARY_VERSION, scalix_summary->uidvalidity);
+
+	return fir;
+}
+
 static int
 scalix_header_save (CamelFolderSummary *summary, FILE *fout)
 {
@@ -439,7 +498,8 @@
 {
 	struct _camel_header_references *refs, *irt, *r;
 	CamelSummaryReferences *references;
-	unsigned char md5sum[16];
+	MD5Context checksum;
+	guint8 digest[16];
 	guint32 i, n;
 
 	refs = camel_header_references_decode (refstr);
@@ -468,8 +528,11 @@
 	references->size = n;
 
 	for (i = 0, r = refs; r != NULL; i++, r = r->next) {
-		md5_get_digest (r->id, strlen (r->id), md5sum);
-		memcpy (references->references[i].id.hash, md5sum, sizeof (CamelSummaryMessageID));
+		md5_init (&checksum);
+		md5_update (&checksum, (guchar *) r->id, strlen (r->id));
+		md5_final (&checksum, digest);
+
+		memcpy (references->references[i].id.hash, digest, sizeof (CamelSummaryMessageID));
 	}
 
 	camel_header_references_list_clear (&refs);
@@ -481,8 +544,9 @@
 decode_envelope (CamelSCALIXEngine *engine, CamelMessageInfo *info, camel_scalix_token_t *token, CamelException *ex)
 {
 	CamelSCALIXMessageInfo *iinfo = (CamelSCALIXMessageInfo *) info;
-	unsigned char md5sum[16];
 	char *nstring, *msgid;
+	MD5Context checksum;
+	guint8 digest[16];
 
 	if (camel_scalix_engine_next_token (engine, token, ex) == -1)
 		return -1;
@@ -498,40 +562,47 @@
 	/* subject */
 	if (envelope_decode_nstring (engine, &nstring, TRUE, ex) == -1)
 		goto exception;
+
 	iinfo->info.subject = camel_pstring_strdup (nstring);
 	g_free(nstring);
 
 	/* from */
 	if (envelope_decode_addresses (engine, &nstring, ex) == -1)
 		goto exception;
+
 	iinfo->info.from = camel_pstring_strdup (nstring);
 	g_free(nstring);
 
 	/* sender */
 	if (envelope_decode_addresses (engine, &nstring, ex) == -1)
 		goto exception;
+
 	g_free (nstring);
 
 	/* reply-to */
 	if (envelope_decode_addresses (engine, &nstring, ex) == -1)
 		goto exception;
+
 	g_free (nstring);
 
 	/* to */
 	if (envelope_decode_addresses (engine, &nstring, ex) == -1)
 		goto exception;
+
 	iinfo->info.to = camel_pstring_strdup (nstring);
 	g_free(nstring);
 
 	/* cc */
 	if (envelope_decode_addresses (engine, &nstring, ex) == -1)
 		goto exception;
+
 	iinfo->info.cc = camel_pstring_strdup (nstring);
 	g_free(nstring);
 
 	/* bcc */
 	if (envelope_decode_addresses (engine, &nstring, ex) == -1)
 		goto exception;
+
 	g_free (nstring);
 
 	/* in-reply-to */
@@ -550,10 +621,12 @@
 		goto exception;
 
 	if (nstring != NULL) {
-
 		if ((msgid = camel_header_msgid_decode (nstring))) {
-			md5_get_digest (msgid, strlen (msgid), md5sum);
-			memcpy (iinfo->info.message_id.id.hash, md5sum, sizeof (CamelSummaryMessageID));
+			md5_init (&checksum);
+			md5_update (&checksum, (guchar *) msgid, strlen (msgid));
+			md5_final (&checksum, digest);
+
+			memcpy (iinfo->info.message_id.id.hash, digest, sizeof (CamelSummaryMessageID));
 			g_free (msgid);
 		}
 
@@ -695,11 +768,13 @@
 }
 
 enum {
-	SCALIX_FETCH_ENVELOPE     = (1 << 1),
-	SCALIX_FETCH_FLAGS        = (1 << 2),
-	SCALIX_FETCH_INTERNALDATE = (1 << 3),
-	SCALIX_FETCH_RFC822SIZE   = (1 << 4),
-	SCALIX_FETCH_UID          = (1 << 5),
+	SCALIX_FETCH_ENVELOPE     = (1 << 0),
+	SCALIX_FETCH_FLAGS        = (1 << 1),
+	SCALIX_FETCH_INTERNALDATE = (1 << 2),
+	SCALIX_FETCH_RFC822SIZE   = (1 << 3),
+	SCALIX_FETCH_UID          = (1 << 4),
+
+	SCALIX_FETCH_SAVED        = (1 << 7),
 };
 
 #define SCALIX_FETCH_ALL (SCALIX_FETCH_ENVELOPE | SCALIX_FETCH_FLAGS | SCALIX_FETCH_INTERNALDATE | SCALIX_FETCH_RFC822SIZE | SCALIX_FETCH_UID)
@@ -714,10 +789,11 @@
 	CamelFolderSummary *summary;
 	GHashTable *uid_hash;
 	GPtrArray *added;
+	guint32 count;
+	guint32 total;
 	guint32 first;
-	guint32 need;
-	int count;
-	int total;
+	guint8 need;
+	guint8 all;
 };
 
 static void
@@ -758,74 +834,101 @@
 	g_free (warning);
 }
 
+/**
+ * scalix_fetch_all_add:
+ * @fetch: FETCH ALL state
+ * @complete: %TRUE if the FETCH command is complete or %FALSE otherwise
+ *
+ * Adds all newly acquired envelopes to the summary. Stops at the
+ * first incomplete envelope.
+ **/
 static void
-scalix_fetch_all_add (struct scalix_fetch_all_t *fetch)
+scalix_fetch_all_add (struct scalix_fetch_all_t *fetch, gboolean complete)
 {
-	CamelFolderChangeInfo *changes = NULL;
 	struct scalix_envelope_t *envelope;
+	CamelFolderChangeInfo *changes;
 	CamelMessageInfo *info;
-	int i;
+	guint32 i;
 	
 	changes = fetch->changes;
 	
 	for (i = 0; i < fetch->added->len; i++) {
 		if (!(envelope = fetch->added->pdata[i])) {
-			courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first);
+			if (complete)
+				courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first);
 			break;
 		}
 		
-		if (envelope->changed != SCALIX_FETCH_ALL) {
-			camel_message_info_free (envelope->info);
-			g_free (envelope);
-			continue;
+		if ((envelope->changed & SCALIX_FETCH_ALL) != SCALIX_FETCH_ALL) {
+			if (complete) {
+				d(fprintf (stderr, "Hmmm, IMAP4 server didn't give us everything for message %d\n",
+				           fetch->first + i));
+			}
+
+			break;
 		}
+
+		if (!(envelope->changed & SCALIX_FETCH_SAVED)) {
+			if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) {
+				camel_message_info_free (info);
+				continue;
+			}
 		
-		if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) {
+			if ((((CamelMessageInfoBase *) envelope->info)->flags & CAMEL_SCALIX_MESSAGE_RECENT))
+				camel_folder_change_info_recent_uid (changes, camel_message_info_uid (envelope->info));
+	
+			camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info));	
+			camel_folder_summary_add (fetch->summary, envelope->info);
+			camel_message_info_ref (envelope->info);
+			envelope->changed |= SCALIX_FETCH_SAVED;
+		}
+	}
+	
+	if (complete) {
+		for (i = 0; i < fetch->added->len; i++) {
+			if (!(envelope = fetch->added->pdata[i]))
+				continue;
+
 			camel_message_info_free (envelope->info);
 			g_free (envelope);
-			continue;
 		}
-		
-		camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info));
-		
-		if ((((CamelMessageInfoBase *) envelope->info)->flags & CAMEL_SCALIX_MESSAGE_RECENT))
-			camel_folder_change_info_recent_uid (changes, camel_message_info_uid (envelope->info));
-		
-		camel_folder_summary_add (fetch->summary, envelope->info);
-		g_free (envelope);
+
+		g_ptr_array_free (fetch->added, TRUE);
+		g_hash_table_destroy (fetch->uid_hash);
 	}
-	
-	g_ptr_array_free (fetch->added, TRUE);
-	g_hash_table_destroy (fetch->uid_hash);
-	
+
 	if (camel_folder_change_info_changed (changes))
 		camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes);
-	camel_folder_change_info_free (changes);
-	
-	g_free (fetch);
+
+	if (complete) {
+		camel_folder_change_info_free (changes);
+		g_free (fetch);
+	} else {
+		camel_folder_summary_save (fetch->summary);
+		camel_folder_change_info_clear (changes);
+	}
 }
 
-static guint32
+static void
 scalix_fetch_all_update (struct scalix_fetch_all_t *fetch)
 {
 	CamelSCALIXMessageInfo *iinfo, *new_iinfo;
-	CamelFolderChangeInfo *changes = NULL;
 	struct scalix_envelope_t *envelope;
+	CamelFolderChangeInfo *changes = NULL;
 	CamelMessageInfo *info;
-	guint32 first = 0;
 	guint32 flags;
-	int scount, i;
+	int total, i;
 	
 	changes = fetch->changes;
 	
-	scount = camel_folder_summary_count (fetch->summary);
-	for (i = fetch->first - 1; i < scount; i++) {
+	total = camel_folder_summary_count (fetch->summary);
+	for (i = 0; i < total; i++) {
 		info = camel_folder_summary_index (fetch->summary, i);
 		if (!(envelope = g_hash_table_lookup (fetch->uid_hash, camel_message_info_uid (info)))) {
 			/* remove it */
 			camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
 			camel_folder_summary_remove (fetch->summary, info);
-			scount--;
+			total--;
 			i--;
 		} else if (envelope->changed & SCALIX_FETCH_FLAGS) {
 			/* update it with the new flags */
@@ -845,16 +948,7 @@
 	for (i = 0; i < fetch->added->len; i++) {
 		if (!(envelope = fetch->added->pdata[i])) {
 			courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first);
-			break;
-		}
-		
-		info = envelope->info;
-		if (!first && camel_message_info_uid (info)) {
-			if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (info)))) {
-				camel_message_info_free(info);
-			} else {
-				first = i + fetch->first;
-			}
+			continue;
 		}
 		
 		camel_message_info_free(envelope->info);
@@ -869,8 +963,6 @@
 	camel_folder_change_info_free (changes);
 	
 	g_free (fetch);
-	
-	return first;
 }
 
 static int
@@ -883,30 +975,43 @@
 	CamelSCALIXMessageInfo *iinfo;
 	CamelMessageInfo *info;
 	guint32 changed = 0;
-	const char *iuid;
-	char uid[12];
+	char uid[16];
 	
 	if (index < fetch->first) {
-		/* we already have this message envelope cached -
-		 * server is probably notifying us of a FLAGS change
-		 * by another client? */
-		g_assert (index < summary->messages->len);
-		iinfo = (CamelSCALIXMessageInfo *)(info = summary->messages->pdata[index - 1]);
-		g_assert (info != NULL);
-	} else {
-		if (index > (added->len + fetch->first - 1))
-			g_ptr_array_set_size (added, index - fetch->first + 1);
-		
-		if (!(envelope = added->pdata[index - fetch->first])) {
-			iinfo = (CamelSCALIXMessageInfo *) (info = camel_message_info_new (summary));
-			envelope = g_new (struct scalix_envelope_t, 1);
-			added->pdata[index - fetch->first] = envelope;
-			envelope->info = info;
-			envelope->changed = 0;
-		} else {
-			iinfo = (CamelSCALIXMessageInfo *) (info = envelope->info);
-		}
-	}
+		/* This can happen if the connection to the
+		 * server was dropped in a previous attempt at
+		 * this FETCH (ALL) command and some other
+		 * client expunged messages in the range
+		 * before fetch->first in the period between
+		 * our previous attempt and now. */
+		size_t movelen = added->len * sizeof (void *);
+		size_t extra = index - fetch->first;
+		void *dest;
+
+		g_assert (fetch->all);
+
+		g_ptr_array_set_size (added, added->len + extra);
+		dest = ((char *) added->pdata) + (extra * sizeof (void *));
+		memmove (dest, added->pdata, movelen);
+		fetch->total += extra;
+		fetch->first = index;
+	} else if (index > (added->len + fetch->first - 1)) {
+		size_t extra = index - (added->len + (fetch->first - 1));
+		g_ptr_array_set_size (added, added->len + extra);
+                fetch->total += extra;
+	}
+
+	if (!(envelope = added->pdata[index - fetch->first])) {
+                info = camel_message_info_new (summary);
+                iinfo = (CamelSCALIXMessageInfo *) info;
+                envelope = g_new (struct scalix_envelope_t, 1);
+                added->pdata[index - fetch->first] = envelope;
+                envelope->info = info;
+                envelope->changed = 0;
+        } else {
+                info = envelope->info;
+                iinfo = (CamelSCALIXMessageInfo *) info;
+        }
 	
 	if (camel_scalix_engine_next_token (engine, token, ex) == -1)
 		return -1;
@@ -984,6 +1089,8 @@
 			
 			changed |= SCALIX_FETCH_RFC822SIZE;
 		} else if (!strcmp (token->v.atom, "UID")) {
+			const char *iuid;
+
 			if (camel_scalix_engine_next_token (engine, token, ex) == -1)
 				goto exception;
 			
@@ -994,10 +1101,11 @@
 			iuid = camel_message_info_uid (info);
 			if (iuid != NULL && iuid[0] != '\0') {
 				if (strcmp (iuid, uid) != 0) {
+					d(fprintf (stderr, "Hmmm, UID mismatch for message %u\n", index));
 					g_assert_not_reached ();
 				}
 			} else {
-				g_free (info->uid);
+				g_free ((void*)info->uid);
 				info->uid = g_strdup (uid);
 				g_hash_table_insert (fetch->uid_hash, (void *) camel_message_info_uid (info), envelope);
 				changed |= SCALIX_FETCH_UID;
@@ -1086,7 +1194,6 @@
 				refs = camel_header_raw_find (&h, "References", NULL);
 				str = camel_header_raw_find (&h, "In-Reply-To", NULL);
 				iinfo->info.references = decode_references (refs, str);
-
 			default:
 				break;
 			}
@@ -1094,13 +1201,29 @@
 			camel_object_unref (parser);
 		} else {
 			/* wtf? */
+			d(fprintf (stderr, "huh? %s?...\n", token->v.atom));
 		}
 	} while (1);
 	
 	if (envelope) {
 		envelope->changed |= changed;
-		if ((envelope->changed & fetch->need) == fetch->need)
-			camel_operation_progress (NULL, (++fetch->count * 100.0f) / fetch->total);
+
+		if ((envelope->changed & fetch->need) == fetch->need) {
+			fetch->count++;
+
+			/* if we're doing a FETCH ALL and fetch->count
+			 * is a multiple of the IMAP_SAVE_INCREMENT,
+			 * sync the newly fetched envelopes to the
+			 * summary and to disk as a convenience to
+			 * users on flaky networks which might drop
+			 * our connection to the IMAP server at any
+			 * time, thus forcing us to reconnect and lose
+			 * our summary fetching state. */
+			if (fetch->all && (fetch->count % IMAP_SAVE_INCREMENT) == 0)
+				scalix_fetch_all_add (fetch, FALSE);
+
+			camel_operation_progress (NULL, (fetch->count * 100.0f) / fetch->total);
+		}
 	} else if (changed & SCALIX_FETCH_FLAGS) {
 		camel_folder_change_info_change_uid (fetch->changes, camel_message_info_uid (info));
 	}
@@ -1120,13 +1243,77 @@
 }
 
 #define SCALIX_ALL "FLAGS INTERNALDATE RFC822.SIZE ENVELOPE"
-#define MAILING_LIST_HEADERS "List-Post List-Id Mailing-List Originator X-Mailing-List X-Loop X-List Sender Delivered-To Return-Path X-BeenThere List-Unsubscribe"
+#define MAILING_LIST_HEADERS "List-Post Mailing-List Originator X-Mailing-List X-Loop X-List Sender Delivered-To Return-Path X-BeenThere List-Unsubscribe"
 
-#define BASE_HEADER_FIELDS "Content-Type References In-Reply-To"
+#define BASE_HEADER_FIELDS "Content-Type References In-Reply-To List-Id"
 #define MORE_HEADER_FIELDS BASE_HEADER_FIELDS " " MAILING_LIST_HEADERS
 
+static void
+scalix_fetch_all_reset (CamelSCALIXCommand *ic, struct scalix_fetch_all_t *fetch)
+{
+	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) fetch->summary;
+	CamelFolder *folder = fetch->summary->folder;
+	struct scalix_envelope_t *envelope;
+	CamelMessageInfo *info;
+	guint32 seqid, iuid;
+	const char *query;
+	char uid[32];
+	int scount;
+	int i;
+
+	/* sync everything we've gotten so far to the summary */
+	scalix_fetch_all_add (fetch, FALSE);
+
+	for (i = 0; i < fetch->added->len; i++) {
+		if (!(envelope = fetch->added->pdata[i]))
+			continue;
+
+		camel_message_info_free (envelope->info);
+		fetch->added->pdata[i] = NULL;
+		g_free (envelope);
+	}
+
+	scount = camel_folder_summary_count (fetch->summary);
+	seqid = scount + 1;
+
+	if (seqid > fetch->first) {
+		/* if we get here, then it means that we managed to
+		 * collect some summary info before the connection
+		 * with the imap server dropped. Update our FETCH
+		 * command state to begin fetching where we left off
+		 * rather than at the beginning. */
+		info = camel_folder_summary_index (fetch->summary, scount - 1);
+		iuid = strtoul (camel_message_info_uid (info), NULL, 10);
+		d(fprintf (stderr, "last known summary id = %d, uid = %s, iuid = %u\n", scount, info->uid, iuid));
+		camel_message_info_free (info);
+		sprintf (uid, "%u", iuid + 1);
+
+		fetch->total = scalix_summary->exists - scount;
+		g_ptr_array_set_size (fetch->added, fetch->total);
+		fetch->first = seqid;
+
+		/* now we hack the SpruceIMAPCommand structure... */
+		if (((CamelSCALIXFolder *) folder)->enable_mlist)
+			query = "UID FETCH %s:* (" SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" MORE_HEADER_FIELDS ")])\r\n";
+		else
+			query = "UID FETCH %s:* (" SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" BASE_HEADER_FIELDS ")])\r\n";
+
+		g_free (ic->part->buffer);
+		ic->part->buffer = g_strdup_printf (query, uid);
+		ic->part->buflen = strlen (ic->part->buffer);
+
+		d(fprintf (stderr, "*** RESETTING FETCH-ALL STATE. New command => %s", ic->part->buffer));
+	} else {
+		/* we didn't manage to fetch any new info before the
+		 * connection dropped... */
+	}
+
+	camel_folder_change_info_clear (fetch->changes);
+	g_hash_table_remove_all (fetch->uid_hash);
+}
+
 static CamelSCALIXCommand *
-scalix_summary_fetch_all (CamelFolderSummary *summary, guint32 first, guint32 last)
+scalix_summary_fetch_all (CamelFolderSummary *summary, guint32 seqid, const char *uid)
 {
 	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) summary;
 	CamelFolder *folder = summary->folder;
@@ -1134,70 +1321,83 @@
 	CamelSCALIXEngine *engine;
 	CamelSCALIXCommand *ic;
 	const char *query;
-	int total;
+	guint32 total;
 	
 	engine = ((CamelSCALIXStore *) folder->parent_store)->engine;
 	
-	total = last ? (last - first) + 1 : (scalix_summary->exists - first) + 1;
+	total = (scalix_summary->exists - seqid) + 1;
 	fetch = g_new (struct scalix_fetch_all_t, 1);
 	fetch->uid_hash = g_hash_table_new (g_str_hash, g_str_equal);
 	fetch->changes = camel_folder_change_info_new ();
 	fetch->added = g_ptr_array_sized_new (total);
 	fetch->summary = summary;
-	fetch->first = first;
+	fetch->first = seqid;
 	fetch->need = SCALIX_FETCH_ALL;
 	fetch->total = total;
 	fetch->count = 0;
+	fetch->all = TRUE;
 	
-	if (last != 0) {
-		if (((CamelSCALIXFolder *) folder)->enable_mlist)
-			query = "FETCH %u:%u (UID " SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" MORE_HEADER_FIELDS ")])\r\n";
-		else
-			query = "FETCH %u:%u (UID " SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" BASE_HEADER_FIELDS ")])\r\n";
-		
-		ic = camel_scalix_engine_queue (engine, folder, query, first, last);
-	} else {
-		if (((CamelSCALIXFolder *) folder)->enable_mlist)
-			query = "FETCH %u:* (UID " SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" MORE_HEADER_FIELDS ")])\r\n";
-		else
-			query = "FETCH %u:* (UID " SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" BASE_HEADER_FIELDS ")])\r\n";
-		
-		ic = camel_scalix_engine_queue (engine, folder, query, first);
-	}
+	if (((CamelSCALIXFolder *) folder)->enable_mlist)
+		query = "UID FETCH %s:* (" SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" MORE_HEADER_FIELDS ")])\r\n";
+	else
+		query = "UID FETCH %s:* (" SCALIX_ALL " BODY.PEEK[HEADER.FIELDS (" BASE_HEADER_FIELDS ")])\r\n";
 	
+	ic = camel_scalix_engine_queue (engine, folder, query, uid);
+
 	camel_scalix_command_register_untagged (ic, "FETCH", untagged_fetch_all);
+	ic->reset = (CamelSCALIXCommandReset) scalix_fetch_all_reset;
 	ic->user_data = fetch;
 	
 	return ic;
 }
 
 static CamelSCALIXCommand *
-scalix_summary_fetch_flags (CamelFolderSummary *summary, guint32 first, guint32 last)
+scalix_summary_fetch_flags (CamelFolderSummary *summary)
 {
+	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) summary;
 	CamelFolder *folder = summary->folder;
 	struct scalix_fetch_all_t *fetch;
+	CamelMessageInfo *info[2];
 	CamelSCALIXEngine *engine;
 	CamelSCALIXCommand *ic;
-	int total;
+	guint32 total;
+	int scount;
 	
 	engine = ((CamelSCALIXStore *) folder->parent_store)->engine;
+
+	scount = camel_folder_summary_count (summary);
+	g_assert (scount > 0);
+
+	info[0] = camel_folder_summary_index (summary, 0);
+	if (scount > 1)
+		info[1] = camel_folder_summary_index (summary, scount - 1);
+	else
+		info[1] = NULL;
 	
-	total = (last - first) + 1;
+	total = scalix_summary->exists < scount ? scalix_summary->exists : scount;
 	fetch = g_new (struct scalix_fetch_all_t, 1);
 	fetch->uid_hash = g_hash_table_new (g_str_hash, g_str_equal);
 	fetch->changes = camel_folder_change_info_new ();
 	fetch->added = g_ptr_array_sized_new (total);
 	fetch->summary = summary;
-	fetch->first = first;
+	fetch->first = 1;
 	fetch->need = SCALIX_FETCH_UID | SCALIX_FETCH_FLAGS;
 	fetch->total = total;
 	fetch->count = 0;
+	fetch->all = FALSE;
 	
-	if (last != 0)
-		ic = camel_scalix_engine_queue (engine, folder, "FETCH %u:%u (UID FLAGS)\r\n", first, last);
-	else
-		ic = camel_scalix_engine_queue (engine, folder, "FETCH %u:* (UID FLAGS)\r\n", first);
+	if (info[1] != NULL) {
+		ic = camel_scalix_engine_queue (engine, folder, "UID FETCH %s:%s (FLAGS)\r\n",
+		                                camel_message_info_uid (info[0]),
+		                                camel_message_info_uid (info[1]));
+		camel_message_info_free (info[1]);
+	} else {
+		ic = camel_scalix_engine_queue (engine, folder, "UID FETCH %s* (FLAGS)\r\n",
+		                                camel_message_info_uid (info[0]));
+	}
 	
+	camel_message_info_free (info[0]);
+
 	camel_scalix_command_register_untagged (ic, "FETCH", untagged_fetch_all);
 	ic->user_data = fetch;
 	
@@ -1216,6 +1416,23 @@
 	return info;
 }
 
+static CamelMessageInfo *
+scalix_message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	CamelSCALIXMessageInfo *minfo;
+	CamelMessageInfo *info;
+
+	info = parent_class->message_info_from_db (s, mir);
+	if (info) {
+		char *part = g_strdup (mir->bdata), *tmp;
+		tmp = part;
+		minfo = (CamelSCALIXMessageInfo *)info;
+		EXTRACT_FIRST_DIGIT (minfo->server_flags)
+		g_free (tmp);
+	}
+
+	return info;
+}
 
 static CamelMessageInfo *
 scalix_message_info_load (CamelFolderSummary *summary, FILE *fin)
@@ -1240,6 +1457,19 @@
 	return NULL;
 }
 
+static CamelMIRecord *
+scalix_message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info)
+{
+	CamelSCALIXMessageInfo *minfo = (CamelSCALIXMessageInfo *) info;
+	struct _CamelMIRecord *mir;
+
+	mir = parent_class->message_info_to_db (s, info);
+	if (mir)
+		mir->bdata = g_strdup_printf ("%u", minfo->server_flags);
+
+	return mir;
+}
+
 static int
 scalix_message_info_save (CamelFolderSummary *summary, FILE *fout, CamelMessageInfo *info)
 {
@@ -1270,6 +1500,25 @@
 }
 
 static CamelMessageContentInfo *
+scalix_content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	char *part = mir->cinfo;
+	guint32 type = 0;
+
+	if (part) {
+		if (*part == ' ')
+			part++;
+		if (part)
+			EXTRACT_FIRST_DIGIT (type)
+	}
+	mir->cinfo = part;
+	if (type)
+		return parent_class->content_info_from_db (s, mir);
+	else
+		return camel_folder_summary_content_info_new (s);
+}
+
+static CamelMessageContentInfo *
 scalix_content_info_load (CamelFolderSummary *summary, FILE *in)
 {
 	if (fgetc (in))
@@ -1279,6 +1528,23 @@
 }
 
 static int
+scalix_content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir)
+{
+	char *oldr;
+	if (info->type) {
+		oldr = mir->cinfo;
+		mir->cinfo = oldr ? g_strdup_printf("%s 1", oldr) : g_strdup ("1");
+		g_free(oldr);
+		return parent_class->content_info_to_db (s, info, mir);
+	} else {
+		oldr = mir->cinfo;
+		mir->cinfo = oldr ? g_strdup_printf("%s 0", oldr) : g_strdup ("0");
+		g_free(oldr);
+		return 0;
+	}
+}
+
+static int
 scalix_content_info_save (CamelFolderSummary *summary, FILE *out, CamelMessageContentInfo *info)
 {
 	if (info->type) {
@@ -1423,9 +1689,11 @@
 	CamelSCALIXSummary *scalix_summary = (CamelSCALIXSummary *) summary;
 	CamelOfflineJournal *journal = scalix_folder->journal;
 	CamelSCALIXEngine *engine;
+	CamelMessageInfo *info;
 	CamelSCALIXCommand *ic;
-	guint32 first = 0;
+	guint32 iuid, seqid = 0;
 	int scount, id;
+	char uid[16];
 	
 	g_return_val_if_fail (CAMEL_IS_SCALIX_SUMMARY (summary), -1);
 	
@@ -1444,15 +1712,18 @@
 		summary->flags ^= CAMEL_SCALIX_SUMMARY_HAVE_MLIST;
 	
 	engine = ((CamelSCALIXStore *) summary->folder->parent_store)->engine;
-	scount = camel_folder_summary_count (summary);
+	if ((scount = camel_folder_summary_count (summary)) == 0)
+		scalix_summary->update_flags = FALSE;
 	
 	if (scalix_summary->uidvalidity_changed) {
-		first = 1;
+		/* need to refetch everything */
+		g_assert (scount == 0);
+		seqid = 1;
 	} else if (scalix_summary->update_flags || scalix_summary->exists < scount) {
 		/* this both updates flags and removes messages which
 		 * have since been expunged from the server by another
 		 * client */
-		ic = scalix_summary_fetch_flags (summary, 1, scount);
+		ic = scalix_summary_fetch_flags (summary);
 		
 		camel_operation_start (NULL, _("Scanning for changed messages"));
 		while ((id = camel_scalix_engine_iterate (engine)) < ic->id && id != -1)
@@ -1466,18 +1737,41 @@
 			camel_operation_end (NULL);
 			return -1;
 		}
-		
-		if (!(first = scalix_fetch_all_update (ic->user_data)) && scalix_summary->exists > scount)
-			first = scount + 1;
-		
+
+		scalix_fetch_all_update (ic->user_data);
 		camel_scalix_command_unref (ic);
 		camel_operation_end (NULL);
+		
+		scount = camel_folder_summary_count (summary);
+		if (scalix_summary->exists < scount) {
+			/* broken server? wtf? this should never happen... */
+			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+			                      _("IMAP server %s is in an inconsistent state."),
+			                      engine->url->host);
+			return -1;
+		} else if (scalix_summary->exists > scount) {
+                        /* need to fetch new envelopes */
+                        seqid = scount + 1;
+                } else {
+                        /* we are fully synced */
+                        seqid = 0;
+                }
 	} else {
-		first = scount + 1;
+		/* need to fetch new envelopes */
+		seqid = scount + 1;
 	}
 	
-	if (first != 0 && first <= scalix_summary->exists) {
-		ic = scalix_summary_fetch_all (summary, first, 0);
+	if (seqid != 0 && seqid <= scalix_summary->exists) {
+		if (scount > 0) {
+			info = camel_folder_summary_index (summary, scount - 1);
+			iuid = strtoul (camel_message_info_uid (info), NULL, 10);
+			camel_message_info_free (info);
+			sprintf (uid, "%u", iuid + 1);
+		} else {
+			strcpy (uid, "1");
+		}
+
+		ic = scalix_summary_fetch_all (summary, seqid, uid);
 		
 		camel_operation_start (NULL, _("Fetching envelopes for new messages"));
 		while ((id = camel_scalix_engine_iterate (engine)) < ic->id && id != -1)
@@ -1492,7 +1786,7 @@
 			return -1;
 		}
 		
-		scalix_fetch_all_add (ic->user_data);
+		scalix_fetch_all_add (ic->user_data, TRUE);
 		camel_scalix_command_unref (ic);
 		camel_operation_end (NULL);
 	}

Modified: trunk/camel/camel-scalix-utils.c
==============================================================================
--- trunk/camel/camel-scalix-utils.c	(original)
+++ trunk/camel/camel-scalix-utils.c	Thu Apr  9 06:15:08 2009
@@ -39,9 +39,78 @@
 
 #include "camel-scalix-utils.h"
 
+#include <libescalix/scalix-version.h>
+
 #define d(x)
 
 
+CamelFolderInfo *
+camel_scalix_build_folder_info_tree (GPtrArray *array, const char *top)
+{
+    CamelFolderInfo *cur, *fi, *root = NULL;
+    const char *p;
+    size_t n = 0;
+    char *pname;
+    int i;
+
+    if (array->len == 0)
+        return NULL;
+
+    if (array->len == 1)
+        return array->pdata[0];
+
+    if (top)
+        n = strlen (top);
+
+    cur = root = array->pdata[0];
+
+    for (i = 1; i < array->len; i++) {
+        fi = (CamelFolderInfo *) array->pdata[i];
+        if (top && strncmp (fi->full_name, top, n) != 0) {
+           /* this folder info was not requested */
+           camel_folder_info_free (fi);
+           continue;
+        }
+
+        if ((p = strrchr (fi->full_name, '/'))) {
+            pname = g_strndup (fi->full_name, p - fi->full_name);
+            if (!strcmp (cur->full_name, pname)) {
+                /* cur is our parent */
+                fi->parent = cur;
+                cur->child = fi;
+                cur = fi;
+            } else if (cur->parent && strcmp (cur->parent->full_name, pname)) {
+                /* cur is our sibling */
+                fi->parent = cur->parent;
+                cur->next = fi;
+                cur = fi;
+            } else {
+                /* search back for our parent */
+                while (cur->parent) {
+                    if (!strcmp (cur->parent->full_name, pname))
+                        break;
+                    cur = cur->parent;
+                }
+
+                /* cur should now be our sibling */
+                fi->parent = cur->parent;
+                cur->next = fi;
+                cur = fi;
+            }
+            g_free (pname);
+        } else {
+            /* traverse back to the most recent top-level fi */
+            while (cur->parent)
+                cur = cur->parent;
+
+            cur->next = fi;
+            cur = fi;
+        }
+    }
+
+    return root;
+}
+
 void
 camel_scalix_flags_diff (flags_diff_t *diff, guint32 old, guint32 new)
 {
@@ -237,7 +306,11 @@
 static int
 uidset_add (struct _uidset *uidset, CamelMessageInfo *info)
 {
+#if EAPI_CHECK_VERSION (2, 24)
+	GPtrArray *messages = uidset->summary->uids;
+#else
 	GPtrArray *messages = uidset->summary->messages;
+#endif
 	struct _uidset_range *node, *tail = uidset->tail;
 	const char *iuid = camel_message_info_uid (info);
 	size_t uidlen, len;

Modified: trunk/camel/camel-scalix-utils.h
==============================================================================
--- trunk/camel/camel-scalix-utils.h	(original)
+++ trunk/camel/camel-scalix-utils.h	Thu Apr  9 06:15:08 2009
@@ -24,7 +24,7 @@
 #include <glib.h>
 
 #include <camel/camel-exception.h>
-#include <camel/camel-folder-summary.h>
+#include <camel/camel-scalix-summary.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -42,6 +42,7 @@
 guint32 camel_scalix_merge_flags (guint32 original, guint32 local, guint32 server);
 
 
+struct _CamelFolderInfo;
 struct _CamelSCALIXEngine;
 struct _CamelSCALIXCommand;
 struct _CamelFolderSummary;
@@ -50,6 +51,8 @@
 struct _CamelSCALIXNamespaceList;
 struct _CamelSCALIXNamespace;
 
+struct _CamelFolderInfo *camel_scalix_build_folder_info_tree (GPtrArray *array, const char *top);
+
 void camel_scalix_namespace_clear (struct _CamelSCALIXNamespace **ns);
 struct _CamelSCALIXNamespaceList *camel_scalix_namespace_list_copy (const struct _CamelSCALIXNamespaceList *nsl);
 void camel_scalix_namespace_list_free (struct _CamelSCALIXNamespaceList *nsl);

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Thu Apr  9 06:15:08 2009
@@ -115,6 +115,15 @@
 	CFLAGS="$CFLAGS -DHANDLE_LIBICAL_MEMORY"
 	;;
 
+	2.24)
+	EVOLUTION_API_VERSION=2.24
+	EAPI_MAJOR_VERSION=2
+	EAPI_MINOR_VERSION=24
+	CAMEL_API_VERSION=1.2
+	EDS_API_VERSION=1.2
+	CFLAGS="$CFLAGS -DHANDLE_LIBICAL_MEMORY"
+	;;
+
 esac
 
 AC_SUBST(EVOLUTION_VERSION)

Modified: trunk/m4/intltool.m4
==============================================================================
--- trunk/m4/intltool.m4	(original)
+++ trunk/m4/intltool.m4	Thu Apr  9 06:15:08 2009
@@ -23,9 +23,10 @@
 ## the same distribution terms that you use for the rest of that program.
 
 dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml])
-# serial 36 IT_PROG_INTLTOOL
-AC_DEFUN([IT_PROG_INTLTOOL],
-[AC_PREREQ([2.50])dnl
+# serial 40 IT_PROG_INTLTOOL
+AC_DEFUN([IT_PROG_INTLTOOL], [
+AC_PREREQ([2.50])dnl
+AC_REQUIRE([AM_NLS])dnl
 
 case "$am__api_version" in
     1.[01234])
@@ -39,14 +40,21 @@
     AC_MSG_CHECKING([for intltool >= $1])
 
     INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'`
-    INTLTOOL_APPLIED_VERSION=`awk -F\" '/\\$VERSION / { print $ 2; }' ${ac_aux_dir}/intltool-update.in`
-    [INTLTOOL_APPLIED_VERSION_AS_INT=`awk -F\" '/\\$VERSION / { split($ 2, VERSION, "."); print VERSION[1] * 1000 + VERSION[2] * 100 + VERSION[3];}' ${ac_aux_dir}/intltool-update.in`
+    INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3`
+    [INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'`
     ]
     AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found])
     test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" ||
 	AC_MSG_ERROR([Your intltool is too old.  You need intltool $1 or later.])
 fi
 
+AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update])
+AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge])
+AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract])
+if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then
+    AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.])
+fi
+
   INTLTOOL_DESKTOP_RULE='%.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
 INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
      INTLTOOL_KEYS_RULE='%.keys:      %.keys.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
@@ -91,6 +99,7 @@
 AC_PATH_PROG(XGETTEXT, xgettext)
 AC_PATH_PROG(MSGMERGE, msgmerge)
 AC_PATH_PROG(MSGFMT, msgfmt)
+AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
 if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then
     AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
 fi
@@ -101,12 +110,7 @@
     AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
 fi
 
-# Use the tools built into the package, not the ones that are installed.
-AC_SUBST(INTLTOOL_EXTRACT, '$(top_builddir)/intltool-extract')
-AC_SUBST(INTLTOOL_MERGE, '$(top_builddir)/intltool-merge')
-AC_SUBST(INTLTOOL_UPDATE, '$(top_builddir)/intltool-update')
-
-AC_PATH_PROG(INTLTOOL_PERL, perl)
+AC_PATH_PROG(INTLTOOL_PERL, [perl])
 if test -z "$INTLTOOL_PERL"; then
    AC_MSG_ERROR([perl not found; required for intltool])
 fi
@@ -152,42 +156,6 @@
 
 IT_PO_SUBDIR([po])
 
-dnl The following is very similar to
-dnl
-dnl	AC_CONFIG_FILES([intltool-extract intltool-merge intltool-update])
-dnl
-dnl with the following slight differences:
-dnl  - the *.in files are in ac_aux_dir,
-dnl  - if the file haven't changed upon reconfigure, it's not touched,
-dnl  - the evaluation of the third parameter enables a hack which computes
-dnl    the actual value of $libdir,
-dnl  - the user sees "executing intltool commands", instead of
-dnl    "creating intltool-extract" and such.
-dnl
-dnl Nothing crucial here, and we could use AC_CONFIG_FILES, if there were
-dnl a reason for it.
-
-AC_CONFIG_COMMANDS([intltool], [
-
-for file in intltool-extract intltool-merge intltool-update; do
-  sed -e "s|@INTLTOOL_EXTRACT@|`pwd`/intltool-extract|g" \
-      -e "s|@INTLTOOL_LIBDIR@|${INTLTOOL_LIBDIR}|g" \
-      -e "s|@INTLTOOL_PERL@|${INTLTOOL_PERL}|g" \
-	< ${ac_aux_dir}/${file}.in > ${file}.out
-  if cmp -s ${file} ${file}.out 2>/dev/null; then
-    rm -f ${file}.out
-  else
-    mv -f ${file}.out ${file}
-  fi
-  chmod ugo+x ${file}
-  chmod u+w ${file}
-done
-
-],
-[INTLTOOL_PERL='${INTLTOOL_PERL}' ac_aux_dir='${ac_aux_dir}'
-prefix="$prefix" exec_prefix="$exec_prefix" INTLTOOL_LIBDIR="$libdir" 
-INTLTOOL_EXTRACT='${INTLTOOL_EXTRACT}'])
-
 ])
 
 
@@ -203,6 +171,9 @@
 dnl of config.status.
 AC_CONFIG_COMMANDS_PRE([
   AC_CONFIG_COMMANDS([$1/stamp-it], [
+    if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" ]; then
+       AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.])
+    fi
     rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp"
     >"$1/stamp-it.tmp"
     [sed '/^#/d
@@ -211,22 +182,17 @@
 	'"s|^|	$ac_top_srcdir/|" \
       "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES"
     ]
-    if test ! -f "$1/Makefile"; then
-      AC_MSG_ERROR([$1/Makefile is not ready.])
-    fi
-    mv "$1/Makefile" "$1/Makefile.tmp"
     [sed '/^POTFILES =/,/[^\\]$/ {
 		/^POTFILES =/!d
 		r $1/POTFILES
 	  }
-	 ' "$1/Makefile.tmp" >"$1/Makefile"]
+	 ' "$1/Makefile.in" >"$1/Makefile"]
     rm -f "$1/Makefile.tmp"
     mv "$1/stamp-it.tmp" "$1/stamp-it"
   ])
 ])dnl
 ])
 
-
 # deprecated macros
 AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
 # A hint is needed for aclocal from Automake <= 1.9.4:



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