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 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;
}
static CamelMessageInfo *
gw_message_info_load (CamelFolderSummary *s, FILE *in)
{
	CamelMessageInfo *info ;
	CamelGroupwiseMessageInfo *gw_info ;


	info = camel_groupwise_summary_parent->message_info_load(s,in) ;
	if (info) {
		gw_info = (CamelGroupwiseMessageInfo*) info ;
		if (camel_file_util_decode_uint32 (in, &gw_info->server_flags) == -1)
			goto error ;
	}

	return info ;
error:
	camel_message_info_free (info) ;
	return NULL ;
}
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 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;
}
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);
}