diff options
-rw-r--r-- | camel/ChangeLog | 47 | ||||
-rw-r--r-- | camel/camel-file-utils.c | 112 | ||||
-rw-r--r-- | camel/camel-file-utils.h | 2 | ||||
-rw-r--r-- | camel/camel-folder-summary.c | 72 | ||||
-rw-r--r-- | camel/camel-folder-summary.h | 7 | ||||
-rw-r--r-- | camel/camel-operation.c | 9 | ||||
-rw-r--r-- | camel/camel.c | 2 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 53 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-summary.c | 28 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-summary.h | 1 | ||||
-rw-r--r-- | camel/providers/imapp/camel-imapp-summary.c | 26 | ||||
-rw-r--r-- | camel/providers/imapp/camel-imapp-summary.h | 1 | ||||
-rw-r--r-- | camel/providers/local/camel-local-summary.c | 38 | ||||
-rw-r--r-- | camel/providers/local/camel-local-summary.h | 4 | ||||
-rw-r--r-- | camel/providers/local/camel-maildir-store.c | 46 | ||||
-rw-r--r-- | camel/providers/local/camel-mbox-store.c | 86 | ||||
-rw-r--r-- | camel/providers/local/camel-mbox-summary.c | 17 | ||||
-rw-r--r-- | camel/providers/local/camel-mbox-summary.h | 1 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-summary.c | 24 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-summary.h | 1 |
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; }; |