aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog47
-rw-r--r--camel/camel-file-utils.c112
-rw-r--r--camel/camel-file-utils.h2
-rw-r--r--camel/camel-folder-summary.c72
-rw-r--r--camel/camel-folder-summary.h7
-rw-r--r--camel/camel-operation.c9
-rw-r--r--camel/camel.c2
-rw-r--r--camel/providers/imap/camel-imap-store.c53
-rw-r--r--camel/providers/imap/camel-imap-summary.c28
-rw-r--r--camel/providers/imap/camel-imap-summary.h1
-rw-r--r--camel/providers/imapp/camel-imapp-summary.c26
-rw-r--r--camel/providers/imapp/camel-imapp-summary.h1
-rw-r--r--camel/providers/local/camel-local-summary.c38
-rw-r--r--camel/providers/local/camel-local-summary.h4
-rw-r--r--camel/providers/local/camel-maildir-store.c46
-rw-r--r--camel/providers/local/camel-mbox-store.c86
-rw-r--r--camel/providers/local/camel-mbox-summary.c17
-rw-r--r--camel/providers/local/camel-mbox-summary.h1
-rw-r--r--camel/providers/nntp/camel-nntp-summary.c24
-rw-r--r--camel/providers/nntp/camel-nntp-summary.h1
20 files changed, 437 insertions, 140 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 1330a2c001..d6eee1ea8a 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,50 @@
+2004-02-16 Not Zed <NotZed@Ximian.com>
+
+ ** See bug #51045.
+
+ * providers/imap/camel-imap-store.c (fill_fi): similar to mbox
+ version.
+ (get_folder_counts): use fill_fi to try and get folder counts if
+ we're not doing the hard slog.
+ (get_one_folder_offline): use fill_fi to try to get folder counts
+ from open folders or summaries.
+
+ * providers/local/camel-maildir-store.c (fill_fi): similar to mbox
+ version.
+ (scan_dir): use fill_fi to get the unread count now.
+
+ * providers/local/camel-mbox-store.c (fill_fi): helper to lookup
+ unread count either from active folder or from summary file, if
+ it's available.
+ (scan_dir, get_folder_info): use helper above to get folder info.
+
+ * devel-docs/camel-folder-summary.txt: New document describing the
+ format/conventions in the CamelFolderSummary file.
+
+ * providers/nntp/camel-nntp-summary.c (summary_header_load/save):
+ * providers/imapp/camel-imapp-summary.c (summary_header_load/save):
+ * providers/imap/camel-imap-summary.c (summary_header_load/save):
+ Handle versions, per-class version number (1).
+
+ * providers/local/camel-mbox-summary.c (summary_header_load/save):
+ Handle versions properly, add a per-class version (1). Write out the
+ folder size as a size_t rather than 32 bit int.
+
+ * providers/local/camel-local-summary.c (summary_header_load/save):
+ read/write the per-class version number (1).
+
+ * camel-folder-summary.c (summary_header_load): do version
+ checking differently, allow the version to be bumped without
+ aborting the load. Added unread/deleted/junk counts to base
+ header.
+ (summary_header_save): Save out the new-format header. Version
+ bumped to 13.
+
+ * camel.c (camel_init): return 0 rather than spit a compiler warning.
+
+ * camel-file-utils.c (camel_file_util_encode_*_t): macro-ise the
+ type encoder/decoders. Also add size_t encoder/decoder.
+
2004-02-13 Jeffrey Stedfast <fejj@ximian.com>
* providers/imap/camel-imap-store.c (get_folder_online): Same.
diff --git a/camel/camel-file-utils.c b/camel/camel-file-utils.c
index f4ed4cd22c..0d51795e32 100644
--- a/camel/camel-file-utils.c
+++ b/camel/camel-file-utils.c
@@ -144,6 +144,37 @@ camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest)
}
}
+#define CFU_ENCODE_T(type) \
+int \
+camel_file_util_encode_##type(FILE *out, type value) \
+{ \
+ int i; \
+ \
+ for (i = sizeof (type) - 1; i >= 0; i--) { \
+ if (fputc((value >> (i * 8)) & 0xff, out) == -1) \
+ return -1; \
+ } \
+ return 0; \
+}
+
+#define CFU_DECODE_T(type) \
+int \
+camel_file_util_decode_##type(FILE *in, type *dest) \
+{ \
+ type save = 0; \
+ int i = sizeof(type) - 1; \
+ int v = EOF; \
+ \
+ while (i >= 0 && (v = fgetc (in)) != EOF) { \
+ save |= ((type)v) << (i * 8); \
+ i--; \
+ } \
+ *dest = save; \
+ if (v == EOF) \
+ return -1; \
+ return 0; \
+}
+
/**
* camel_file_util_encode_time_t:
@@ -154,18 +185,7 @@ camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest)
*
* Return value: 0 on success, -1 on error.
**/
-int
-camel_file_util_encode_time_t(FILE *out, time_t value)
-{
- int i;
-
- for (i = sizeof (time_t) - 1; i >= 0; i--) {
- if (fputc((value >> (i * 8)) & 0xff, out) == -1)
- return -1;
- }
- return 0;
-}
-
+CFU_ENCODE_T(time_t)
/**
* camel_file_util_decode_time_t:
@@ -176,23 +196,7 @@ camel_file_util_encode_time_t(FILE *out, time_t value)
*
* Return value: 0 on success, -1 on error.
**/
-int
-camel_file_util_decode_time_t (FILE *in, time_t *dest)
-{
- time_t save = 0;
- int i = sizeof (time_t) - 1;
- int v = EOF;
-
- while (i >= 0 && (v = fgetc (in)) != EOF) {
- save |= ((time_t)v) << (i * 8);
- i--;
- }
- *dest = save;
- if (v == EOF)
- return -1;
- return 0;
-}
-
+CFU_DECODE_T(time_t)
/**
* camel_file_util_encode_off_t:
@@ -203,17 +207,7 @@ camel_file_util_decode_time_t (FILE *in, time_t *dest)
*
* Return value: 0 on success, -1 on error.
**/
-int
-camel_file_util_encode_off_t (FILE *out, off_t value)
-{
- int i;
-
- for (i = sizeof (off_t) - 1; i >= 0; i--) {
- if (fputc ((value >> (i * 8)) & 0xff, out) == -1)
- return -1;
- }
- return 0;
-}
+CFU_ENCODE_T(off_t)
/**
@@ -225,22 +219,30 @@ camel_file_util_encode_off_t (FILE *out, off_t value)
*
* Return value: 0 on success, -1 on failure.
**/
-int
-camel_file_util_decode_off_t (FILE *in, off_t *dest)
-{
- off_t save = 0;
- int i = sizeof(off_t) - 1;
- int v = EOF;
+CFU_DECODE_T(off_t)
- while (i >= 0 && (v = fgetc (in)) != EOF) {
- save |= ((off_t)v) << (i * 8);
- i--;
- }
- *dest = save;
- if (v == EOF)
- return -1;
- return 0;
-}
+/**
+ * camel_file_util_encode_size_t:
+ * @out: file to output to
+ * @value: value to output
+ *
+ * Encode an size_t type.
+ *
+ * Return value: 0 on success, -1 on error.
+ **/
+CFU_ENCODE_T(size_t)
+
+
+/**
+ * camel_file_util_decode_size_t:
+ * @in: file to read from
+ * @dest: pointer to a variable to put the value in
+ *
+ * Decode an size_t type.
+ *
+ * Return value: 0 on success, -1 on failure.
+ **/
+CFU_DECODE_T(size_t)
/**
diff --git a/camel/camel-file-utils.h b/camel/camel-file-utils.h
index 15022d99b3..1e37b2725a 100644
--- a/camel/camel-file-utils.h
+++ b/camel/camel-file-utils.h
@@ -45,6 +45,8 @@ int camel_file_util_encode_time_t (FILE *out, time_t);
int camel_file_util_decode_time_t (FILE *in, time_t *);
int camel_file_util_encode_off_t (FILE *out, off_t);
int camel_file_util_decode_off_t (FILE *in, off_t *);
+int camel_file_util_encode_size_t (FILE *out, size_t);
+int camel_file_util_decode_size_t (FILE *in, size_t *);
int camel_file_util_encode_string (FILE *out, const char *);
int camel_file_util_decode_string (FILE *in, char **);
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index 05b3f3a056..ac0ca87386 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -75,7 +75,7 @@ static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER;
extern int strdup_count, malloc_count, free_count;
#endif
-#define CAMEL_FOLDER_SUMMARY_VERSION (12)
+#define CAMEL_FOLDER_SUMMARY_VERSION (13)
#define _PRIVATE(o) (((CamelFolderSummary *)(o))->priv)
@@ -1403,45 +1403,81 @@ my_list_size(struct _node **list)
static int
summary_header_load(CamelFolderSummary *s, FILE *in)
{
- gint32 version, flags, nextuid, count;
- time_t time;
-
fseek(in, 0, SEEK_SET);
io(printf("Loading header\n"));
- if (camel_file_util_decode_fixed_int32(in, &version) == -1
- || camel_file_util_decode_fixed_int32(in, &flags) == -1
- || camel_file_util_decode_fixed_int32(in, &nextuid) == -1
- || camel_file_util_decode_time_t(in, &time) == -1
- || camel_file_util_decode_fixed_int32(in, &count) == -1) {
+ if (camel_file_util_decode_fixed_int32(in, &s->version) == -1)
return -1;
- }
- s->nextuid = nextuid;
- s->flags = flags;
- s->time = time;
- s->saved_count = count;
- if (s->version != version) {
- d(printf ("Summary header version mismatch"));
+ /* Legacy version check, before version 12 we have no upgrade knowledge */
+ if ((s->version > 0xff) && (s->version & 0xff) < 12) {
+ (printf ("Summary header version mismatch"));
errno = EINVAL;
return -1;
}
+
+ if (!(s->version < 0x100 && s->version >= 13))
+ printf("Loading legacy summary\n");
+ else
+ printf("loading new-format summary\n");
+
+ /* legacy version */
+ if (camel_file_util_decode_fixed_int32(in, &s->flags) == -1
+ || camel_file_util_decode_fixed_int32(in, &s->nextuid) == -1
+ || camel_file_util_decode_time_t(in, &s->time) == -1
+ || camel_file_util_decode_fixed_int32(in, &s->saved_count) == -1) {
+ return -1;
+ }
+
+ /* version 13 */
+ if (s->version < 0x100 && s->version >= 13
+ && (camel_file_util_decode_fixed_int32(in, &s->unread_count) == -1
+ || camel_file_util_decode_fixed_int32(in, &s->deleted_count) == -1
+ || camel_file_util_decode_fixed_int32(in, &s->junk_count) == -1)) {
+ return -1;
+ }
+
return 0;
}
static int
summary_header_save(CamelFolderSummary *s, FILE *out)
{
+ int unread = 0, deleted = 0, junk = 0, count, i;
+
fseek(out, 0, SEEK_SET);
io(printf("Savining header\n"));
- camel_file_util_encode_fixed_int32(out, s->version);
+ /* we always write out the current version */
+ camel_file_util_encode_fixed_int32(out, CAMEL_FOLDER_SUMMARY_VERSION);
camel_file_util_encode_fixed_int32(out, s->flags);
camel_file_util_encode_fixed_int32(out, s->nextuid);
camel_file_util_encode_time_t(out, s->time);
- return camel_file_util_encode_fixed_int32(out, camel_folder_summary_count(s));
+
+ count = camel_folder_summary_count(s);
+ for (i=0; i<count; i++) {
+ CamelMessageInfo *info = camel_folder_summary_index(s, i);
+
+ if (info == NULL)
+ continue;
+
+ if ((info->flags & CAMEL_MESSAGE_SEEN) == 0)
+ unread++;
+ if ((info->flags & CAMEL_MESSAGE_DELETED) != 0)
+ deleted++;
+ if ((info->flags & CAMEL_MESSAGE_JUNK) != 0)
+ junk++;
+
+ camel_folder_summary_info_free(s, info);
+ }
+
+ camel_file_util_encode_fixed_int32(out, count);
+ camel_file_util_encode_fixed_int32(out, unread);
+ camel_file_util_encode_fixed_int32(out, deleted);
+
+ return camel_file_util_encode_fixed_int32(out, junk);
}
/* are these even useful for anything??? */
diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h
index e57be75ae1..366df70395 100644
--- a/camel/camel-folder-summary.h
+++ b/camel/camel-folder-summary.h
@@ -160,11 +160,14 @@ struct _CamelFolderSummary {
struct _CamelFolderSummaryPrivate *priv;
/* header info */
- guint32 version; /* version of file required, should be set by implementors */
+ guint32 version; /* version of file loaded/loading */
guint32 flags; /* flags */
guint32 nextuid; /* next uid? */
- guint32 saved_count; /* how many were saved/loaded */
time_t time; /* timestamp for this summary (for implementors to use) */
+ guint32 saved_count; /* how many were saved/loaded */
+ guint32 unread_count; /* handy totals */
+ guint32 deleted_count;
+ guint32 junk_count;
/* sizes of memory objects */
guint32 message_info_size;
diff --git a/camel/camel-operation.c b/camel/camel-operation.c
index 03c0c77617..5e041a18cf 100644
--- a/camel/camel-operation.c
+++ b/camel/camel-operation.c
@@ -312,10 +312,11 @@ camel_operation_cancel (CamelOperation *cc)
* Register a thread or the main thread for cancellation through @cc.
* If @cc is NULL, then a new cancellation is created for this thread.
*
- * All calls to operation_register() should be matched with calls to
- * operation_unregister(), or resources will be lost.
+ * All calls to operation_register() should save their value and call
+ * operation_register again with that, to automatically stack
+ * registrations.
*
- * Return Value: Returns @cc, or if NULL, the new operation.
+ * Return Value: Returns the previously registered operatoin.
*
**/
CamelOperation *
@@ -332,7 +333,7 @@ camel_operation_register (CamelOperation *cc)
* camel_operation_unregister:
* @cc: operation context
*
- * Unregister the current thread.
+ * Unregister the current thread for all cancellations.
**/
void
camel_operation_unregister (CamelOperation *cc)
diff --git a/camel/camel.c b/camel/camel.c
index 8d60968705..44a894cfc0 100644
--- a/camel/camel.c
+++ b/camel/camel.c
@@ -74,7 +74,7 @@ camel_init (const char *configdir, gboolean nss_init)
void camel_operation_init(void);
if (initialised)
- return;
+ return 0;
if (getenv ("CAMEL_VERBOSE_DEBUG"))
camel_verbose_debug = TRUE;
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 7b86773b4c..4ca1b1d4bd 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -2349,6 +2349,48 @@ dumpfi(CamelFolderInfo *fi)
#endif
static void
+fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
+{
+ CamelFolder *folder;
+ int unread = -1;
+
+ folder = camel_object_bag_get(store->folders, fi->full_name);
+ if (folder) {
+ if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
+ camel_folder_refresh_info(folder, NULL);
+ unread = camel_folder_get_unread_message_count(folder);
+ camel_object_unref(folder);
+ } else {
+ char *storage_path, *folder_dir, *path;
+ CamelFolderSummary *s;
+
+ printf("looking up counts from '%s'\n", fi->full_name);
+
+ /* This is a lot of work for one path! */
+ storage_path = g_strdup_printf("%s/folders", ((CamelImapStore *)store)->storage_path);
+ folder_dir = e_path_to_physical(storage_path, fi->full_name);
+ path = g_strdup_printf("%s/summary", folder_dir);
+ s = (CamelFolderSummary *)camel_object_new(camel_imap_summary_get_type());
+ camel_folder_summary_set_build_content(s, TRUE);
+ camel_folder_summary_set_filename(s, path);
+ if (camel_folder_summary_header_load(s) != -1) {
+ unread = s->unread_count;
+ printf("loaded summary header unread = %d\n", unread);
+ } else {
+ printf("couldn't load summary header?\n");
+ }
+
+ g_free(storage_path);
+ g_free(folder_dir);
+ g_free(path);
+
+ camel_object_unref(s);
+ }
+
+ fi->unread_message_count = unread;
+}
+
+static void
get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelException *ex)
{
GSList *q;
@@ -2393,13 +2435,8 @@ get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelExceptio
CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
} else {
- /* since its cheap, get it if they're open */
- folder = camel_object_bag_get(CAMEL_STORE(imap_store)->folders, fi->full_name);
- if (folder) {
- fi->unread_message_count = camel_folder_get_unread_message_count(folder);
- camel_object_unref(folder);
- } else
- fi->unread_message_count = -1;
+ /* since its cheap, get it if they're open/consult summary file */
+ fill_fi((CamelStore *)imap_store, fi, 0);
}
if (fi->child)
@@ -2636,6 +2673,8 @@ get_one_folder_offline (const char *physical_path, const char *path, gpointer da
g_free(fi->url);
fi->url = camel_url_to_string (url, 0);
camel_url_free (url);
+ } else {
+ fill_fi((CamelStore *)imap_store, fi, 0);
}
g_ptr_array_add (folders, fi);
}
diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c
index dba1134fa1..bebc672866 100644
--- a/camel/providers/imap/camel-imap-summary.c
+++ b/camel/providers/imap/camel-imap-summary.c
@@ -35,7 +35,7 @@
#include "camel-imap-summary.h"
#include "camel-file-utils.h"
-#define CAMEL_IMAP_SUMMARY_VERSION (0x300)
+#define CAMEL_IMAP_SUMMARY_VERSION (1)
static int summary_header_load (CamelFolderSummary *, FILE *);
static int summary_header_save (CamelFolderSummary *, FILE *);
@@ -94,9 +94,6 @@ camel_imap_summary_init (CamelImapSummary *obj)
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof(CamelImapMessageInfo);
s->content_info_size = sizeof(CamelImapMessageContentInfo);
-
- /* and a unique file version */
- s->version += CAMEL_IMAP_SUMMARY_VERSION;
}
/**
@@ -125,7 +122,6 @@ camel_imap_summary_new (const char *filename)
return summary;
}
-
static int
summary_header_load (CamelFolderSummary *s, FILE *in)
{
@@ -134,7 +130,22 @@ summary_header_load (CamelFolderSummary *s, FILE *in)
if (camel_imap_summary_parent->summary_header_load (s, in) == -1)
return -1;
- return camel_file_util_decode_uint32 (in, &ims->validity);
+ /* Legacy version */
+ if (s->version == 0x30c)
+ return camel_file_util_decode_uint32(in, &ims->validity);
+
+ /* Version 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 (ims->version > CAMEL_IMAP_SUMMARY_VERSION) {
+ g_warning("Unkown summary version\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
}
static int
@@ -145,9 +156,10 @@ summary_header_save (CamelFolderSummary *s, FILE *out)
if (camel_imap_summary_parent->summary_header_save (s, out) == -1)
return -1;
- return camel_file_util_encode_uint32 (out, ims->validity);
-}
+ camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_SUMMARY_VERSION);
+ return camel_file_util_encode_fixed_int32(out, ims->validity);
+}
static CamelMessageInfo *
message_info_load (CamelFolderSummary *s, FILE *in)
diff --git a/camel/providers/imap/camel-imap-summary.h b/camel/providers/imap/camel-imap-summary.h
index 817e884408..fc54d8d0d8 100644
--- a/camel/providers/imap/camel-imap-summary.h
+++ b/camel/providers/imap/camel-imap-summary.h
@@ -55,6 +55,7 @@ typedef struct _CamelImapMessageInfo {
struct _CamelImapSummary {
CamelFolderSummary parent;
+ guint32 version;
guint32 validity;
};
diff --git a/camel/providers/imapp/camel-imapp-summary.c b/camel/providers/imapp/camel-imapp-summary.c
index a0df21bcb0..05f0ec55c7 100644
--- a/camel/providers/imapp/camel-imapp-summary.c
+++ b/camel/providers/imapp/camel-imapp-summary.c
@@ -35,7 +35,7 @@
#include "camel-imapp-summary.h"
#include <camel/camel-file-utils.h>
-#define CAMEL_IMAPP_SUMMARY_VERSION (0x1000)
+#define CAMEL_IMAPP_SUMMARY_VERSION (1)
static int summary_header_load(CamelFolderSummary *, FILE *);
static int summary_header_save(CamelFolderSummary *, FILE *);
@@ -119,8 +119,22 @@ summary_header_load(CamelFolderSummary *s, FILE *in)
if (camel_imapp_summary_parent->summary_header_load(s, in) == -1)
return -1;
- return camel_file_util_decode_uint32(in, &ims->uidvalidity);
-}
+ /* Legacy version */
+ if (s->version == 0x100c)
+ return camel_file_util_decode_uint32(in, &ims->uidvalidity);
+
+ if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1
+ || camel_file_util_decode_fixed_int32(in, &ims->uidvalidity) == -1)
+ return -1;
+
+ if (ims->version > CAMEL_IMAPP_SUMMARY_VERSION) {
+ g_warning("Unkown summary version\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
static int
summary_header_save(CamelFolderSummary *s, FILE *out)
@@ -130,7 +144,11 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
if (camel_imapp_summary_parent->summary_header_save(s, out) == -1)
return -1;
- return camel_file_util_encode_uint32(out, ims->uidvalidity);
+ if (camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_SUMMARY_VERSION) == -1
+ || camel_file_util_encode_fixed_int32(out, ims->uidvalidity) == -1)
+ return -1;
+
+ return 0;
}
diff --git a/camel/providers/imapp/camel-imapp-summary.h b/camel/providers/imapp/camel-imapp-summary.h
index e9783625f4..215ad2465a 100644
--- a/camel/providers/imapp/camel-imapp-summary.h
+++ b/camel/providers/imapp/camel-imapp-summary.h
@@ -50,6 +50,7 @@ typedef struct _CamelIMAPPMessageInfo {
struct _CamelIMAPPSummary {
CamelFolderSummary parent;
+ guint32 version;
guint32 uidvalidity;
};
diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c
index 42534b361d..a1f4831675 100644
--- a/camel/providers/local/camel-local-summary.c
+++ b/camel/providers/local/camel-local-summary.c
@@ -34,12 +34,16 @@
#include "camel-local-summary.h"
#include "camel/camel-mime-message.h"
#include "camel/camel-stream-null.h"
+#include "camel/camel-file-utils.h"
#define w(x)
#define io(x)
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
-#define CAMEL_LOCAL_SUMMARY_VERSION (0x200)
+#define CAMEL_LOCAL_SUMMARY_VERSION (1)
+
+static int summary_header_load (CamelFolderSummary *, FILE *);
+static int summary_header_save (CamelFolderSummary *, FILE *);
static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _camel_header_raw *);
@@ -81,6 +85,9 @@ camel_local_summary_class_init(CamelLocalSummaryClass *klass)
camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
+ sklass->summary_header_load = summary_header_load;
+ sklass->summary_header_save = summary_header_save;
+
sklass->message_info_new = message_info_new;
klass->load = local_summary_load;
@@ -577,6 +584,35 @@ local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelM
return 0;
}
+static int
+summary_header_load(CamelFolderSummary *s, FILE *in)
+{
+ CamelLocalSummary *cls = (CamelLocalSummary *)s;
+
+ /* We dont actually add our own headers, but version that we don't anyway */
+
+ if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_load(s, in) == -1)
+ return -1;
+
+ /* Legacy version, version is in summary only */
+ if ((s->version & 0xfff) == 0x20c)
+ return 0;
+
+ /* otherwise load the version number */
+ return camel_file_util_decode_fixed_int32(in, &cls->version);
+}
+
+static int
+summary_header_save(CamelFolderSummary *s, FILE *out)
+{
+ /*CamelLocalSummary *cls = (CamelLocalSummary *)s;*/
+
+ if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_save(s, out) == -1)
+ return -1;
+
+ return camel_file_util_encode_fixed_int32(out, CAMEL_LOCAL_SUMMARY_VERSION);
+}
+
static CamelMessageInfo *
message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h)
{
diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h
index 25d77e62c3..99a520f243 100644
--- a/camel/providers/local/camel-local-summary.h
+++ b/camel/providers/local/camel-local-summary.h
@@ -42,7 +42,9 @@ enum {
struct _CamelLocalSummary {
CamelFolderSummary parent;
-
+
+ guint32 version; /* file version being loaded */
+
char *folder_path; /* name of matching folder */
CamelIndex *index;
diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c
index 0eff01f1d2..df17bcd5d9 100644
--- a/camel/providers/local/camel-maildir-store.c
+++ b/camel/providers/local/camel-maildir-store.c
@@ -36,6 +36,7 @@
#include "camel-exception.h"
#include "camel-url.h"
#include "camel-private.h"
+#include "camel-maildir-summary.h"
#define d(x)
@@ -237,6 +238,45 @@ static CamelFolderInfo *camel_folder_info_new(const char *url, const char *full,
return fi;
}
+static void
+fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
+{
+ CamelFolder *folder;
+ int unread = -1;
+
+ folder = camel_object_bag_get(store->folders, fi->full_name);
+ if (folder) {
+ if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
+ camel_folder_refresh_info(folder, NULL);
+ unread = camel_folder_get_unread_message_count(folder);
+ camel_object_unref(folder);
+ } else {
+ char *path, *folderpath;
+ CamelFolderSummary *s;
+ const char *root;
+
+ printf("looking up counts from '%s'\n", fi->full_name);
+
+ /* This should be fast enough not to have to test for INFO_FAST */
+ root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store);
+ path = g_strdup_printf("%s/%s.ev-summary", root, fi->full_name);
+ folderpath = g_strdup_printf("%s/%s", root, fi->full_name);
+ s = (CamelFolderSummary *)camel_maildir_summary_new(path, folderpath, NULL);
+ if (camel_folder_summary_header_load(s) != -1) {
+ unread = s->unread_count;
+ printf("loaded summary header unread = %d\n", unread);
+ } else {
+ printf("couldn't load summary header?\n");
+ }
+
+ camel_object_unref(s);
+ g_free(folderpath);
+ g_free(path);
+ }
+
+ fi->unread_message_count = unread;
+}
+
/* used to find out where we've visited already */
struct _inode {
dev_t dnode;
@@ -316,8 +356,10 @@ static int scan_dir(CamelStore *store, GHashTable *visited, char *root, const ch
}
}
- fi = camel_folder_info_new(uri, path, base, unread);
-
+ fi = camel_folder_info_new(uri, path, base, -1);
+ /* fills the unread count */
+ fill_fi(store, fi, flags);
+
d(printf("found! uri = %s\n", fi->url));
d(printf(" full_name = %s\n name = '%s'\n", fi->full_name, fi->name));
diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c
index b1a5664c33..ef11791e8c 100644
--- a/camel/providers/local/camel-mbox-store.c
+++ b/camel/providers/local/camel-mbox-store.c
@@ -581,6 +581,47 @@ inode_free(void *k, void *v, void *d)
g_free(k);
}
+/* NB: duplicated in maildir store */
+static void
+fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
+{
+ CamelFolder *folder;
+ int unread = -1;
+
+ folder = camel_object_bag_get(store->folders, fi->full_name);
+ if (folder) {
+ if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
+ camel_folder_refresh_info(folder, NULL);
+ unread = camel_folder_get_unread_message_count(folder);
+ camel_object_unref(folder);
+ } else {
+ char *path, *folderpath;
+ CamelMboxSummary *mbs;
+ const char *root;
+
+ printf("looking up counts from '%s'\n", fi->full_name);
+
+ /* This should be fast enough not to have to test for INFO_FAST */
+ root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store);
+ path = camel_mbox_folder_get_meta_path(root, fi->full_name, ".ev-summary");
+ folderpath = camel_mbox_folder_get_full_path(root, fi->full_name);
+
+ mbs = (CamelMboxSummary *)camel_mbox_summary_new(path, folderpath, NULL);
+ if (camel_folder_summary_header_load((CamelFolderSummary *)mbs) != -1) {
+ unread = ((CamelFolderSummary *)mbs)->unread_count;
+ printf("loaded summary header unread = %d\n", unread);
+ } else {
+ printf("couldn't load summary header?\n");
+ }
+
+ camel_object_unref(mbs);
+ g_free(folderpath);
+ g_free(path);
+ }
+
+ fi->unread_message_count = unread;
+}
+
static CamelFolderInfo *
scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const char *root,
const char *name, guint32 flags, CamelException *ex)
@@ -603,9 +644,7 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
while ((dent = readdir(dir))) {
char *short_name, *full_name, *path, *ext;
- CamelFolder *folder;
struct stat st;
- int unread = -1;
if (dent->d_name[0] == '.')
continue;
@@ -636,17 +675,7 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
full_name = g_strdup_printf("%s/%s", name, short_name);
else
full_name = g_strdup(short_name);
-
- if (!S_ISDIR(st.st_mode)) {
- folder = camel_object_bag_get(store->folders, full_name);
- if (folder) {
- if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
- camel_folder_refresh_info(folder, NULL);
- unread = camel_folder_get_unread_message_count(folder);
- camel_object_unref(folder);
- }
- }
-
+
if ((fi = g_hash_table_lookup(folder_hash, short_name)) != NULL) {
g_free(short_name);
g_free(full_name);
@@ -654,7 +683,6 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
if (S_ISDIR(st.st_mode)) {
fi->flags =(fi->flags & ~CAMEL_FOLDER_NOCHILDREN) | CAMEL_FOLDER_CHILDREN;
} else {
- fi->unread_message_count = unread;
fi->flags &= ~CAMEL_FOLDER_NOSELECT;
if ((ext = strchr(fi->url, ';')) && !strncmp(ext, ";noselect=yes", 13))
memmove(ext, ext + 13, strlen(ext + 13) + 1);
@@ -669,7 +697,7 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
fi->name = short_name;
fi->full_name = full_name;
fi->path = g_strdup_printf("/%s", full_name);
- fi->unread_message_count = unread;
+ fi->unread_message_count = -1;
if (S_ISDIR(st.st_mode))
fi->flags = CAMEL_FOLDER_NOSELECT;
@@ -686,7 +714,9 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
g_hash_table_insert(folder_hash, fi->name, fi);
}
- if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) && S_ISDIR(st.st_mode)) {
+ if (!S_ISDIR(st.st_mode))
+ fill_fi(store, fi, flags);
+ else if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) {
struct _inode in = { st.st_dev, st.st_ino };
if (g_hash_table_lookup(visited, &in) == NULL) {
@@ -718,10 +748,8 @@ get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelExceptio
struct _inode *inode;
char *path, *subdir;
CamelFolderInfo *fi;
- CamelFolder *folder;
const char *base;
struct stat st;
- int unread = -1;
top = top ? top : "";
path = mbox_folder_name_to_path(store, top);
@@ -735,7 +763,7 @@ get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelExceptio
visited = g_hash_table_new(inode_hash, inode_equal);
- inode = g_new(struct _inode, 1);
+ inode = g_malloc0(sizeof(*inode));
inode->dnode = st.st_dev;
inode->inode = st.st_ino;
@@ -761,26 +789,22 @@ get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelExceptio
base = top;
else
base++;
-
- folder = camel_object_bag_get(store->folders, top);
- if (folder) {
- if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
- camel_folder_refresh_info(folder, NULL);
- unread = camel_folder_get_unread_message_count(folder);
- camel_object_unref(folder);
- }
-
+
fi = g_new0(CamelFolderInfo, 1);
fi->parent = NULL;
fi->url = g_strdup_printf("mbox:%s#%s",((CamelService *) store)->url->path, top);
fi->name = g_strdup(base);
fi->full_name = g_strdup(top);
- fi->unread_message_count = unread;
+ fi->unread_message_count = -1;
fi->path = g_strdup_printf("/%s", top);
subdir = g_strdup_printf("%s.sbd", path);
- if (stat(subdir, &st) == 0 && S_ISDIR(st.st_mode))
- fi->child = scan_dir(store, visited, fi, subdir, top, flags, ex);
+ if (stat(subdir, &st) == 0) {
+ if (S_ISDIR(st.st_mode))
+ fi->child = scan_dir(store, visited, fi, subdir, top, flags, ex);
+ else
+ fill_fi(store, fi, flags);
+ }
if (fi->child)
fi->flags |= CAMEL_FOLDER_CHILDREN;
diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c
index 4018fc93c9..ac87fd2476 100644
--- a/camel/providers/local/camel-mbox-summary.c
+++ b/camel/providers/local/camel-mbox-summary.c
@@ -44,7 +44,7 @@
#define io(x)
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
-#define CAMEL_MBOX_SUMMARY_VERSION (0x1000)
+#define CAMEL_MBOX_SUMMARY_VERSION (1)
static int summary_header_load (CamelFolderSummary *, FILE *);
static int summary_header_save (CamelFolderSummary *, FILE *);
@@ -172,7 +172,16 @@ summary_header_load(CamelFolderSummary *s, FILE *in)
if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_load(s, in) == -1)
return -1;
- return camel_file_util_decode_uint32(in, (guint32 *) &mbs->folder_size);
+ /* legacy version */
+ if (s->version == 0x120c)
+ return camel_file_util_decode_uint32(in, (guint32 *) &mbs->folder_size);
+
+ /* version 1 */
+ if (camel_file_util_decode_fixed_int32(in, &mbs->version) == -1
+ || camel_file_util_decode_size_t(in, &mbs->folder_size) == -1)
+ return -1;
+
+ return 0;
}
static int
@@ -183,7 +192,9 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_save(s, out) == -1)
return -1;
- return camel_file_util_encode_uint32(out, mbs->folder_size);
+ camel_file_util_encode_fixed_int32(out, CAMEL_MBOX_SUMMARY_VERSION);
+
+ return camel_file_util_encode_size_t(out, mbs->folder_size);
}
static CamelMessageInfo *
diff --git a/camel/providers/local/camel-mbox-summary.h b/camel/providers/local/camel-mbox-summary.h
index dc64aa23fa..34402ad264 100644
--- a/camel/providers/local/camel-mbox-summary.h
+++ b/camel/providers/local/camel-mbox-summary.h
@@ -48,6 +48,7 @@ struct _CamelMboxSummary {
CamelFolderChangeInfo *changes; /* used to build change sets */
+ guint32 version;
size_t folder_size; /* size of the mbox file, last sync */
unsigned int xstatus:1; /* do we store/honour xstatus/status headers */
diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c
index 2fa753bef1..6c9c7e54b8 100644
--- a/camel/providers/nntp/camel-nntp-summary.c
+++ b/camel/providers/nntp/camel-nntp-summary.c
@@ -48,7 +48,7 @@
extern int camel_verbose_debug;
#define dd(x) (camel_verbose_debug?(x):0)
-#define CAMEL_NNTP_SUMMARY_VERSION (0x200)
+#define CAMEL_NNTP_SUMMARY_VERSION (1)
static int xover_setup(CamelNNTPSummary *cns, CamelException *ex);
static int add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex);
@@ -191,8 +191,25 @@ summary_header_load(CamelFolderSummary *s, FILE *in)
{
CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
- if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_load(s, in) == -1
- || camel_file_util_decode_fixed_int32(in, &cns->high) == -1
+ if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_load(s, in) == -1)
+ return -1;
+
+ /* Legacy version */
+ if (s->version == 0x20c) {
+ camel_file_util_decode_fixed_int32(in, &cns->high);
+ return camel_file_util_decode_fixed_int32(in, &cns->low);
+ }
+
+ if (camel_file_util_decode_fixed_int32(in, &cns->version) == -1)
+ return -1;
+
+ if (cns->version > CAMEL_NNTP_SUMMARY_VERSION) {
+ g_warning("Unknown NNTP summary version");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (camel_file_util_decode_fixed_int32(in, &cns->high) == -1
|| camel_file_util_decode_fixed_int32(in, &cns->low) == -1)
return -1;
@@ -205,6 +222,7 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_save(s, out) == -1
+ || camel_file_util_encode_fixed_int32(out, CAMEL_NNTP_SUMMARY_VERSION) == -1
|| camel_file_util_encode_fixed_int32(out, cns->high) == -1
|| camel_file_util_encode_fixed_int32(out, cns->low) == -1)
return -1;
diff --git a/camel/providers/nntp/camel-nntp-summary.h b/camel/providers/nntp/camel-nntp-summary.h
index 9db3297da7..b89ffe9209 100644
--- a/camel/providers/nntp/camel-nntp-summary.h
+++ b/camel/providers/nntp/camel-nntp-summary.h
@@ -39,6 +39,7 @@ struct _CamelNNTPSummary {
struct _CamelNNTPFolder *folder;
+ guint32 version;
guint32 high, low;
};