static gpointer
exchange_journal_entry_load (CamelOfflineJournal *journal,
                             FILE *in)
{
	CamelExchangeJournalEntry *entry;
	gchar *tmp;

	entry = g_malloc0 (sizeof (CamelExchangeJournalEntry));

	if (camel_file_util_decode_uint32 (in, (guint32 *) &entry->type) == -1)
		goto exception;

	switch (entry->type) {
	case CAMEL_EXCHANGE_JOURNAL_ENTRY_APPEND:
		if (camel_file_util_decode_string (in, &entry->uid) == -1)
			goto exception;

		break;
	case CAMEL_EXCHANGE_JOURNAL_ENTRY_TRANSFER:
		if (camel_file_util_decode_string (in, &entry->uid) == -1)
			goto exception;
		if (camel_file_util_decode_string (in, &entry->original_uid) == -1)
			goto exception;
		if (camel_file_util_decode_string (in, &entry->folder_name) == -1)
			goto exception;
		if (camel_file_util_decode_string (in, &tmp) == -1)
			goto exception;
		if (g_ascii_strcasecmp (tmp, "True") == 0)
			entry->delete_original = TRUE;
		else
			entry->delete_original = FALSE;
		g_free (tmp);
		break;
	case CAMEL_EXCHANGE_JOURNAL_ENTRY_DELETE:
		if (camel_file_util_decode_string (in, &entry->uid) == -1)
			goto exception;
		if (camel_file_util_decode_string (in, &tmp) == -1)
			goto exception;
		entry->flags = atoi (tmp);
		g_free (tmp);
		if (camel_file_util_decode_string (in, &tmp) == -1)
			goto exception;
		entry->set = atoi (tmp);
		g_free (tmp);
		break;
	default:
		goto exception;
	}

	return entry;

 exception:

	g_free (entry->folder_name);
	g_free (entry->original_uid);
	g_free (entry->uid);
	g_free (entry);

	return NULL;
}
static CamelFolder *
diary_decode_folder (CamelDiscoDiary *diary)
{
	CamelFolder *folder;
	char *name;

	if (camel_file_util_decode_string (diary->file, &name) == -1)
		return NULL;
	folder = g_hash_table_lookup (diary->folders, name);
	if (!folder) {
		CamelException ex;
		char *msg;

		camel_exception_init (&ex);
		folder = camel_store_get_folder (CAMEL_STORE (diary->store),
						 name, 0, &ex);
		if (folder)
			g_hash_table_insert (diary->folders, name, folder);
		else {
			msg = g_strdup_printf (_("Could not open `%s':\n%s\nChanges made to this folder will not be resynchronized."),
					       name, camel_exception_get_description (&ex));
			camel_exception_clear (&ex);
			camel_session_alert_user (camel_service_get_session (CAMEL_SERVICE (diary->store)),
						  CAMEL_SESSION_ALERT_WARNING,
						  msg, FALSE);
			g_free (msg);
			g_free (name);
		}
	} else
		g_free (name);
	return folder;
}
static EDListNode *
groupwise_entry_load (CamelOfflineJournal *journal, FILE *in)
{
	CamelGroupwiseJournalEntry *entry;

	entry = g_malloc0 (sizeof (CamelGroupwiseJournalEntry));

	if (camel_file_util_decode_uint32 (in, &entry->type) == -1)
		goto exception;

	switch (entry->type) {
	case CAMEL_GROUPWISE_JOURNAL_ENTRY_APPEND:
		if (camel_file_util_decode_string (in, &entry->uid) == -1)
			goto exception;
		break;
	case CAMEL_GROUPWISE_JOURNAL_ENTRY_TRANSFER:
		if (camel_file_util_decode_string (in, &entry->uid) == -1)
			goto exception;
		if (camel_file_util_decode_string (in, &entry->original_uid) == -1)
			goto exception;
		if (camel_file_util_decode_string (in, &entry->source_container) == -1)
			goto exception;
		break;
	default:
		goto exception;
	}

	return (EDListNode *) entry;

 exception:

	if (entry->type == CAMEL_GROUPWISE_JOURNAL_ENTRY_TRANSFER)
		g_free (entry->source_container);

	g_free (entry->uid);
	g_free (entry);

	return NULL;
}
static int
gw_summary_header_load (CamelFolderSummary *s, FILE *in)
{
	CamelGroupwiseSummary *ims = CAMEL_GROUPWISE_SUMMARY (s);

	if (camel_groupwise_summary_parent->summary_header_load (s, in) == -1)
		return -1 ;

	if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1
			|| camel_file_util_decode_fixed_int32(in, &ims->validity) == -1)
		return -1;

	if (camel_file_util_decode_string (in, &ims->time_string) == -1)
		return -1;
	return 0 ;
}
static GPtrArray *
diary_decode_uids (CamelDiscoDiary *diary)
{
	GPtrArray *uids;
	char *uid;
	guint32 i;

	if (camel_file_util_decode_uint32 (diary->file, &i) == -1)
		return NULL;
	uids = g_ptr_array_new ();
	while (i--) {
		if (camel_file_util_decode_string (diary->file, &uid) == -1) {
			free_uids (uids);
			return NULL;
		}
		g_ptr_array_add (uids, uid);
	}

	return uids;
}
static CamelStoreInfo *
store_info_load (CamelStoreSummary *s, FILE *in)
{
	CamelNNTPStoreInfo *ni;

	ni = (CamelNNTPStoreInfo *) camel_nntp_store_summary_parent->store_info_load (s, in);
	if (ni) {
		if (camel_file_util_decode_string (in, &ni->full_name) == -1) {
			camel_store_summary_info_free (s, (CamelStoreInfo *) ni);
			return NULL;
		}
		if (((CamelNNTPStoreSummary *)s)->version >= CAMEL_NNTP_STORE_SUMMARY_VERSION_1) {
			if (camel_file_util_decode_uint32(in, &ni->first) == -1
			    || camel_file_util_decode_uint32(in, &ni->last) == -1) {
				camel_store_summary_info_free (s, (CamelStoreInfo *) ni);
				return NULL;
			}
		}
		/* set the URL */
	}

	return (CamelStoreInfo *) ni;
}
void
camel_disco_diary_replay (CamelDiscoDiary *diary, CamelException *ex)
{
	guint32 action;
	off_t size;
	double pc;

	d(printf("disco diary replay\n"));

	fseek (diary->file, 0, SEEK_END);
	size = ftell (diary->file);
	g_return_if_fail (size != 0);
	rewind (diary->file);

	camel_operation_start (NULL, _("Resynchronizing with server"));
	while (!camel_exception_is_set (ex)) {
		pc = ftell (diary->file) / size;
		camel_operation_progress (NULL, pc * 100);

		if (camel_file_util_decode_uint32 (diary->file, &action) == -1)
			break;
		if (action == CAMEL_DISCO_DIARY_END)
			break;

		switch (action) {
		case CAMEL_DISCO_DIARY_FOLDER_EXPUNGE:
		{
			CamelFolder *folder;
			GPtrArray *uids;

			folder = diary_decode_folder (diary);
			uids = diary_decode_uids (diary);
			if (!uids)
				goto lose;

			if (folder)
				camel_disco_folder_expunge_uids (folder, uids, ex);
			free_uids (uids);
			break;
		}

		case CAMEL_DISCO_DIARY_FOLDER_APPEND:
		{
			CamelFolder *folder;
			char *uid, *ret_uid;
			CamelMimeMessage *message;
			CamelMessageInfo *info;

			folder = diary_decode_folder (diary);
			if (camel_file_util_decode_string (diary->file, &uid) == -1)
				goto lose;

			if (!folder) {
				g_free (uid);
				continue;
			}

			message = camel_folder_get_message (folder, uid, NULL);
			if (!message) {
				/* The message was appended and then deleted. */
				g_free (uid);
				continue;
			}
			info = camel_folder_get_message_info (folder, uid);

			camel_folder_append_message (folder, message, info, &ret_uid, ex);
			camel_folder_free_message_info (folder, info);

			if (ret_uid) {
				camel_disco_diary_uidmap_add (diary, uid, ret_uid);
				g_free (ret_uid);
			}
			g_free (uid);

			break;
		}

		case CAMEL_DISCO_DIARY_FOLDER_TRANSFER:
		{
			CamelFolder *source, *destination;
			GPtrArray *uids, *ret_uids;
			guint32 delete_originals;
			int i;

			source = diary_decode_folder (diary);
			destination = diary_decode_folder (diary);
			uids = diary_decode_uids (diary);
			if (!uids)
				goto lose;
			if (camel_file_util_decode_uint32 (diary->file, &delete_originals) == -1)
				goto lose;

			if (!source || !destination) {
				free_uids (uids);
				continue;
			}

			camel_folder_transfer_messages_to (source, uids, destination, &ret_uids, delete_originals, ex);

			if (ret_uids) {
				for (i = 0; i < uids->len; i++) {
					if (!ret_uids->pdata[i])
						continue;
					camel_disco_diary_uidmap_add (diary, uids->pdata[i], ret_uids->pdata[i]);
					g_free (ret_uids->pdata[i]);
				}
				g_ptr_array_free (ret_uids, TRUE);
			}
			free_uids (uids);
			break;
		}

		}
	}

 lose:
	camel_operation_end (NULL);

	/* Close folders */
	g_hash_table_foreach (diary->folders, close_folder, diary);
	g_hash_table_destroy (diary->folders);
	diary->folders = NULL;

	/* Truncate the log */
	ftruncate (fileno (diary->file), 0);
}