diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/broken-date-parser.c ./broken-date-parser.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/broken-date-parser.c 2007-05-12 09:58:58.000000000 +0200 +++ ./broken-date-parser.c 2007-05-12 10:01:18.000000000 +0200 @@ -122,7 +122,7 @@ const unsigned char *start, *end; unsigned int mask; - start = date; + start = (const unsigned char *)date; while (*start) { /* kill leading whitespace */ while (*start && isspace ((int) *start)) @@ -195,7 +195,7 @@ return -1; for (wday = 0; wday < 7; wday++) - if (!g_ascii_strncasecmp (in, tm_days[wday], 3)) + if (!g_ascii_strncasecmp ((const char *)in, tm_days[wday], 3)) return wday; return -1; /* unknown week day */ @@ -223,7 +223,7 @@ return -1; for (i = 0; i < 12; i++) - if (!g_ascii_strncasecmp (in, tm_months[i], 3)) + if (!g_ascii_strncasecmp ((const char*)in, tm_months[i], 3)) return i; return -1; /* unknown month */ @@ -313,7 +313,7 @@ if (len != inlen) continue; - if (!strncmp (inptr, tz_offsets[t].name, len)) + if (!strncmp ((const char*)inptr, tz_offsets[t].name, len)) return tz_offsets[t].offset; } } Only in .: broken-date-parser.lo Only in .: broken-date-parser.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-address.c ./camel-address.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-address.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-address.c 2007-03-11 16:44:11.000000000 +0100 @@ -233,7 +233,7 @@ void camel_address_remove (CamelAddress *addr, int index) { - g_return_if_fail(CAMEL_IS_ADDRESS(addr)); + /* g_return_if_fail(CAMEL_IS_ADDRESS(addr)); */ if (index == -1) { for (index = addr->addresses->len; index>-1; index--) Only in .: camel-address.lo Only in .: camel-address.o Only in .: camel-arg.lo Only in .: camel-arg.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-block-file.c ./camel-block-file.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-block-file.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-block-file.c 2007-05-12 10:01:18.000000000 +0200 @@ -564,7 +564,7 @@ bl = g_malloc0(sizeof(*bl)); bl->id = id; if (lseek(bs->fd, id, SEEK_SET) == -1 || - camel_read (bs->fd, bl->data, CAMEL_BLOCK_SIZE) == -1) { + camel_read (bs->fd, (char*)bl->data, CAMEL_BLOCK_SIZE) == -1) { block_file_unuse(bs); CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock); g_free(bl); Only in .: camel-block-file.lo Only in .: camel-block-file.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel.c ./camel.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel.c 2007-05-12 10:01:18.000000000 +0200 @@ -81,7 +81,7 @@ if (initialised) return 0; - bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); camel_debug_init(); diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-certdb.c ./camel-certdb.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-certdb.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-certdb.c 2007-05-12 10:01:18.000000000 +0200 @@ -112,14 +112,11 @@ certdb->cert_size = sizeof (CamelCert); - certdb->cert_chunks = NULL; - certdb->certs = g_ptr_array_new (); certdb->cert_hash = g_hash_table_new (g_str_hash, g_str_equal); certdb->priv->db_lock = g_mutex_new (); certdb->priv->io_lock = g_mutex_new (); - certdb->priv->alloc_lock = g_mutex_new (); certdb->priv->ref_lock = g_mutex_new (); } @@ -140,12 +137,8 @@ g_free (certdb->filename); - if (certdb->cert_chunks) - e_memchunk_destroy (certdb->cert_chunks); - g_mutex_free (p->db_lock); g_mutex_free (p->io_lock); - g_mutex_free (p->alloc_lock); g_mutex_free (p->ref_lock); g_free (p); @@ -478,10 +471,7 @@ { CamelCert *cert; - if (certdb->cert_chunks) - cert = e_memchunk_alloc0 (certdb->cert_chunks); - else - cert = g_malloc0 (certdb->cert_size); + cert = g_slice_alloc0 (certdb->cert_size); cert->refcount = 1; @@ -491,17 +481,9 @@ CamelCert * camel_certdb_cert_new (CamelCertDB *certdb) { - CamelCert *cert; - g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL); - - CAMEL_CERTDB_LOCK (certdb, alloc_lock); - - cert = CAMEL_CERTDB_GET_CLASS (certdb)->cert_new (certdb); - - CAMEL_CERTDB_UNLOCK (certdb, alloc_lock); - - return cert; + + return CAMEL_CERTDB_GET_CLASS (certdb)->cert_new (certdb); } void @@ -536,10 +518,7 @@ if (cert->refcount <= 1) { CAMEL_CERTDB_GET_CLASS (certdb)->cert_free (certdb, cert); - if (certdb->cert_chunks) - e_memchunk_free (certdb->cert_chunks, cert); - else - g_free (cert); + g_slice_free1(certdb->cert_size, cert); } else { cert->refcount--; } diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-certdb.h ./camel-certdb.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-certdb.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-certdb.h 2007-05-12 10:01:18.000000000 +0200 @@ -79,8 +79,6 @@ guint32 cert_size; - struct _EMemChunk *cert_chunks; - GPtrArray *certs; GHashTable *cert_hash; }; Only in .: camel-certdb.lo Only in .: camel-certdb.o Only in .: camel-charset-map.lo Only in .: camel-charset-map.o Only in .: camel-cipher-context.lo Only in .: camel-cipher-context.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-data-cache.c ./camel-data-cache.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-data-cache.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-data-cache.c 2007-05-12 10:01:18.000000000 +0200 @@ -132,7 +132,7 @@ { CamelDataCache *cdc; - if (g_mkdir_with_parents (path, 0700) == -1) { + if (e_util_mkdir_hier (path, 0700) == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unable to create cache path")); return NULL; @@ -227,6 +227,84 @@ g_dir_close(dir); } + +void +camel_data_cache_set_flags (CamelDataCache *cdc, const char *path, CamelMessageInfoBase *mi) +{ + char mystring [512]; + guint32 hash; + hash = g_str_hash(mi->uid); + hash = (hash>>5)&CAMEL_DATA_CACHE_MASK; + + snprintf (mystring, 512, "%s/%s/%02x/%s", cdc->path, path, hash, mi->uid); + + if (g_file_test (mystring, G_FILE_TEST_IS_REGULAR)) + { + mi->flags |= CAMEL_MESSAGE_CACHED; + snprintf (mystring, 512, "%s/%s/%02x/%s.ispartial", cdc->path, path, hash, mi->uid); + if (g_file_test (mystring, G_FILE_TEST_IS_REGULAR)) + mi->flags |= CAMEL_MESSAGE_PARTIAL; + else + mi->flags &= ~CAMEL_MESSAGE_PARTIAL; + } else { + mi->flags &= ~CAMEL_MESSAGE_CACHED; + mi->flags &= ~CAMEL_MESSAGE_PARTIAL; + } +} + +gboolean +camel_data_cache_is_partial (CamelDataCache *cdc, const char *path, + const char *uid) +{ + gboolean retval = FALSE; + gchar *mpath; char *dir; + guint32 hash; + hash = g_str_hash(uid); + hash = (hash>>5)&CAMEL_DATA_CACHE_MASK; + dir = alloca(strlen(cdc->path) + strlen(path) + 8); + sprintf(dir, "%s/%s/%02x", cdc->path, path, hash); + + mpath = g_strdup_printf ("%s/%s.ispartial", dir, uid); + + retval = g_file_test (mpath, G_FILE_TEST_IS_REGULAR); + + g_free (mpath); + + return retval; +} + + +void +camel_data_cache_set_partial (CamelDataCache *cdc, const char *path, + const char *uid, gboolean partial) +{ + int fd; char *dir; + gchar *mpath; + guint32 hash; + hash = g_str_hash(uid); + hash = (hash>>5)&CAMEL_DATA_CACHE_MASK; + dir = alloca(strlen(cdc->path) + strlen(path) + 8); + sprintf(dir, "%s/%s/%02x", cdc->path, path, hash); + + mpath = g_strdup_printf ("%s/%s.ispartial", dir, uid); + + if (!partial) + { + if (g_file_test (mpath, G_FILE_TEST_IS_REGULAR)) + g_unlink (mpath); + } else { + if (!g_file_test (mpath, G_FILE_TEST_IS_REGULAR)) + { + fd = g_open (mpath, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600); + if (fd) close (fd); + } + } + + g_free (mpath); + +} + + /* Since we have to stat the directory anyway, we use this opportunity to lazily expire old data. If it is this directories 'turn', and we haven't done it for CYCLE_TIME seconds, @@ -248,7 +326,7 @@ if (access (dir, F_OK) == -1) { #endif if (create) - g_mkdir_with_parents (dir, 0700); + e_util_mkdir_hier (dir, 0700); } else if (cdc->priv->expire_inc == hash && (cdc->expire_age != -1 || cdc->expire_access != -1)) { time_t now; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-data-cache.h ./camel-data-cache.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-data-cache.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-data-cache.h 2007-05-12 10:00:17.000000000 +0200 @@ -28,6 +28,7 @@ #include #include +#include #define CAMEL_DATA_CACHE_TYPE (camel_data_cache_get_type ()) #define CAMEL_DATA_CACHE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_DATA_CACHE_TYPE, CamelFolder)) @@ -85,6 +86,15 @@ int camel_data_cache_clear(CamelDataCache *cache, const char *path, CamelException *ex); + +gboolean camel_data_cache_is_partial (CamelDataCache *cache, const char *path, + const char *uid); + +void camel_data_cache_set_partial (CamelDataCache *cache, const char *path, + const char *uid, gboolean partial); + +void camel_data_cache_set_flags (CamelDataCache *cdc, const char *path, CamelMessageInfoBase *mi); + /* Standard Camel function */ CamelType camel_data_cache_get_type (void); Only in .: camel-data-cache.lo Only in .: camel-data-cache.o Only in .: camel-data-wrapper.lo Only in .: camel-data-wrapper.o Only in .: camel-debug.lo Only in .: camel-debug.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-digest-folder.c ./camel-digest-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-digest-folder.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-digest-folder.c 2007-05-12 10:01:18.000000000 +0200 @@ -53,7 +53,7 @@ /* message manipulation */ static CamelMimeMessage *digest_get_message (CamelFolder *folder, const gchar *uid, - CamelException *ex); + CamelFolderReceiveType type, gint param, CamelException *ex); static void digest_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex); static void digest_transfer_messages_to (CamelFolder *source, GPtrArray *uids, @@ -282,7 +282,7 @@ } static CamelMimeMessage * -digest_get_message (CamelFolder *folder, const char *uid, CamelException *ex) +digest_get_message (CamelFolder *folder, const char *uid, CamelFolderReceiveType type, gint param, CamelException *ex) { CamelDigestFolder *digest = CAMEL_DIGEST_FOLDER (folder); CamelDataWrapper *wrapper; @@ -290,6 +290,9 @@ CamelMimePart *part; char *subuid; int id; + + /* TNY TODO: Implement partial message retrieval if full==TRUE + (after figuring out what a digest folder does, of course) */ part = CAMEL_MIME_PART (digest->priv->message); wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part)); Only in .: camel-digest-folder.lo Only in .: camel-digest-folder.o Only in .: camel-digest-store.lo Only in .: camel-digest-store.o Only in .: camel-digest-summary.lo Only in .: camel-digest-summary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-disco-diary.c ./camel-disco-diary.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-disco-diary.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-disco-diary.c 2007-05-12 10:01:18.000000000 +0200 @@ -285,7 +285,6 @@ { guint32 action; off_t size; - double pc; d(printf("disco diary replay\n")); @@ -296,8 +295,7 @@ camel_operation_start (NULL, _("Resynchronizing with server")); while (!camel_exception_is_set (ex)) { - pc = ftell (diary->file) / size; - camel_operation_progress (NULL, pc * 100); + camel_operation_progress (NULL, ftell (diary->file) , size); if (camel_file_util_decode_uint32 (diary->file, &action) == -1) break; @@ -337,7 +335,8 @@ continue; } - message = camel_folder_get_message (folder, uid, NULL); + /* TNY TODO Partial message retrieval exception */ + message = camel_folder_get_message (folder, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); if (!message) { /* The message was appended and then deleted. */ g_free (uid); Only in .: camel-disco-diary.lo Only in .: camel-disco-diary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-disco-folder.c ./camel-disco-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-disco-folder.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-disco-folder.c 2007-05-12 10:01:18.000000000 +0200 @@ -106,9 +106,8 @@ if (m->changes) { for (i=0;ichanges->uid_added->len;i++) { - int pc = i * 100 / m->changes->uid_added->len; - - camel_operation_progress(NULL, pc); + + camel_operation_progress(NULL, i, m->changes->uid_added->len); camel_disco_folder_cache_message((CamelDiscoFolder *)m->folder, m->changes->uid_added->pdata[i], &mm->ex); @@ -478,10 +477,9 @@ } for (i = 0; i < uids->len; i++) { - int pc = i * 100 / uids->len; - + camel_disco_folder_cache_message (disco_folder, uids->pdata[i], ex); - camel_operation_progress(NULL, pc); + camel_operation_progress(NULL, i, uids->len); if (camel_exception_is_set (ex)) break; } Only in .: camel-disco-folder.lo Only in .: camel-disco-folder.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-disco-store.c ./camel-disco-store.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-disco-store.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-disco-store.c 2007-05-12 10:01:18.000000000 +0200 @@ -256,12 +256,12 @@ return CDS_CLASS (store)->get_folder_info_online (store, top, flags, ex); case CAMEL_DISCO_STORE_OFFLINE: - /* Can't edit subscriptions while offline */ + /* Can't edit subscriptions while offline if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) && !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) { camel_disco_store_check_online (disco_store, ex); return NULL; - } + }*/ return CDS_CLASS (store)->get_folder_info_offline (store, top, flags, ex); Only in .: camel-disco-store.lo Only in .: camel-disco-store.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-exception.c ./camel-exception.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-exception.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-exception.c 2007-05-12 10:01:18.000000000 +0200 @@ -39,16 +39,6 @@ /* dont turn this off */ #define w(x) x -/* i dont know why gthread_mutex stuff even exists, this is easier */ - -/* also, i'm not convinced mutexes are needed here. But it - doesn't really hurt either */ -static pthread_mutex_t exception_mutex = PTHREAD_MUTEX_INITIALIZER; - -#define CAMEL_EXCEPTION_LOCK(e) (pthread_mutex_lock(&exception_mutex)) -#define CAMEL_EXCEPTION_UNLOCK(e) (pthread_mutex_unlock(&exception_mutex)) - -static EMemChunk *exception_chunks = NULL; /** * camel_exception_new: allocate a new exception object. @@ -62,19 +52,12 @@ { CamelException *ex; - CAMEL_EXCEPTION_LOCK(exception); - - if (exception_chunks == NULL) - exception_chunks = e_memchunk_new(16, sizeof(CamelException)); - - ex = e_memchunk_alloc(exception_chunks); + ex = g_slice_new (CamelException); ex->desc = NULL; /* set the Exception Id to NULL */ ex->id = CAMEL_EXCEPTION_NONE; - CAMEL_EXCEPTION_UNLOCK(exception); - return ex; } @@ -109,14 +92,10 @@ if (!exception) return; - CAMEL_EXCEPTION_LOCK(exception); - if (exception->desc) g_free (exception->desc); exception->desc = NULL; exception->id = CAMEL_EXCEPTION_NONE; - - CAMEL_EXCEPTION_UNLOCK(exception); } /** @@ -135,11 +114,7 @@ if (exception->desc) g_free (exception->desc); - CAMEL_EXCEPTION_LOCK(exception); - - e_memchunk_free(exception_chunks, exception); - - CAMEL_EXCEPTION_UNLOCK(exception); + g_slice_free (CamelException, exception); } /** @@ -161,20 +136,13 @@ { if (camel_debug("exception")) printf("CamelException.set(%p, %u, '%s')\n", ex, id, desc); - if (!ex) return; - - CAMEL_EXCEPTION_LOCK(exception); - ex->id = id; - if (desc != ex->desc) { g_free (ex->desc); ex->desc = g_strdup (desc); } - - CAMEL_EXCEPTION_UNLOCK(exception); } /** @@ -215,13 +183,9 @@ return; } - CAMEL_EXCEPTION_LOCK(exception); - g_free(ex->desc); ex->desc = desc; ex->id = id; - - CAMEL_EXCEPTION_UNLOCK(exception); } /** @@ -248,8 +212,6 @@ return; } - CAMEL_EXCEPTION_LOCK(exception); - if (ex_dst->desc) g_free (ex_dst->desc); @@ -258,8 +220,6 @@ ex_src->desc = NULL; ex_src->id = CAMEL_EXCEPTION_NONE; - - CAMEL_EXCEPTION_UNLOCK(exception); } /** Only in .: camel-exception.lo Only in .: camel-exception.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-file-utils.c ./camel-file-utils.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-file-utils.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-file-utils.c 2007-05-12 10:01:18.000000000 +0200 @@ -47,137 +47,120 @@ #include "camel-operation.h" #include "camel-url.h" -#define IO_TIMEOUT (60*4) +#define IO_TIMEOUT (15*4) + /** - * camel_file_util_encode_uint32: + * camel_file_util_encode_fixed_int32: * @out: file to output to * @value: value to output * - * Utility function to save an uint32 to a file. + * Encode a gint32, performing no compression, but converting + * to network order. * * Return value: 0 on success, -1 on error. **/ int -camel_file_util_encode_uint32 (FILE *out, guint32 value) +camel_file_util_encode_fixed_int32 (FILE *out, gint32 value) { - int i; + guint32 save; - for (i = 28; i > 0; i -= 7) { - if (value >= (1 << i)) { - unsigned int c = (value >> i) & 0x7f; - if (fputc (c, out) == -1) - return -1; - } - } - return fputc (value | 0x80, out); + save = g_htonl (value); + if (fwrite (&save, sizeof (save), 1, out) != 1) + return -1; + return 0; } /** - * camel_file_util_decode_uint32: + * camel_file_util_decode_fixed_int32: * @in: file to read from * @dest: pointer to a variable to store the value in * - * Retrieve an encoded uint32 from a file. + * Retrieve a gint32. * - * Return value: 0 on success, -1 on error. @*dest will contain the - * decoded value. + * Return value: 0 on success, -1 on error. **/ int -camel_file_util_decode_uint32 (FILE *in, guint32 *dest) +camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest) { - guint32 value = 0; - int v; + guint32 save; - /* until we get the last byte, keep decoding 7 bits at a time */ - while ( ((v = fgetc (in)) & 0x80) == 0 && v!=EOF) { - value |= v; - value <<= 7; - } - if (v == EOF) { - *dest = value >> 7; + if (fread (&save, sizeof (save), 1, in) == 1) { + *dest = g_ntohl (save); + return 0; + } else { return -1; } - *dest = value | (v & 0x7f); - - return 0; } /** - * camel_file_util_encode_fixed_int32: + * camel_file_util_encode_uint32: * @out: file to output to * @value: value to output * - * Encode a gint32, performing no compression, but converting - * to network order. + * Utility function to save an uint32 to a file. * * Return value: 0 on success, -1 on error. **/ int -camel_file_util_encode_fixed_int32 (FILE *out, gint32 value) +camel_file_util_encode_uint32 (FILE *out, guint32 value) { - guint32 save; - - save = g_htonl (value); - if (fwrite (&save, sizeof (save), 1, out) != 1) - return -1; - return 0; + return camel_file_util_encode_fixed_int32 (out, value); } /** - * camel_file_util_decode_fixed_int32: + * camel_file_util_decode_uint32: * @in: file to read from * @dest: pointer to a variable to store the value in * - * Retrieve a gint32. + * Retrieve an encoded uint32 from a file. * - * Return value: 0 on success, -1 on error. + * Return value: 0 on success, -1 on error. @*dest will contain the + * decoded value. **/ int -camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest) +camel_file_util_decode_uint32 (FILE *in, guint32 *dest) { - guint32 save; + return camel_file_util_decode_fixed_int32 (in, (gint32*)dest); +} - if (fread (&save, sizeof (save), 1, in) == 1) { - *dest = g_ntohl (save); - return 0; - } else { - return -1; - } + +unsigned char* +camel_file_util_mmap_decode_uint32 (unsigned char *start, guint32 *dest, gboolean is_string) +{ + guint32 value = 0; + value = g_ntohl(get_unaligned_u32(start)); start += 4; + *dest = value; + return start; +} + + +/* This casting should be okay, because it also gets BOTH written and read from + the file using a 4 byte integer. */ + +#define CFU_ENCODE_T(type) \ +int \ +camel_file_util_encode_##type(FILE *out, type value) \ +{ \ + return camel_file_util_encode_fixed_int32 (out, (guint32) value); \ } -#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; \ +#define CFU_DECODE_T(type) \ +int \ +camel_file_util_decode_##type(FILE *in, type *dest) \ +{ \ + return camel_file_util_decode_fixed_int32 (in, (gint32*) dest); \ +} + + +#define MMAP_DECODE_T(type) \ +unsigned char* \ +camel_file_util_mmap_decode_##type(unsigned char *start, type *dest) \ +{ \ + return camel_file_util_mmap_decode_uint32 (start, (guint32*) dest, FALSE); \ } @@ -202,6 +185,7 @@ * Return value: 0 on success, -1 on error. **/ CFU_DECODE_T(time_t) +MMAP_DECODE_T(time_t) /** * camel_file_util_encode_off_t: @@ -225,6 +209,7 @@ * Return value: 0 on success, -1 on failure. **/ CFU_DECODE_T(off_t) +MMAP_DECODE_T(off_t) /** * camel_file_util_encode_size_t: @@ -248,6 +233,7 @@ * Return value: 0 on success, -1 on failure. **/ CFU_DECODE_T(size_t) +MMAP_DECODE_T(size_t) /** @@ -262,18 +248,31 @@ int camel_file_util_encode_string (FILE *out, const char *str) { - register int len; + register int lena, len; + + if (str == NULL) { + if (camel_file_util_encode_uint32 (out, 0) == -1) + return -1; - if (str == NULL) - return camel_file_util_encode_uint32 (out, 1); - - if ((len = strlen (str)) > 65536) - len = 65536; - - if (camel_file_util_encode_uint32 (out, len+1) == -1) - return -1; - if (len == 0 || fwrite (str, len, 1, out) == 1) return 0; + } + + lena = len = strlen (str) + 1; + + if (lena % G_MEM_ALIGN) + lena += G_MEM_ALIGN - (lena % G_MEM_ALIGN); + + if (camel_file_util_encode_uint32 (out, lena) == -1) + return -1; + + if (fwrite (str, len, 1, out) == 1) { + if (lena > len) { + if (fwrite ("\0\0\0\0\0\0\0\0", lena-len, 1, out) == 1) + return 0; + else return -1; + } else return 0; + } + return -1; } @@ -298,12 +297,6 @@ return -1; } - len--; - if (len > 65536) { - *str = NULL; - return -1; - } - ret = g_malloc (len+1); if (len > 0 && fread (ret, len, 1, in) != 1) { g_free (ret); @@ -313,6 +306,7 @@ ret[len] = 0; *str = ret; + return 0; } @@ -487,6 +481,46 @@ return nread; } +ssize_t +camel_read_nb (int fd, char *buf, size_t n) +{ + ssize_t nread; + + int errnosav, flags, fdmax; + fd_set rdset; + + flags = fcntl (fd, F_GETFL); + fcntl (fd, F_SETFL, flags | O_NONBLOCK); + + do { + struct timeval tv; + int res; + + FD_ZERO (&rdset); + FD_SET (fd, &rdset); + fdmax = fd + 1; + tv.tv_sec = 0; + tv.tv_usec = 0; + nread = -1; + + res = select(fdmax, &rdset, 0, 0, &tv); + if (res == -1) + ; + else if (res == 0) + errno = ETIMEDOUT; + else { + do { + nread = read (fd, buf, n); + } while (0 && (nread == -1 && errno == EINTR)); + } + } while (0 && (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))); + + errnosav = errno; + fcntl (fd, F_SETFL, flags); + errno = errnosav; + + return nread; +} /** * camel_write: @@ -543,7 +577,7 @@ FD_SET (fd, &wrset); FD_SET (cancel_fd, &rdset); tv.tv_sec = IO_TIMEOUT; - tv.tv_usec = 0; + tv.tv_usec = 0; w = -1; res = select (fdmax, &rdset, &wrset, 0, &tv); @@ -611,7 +645,7 @@ if (cancel_fd == -1) { do { nread = recv (fd, buf, n, 0); - } while (nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK); + } while ((nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)); } else { int fdmax; fd_set rdset; @@ -641,7 +675,64 @@ } else { nread = recv (fd, buf, n, 0); } - } while (nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK); + } while ((nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK)); + failed: + ; + } + + return nread; +#endif +} + +ssize_t +camel_read_socket_nb (int fd, char *buf, size_t n) +{ +#ifndef G_OS_WIN32 + return camel_read_nb (fd, buf, n); +#else + ssize_t nread; + int cancel_fd; + + if (camel_operation_cancel_check (NULL)) { + errno = EINTR; + return -1; + } + cancel_fd = camel_operation_cancel_fd (NULL); + + if (cancel_fd == -1) { + do { + nread = recv (fd, buf, n, 0); + } while (0&&(nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)); + } else { + int fdmax; + fd_set rdset; + u_long yes = 1; + + ioctlsocket (fd, FIONBIO, &yes); + fdmax = MAX (fd, cancel_fd) + 1; + do { + struct timeval tv; + int res; + + FD_ZERO (&rdset); + FD_SET (fd, &rdset); + FD_SET (cancel_fd, &rdset); + tv.tv_sec = IO_TIMEOUT; + tv.tv_usec = 0; + nread = -1; + + res = select(fdmax, &rdset, 0, 0, &tv); + if (res == -1) + ; + else if (res == 0) + errno = ETIMEDOUT; + else if (FD_ISSET (cancel_fd, &rdset)) { + errno = EINTR; + goto failed; + } else { + nread = recv (fd, buf, n, 0); + } + } while (0&&(nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK)); failed: ; } @@ -702,7 +793,7 @@ FD_SET (fd, &wrset); FD_SET (cancel_fd, &rdset); tv.tv_sec = IO_TIMEOUT; - tv.tv_usec = 0; + tv.tv_usec = 0; w = -1; res = select (fdmax, &rdset, &wrset, 0, &tv); diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-file-utils.h ./camel-file-utils.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-file-utils.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-file-utils.h 2007-05-12 10:01:18.000000000 +0200 @@ -43,6 +43,7 @@ int camel_file_util_decode_fixed_int32 (FILE *in, gint32 *); int camel_file_util_encode_uint32 (FILE *out, guint32); int camel_file_util_decode_uint32 (FILE *in, guint32 *); + 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); @@ -55,6 +56,11 @@ int camel_file_util_decode_fixed_string (FILE *in, char **str, size_t len); +unsigned char* camel_file_util_mmap_decode_time_t(unsigned char *start, time_t *dest); +unsigned char* camel_file_util_mmap_decode_off_t(unsigned char *start, off_t *dest); +unsigned char* camel_file_util_mmap_decode_size_t(unsigned char *start, size_t *dest); +unsigned char* camel_file_util_mmap_decode_uint32 (unsigned char *start, guint32 *dest, gboolean is_string); + char *camel_file_util_safe_filename (const char *name); /* Code that intends to be portable to Win32 should use camel_read() @@ -70,8 +76,15 @@ ssize_t camel_read_socket (int fd, char *buf, size_t n); ssize_t camel_write_socket (int fd, const char *buf, size_t n); +ssize_t camel_read_socket_nb (int fd, char *buf, size_t n); + char *camel_file_util_savename(const char *filename); +#define get_unaligned_u32(p) ((((unsigned char*)(p))[0]) | \ + (((unsigned char*)(p))[1] << 8) | \ + (((unsigned char*)(p))[2] << 16) | \ + (((unsigned char*)(p))[3] << 24)) + G_END_DECLS #endif /* CAMEL_FILE_UTILS_H */ Only in .: camel-file-utils.lo Only in .: camel-file-utils.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-filter-driver.c ./camel-filter-driver.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-filter-driver.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-filter-driver.c 2007-05-12 10:01:18.000000000 +0200 @@ -486,8 +486,9 @@ camel_folder_transfer_messages_to (p->source, uids, outbox, NULL, FALSE, p->ex); g_ptr_array_free (uids, TRUE); } else { + /* TNY TODO: Partial message retrieval exception */ if (p->message == NULL) - p->message = camel_folder_get_message (p->source, p->uid, p->ex); + p->message = camel_folder_get_message (p->source, p->uid, CAMEL_FOLDER_RECEIVE_FULL, -1, p->ex); if (!p->message) continue; @@ -539,8 +540,9 @@ camel_folder_transfer_messages_to (p->source, uids, outbox, NULL, last, p->ex); g_ptr_array_free (uids, TRUE); } else { + /* TNY TODO: Partial message retrieval exception */ if (p->message == NULL) - p->message = camel_folder_get_message (p->source, p->uid, p->ex); + p->message = camel_folder_get_message (p->source, p->uid, CAMEL_FOLDER_RECEIVE_FULL, -1, p->ex); if (!p->message) continue; @@ -724,7 +726,8 @@ /* make sure we have the message... */ if (p->message == NULL) { - if (!(p->message = camel_folder_get_message (p->source, p->uid, p->ex))) + /* TNY TODO: Partial message retrieval exception */ + if (!(p->message = camel_folder_get_message (p->source, p->uid, CAMEL_FOLDER_RECEIVE_FULL, -1, p->ex))) return -1; } @@ -1190,7 +1193,8 @@ } info = camel_message_info_new_from_header(NULL, ((CamelMimePart *)msg)->headers); - ((CamelMessageInfoBase *)info)->size = camel_mime_parser_tell(mp) - last; + ((CamelMessageInfoBase *)info)->size = ((camel_mime_parser_tell(mp) - last)); + last = camel_mime_parser_tell(mp); status = camel_filter_driver_filter_message (driver, msg, info, NULL, NULL, source_url, original_source_url ? original_source_url : source_url, ex); @@ -1342,7 +1346,8 @@ else uid = camel_message_info_uid (p->info); - message = camel_folder_get_message (p->source, uid, ex); + /* TNY TODO: Partial message retrieval exception */ + message = camel_folder_get_message (p->source, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); } if (source_url && message && camel_mime_message_get_source (message) == NULL) @@ -1398,7 +1403,8 @@ if (message) { camel_object_ref (message); } else { - message = camel_folder_get_message (source, uid, ex); + /* TNY TODO: Partial message retrieval exception */ + message = camel_folder_get_message (source, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); if (!message) return -1; } @@ -1506,7 +1512,8 @@ g_ptr_array_free (uids, TRUE); } else { if (p->message == NULL) { - p->message = camel_folder_get_message (source, uid, ex); + /* TNY TODO: Partial message retrieval exception */ + p->message = camel_folder_get_message (source, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); if (!p->message) goto error; } Only in .: camel-filter-driver.lo Only in .: camel-filter-driver.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-filter-search.c ./camel-filter-search.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-filter-search.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-filter-search.c 2007-05-12 10:00:17.000000000 +0200 @@ -153,7 +153,7 @@ /* shortcut: a match for "" against any header always matches */ for (i=1; itype == ESEXP_RES_STRING && argv[i]->value.string[0] == 0; - +#if NON_TINYMAIL_FEATURES if (g_ascii_strcasecmp(name, "x-camel-mlist") == 0) { const char *list = camel_message_info_mlist(fms->info); @@ -164,6 +164,7 @@ } } } else { +#endif CamelMimeMessage *message = camel_filter_search_get_message (fms, f); struct _camel_header_raw *header; const char *charset = NULL; @@ -189,7 +190,9 @@ } } } +#ifdef NON_TINYMAIL_FEATURES } +#endif } r = e_sexp_result_new (f, ESEXP_RES_BOOL); @@ -504,7 +507,8 @@ ESExpResult *r; r = e_sexp_result_new(f, ESEXP_RES_INT); - r->value.number = camel_message_info_size(fms->info) / 1024; + + r->value.number = camel_message_info_size(fms->info); return r; } Only in .: camel-filter-search.lo Only in .: camel-filter-search.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder.c ./camel-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder.c 2007-05-12 10:01:18.000000000 +0200 @@ -93,7 +93,7 @@ static void free_summary (CamelFolder *folder, GPtrArray *array); -static CamelMimeMessage *get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); +static CamelMimeMessage *get_message (CamelFolder *folder, const gchar *uid, CamelFolderReceiveType type, gint param, CamelException *ex); static CamelMessageInfo *get_message_info (CamelFolder *folder, const char *uid); static void free_message_info (CamelFolder *folder, CamelMessageInfo *info); @@ -116,6 +116,18 @@ static gboolean folder_changed (CamelObject *object, gpointer event_data); +static void +folder_set_push_email (CamelFolder *folder, gboolean setting) +{ + return; +} + +void +camel_folder_set_push_email (CamelFolder *folder, gboolean setting) +{ + CF_CLASS (folder)->set_push_email (folder, setting); +} + static void camel_folder_class_init (CamelFolderClass *camel_folder_class) { @@ -124,6 +136,7 @@ parent_class = camel_type_get_global_classfuncs (camel_object_get_type ()); /* virtual method definition */ + camel_folder_class->set_push_email = folder_set_push_email; camel_folder_class->sync = folder_sync; camel_folder_class->refresh_info = refresh_info; camel_folder_class->get_name = get_name; @@ -308,15 +321,17 @@ CamelFolder *folder = (CamelFolder *)object; int i; guint32 tag; - int unread = -1, deleted = 0, junked = 0, visible = 0, count = -1; + int unread = -1, deleted = 0, count = -1; - for (i=0;iargc;i++) { - CamelArgGet *arg = &args->argv[i]; + for (i=0; i < args->argc; i++) + { + CamelArgGet *arg = &args->argv[i]; - tag = arg->tag; + tag = arg->tag; - switch (tag & CAMEL_ARG_TAG) { - /* CamelObject args */ + switch (tag & CAMEL_ARG_TAG) + { + /* CamelObject args */ case CAMEL_OBJECT_ARG_DESCRIPTION: if (folder->description == NULL) folder->description = g_strdup_printf("%s", folder->full_name); @@ -341,28 +356,30 @@ break; case CAMEL_FOLDER_ARG_UNREAD: case CAMEL_FOLDER_ARG_DELETED: - case CAMEL_FOLDER_ARG_JUNKED: - case CAMEL_FOLDER_ARG_VISIBLE: - /* This is so we can get the values atomically, and also so we can calculate them only once */ + + /* This is so we can get the values atomically, and also + * so we can calculate them only once */ + if (unread == -1) { int j; CamelMessageInfo *info; /* TODO: Locking? */ unread = 0; - count = camel_folder_summary_count(folder->summary); - for (j=0; jsummary, j))) { - guint32 flags = camel_message_info_flags(info); + count = camel_folder_summary_count (folder->summary); + for (j=0; j < count; j++) + { + info = camel_folder_summary_index (folder->summary, j); + if (info) + { + guint32 flags = camel_message_info_flags (info); - if ((flags & (CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0) - unread++; if (flags & CAMEL_MESSAGE_DELETED) deleted++; - if (flags & CAMEL_MESSAGE_JUNK) - junked++; - if ((flags & (CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0) - visible++; + else + if ((flags & CAMEL_MESSAGE_SEEN) == 0) + unread++; + camel_message_info_free(info); } } @@ -375,12 +392,6 @@ case CAMEL_FOLDER_ARG_DELETED: count = deleted; break; - case CAMEL_FOLDER_ARG_JUNKED: - count = junked; - break; - case CAMEL_FOLDER_ARG_VISIBLE: - count = visible; - break; } *arg->ca_int = count; @@ -409,9 +420,9 @@ break; default: continue; - } + } - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; + arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; } return parent_class->getv(object, ex, args); @@ -762,11 +773,6 @@ { g_return_val_if_fail(CAMEL_IS_FOLDER(folder), FALSE); - if ((flags & (CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN)) == CAMEL_MESSAGE_JUNK) { - flags |= CAMEL_MESSAGE_JUNK_LEARN; - set &= ~CAMEL_MESSAGE_JUNK_LEARN; - } - return CF_CLASS(folder)->set_message_flags(folder, uid, flags, set); } @@ -1043,7 +1049,7 @@ /* UIDs stuff */ static CamelMimeMessage * -get_message (CamelFolder *folder, const char *uid, CamelException *ex) +get_message (CamelFolder *folder, const char *uid, CamelFolderReceiveType type, gint param, CamelException *ex) { w(g_warning ("CamelFolder::get_message not implemented for `%s'", camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)))); @@ -1063,7 +1069,7 @@ * Returns a #CamelMimeMessage corresponding to @uid **/ CamelMimeMessage * -camel_folder_get_message (CamelFolder *folder, const char *uid, CamelException *ex) +camel_folder_get_message (CamelFolder *folder, const char *uid, CamelFolderReceiveType type, gint param, CamelException *ex) { CamelMimeMessage *ret; @@ -1071,7 +1077,7 @@ CAMEL_FOLDER_REC_LOCK(folder, lock); - ret = CF_CLASS (folder)->get_message (folder, uid, ex); + ret = CF_CLASS (folder)->get_message (folder, uid, type, param, ex); CAMEL_FOLDER_REC_UNLOCK(folder, lock); @@ -1355,7 +1361,9 @@ /* Default implementation. */ - msg = camel_folder_get_message(source, uid, ex); + /* TNY: Partial message retrieval exception (always transfer the full + message, not just the body part) */ + msg = camel_folder_get_message(source, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); if (!msg) return; @@ -1406,7 +1414,7 @@ if (transferred_uids) ret_uid = (char **)&((*transferred_uids)->pdata[i]); transfer_message_to (source, uids->pdata[i], dest, ret_uid, delete_originals, ex); - camel_operation_progress(NULL, i * 100 / uids->len); + camel_operation_progress(NULL, i , uids->len); } if (uids->len > 1) { camel_folder_thaw(dest); @@ -1637,6 +1645,7 @@ CamelException ex; }; +#if 0 static void filter_filter(CamelSession *session, CamelSessionThreadMsg *tmsg) { @@ -1652,10 +1661,10 @@ camel_operation_start (NULL, _("Learning junk")); for (i = 0; i < m->junk->len; i ++) { - CamelMimeMessage *msg = camel_folder_get_message(m->folder, m->junk->pdata[i], NULL); - int pc = 100 * i / m->junk->len; + /* TNY TODO: Partial message retrieval exception */ + CamelMimeMessage *msg = camel_folder_get_message(m->folder, m->junk->pdata[i], CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); - camel_operation_progress(NULL, pc); + camel_operation_progress(NULL, i, m->junk->len); if (msg) { camel_junk_plugin_report_junk (csp, msg); @@ -1668,10 +1677,10 @@ if (m->notjunk) { camel_operation_start (NULL, _("Learning non-junk")); for (i = 0; i < m->notjunk->len; i ++) { - CamelMimeMessage *msg = camel_folder_get_message(m->folder, m->notjunk->pdata[i], NULL); - int pc = 100 * i / m->notjunk->len; - - camel_operation_progress(NULL, pc); + /* TNY TODO: Partial message retrieval exception */ + CamelMimeMessage *msg = camel_folder_get_message(m->folder, m->notjunk->pdata[i], CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); + + camel_operation_progress(NULL, i, m->notjunk->len); if (msg) { camel_junk_plugin_report_notjunk (csp, msg); @@ -1702,9 +1711,8 @@ for (i=0;status == 0 && irecents->len;i++) { char *uid = m->recents->pdata[i]; - int pc = 100 * i / m->recents->len; - camel_operation_progress(NULL, pc); + camel_operation_progress(NULL, i, m->recents->len); info = camel_folder_get_message_info(m->folder, uid); if (info == NULL) { @@ -1745,11 +1753,8 @@ camel_folder_thaw(m->folder); camel_object_unref(m->folder); } +#endif -static CamelSessionThreadOps filter_ops = { - filter_filter, - filter_free, -}; /* Event hooks that block emission when frozen */ static gboolean @@ -1759,8 +1764,6 @@ CamelFolderChangeInfo *changed = event_data; CamelSession *session = ((CamelService *)folder->parent_store)->session; CamelFilterDriver *driver = NULL; - GPtrArray *junk = NULL; - GPtrArray *notjunk = NULL; GPtrArray *recents = NULL; int i; @@ -1784,56 +1787,17 @@ } CAMEL_FOLDER_UNLOCK(folder, change_lock); - if (session->junk_plugin && changed->uid_changed->len) { - guint32 flags; - - for (i = 0; i < changed->uid_changed->len; i ++) { - flags = camel_folder_get_message_flags (folder, changed->uid_changed->pdata [i]); - if (flags & CAMEL_MESSAGE_JUNK_LEARN) { - if (flags & CAMEL_MESSAGE_JUNK) { - if (!junk) - junk = g_ptr_array_new(); - g_ptr_array_add (junk, g_strdup (changed->uid_changed->pdata [i])); - } else { - if (!notjunk) - notjunk = g_ptr_array_new(); - g_ptr_array_add (notjunk, g_strdup (changed->uid_changed->pdata [i])); - } - /* reset junk learn flag so that we don't process it again*/ - camel_folder_set_message_flags (folder, changed->uid_changed->pdata [i], CAMEL_MESSAGE_JUNK_LEARN, 0); - } - } - } - if ((folder->folder_flags & (CAMEL_FOLDER_FILTER_RECENT|CAMEL_FOLDER_FILTER_JUNK)) + if ((folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT) && changed->uid_recent->len > 0) - driver = camel_session_get_filter_driver(session, - (folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT) - ? "incoming":"junktest", NULL); - + driver = camel_session_get_filter_driver(session, "incoming", NULL); + if (driver) { recents = g_ptr_array_new(); for (i=0;iuid_recent->len;i++) g_ptr_array_add(recents, g_strdup(changed->uid_recent->pdata[i])); } - if (driver || junk || notjunk) { - struct _folder_filter_msg *msg; - - d(printf("* launching filter thread %d new mail, %d junk and %d not junk\n", - recents?recents->len:0, junk?junk->len:0, notjunk?notjunk->len:0)); - - msg = camel_session_thread_msg_new(session, &filter_ops, sizeof(*msg)); - msg->recents = recents; - msg->junk = junk; - msg->notjunk = notjunk; - msg->folder = folder; - camel_object_ref(folder); - camel_folder_freeze(folder); - msg->driver = driver; - camel_exception_init(&msg->ex); - camel_session_thread_queue(session, &msg->msg, 0); - } return TRUE; } @@ -2120,7 +2084,7 @@ struct _CamelFolderChangeInfoPrivate *p; GPtrArray *olduids; char *olduid; - + g_assert(info != NULL); p = info->priv; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder.h ./camel-folder.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder.h 2007-05-12 10:01:18.000000000 +0200 @@ -34,6 +34,16 @@ #define CAMEL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_FOLDER_TYPE, CamelFolderClass)) #define CAMEL_IS_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_FOLDER_TYPE)) + +typedef enum _CamelFolderReceiveType CamelFolderReceiveType; + +enum _CamelFolderReceiveType +{ + CAMEL_FOLDER_RECEIVE_FULL = 1<<0, + CAMEL_FOLDER_RECEIVE_PARTIAL = 1<<1, + CAMEL_FOLDER_RECEIVE_SIZE_LIMITED = CAMEL_FOLDER_RECEIVE_PARTIAL<<2 +}; + G_BEGIN_DECLS typedef struct _CamelFolderChangeInfo CamelFolderChangeInfo; @@ -47,8 +57,6 @@ CAMEL_FOLDER_ARG_TOTAL, CAMEL_FOLDER_ARG_UNREAD, /* unread messages */ CAMEL_FOLDER_ARG_DELETED, /* deleted messages */ - CAMEL_FOLDER_ARG_JUNKED, /* junked messages */ - CAMEL_FOLDER_ARG_VISIBLE, /* visible !(deleted or junked) */ CAMEL_FOLDER_ARG_UID_ARRAY, CAMEL_FOLDER_ARG_INFO_ARRAY, CAMEL_FOLDER_ARG_PROPERTIES, @@ -63,8 +71,6 @@ CAMEL_FOLDER_TOTAL = CAMEL_FOLDER_ARG_TOTAL | CAMEL_ARG_INT, CAMEL_FOLDER_UNREAD = CAMEL_FOLDER_ARG_UNREAD | CAMEL_ARG_INT, CAMEL_FOLDER_DELETED = CAMEL_FOLDER_ARG_DELETED | CAMEL_ARG_INT, - CAMEL_FOLDER_JUNKED = CAMEL_FOLDER_ARG_JUNKED | CAMEL_ARG_INT, - CAMEL_FOLDER_VISIBLE = CAMEL_FOLDER_ARG_VISIBLE | CAMEL_ARG_INT, CAMEL_FOLDER_UID_ARRAY = CAMEL_FOLDER_ARG_UID_ARRAY | CAMEL_ARG_PTR, CAMEL_FOLDER_INFO_ARRAY = CAMEL_FOLDER_ARG_INFO_ARRAY | CAMEL_ARG_PTR, @@ -105,7 +111,9 @@ #define CAMEL_FOLDER_HAS_BEEN_DELETED (1<<3) #define CAMEL_FOLDER_IS_TRASH (1<<4) #define CAMEL_FOLDER_IS_JUNK (1<<5) -#define CAMEL_FOLDER_FILTER_JUNK (1<<6) +#define CAMEL_FOLDER_FILTER_JUNK (1<<6) +#define CAMEL_FOLDER_IS_READONLY (1<<7) +#define CAMEL_FOLDER_HAS_PUSHEMAIL_CAPABILITY (1<<8) typedef struct { CamelObjectClass parent_class; @@ -156,7 +164,8 @@ const char *value); CamelMimeMessage * (*get_message) (CamelFolder *folder, - const char *uid, + const char *uid, CamelFolderReceiveType type, + gint param, CamelException *ex); GPtrArray * (*get_uids) (CamelFolder *folder); @@ -191,6 +200,8 @@ void (*freeze) (CamelFolder *folder); void (*thaw) (CamelFolder *folder); gboolean (*is_frozen) (CamelFolder *folder); + void (*set_push_email) (CamelFolder *folder, gboolean setting); + } CamelFolderClass; /* Standard Camel function */ @@ -281,8 +292,8 @@ /* uid based access operations */ CamelMimeMessage * camel_folder_get_message (CamelFolder *folder, - const char *uid, - CamelException *ex); + const char *uid, CamelFolderReceiveType type, + gint param, CamelException *ex); #define camel_folder_delete_message(folder, uid) \ camel_folder_set_message_flags (folder, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN) @@ -343,6 +354,8 @@ void camel_folder_change_info_change_uid (CamelFolderChangeInfo *info, const char *uid); void camel_folder_change_info_recent_uid (CamelFolderChangeInfo *info, const char *uid); +void camel_folder_set_push_email (CamelFolder *folder, gboolean setting); + G_END_DECLS #endif /* CAMEL_FOLDER_H */ Only in .: camel-folder.lo Only in .: camel-folder.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-search.c ./camel-folder-search.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-search.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder-search.c 2007-05-12 10:01:18.000000000 +0200 @@ -880,10 +880,14 @@ } else if (!g_ascii_strcasecmp(headername, "cc")) { header = camel_message_info_cc(search->current); type = CAMEL_SEARCH_TYPE_ADDRESS; - } else if (!g_ascii_strcasecmp(headername, "x-camel-mlist")) { + } +#ifdef NON_TINYMAIL_FEATURES + else if (!g_ascii_strcasecmp(headername, "x-camel-mlist")) { header = camel_message_info_mlist(search->current); type = CAMEL_SEARCH_TYPE_MLIST; - } else { + } +#endif + else { e_sexp_resultv_free(f, argc, argv); e_sexp_fatal_error(f, _("Performing query on unknown header: %s"), headername); } @@ -898,7 +902,7 @@ truth = TRUE; } else if (how == CAMEL_SEARCH_MATCH_CONTAINS) { /* doesn't make sense to split words on anything but contains i.e. we can't have an ending match different words */ - words = camel_search_words_split(argv[i]->value.string); + words = camel_search_words_split((const unsigned char*)argv[i]->value.string); truth = TRUE; for (j=0;jlen && truth;j++) { truth = camel_search_header_match(header, words->words[j]->word, how, type, NULL); @@ -1099,7 +1103,7 @@ camel_stream_write (CAMEL_STREAM (mem), "", 1); for (i=0;ilen;i++) { /* FIXME: This is horridly slow, and should use a real search algorithm */ - if (camel_ustrstrcase(mem->buffer->data, words->words[i]->word) != NULL) { + if (camel_ustrstrcase((const char*)mem->buffer->data, words->words[i]->word) != NULL) { *mask |= (1<len))-1) @@ -1121,7 +1125,8 @@ CamelException x = CAMEL_EXCEPTION_INITIALISER; int truth; - msg = camel_folder_get_message(folder, uid, &x); + /* TNY TODO: Partial message retrieval exception */ + msg = camel_folder_get_message(folder, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, &x); if (msg) { mask = 0; truth = match_words_1message((CamelDataWrapper *)msg, words, &mask); @@ -1188,7 +1193,7 @@ } else { for (i=0;itype == ESEXP_RES_STRING) { - words = camel_search_words_split(argv[i]->value.string); + words = camel_search_words_split((const unsigned char*)argv[i]->value.string); truth = TRUE; if ((words->type & CAMEL_SEARCH_WORD_COMPLEX) == 0 && search->body_index) { for (j=0;jlen && truth;j++) @@ -1221,7 +1226,7 @@ for (i=0;itype == ESEXP_RES_STRING) { - words = camel_search_words_split(argv[i]->value.string); + words = camel_search_words_split((const unsigned char*)argv[i]->value.string); if ((words->type & CAMEL_SEARCH_WORD_COMPLEX) == 0 && search->body_index) { matches = match_words_index(search, words, ex); } else { Only in .: camel-folder-search.lo Only in .: camel-folder-search.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-summary.c ./camel-folder-summary.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-summary.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder-summary.c 2007-05-12 10:30:33.000000000 +0200 @@ -2,7 +2,13 @@ /* * Copyright (C) 2000-2003 Ximian Inc. * - * Authors: Michael Zucchi + * This is the mmap version of camel-folder-summary.c which maps + * the header data into memory in stead of fread()ing it. It uses + * the mmap() syscall for this. + * + * Authors: + * Michael Zucchi + * Philip Van Hoof * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU Lesser General Public @@ -40,6 +46,7 @@ #include #include + #include "camel-file-utils.h" #include "camel-folder-summary.h" #include "camel-folder.h" @@ -55,6 +62,17 @@ #include "camel-stream-mem.h" #include "camel-stream-null.h" #include "camel-string-utils.h" +#include "camel-disco-folder.h" + + + +#include +#include +#include +#include + +#include +#include static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER; @@ -66,19 +84,20 @@ /* this should probably be conditional on it existing */ #define USE_BSEARCH -#define d(x) +#define d(x) #define io(x) /* io debug */ -#define w(x) +#define w(x) #if 0 extern int strdup_count, malloc_count, free_count; #endif -#define CAMEL_FOLDER_SUMMARY_VERSION (13) +#define CAMEL_FOLDER_SUMMARY_VERSION (15) #define _PRIVATE(o) (((CamelFolderSummary *)(o))->priv) -#define META_SUMMARY_SUFFIX_LEN 5 /* strlen("-meta") */ +static GStaticRecMutex global_lock = G_STATIC_REC_MUTEX_INIT; +static GStaticMutex global_lock2 = G_STATIC_MUTEX_INIT; /* trivial lists, just because ... */ struct _node { @@ -88,23 +107,20 @@ static struct _node *my_list_append(struct _node **list, struct _node *n); static int my_list_size(struct _node **list); -static int summary_header_load(CamelFolderSummary *, FILE *); -static int summary_header_save(CamelFolderSummary *, FILE *); -static int summary_meta_header_load(CamelFolderSummary *, FILE *); -static int summary_meta_header_save(CamelFolderSummary *, FILE *); +static int summary_header_load(CamelFolderSummary *); +static int summary_header_save(CamelFolderSummary *, FILE *out); static CamelMessageInfo * message_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *); static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *); static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg); -static CamelMessageInfo * message_info_load(CamelFolderSummary *, FILE *); +static CamelMessageInfo * message_info_load(CamelFolderSummary *, gboolean *must_add); static int message_info_save(CamelFolderSummary *, FILE *, CamelMessageInfo *); -static int meta_message_info_save(CamelFolderSummary *s, FILE *out_meta, FILE *out, CamelMessageInfo *info); static void message_info_free(CamelFolderSummary *, CamelMessageInfo *); - +static void destroy_possible_pstring_stuff (CamelFolderSummary *, CamelMessageInfo *, gboolean); static CamelMessageContentInfo * content_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *); static CamelMessageContentInfo * content_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *); static CamelMessageContentInfo * content_info_new_from_message(CamelFolderSummary *s, CamelMimePart *mp); -static CamelMessageContentInfo * content_info_load(CamelFolderSummary *, FILE *); +static CamelMessageContentInfo * content_info_load(CamelFolderSummary *); static int content_info_save(CamelFolderSummary *, FILE *, CamelMessageContentInfo *); static void content_info_free(CamelFolderSummary *, CamelMessageContentInfo *); @@ -117,22 +133,105 @@ static void camel_folder_summary_init (CamelFolderSummary *obj); static void camel_folder_summary_finalize (CamelObject *obj); + +static void camel_folder_summary_mmap_add(CamelFolderSummary *s, CamelMessageInfo *info); +static void camel_folder_summary_unload_mmap (CamelFolderSummary *s); + static CamelObjectClass *camel_folder_summary_parent; + +void +camel_message_info_clear_normal_flags (CamelMessageInfo *min) +{ + + CamelMessageInfoBase *mi = (CamelMessageInfoBase*) min; + + mi->flags &= ~CAMEL_MESSAGE_ANSWERED; + mi->flags &= ~CAMEL_MESSAGE_DELETED; + mi->flags &= ~CAMEL_MESSAGE_DRAFT; + mi->flags &= ~CAMEL_MESSAGE_FLAGGED; + mi->flags &= ~CAMEL_MESSAGE_SEEN; + mi->flags &= ~CAMEL_MESSAGE_ATTACHMENTS; + mi->flags &= ~CAMEL_MESSAGE_CACHED; + mi->flags &= ~CAMEL_MESSAGE_PARTIAL; + mi->flags &= ~CAMEL_MESSAGE_EXPUNGED; + mi->flags &= ~CAMEL_MESSAGE_HIGH_PRIORITY; + mi->flags &= ~CAMEL_MESSAGE_NORMAL_PRIORITY; + mi->flags &= ~CAMEL_MESSAGE_LOW_PRIORITY; + + mi->flags &= ~CAMEL_MESSAGE_SECURE; + mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; +} + +static CamelMessageInfo* +find_message_info_with_uid (CamelFolderSummary *s, const char *uid) +{ + CamelMessageInfo *retval = NULL; + guint i = 0; + + if (uid == NULL || strlen (uid) <= 0) + return NULL; + + g_mutex_lock (s->hash_lock); + if (s->uidhash != NULL) + retval = g_hash_table_lookup (s->uidhash, uid); + g_mutex_unlock (s->hash_lock); + + if (retval == NULL) + for (i=0; G_LIKELY (i < s->messages->len) ; i++) + { + CamelMessageInfo *info = s->messages->pdata[i]; + + /* This can cause cache trashing */ + if (G_UNLIKELY (info->uid[0] == uid[0]) && + G_UNLIKELY (!strcmp (info->uid, uid))) + { + retval = info; + break; + } + } + + return retval; +} + +int +camel_folder_summary_get_index_for (CamelFolderSummary *s, const char *uid) +{ + int retval = -1, i; + + if (uid == NULL || strlen (uid) == 0) + return -1; + + for (i=0; G_LIKELY (i < s->messages->len) ; i++) + { + CamelMessageInfo *info = s->messages->pdata[i]; + + /* This can cause cache trashing */ + if (G_UNLIKELY (info->uid[0] == uid[0]) && + G_UNLIKELY (!strcmp (info->uid, uid))) + { + retval = i; + break; + } + } + + return retval; +} + +static void do_nothing (CamelFolder *folder, CamelMessageInfoBase *mi) { } + static void camel_folder_summary_init (CamelFolderSummary *s) { struct _CamelFolderSummaryPrivate *p; - p = _PRIVATE(s) = g_malloc0(sizeof(*p)); + p = _PRIVATE(s) = g_slice_alloc0 (sizeof (*p)); p->filter_charset = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - + s->dump_lock = g_mutex_new (); s->message_info_size = sizeof(CamelMessageInfoBase); s->content_info_size = sizeof(CamelMessageContentInfo); - - s->message_info_chunks = NULL; - s->content_info_chunks = NULL; + s->set_extra_flags_func = do_nothing; #if defined (DOESTRV) || defined (DOEPOOLV) s->message_info_strings = CAMEL_MESSAGE_INFO_LAST; @@ -142,30 +241,86 @@ s->flags = 0; s->time = 0; s->nextuid = 1; + s->in_reload = FALSE; s->messages = g_ptr_array_new(); - s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal); - + s->expunged = g_ptr_array_new(); + s->uidhash = NULL; + s->hash_lock = g_mutex_new (); + p->summary_lock = g_mutex_new(); p->io_lock = g_mutex_new(); p->filter_lock = g_mutex_new(); - p->alloc_lock = g_mutex_new(); p->ref_lock = g_mutex_new(); +} - s->meta_summary = g_malloc0(sizeof(CamelFolderMetaSummary)); +void +camel_folder_summary_prepare_hash (CamelFolderSummary *s) +{ + guint i = 0; + + g_mutex_lock (s->hash_lock); + + if (s->uidhash == NULL) + { + s->uidhash = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify)g_free, NULL); - /* Default is 20, any implementor having UIDs that has length - exceeding 20, has to override this value - */ - s->meta_summary->uid_len = 20; + for (i=0; G_LIKELY (i < s->messages->len) ; i++) + { + CamelMessageInfo *info = s->messages->pdata[i]; + g_hash_table_insert(s->uidhash, g_strdup (info->uid), info); + } + } + + g_mutex_unlock (s->hash_lock); + +} + +void +camel_folder_summary_kill_hash (CamelFolderSummary *s) +{ + g_mutex_lock (s->hash_lock); + if (s->uidhash != NULL) + g_hash_table_destroy (s->uidhash); + s->uidhash = NULL; + g_mutex_unlock (s->hash_lock); } + static void free_o_name(void *key, void *value, void *data) { camel_object_unref((CamelObject *)value); g_free(key); } +static inline void +foreach_msginfo (gpointer data, gpointer user_data) +{ + camel_message_info_free (data); + /* g_slice_free1 ((gint)user_data, data); */ +} + +static inline +gboolean always_true (gpointer key, gpointer value, gpointer gp) +{ + return TRUE; +} + +static void +camel_folder_summary_unload_mmap (CamelFolderSummary *s) +{ + struct _CamelFolderSummaryPrivate *p; + + p = _PRIVATE(s); + + if (s->file) + g_mapped_file_free (s->file); + s->file = NULL; + + return; +} + static void camel_folder_summary_finalize (CamelObject *obj) { @@ -174,49 +329,51 @@ p = _PRIVATE(obj); - camel_folder_summary_clear(s); + g_mutex_lock (s->dump_lock); + + g_ptr_array_foreach (s->messages, foreach_msginfo, (gpointer)s->message_info_size); + g_ptr_array_foreach (s->expunged, foreach_msginfo, (gpointer)s->message_info_size); + + /* camel_folder_summary_clear(s); */ g_ptr_array_free(s->messages, TRUE); - g_hash_table_destroy(s->messages_uid); + g_ptr_array_free(s->expunged, TRUE); - g_hash_table_foreach(p->filter_charset, free_o_name, 0); - g_hash_table_destroy(p->filter_charset); + camel_folder_summary_unload_mmap (s); - g_free(s->summary_path); + g_mutex_unlock (s->dump_lock); + g_mutex_free (s->dump_lock); - if (s->message_info_chunks) - e_memchunk_destroy(s->message_info_chunks); - if (s->content_info_chunks) - e_memchunk_destroy(s->content_info_chunks); + g_hash_table_foreach(p->filter_charset, free_o_name, 0); + g_hash_table_destroy(p->filter_charset); - if (p->filter_index) + if (p->filter_index && CAMEL_IS_OBJECT (p->filter_index)) camel_object_unref((CamelObject *)p->filter_index); - if (p->filter_64) + if (p->filter_64 && CAMEL_IS_OBJECT (p->filter_64)) camel_object_unref((CamelObject *)p->filter_64); - if (p->filter_qp) + if (p->filter_qp && CAMEL_IS_OBJECT (p->filter_qp)) camel_object_unref((CamelObject *)p->filter_qp); - if (p->filter_uu) + if (p->filter_uu && CAMEL_IS_OBJECT (p->filter_uu)) camel_object_unref((CamelObject *)p->filter_uu); - if (p->filter_save) + if (p->filter_save && CAMEL_IS_OBJECT (p->filter_save)) camel_object_unref((CamelObject *)p->filter_save); - if (p->filter_html) + if (p->filter_html && CAMEL_IS_OBJECT (p->filter_html)) camel_object_unref((CamelObject *)p->filter_html); - - if (p->filter_stream) + if (p->filter_stream && CAMEL_IS_OBJECT (p->filter_stream)) camel_object_unref((CamelObject *)p->filter_stream); - if (p->index) - camel_object_unref((CamelObject *)p->index); - /* Freeing memory occupied by meta-summary-header */ - g_free(s->meta_summary->path); - g_free(s->meta_summary); - + g_free(s->summary_path); + + if (s->uidhash != NULL) + g_hash_table_destroy (s->uidhash); + g_mutex_free(s->hash_lock); + g_mutex_free(p->summary_lock); g_mutex_free(p->io_lock); g_mutex_free(p->filter_lock); - g_mutex_free(p->alloc_lock); g_mutex_free(p->ref_lock); - - g_free(p); + + + g_slice_free1 (sizeof (*p), p); } CamelType @@ -250,9 +407,7 @@ camel_folder_summary_new (struct _CamelFolder *folder) { CamelFolderSummary *new = CAMEL_FOLDER_SUMMARY ( camel_object_new (camel_folder_summary_get_type ())); - new->folder = folder; - return new; } @@ -272,35 +427,10 @@ g_free(s->summary_path); s->summary_path = g_strdup(name); - g_free(s->meta_summary->path); - s->meta_summary->path = g_strconcat(name, "-meta", NULL); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); } -/** - * camel_folder_summary_set_index: - * @summary: a #CamelFolderSummary object - * @index: a #CamelIndex - * - * Set the index used to index body content. If the index is %NULL, or - * not set (the default), no indexing of body content will take place. - * - * Unlike earlier behaviour, build_content need not be set to perform indexing. - **/ -void -camel_folder_summary_set_index(CamelFolderSummary *s, CamelIndex *index) -{ - struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); - - if (p->index) - camel_object_unref((CamelObject *)p->index); - - p->index = index; - if (index) - camel_object_ref((CamelObject *)index); -} /** @@ -441,7 +571,7 @@ CAMEL_SUMMARY_LOCK(s, summary_lock); CAMEL_SUMMARY_LOCK(s, ref_lock); - info = g_hash_table_lookup(s->messages_uid, uid); + info = find_message_info_with_uid (s, uid); if (info) info->refcount++; @@ -492,12 +622,7 @@ void camel_folder_summary_set_uid(CamelFolderSummary *s, guint32 uid) { - /* TODO: sync to disk? */ - CAMEL_SUMMARY_LOCK(s, summary_lock); - s->nextuid = MAX(s->nextuid, uid); - - CAMEL_SUMMARY_UNLOCK(s, summary_lock); } @@ -518,29 +643,38 @@ /* loads the content descriptions, recursively */ static CamelMessageContentInfo * -perform_content_info_load(CamelFolderSummary *s, FILE *in) +perform_content_info_load(CamelFolderSummary *s) { int i; guint32 count; CamelMessageContentInfo *ci, *part; + unsigned char *ptrchr = s->filepos; + + ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_load (s); - ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_load(s, in); if (ci == NULL) return NULL; - if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) { - camel_folder_summary_content_info_free(s, ci); + ptrchr = s->filepos; + ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &count, FALSE); + s->filepos = ptrchr; + + if (count > 500) + { + camel_folder_summary_content_info_free (s, ci); return NULL; } - for (i=0;ichilds, (struct _node *)part); part->parent = ci; } else { d(fprintf (stderr, "Summary file format messed up?")); - camel_folder_summary_content_info_free(s, ci); + camel_folder_summary_content_info_free (s, ci); return NULL; } } @@ -559,48 +693,77 @@ int camel_folder_summary_load(CamelFolderSummary *s) { - FILE *in; int i; CamelMessageInfo *mi; + GError *err = NULL; - if (s->summary_path == NULL || - s->meta_summary->path == NULL) - return 0; - - in = g_fopen(s->summary_path, "rb"); - if (in == NULL) + if (s->summary_path == NULL || !g_file_test (s->summary_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) return -1; CAMEL_SUMMARY_LOCK(s, io_lock); - if ( ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in) == -1) + + if (!s->file) + { + s->file = g_mapped_file_new (s->summary_path, FALSE, &err); + if (err != NULL) + { + g_critical ("Unable to mmap file: %s\n", err->message); + g_error_free (err); + goto error; + } + } + + s->filepos = (unsigned char*) g_mapped_file_get_contents (s->file); + + if ( ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s) == -1) goto error; + if (s->messages && s->messages->len > s->saved_count) + { + int r, curlen = s->messages->len; + for (r = curlen - 1; r >= s->saved_count - 1; r--) + { + CamelMessageInfo *ri = g_ptr_array_index (s->messages, r); + if (ri) + camel_folder_summary_remove (s, ri); + } + } + /* now read in each message ... */ - for (i=0;isaved_count;i++) { - mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_load(s, in); + for (i=0; i < s->saved_count; i++) + { + gboolean must_add = FALSE; + s->idx = i; + + g_static_rec_mutex_lock (&global_lock); + mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_load(s, &must_add); + g_static_rec_mutex_unlock (&global_lock); if (mi == NULL) goto error; - /* FIXME: this should be done differently, how i don't know */ - if (s->build_content) { - ((CamelMessageInfoBase *)mi)->content = perform_content_info_load(s, in); + if (s->build_content) + { + if (((CamelMessageInfoBase *)mi)->content != NULL) + camel_folder_summary_content_info_free(s, ((CamelMessageInfoBase *)mi)->content); + + ((CamelMessageInfoBase *)mi)->content = perform_content_info_load (s); if (((CamelMessageInfoBase *)mi)->content == NULL) { camel_message_info_free(mi); goto error; } } - camel_folder_summary_add(s, mi); + if (must_add) + camel_folder_summary_mmap_add(s, mi); } + CAMEL_SUMMARY_UNLOCK(s, io_lock); - - if (fclose (in) != 0) - return -1; s->flags &= ~CAMEL_SUMMARY_DIRTY; + return 0; error: @@ -608,12 +771,12 @@ g_warning ("Cannot load summary file: `%s': %s", s->summary_path, g_strerror (errno)); CAMEL_SUMMARY_UNLOCK(s, io_lock); - fclose (in); s->flags |= ~CAMEL_SUMMARY_DIRTY; return -1; } + /* saves the content descriptions, recursively */ static int perform_content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci) @@ -650,53 +813,41 @@ camel_folder_summary_save(CamelFolderSummary *s) { FILE *out; - FILE *out_meta; - int fd, i, fd_meta; + int fd, i; guint32 count; CamelMessageInfo *mi; char *path; - char *path_meta; + gboolean herr = FALSE; + gboolean hadhash; + + g_mutex_lock (s->dump_lock); + + hadhash = (s->uidhash != NULL); g_assert(s->message_info_size >= sizeof(CamelMessageInfoBase)); - if (s->summary_path == NULL - || s->meta_summary->path == NULL - || (s->flags & CAMEL_SUMMARY_DIRTY) == 0) - return 0; + if (s->summary_path == NULL || (s->flags & CAMEL_SUMMARY_DIRTY) == 0) { + g_mutex_unlock (s->dump_lock); + return 0; + } path = alloca(strlen(s->summary_path)+4); sprintf(path, "%s~", s->summary_path); fd = g_open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600); - if (fd == -1) - return -1; - out = fdopen(fd, "wb"); - if (out == NULL) { - i = errno; - g_unlink(path); - close(fd); - errno = i; - return -1; + + if (fd == -1) { + g_mutex_unlock (s->dump_lock); + return -1; } - /* Meta summary code */ - /* This meta summary will be used by beagle in order to - quickly pass through the actual summary file, which - is quite time consuming otherwise. - */ - /* FIXME: Merge meta-summary and summary */ - path_meta = alloca(strlen(s->meta_summary->path)+4); - sprintf(path_meta, "%s~", s->meta_summary->path); - fd_meta = g_open(path_meta, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600); - if (fd_meta == -1) - return -1; - out_meta = fdopen(fd_meta, "wb"); - if (out_meta == NULL) { + out = fdopen(fd, "wb"); + if (out == NULL) + { i = errno; g_unlink(path); - g_unlink(path_meta); close(fd); - close(fd_meta); errno = i; + g_mutex_unlock (s->dump_lock); return -1; } @@ -705,40 +856,62 @@ CAMEL_SUMMARY_LOCK(s, io_lock); if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_save(s, out) == -1) - goto exception; - - if (summary_meta_header_save(s, out_meta) == -1) - goto exception; + goto haerror; /* now write out each message ... */ /* we check ferorr when done for i/o errors */ + count = s->messages->len; - for (i = 0; i < count; i++) { + + for (i = 0; i < count; i++) + { mi = s->messages->pdata[i]; - if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->meta_message_info_save (s, out_meta, out, mi) == -1) - goto exception; - + if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->message_info_save (s, out, mi) == -1) - goto exception; + { + herr = TRUE; + goto haerror; + } if (s->build_content) { if (perform_content_info_save (s, out, ((CamelMessageInfoBase *)mi)->content) == -1) - goto exception; + { + herr = TRUE; + goto haerror; + } } } - - /* FIXME: Can't we use the above "fd" variables, instead of fileno()? */ + if (fflush (out) != 0 || fsync (fileno (out)) == -1) - goto exception; - - if (fflush (out_meta) != 0 || fsync (fileno (out_meta)) == -1) + herr = TRUE; + +haerror: + + if (s->build_content) + for (i = 0; i < count; i++) + { + mi = s->messages->pdata[i]; + if (((CamelMessageInfoBase *)mi)->content != NULL) + camel_folder_summary_content_info_free (s, ((CamelMessageInfoBase *)mi)->content); + ((CamelMessageInfoBase *)mi)->content = NULL; + } + + CAMEL_SUMMARY_UNLOCK(s, io_lock); + + if (herr) goto exception; fclose (out); - fclose (out_meta); + s->in_reload = TRUE; + + if (!hadhash) + camel_folder_summary_prepare_hash (s); + + g_static_rec_mutex_lock (&global_lock); + g_static_mutex_lock (&global_lock2); + + camel_folder_summary_unload_mmap (s); - CAMEL_SUMMARY_UNLOCK(s, io_lock); - #ifdef G_OS_WIN32 g_unlink(s->summary_path); #endif @@ -746,32 +919,33 @@ i = errno; g_unlink(path); errno = i; + g_static_mutex_unlock (&global_lock2); + g_static_rec_mutex_unlock (&global_lock); return -1; } + camel_folder_summary_load (s); + + g_static_mutex_unlock (&global_lock2); + g_static_rec_mutex_unlock (&global_lock); + + if (!hadhash) + camel_folder_summary_kill_hash (s); + + s->in_reload = FALSE; - if (g_rename(path_meta, s->meta_summary->path) == -1) { - i = errno; - g_unlink(path_meta); - errno = i; - return -1; - } - s->flags &= ~CAMEL_SUMMARY_DIRTY; + g_mutex_unlock (s->dump_lock); + return 0; - - exception: - + +exception: + i = errno; - fclose (out); - fclose (out_meta); - - CAMEL_SUMMARY_UNLOCK(s, io_lock); - g_unlink (path); - g_unlink (path_meta); errno = i; - + g_mutex_unlock (s->dump_lock); + return -1; } @@ -789,61 +963,66 @@ int camel_folder_summary_header_load(CamelFolderSummary *s) { - FILE *in; - FILE *in_meta; int ret; + GError *err = NULL; - if (s->summary_path == NULL || - s->meta_summary->path == NULL) - return 0; - - in = g_fopen(s->summary_path, "rb"); - if (in == NULL) + if (s->summary_path == NULL || !g_file_test (s->summary_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) return -1; - in_meta = g_fopen(s->meta_summary->path, "rb"); - if (in_meta == NULL) { - fclose(in); - return -1; + CAMEL_SUMMARY_LOCK(s, io_lock); + + if (!s->file) + { + s->file = g_mapped_file_new (s->summary_path, FALSE, &err); + if (err != NULL) + { + g_critical ("Unable to mmap file: %s\n", err->message); + g_error_free (err); + return -1; + } } - CAMEL_SUMMARY_LOCK(s, io_lock); - ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in); - ret = summary_meta_header_load(s, in_meta); - CAMEL_SUMMARY_UNLOCK(s, io_lock); + s->filepos = (unsigned char*) g_mapped_file_get_contents (s->file); + + + ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s); - fclose(in); - fclose(in_meta); s->flags &= ~CAMEL_SUMMARY_DIRTY; + CAMEL_SUMMARY_UNLOCK(s, io_lock); + return ret; } + + static int summary_assign_uid(CamelFolderSummary *s, CamelMessageInfo *info) { const char *uid; CamelMessageInfo *mi; + CamelMessageInfoBase *bi = (CamelMessageInfoBase*)info; - uid = camel_message_info_uid(info); + uid = camel_message_info_uid (info); if (uid == NULL || uid[0] == 0) { - g_free(info->uid); uid = info->uid = camel_folder_summary_next_uid_string(s); + bi->flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; } - CAMEL_SUMMARY_LOCK(s, summary_lock); - - while ((mi = g_hash_table_lookup(s->messages_uid, uid))) { - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - if (mi == info) + while ((mi = find_message_info_with_uid (s, uid))) + { + if (mi == info) return 0; + d(printf ("Trying to insert message with clashing uid (%s). new uid re-assigned", camel_message_info_uid(info))); - g_free(info->uid); + + if (bi->flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE) + g_free(info->uid); uid = info->uid = camel_folder_summary_next_uid_string(s); + bi->flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + camel_message_info_set_flags(info, CAMEL_MESSAGE_FOLDER_FLAGGED, CAMEL_MESSAGE_FOLDER_FLAGGED); - CAMEL_SUMMARY_LOCK(s, summary_lock); } - CAMEL_SUMMARY_UNLOCK(s, summary_lock); return 1; } @@ -865,11 +1044,20 @@ void camel_folder_summary_add(CamelFolderSummary *s, CamelMessageInfo *info) { - if (info == NULL) + + g_mutex_lock (s->dump_lock); + + if (info == NULL) + { + g_mutex_unlock (s->dump_lock); return; + } if (summary_assign_uid(s, info) == 0) + { + g_mutex_unlock (s->dump_lock); return; + } CAMEL_SUMMARY_LOCK(s, summary_lock); @@ -881,12 +1069,42 @@ #endif g_ptr_array_add(s->messages, info); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); + + g_mutex_lock (s->hash_lock); + if (s->uidhash != NULL) + g_hash_table_insert (s->uidhash, g_strdup (info->uid), info); + g_mutex_unlock (s->hash_lock); + s->flags |= CAMEL_SUMMARY_DIRTY; CAMEL_SUMMARY_UNLOCK(s, summary_lock); + + g_mutex_unlock (s->dump_lock); } +static void +camel_folder_summary_mmap_add(CamelFolderSummary *s, CamelMessageInfo *info) +{ + CAMEL_SUMMARY_LOCK(s, summary_lock); + +/* unnecessary for pooled vectors */ +#ifdef DOESTRV + /* this is vitally important, and also if this is ever modified, then + the hash table needs to be resynced */ + info->strings = e_strv_pack(info->strings); +#endif + + g_ptr_array_add(s->messages, info); + + g_mutex_lock (s->hash_lock); + if (s->uidhash != NULL) + g_hash_table_insert (s->uidhash, g_strdup (info->uid), info); + g_mutex_unlock (s->hash_lock); + + s->flags |= CAMEL_SUMMARY_DIRTY; + + CAMEL_SUMMARY_UNLOCK(s, summary_lock); +} /** * camel_folder_summary_add_from_header: @@ -972,6 +1190,28 @@ return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_header(s, h); } +CamelMessageInfo * +camel_folder_summary_info_new_from_header_with_uid (CamelFolderSummary *s, struct _camel_header_raw *h, const gchar *uid) +{ + + CamelMessageInfo *mi; + CamelMessageInfoBase *bi; + + if (s != NULL) + mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_header(s, h); + else + mi = message_info_new_from_header(s, h); + + bi = (CamelMessageInfoBase *)mi; + + if (bi->uid && (bi->flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE)) + g_free (bi->uid); + + ((CamelMessageInfoBase *)mi)->uid = g_strdup (uid); + ((CamelMessageInfoBase*)mi)->flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + + return mi; +} /** * camel_folder_summary_info_new_from_parser: @@ -1000,45 +1240,15 @@ CamelMessageInfo *info = NULL; char *buffer; size_t len; - struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); off_t start; - CamelIndexName *name = NULL; /* should this check the parser is in the right state, or assume it is?? */ start = camel_mime_parser_tell(mp); if (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_EOF) { info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_parser(s, mp); - camel_mime_parser_unstep(mp); - - /* assign a unique uid, this is slightly 'wrong' as we do not really - * know if we are going to store this in the summary, but no matter */ - if (p->index) - summary_assign_uid(s, info); - - CAMEL_SUMMARY_LOCK(s, filter_lock); - - if (p->index) { - if (p->filter_index == NULL) - p->filter_index = camel_mime_filter_index_new_index(p->index); - camel_index_delete_name(p->index, camel_message_info_uid(info)); - name = camel_index_add_name(p->index, camel_message_info_uid(info)); - camel_mime_filter_index_set_name(p->filter_index, name); - } - - /* always scan the content info, even if we dont save it */ - ((CamelMessageInfoBase *)info)->content = summary_build_content_info(s, info, mp); - - if (name && p->index) { - camel_index_write_name(p->index, name); - camel_object_unref((CamelObject *)name); - camel_mime_filter_index_set_name(p->filter_index, NULL); - } - - CAMEL_SUMMARY_UNLOCK(s, filter_lock); - - ((CamelMessageInfoBase *)info)->size = camel_mime_parser_tell(mp) - start; + ((CamelMessageInfoBase *)info)->size = ( (camel_mime_parser_tell(mp) - start) ); } return info; } @@ -1058,42 +1268,22 @@ camel_folder_summary_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg) { CamelMessageInfo *info; - struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); - CamelIndexName *name = NULL; - info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_message(s, msg); + if (s != NULL) + { + info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_message(s, msg); + } else + info = message_info_new_from_message(s, msg); - /* assign a unique uid, this is slightly 'wrong' as we do not really - * know if we are going to store this in the summary, but we need it set for indexing */ - if (p->index) - summary_assign_uid(s, info); - - CAMEL_SUMMARY_LOCK(s, filter_lock); - - if (p->index) { - if (p->filter_index == NULL) - p->filter_index = camel_mime_filter_index_new_index(p->index); - camel_index_delete_name(p->index, camel_message_info_uid(info)); - name = camel_index_add_name(p->index, camel_message_info_uid(info)); - camel_mime_filter_index_set_name(p->filter_index, name); - if (p->filter_stream == NULL) { - CamelStream *null = camel_stream_null_new(); - - p->filter_stream = camel_stream_filter_new_with_stream(null); - camel_object_unref((CamelObject *)null); - } - } + if (s!=NULL) + CAMEL_SUMMARY_LOCK(s, filter_lock); ((CamelMessageInfoBase *)info)->content = summary_build_content_info_message(s, info, (CamelMimePart *)msg); - if (name) { - camel_index_write_name(p->index, name); - camel_object_unref((CamelObject *)name); - camel_mime_filter_index_set_name(p->filter_index, NULL); - } - CAMEL_SUMMARY_UNLOCK(s, filter_lock); + if (s!=NULL) + CAMEL_SUMMARY_UNLOCK(s, filter_lock); return info; } @@ -1112,7 +1302,12 @@ CamelMessageContentInfo *pw, *pn; pw = ci->childs; - ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_free(s, ci); + + if (s != NULL) + ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_free(s, ci); + else + content_info_free (NULL, ci); + while (pw) { pn = pw->next; camel_folder_summary_content_info_free(s, pw); @@ -1131,9 +1326,7 @@ void camel_folder_summary_touch(CamelFolderSummary *s) { - CAMEL_SUMMARY_LOCK(s, summary_lock); s->flags |= CAMEL_SUMMARY_DIRTY; - CAMEL_SUMMARY_UNLOCK(s, summary_lock); } @@ -1158,10 +1351,7 @@ camel_message_info_free(s->messages->pdata[i]); g_ptr_array_set_size(s->messages, 0); - g_hash_table_destroy(s->messages_uid); - s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal); s->flags |= CAMEL_SUMMARY_DIRTY; - s->meta_summary->msg_expunged = TRUE; CAMEL_SUMMARY_UNLOCK(s, summary_lock); } @@ -1176,14 +1366,25 @@ void camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info) { - CAMEL_SUMMARY_LOCK(s, summary_lock); - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - g_ptr_array_remove(s->messages, info); - s->flags |= CAMEL_SUMMARY_DIRTY; - s->meta_summary->msg_expunged = TRUE; - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - - camel_message_info_free(info); + g_mutex_lock (s->dump_lock); + + if (((CamelMessageInfoBase*)info)->flags & CAMEL_MESSAGE_EXPUNGED) + { + CAMEL_SUMMARY_LOCK(s, summary_lock); + g_ptr_array_remove(s->messages, info); + g_ptr_array_add (s->expunged, info); + s->flags |= CAMEL_SUMMARY_DIRTY; + CAMEL_SUMMARY_UNLOCK(s, summary_lock); + } else { + + CAMEL_SUMMARY_LOCK(s, summary_lock); + g_ptr_array_remove(s->messages, info); + s->flags |= CAMEL_SUMMARY_DIRTY; + CAMEL_SUMMARY_UNLOCK(s, summary_lock); + camel_message_info_free(info); + } + + g_mutex_unlock (s->dump_lock); } @@ -1197,19 +1398,22 @@ void camel_folder_summary_remove_uid(CamelFolderSummary *s, const char *uid) { - CamelMessageInfo *oldinfo; - char *olduid; + CamelMessageInfo *oldinfo = NULL; CAMEL_SUMMARY_LOCK(s, summary_lock); CAMEL_SUMMARY_LOCK(s, ref_lock); - if (g_hash_table_lookup_extended(s->messages_uid, uid, (void *)&olduid, (void *)&oldinfo)) { + + oldinfo = find_message_info_with_uid (s, uid); + + if (oldinfo) + { /* make sure it doesn't vanish while we're removing it */ oldinfo->refcount++; CAMEL_SUMMARY_UNLOCK(s, ref_lock); CAMEL_SUMMARY_UNLOCK(s, summary_lock); camel_folder_summary_remove(s, oldinfo); camel_message_info_free(oldinfo); - } else { + } else { CAMEL_SUMMARY_UNLOCK(s, ref_lock); CAMEL_SUMMARY_UNLOCK(s, summary_lock); } @@ -1230,7 +1434,6 @@ if (index < s->messages->len) { CamelMessageInfo *info = s->messages->pdata[index]; - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); g_ptr_array_remove_index(s->messages, index); s->flags |= CAMEL_SUMMARY_DIRTY; @@ -1256,6 +1459,7 @@ if (end < start) return; + g_mutex_lock (s->dump_lock); CAMEL_SUMMARY_LOCK(s, summary_lock); if (start < s->messages->len) { CamelMessageInfo **infos; @@ -1264,13 +1468,6 @@ end = MIN(end+1, s->messages->len); infos = g_malloc((end-start)*sizeof(infos[0])); - for (i=start;imessages->pdata[i]; - - infos[i-start] = info; - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - } - memmove(s->messages->pdata+start, s->messages->pdata+end, (s->messages->len-end)*sizeof(s->messages->pdata[0])); g_ptr_array_set_size(s->messages, s->messages->len - (end - start)); s->flags |= CAMEL_SUMMARY_DIRTY; @@ -1283,6 +1480,8 @@ } else { CAMEL_SUMMARY_UNLOCK(s, summary_lock); } + + g_mutex_unlock (s->dump_lock); } /* should be sorted, for binary search */ @@ -1319,6 +1518,41 @@ #define tokens_len (sizeof(tokens)/sizeof(tokens[0])) +guint bytes; +static gchar* +token_add (gchar *str) +{ + int i; + + if (!str) + return NULL; + + for (i=0; i len) { + if (fwrite ("\0\0\0\0\0\0\0\0", lena-len, 1, out) == 1) + return 0; + else return -1; + } + } } } + return 0; } @@ -1399,24 +1647,22 @@ * Returns %0 on success or %-1 on fail **/ int -camel_folder_summary_decode_token(FILE *in, char **str) +camel_folder_summary_decode_token(CamelFolderSummary *s, char **str) { char *ret; guint32 len; + unsigned char *ptrchr = s->filepos; io(printf("Decode token ...\n")); - - if (camel_file_util_decode_uint32(in, &len) == -1) { - io(printf ("Could not decode token from file")); - *str = NULL; - return -1; - } + + ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &len, FALSE); if (len<32) { + if (len <= 0) { ret = NULL; } else if (len<= tokens_len) { - ret = g_strdup(tokens[len-1]); + ret = tokens[len-1]; } else { io(printf ("Invalid token encountered: %d", len)); *str = NULL; @@ -1427,17 +1673,17 @@ *str = NULL; return -1; } else { + len -= 32; - ret = g_malloc(len+1); - if (len > 0 && fread(ret, len, 1, in) != 1) { - g_free(ret); - *str = NULL; - return -1; - } - ret[len]=0; + + if (len != 0) + ret = (char*)ptrchr; + else ret = NULL; + + ptrchr += len; } - io(printf("Token = '%s'\n", ret)); + s->filepos = ptrchr; *str = ret; return 0; @@ -1467,63 +1713,42 @@ } static int -summary_meta_header_load(CamelFolderSummary *s, FILE *in) -{ - if (!s->meta_summary->path) - return -1; - - fseek(in, 0, SEEK_SET); - - io(printf("Loading meta-header\n")); - - if (camel_file_util_decode_uint32(in, &s->meta_summary->major) == -1 - || camel_file_util_decode_uint32(in, &s->meta_summary->minor) == -1 - || camel_file_util_decode_uint32(in, &s->meta_summary->uid_len) == -1) { - return -1; - } - - return 0; -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) +summary_header_load(CamelFolderSummary *s) { - if (!s->summary_path) - return -1; + s->version = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; - fseek(in, 0, SEEK_SET); + io(printf("Loading header %d", (s->version&0xff))); - io(printf("Loading header\n")); - - if (camel_file_util_decode_fixed_int32(in, &s->version) == -1) - return -1; - - /* Legacy version check, before version 12 we have no upgrade knowledge */ + /* Legacy version check, before version 13 we have no upgrade knowledge */ if ((s->version > 0xff) && (s->version & 0xff) < 12) { io(printf ("Summary header version mismatch")); errno = EINVAL; return -1; } - if (!(s->version < 0x100 && s->version >= 13)) - io(printf("Loading legacy summary\n")); - else - io(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) { + /* Check for MMAPable file */ + if (s->version != CAMEL_FOLDER_SUMMARY_VERSION) { + errno = EINVAL; 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; + s->flags = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + s->nextuid = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + s->time = (time_t)g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + s->saved_count = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + + if (s->version < 0x100 && s->version >= 13) { + s->unread_count = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + s->deleted_count = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + s->junk_count = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; } return 0; @@ -1557,8 +1782,6 @@ unread++; if ((flags & CAMEL_MESSAGE_DELETED) != 0) deleted++; - if ((flags & CAMEL_MESSAGE_JUNK) != 0) - junk++; camel_message_info_free(info); } @@ -1570,25 +1793,6 @@ return camel_file_util_encode_fixed_int32(out, junk); } -static int -summary_meta_header_save(CamelFolderSummary *s, FILE *out_meta) -{ - fseek(out_meta, 0, SEEK_SET); - - /* Save meta-summary header */ - if (s->meta_summary->msg_expunged) { - s->meta_summary->msg_expunged = FALSE; - camel_file_util_encode_uint32(out_meta, ++s->meta_summary->major); - camel_file_util_encode_uint32(out_meta, (s->meta_summary->minor=0)); - } else { - camel_file_util_encode_uint32(out_meta, s->meta_summary->major); - camel_file_util_encode_uint32(out_meta, ++s->meta_summary->minor); - } - camel_file_util_encode_uint32(out_meta, s->meta_summary->uid_len); - - return ferror(out_meta); -} - /* are these even useful for anything??? */ static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) @@ -1637,7 +1841,10 @@ { CamelMessageInfo *mi; - mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_header(s, ((CamelMimePart *)msg)->headers); + if (s != NULL) + mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_header(s, ((CamelMimePart *)msg)->headers); + else + mi = message_info_new_from_header(s, ((CamelMimePart *)msg)->headers); return mi; } @@ -1647,7 +1854,10 @@ { CamelMessageContentInfo *ci; - ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_header(s, mp->headers); + if (s != NULL) + ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_header(s, mp->headers); + else + ci = content_info_new_from_header(NULL, mp->headers); return ci; } @@ -1677,6 +1887,7 @@ const char *text; text = camel_header_raw_find (&h, name, NULL); + if (text) { while (isspace ((unsigned) *text)) text++; @@ -1686,9 +1897,44 @@ } } +#ifndef _GNU_SOURCE +static char *strcasestr(const char *haystack, const char *needle) +{ + const gchar *p = haystack; + gsize needle_len = strlen (needle); + gsize haystack_len; + const gchar *end; + gsize i; + + if (needle_len == 0) + return (gchar *)haystack; + + haystack_len = strlen (haystack); + + if (haystack_len < needle_len) + return NULL; + end = haystack + haystack_len - needle_len; + while (*p && p <= end) + { + for (i = 0; i < needle_len; i++) + if (tolower (p[i]) != tolower (needle[i])) + goto next; + + return (gchar *)p; + + next: + p++; + } + + return NULL; +} +#else +char *strcasestr(const char *haystack, const char *needle); +#endif /** - * camel_folder_summary_content_info_new: + * + : * @summary: a #CamelFolderSummary object * * Allocate a new #CamelMessageContentInfo, suitable for adding @@ -1699,16 +1945,9 @@ CamelMessageContentInfo * camel_folder_summary_content_info_new(CamelFolderSummary *s) { - CamelMessageContentInfo *ci; - - CAMEL_SUMMARY_LOCK(s, alloc_lock); - if (s->content_info_chunks == NULL) - s->content_info_chunks = e_memchunk_new(32, s->content_info_size); - ci = e_memchunk_alloc(s->content_info_chunks); - CAMEL_SUMMARY_UNLOCK(s, alloc_lock); - - memset(ci, 0, s->content_info_size); - return ci; + if (s != NULL) + return g_slice_alloc0(s->content_info_size); + return g_slice_new0 (CamelMessageContentInfo); } static CamelMessageInfo * @@ -1717,14 +1956,15 @@ CamelMessageInfoBase *mi; const char *received; guchar digest[16]; - struct _camel_header_references *refs, *irt, *scan; - char *msgid; - int count; - char *subject, *from, *to, *cc, *mlist; + char *msgid, *r=NULL; + char *subject, *from, *to, *cc; CamelContentType *ct = NULL; const char *content, *charset = NULL; + const char *prio = NULL; + const char *attach = NULL; mi = (CamelMessageInfoBase *)camel_message_info_new(s); + mi->flags |= CAMEL_MESSAGE_INFO_NEEDS_FREE; if ((content = camel_header_raw_find(&h, "Content-Type", NULL)) && (ct = camel_content_type_decode(content)) @@ -1738,191 +1978,295 @@ from = summary_format_address(h, "from", charset); to = summary_format_address(h, "to", charset); cc = summary_format_address(h, "cc", charset); - mlist = camel_header_raw_check_mailing_list(&h); + + prio = camel_header_raw_find(&h, "X-Priority", NULL); + if (!prio) + prio = camel_header_raw_find(&h, "X-MSMail-Priority", NULL); + + if (prio) + { + if (strcasestr (prio, "high") != NULL) + mi->flags |= CAMEL_MESSAGE_HIGH_PRIORITY; + else if (strchr (prio, '1') != NULL) + mi->flags |= CAMEL_MESSAGE_HIGH_PRIORITY; + else if (strcasestr (prio, "normal") != NULL) + mi->flags |= CAMEL_MESSAGE_NORMAL_PRIORITY; + else if (strchr (prio, '2') != NULL) + mi->flags |= CAMEL_MESSAGE_NORMAL_PRIORITY; + else if (strcasestr (prio, "low") != NULL) + mi->flags |= CAMEL_MESSAGE_LOW_PRIORITY; + else if (strchr (prio, '3') != NULL) + mi->flags |= CAMEL_MESSAGE_LOW_PRIORITY; + } else + mi->flags |= CAMEL_MESSAGE_NORMAL_PRIORITY; + + attach = camel_header_raw_find(&h, "X-MS-Has-Attach", NULL); + if (attach) + if (strcasestr (attach, "yes") != NULL) + mi->flags |= CAMEL_MESSAGE_ATTACHMENTS; + /* else { + attach = camel_header_raw_find(&h, "Content-Type", NULL); + if (strcasestr (attach, "multi") != NULL) + mi->flags |= CAMEL_MESSAGE_ATTACHMENTS; + } */ + if (ct) camel_content_type_unref(ct); - - mi->subject = camel_pstring_add (subject, TRUE); - mi->from = camel_pstring_add (from, TRUE); - mi->to = camel_pstring_add (to, TRUE); - mi->cc = camel_pstring_add (cc, TRUE); - mi->mlist = camel_pstring_add (mlist, TRUE); - - mi->user_flags = NULL; - mi->user_tags = NULL; + + if (subject) + mi->subject = camel_pstring_add (subject, TRUE); + else + mi->subject = camel_pstring_add (g_strdup (""), TRUE); + + if (from) + mi->from = camel_pstring_add (from, TRUE); + else + mi->from = camel_pstring_add (g_strdup (""), TRUE); + + if (to) + mi->to = camel_pstring_add (to, TRUE); + else + mi->to = camel_pstring_add (g_strdup (""), TRUE); + + if (cc) + mi->cc = camel_pstring_add (cc, TRUE); + else + mi->cc = camel_pstring_add (g_strdup (""), TRUE); + mi->date_sent = camel_header_decode_date(camel_header_raw_find(&h, "date", NULL), NULL); received = camel_header_raw_find(&h, "received", NULL); + if (received) - received = strrchr(received, ';'); - if (received) - mi->date_received = camel_header_decode_date(received + 1, NULL); - else + r = strrchr(received, ';'); + if (r) + mi->date_received = camel_header_decode_date(r + 1, NULL); + + else if (received) + mi->date_received = camel_header_decode_date(received, NULL); + else mi->date_received = 0; msgid = camel_header_msgid_decode(camel_header_raw_find(&h, "message-id", NULL)); - if (msgid) { + if (msgid) + { md5_get_digest(msgid, strlen(msgid), digest); memcpy(mi->message_id.id.hash, digest, sizeof(mi->message_id.id.hash)); g_free(msgid); } - - /* decode our references and in-reply-to headers */ - refs = camel_header_references_decode (camel_header_raw_find (&h, "references", NULL)); - irt = camel_header_references_inreplyto_decode (camel_header_raw_find (&h, "in-reply-to", NULL)); - if (refs || irt) { - if (irt) { - /* The References field is populated from the ``References'' and/or ``In-Reply-To'' - headers. If both headers exist, take the first thing in the In-Reply-To header - that looks like a Message-ID, and append it to the References header. */ - - if (refs) - irt->next = refs; - - refs = irt; - } - - count = camel_header_references_list_size(&refs); - mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0]))); - count = 0; - scan = refs; - while (scan) { - md5_get_digest(scan->id, strlen(scan->id), digest); - memcpy(mi->references->references[count].id.hash, digest, sizeof(mi->message_id.id.hash)); - count++; - scan = scan->next; - } - mi->references->size = count; - camel_header_references_list_clear(&refs); - } + return (CamelMessageInfo *)mi; } + static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) +message_info_load(CamelFolderSummary *s, gboolean *must_add) { - CamelMessageInfoBase *mi; - guint count; - int i; - char *subject, *from, *to, *cc, *mlist, *uid; - - mi = (CamelMessageInfoBase *)camel_message_info_new(s); + CamelMessageInfoBase *mi = NULL; + guint count, len; + unsigned char *ptrchr = s->filepos; + unsigned int i; + gchar *theuid; io(printf("Loading message info\n")); - camel_file_util_decode_string(in, &uid); - camel_file_util_decode_uint32(in, &mi->flags); - camel_file_util_decode_uint32(in, &mi->size); - camel_file_util_decode_time_t(in, &mi->date_sent); - camel_file_util_decode_time_t(in, &mi->date_received); - camel_file_util_decode_string(in, &subject); - camel_file_util_decode_string(in, &from); - camel_file_util_decode_string(in, &to); - camel_file_util_decode_string(in, &cc); - camel_file_util_decode_string(in, &mlist); - - mi->uid = uid; - mi->subject = camel_pstring_add (subject, TRUE); - mi->from = camel_pstring_add (from, TRUE); - mi->to = camel_pstring_add (to, TRUE); - mi->cc = camel_pstring_add (cc, TRUE); - mi->mlist = camel_pstring_add (mlist, TRUE); - - mi->content = NULL; + /* Try to find the original instance in case we are in reloading */ - camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.hi); - camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.lo); + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE); + if (len) + theuid = (char*)ptrchr; + ptrchr += len; + + if (!s->in_reload) + { + /* We are not reloading, so searching for recoverable + * CamelMessageInfo struct instances is avoidable */ + mi = (CamelMessageInfoBase *) camel_message_info_new (s); + *must_add = TRUE; + mi->uid = theuid; + } else + { + CAMEL_SUMMARY_LOCK(s, summary_lock); - if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) - goto error; + if (s->messages && s->idx >=0 && s->idx < s->messages->len) + { + CAMEL_SUMMARY_LOCK(s, ref_lock); + + mi = (CamelMessageInfoBase *) s->messages->pdata[s->idx]; + destroy_possible_pstring_stuff (s, (CamelMessageInfo*) mi, FALSE); + *must_add = FALSE; + if (mi->uid && (mi->flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE)) + g_free (mi->uid); + mi->uid = theuid; + CAMEL_SUMMARY_UNLOCK(s, ref_lock); + } else + printf ("Problem with %s. Can't find original instance (index=%d)\n", theuid, s->idx); - if (count > 0) { - mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0]))); - mi->references->size = count; - for (i=0;ireferences->references[i].id.part.hi); - camel_file_util_decode_fixed_int32(in, &mi->references->references[i].id.part.lo); - } + CAMEL_SUMMARY_UNLOCK(s, summary_lock); } - if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) - goto error; + i = 0; - for (i=0;iuser_flags, name, TRUE); - g_free(name); + if (!mi) + { + mi = (CamelMessageInfoBase *) camel_message_info_new(s); + *must_add = TRUE; + mi->uid = theuid; } - if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) - goto error; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &mi->size, FALSE); + + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &mi->flags, FALSE); + + mi->flags &= ~CAMEL_MESSAGE_INFO_NEEDS_FREE; + mi->flags &= ~CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + mi->flags &= ~CAMEL_MESSAGE_FREED; + + s->set_extra_flags_func (s->folder, mi); + + ptrchr = camel_file_util_mmap_decode_time_t (ptrchr, &mi->date_sent); + ptrchr = camel_file_util_mmap_decode_time_t (ptrchr, &mi->date_received); + + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE); + + if (len) + mi->subject = (const char*)ptrchr; + + ptrchr += len; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE); + + if (len) + mi->from = (const char*)ptrchr; + + ptrchr += len; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE); + + if (len) + mi->to = (const char*)ptrchr; + ptrchr += len; + + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE); + + if (len) + mi->cc = (const char*)ptrchr; + ptrchr += len; + + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE); + +#ifdef NON_TINYMAIL_FEATURES + if (len) + mi->mlist = (const char*)ptrchr; +#endif + + ptrchr += len; + s->filepos = ptrchr; + +/* #ifdef NON_TINYMAIL_FEATURES */ + mi->message_id.id.part.hi = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + mi->message_id.id.part.lo = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; +/* #else + s->filepos += 8; +#endif */ + + ptrchr = (unsigned char*) s->filepos; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &count, FALSE); + +#ifdef NON_TINYMAIL_FEATURES + if (mi->references) + g_free (mi->references); + mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0]))); + mi->references->size = count; +#endif + + s->filepos = ptrchr; + +#ifdef NON_TINYMAIL_FEATURES for (i=0;iuser_tags, name, value); - g_free(name); - g_free(value); + mi->references->references[i].id.part.hi = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; + mi->references->references[i].id.part.lo = g_ntohl(get_unaligned_u32(s->filepos)); + s->filepos += 4; } +#else + s->filepos += (count * 8); +#endif - if (!ferror(in)) - return (CamelMessageInfo *)mi; - -error: - camel_message_info_free((CamelMessageInfo *)mi); + ptrchr = s->filepos; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &count, FALSE); - return NULL; -} + for (i=0;ifilepos = ptrchr; - time (×tamp); - offset = ftell (out); - /* FIXME: errno check after ftell */ - - camel_file_util_encode_time_t(out_meta, timestamp); - camel_file_util_encode_fixed_string(out_meta, camel_message_info_uid(mi), s->meta_summary->uid_len); - camel_file_util_encode_uint32(out_meta, mi->flags); - camel_file_util_encode_off_t(out_meta, offset); + return (CamelMessageInfo *)mi; - return ferror(out); } static int message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) { guint32 count; +#ifdef NON_TINYMAIL_FEATURES CamelFlag *flag; CamelTag *tag; int i; +#endif CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; + /* if (mi->flags & CAMEL_MESSAGE_INFO_NEEDS_FREE) + return -1; */ + io(printf("Saving message info\n")); camel_file_util_encode_string(out, camel_message_info_uid(mi)); - camel_file_util_encode_uint32(out, mi->flags); + camel_file_util_encode_uint32(out, mi->size); + camel_file_util_encode_uint32(out, mi->flags); + camel_file_util_encode_time_t(out, mi->date_sent); camel_file_util_encode_time_t(out, mi->date_received); camel_file_util_encode_string(out, camel_message_info_subject(mi)); camel_file_util_encode_string(out, camel_message_info_from(mi)); camel_file_util_encode_string(out, camel_message_info_to(mi)); camel_file_util_encode_string(out, camel_message_info_cc(mi)); + +#ifdef NON_TINYMAIL_FEATURES camel_file_util_encode_string(out, camel_message_info_mlist(mi)); +#else + camel_file_util_encode_string(out, ""); +#endif camel_file_util_encode_fixed_int32(out, mi->message_id.id.part.hi); camel_file_util_encode_fixed_int32(out, mi->message_id.id.part.lo); +#ifdef NON_TINYMAIL_FEATURES if (mi->references) { camel_file_util_encode_uint32(out, mi->references->size); for (i=0;ireferences->size;i++) { @@ -1930,47 +2274,115 @@ camel_file_util_encode_fixed_int32(out, mi->references->references[i].id.part.lo); } } else { +#endif camel_file_util_encode_uint32(out, 0); - } +#ifdef NON_TINYMAIL_FEATURES + } count = camel_flag_list_size(&mi->user_flags); +#else + count = 0; +#endif + camel_file_util_encode_uint32(out, count); + +#ifdef NON_TINYMAIL_FEATURES flag = mi->user_flags; while (flag) { camel_file_util_encode_string(out, flag->name); flag = flag->next; } +#endif +#ifdef NON_TINYMAIL_FEATURES count = camel_tag_list_size(&mi->user_tags); +#else + count = 0; +#endif + camel_file_util_encode_uint32(out, count); + +#ifdef NON_TINYMAIL_FEATURES tag = mi->user_tags; while (tag) { camel_file_util_encode_string(out, tag->name); camel_file_util_encode_string(out, tag->value); tag = tag->next; } +#endif return ferror(out); } +#ifdef MEMDEBUG +static int freed=0; +#endif + +static void +destroy_possible_pstring_stuff(CamelFolderSummary *s, CamelMessageInfo *info, gboolean freeuid) +{ + CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; + +#ifdef MEMDEBUG + printf ("Freeup %d, %s\n", freed++, (mi->flags & CAMEL_MESSAGE_INFO_NEEDS_FREE)?"YES":"NO"); +#endif + + if (mi->flags & CAMEL_MESSAGE_INFO_NEEDS_FREE) + { + if (freeuid && (mi->flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE)) + { + g_free(mi->uid); + mi->flags &= ~CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + } + + if (mi->subject) + camel_pstring_free(mi->subject); + if (mi->from) + camel_pstring_free(mi->from); + if (mi->to) + camel_pstring_free(mi->to); + if (mi->cc) + camel_pstring_free(mi->cc); + +#ifdef NON_TINYMAIL_FEATURES + if (mi->mlist) + camel_pstring_free(mi->mlist); + camel_flag_list_free(&mi->user_flags); + camel_tag_list_free(&mi->user_tags); +#endif + + mi->flags &= ~CAMEL_MESSAGE_INFO_NEEDS_FREE; + + } else if (freeuid && (mi->flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE)) + { + g_free (mi->uid); + mi->flags &= ~CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + } +#ifdef NON_TINYMAIL_FEATURES + g_free(mi->references); +#endif + + return; +} + static void message_info_free(CamelFolderSummary *s, CamelMessageInfo *info) { CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; - g_free(mi->uid); - camel_pstring_free(mi->subject); - camel_pstring_free(mi->from); - camel_pstring_free(mi->to); - camel_pstring_free(mi->cc); - camel_pstring_free(mi->mlist); - g_free(mi->references); - camel_flag_list_free(&mi->user_flags); - camel_tag_list_free(&mi->user_tags); + destroy_possible_pstring_stuff (s, info, TRUE); + + /* memset: Trash it, makes debugging more easy */ + if (s) - e_memchunk_free(s->message_info_chunks, mi); - else - g_free(mi); + { + memset (info, 0, s->message_info_size); + g_slice_free1 (s->message_info_size, mi); + } else + { + memset (info, 0, sizeof (CamelMessageInfoBase)); + g_slice_free (CamelMessageInfoBase, (CamelMessageInfoBase*) mi); + } } static CamelMessageContentInfo * @@ -1980,75 +2392,75 @@ const char *charset; ci = camel_folder_summary_content_info_new (s); + ci->needs_free = TRUE; charset = e_iconv_locale_charset (); - ci->id = camel_header_msgid_decode (camel_header_raw_find (&h, "content-id", NULL)); - ci->description = camel_header_decode_string (camel_header_raw_find (&h, "content-description", NULL), charset); - ci->encoding = camel_content_transfer_encoding_decode (camel_header_raw_find (&h, "content-transfer-encoding", NULL)); + + ci->id = token_add (camel_header_msgid_decode (camel_header_raw_find (&h, "content-id", NULL))); + ci->description = token_add (camel_header_decode_string (camel_header_raw_find (&h, "content-description", NULL), charset)); + ci->encoding = token_add (camel_content_transfer_encoding_decode (camel_header_raw_find (&h, "content-transfer-encoding", NULL))); ci->type = camel_content_type_decode(camel_header_raw_find(&h, "content-type", NULL)); return ci; } static CamelMessageContentInfo * -content_info_load(CamelFolderSummary *s, FILE *in) +content_info_load(CamelFolderSummary *s) { CamelMessageContentInfo *ci; char *type, *subtype; guint32 count, i; CamelContentType *ct; + unsigned char *ptrchr = s->filepos; io(printf("Loading content info\n")); ci = camel_folder_summary_content_info_new(s); - - camel_folder_summary_decode_token(in, &type); - camel_folder_summary_decode_token(in, &subtype); + ci->needs_free = FALSE; + + camel_folder_summary_decode_token(s, &type); + camel_folder_summary_decode_token(s, &subtype); + ct = camel_content_type_new(type, subtype); - g_free(type); /* can this be removed? */ - g_free(subtype); - if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) - goto error; - - for (i=0;ifilepos; + ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &count, FALSE); + s->filepos = ptrchr; + + for (i=0; i < count; i++) + { char *name, *value; - camel_folder_summary_decode_token(in, &name); - camel_folder_summary_decode_token(in, &value); - if (!(name && value)) - goto error; + camel_folder_summary_decode_token(s, &name); + camel_folder_summary_decode_token(s, &value); - camel_content_type_set_param(ct, name, value); - /* TODO: do this so we dont have to double alloc/free */ - g_free(name); - g_free(value); + camel_content_type_set_param (ct, name, value); } - ci->type = ct; - camel_folder_summary_decode_token(in, &ci->id); - camel_folder_summary_decode_token(in, &ci->description); - camel_folder_summary_decode_token(in, &ci->encoding); + ci->type = ct; - camel_file_util_decode_uint32(in, &ci->size); + camel_folder_summary_decode_token(s, &ci->id); + camel_folder_summary_decode_token(s, &ci->description); + camel_folder_summary_decode_token(s, &ci->encoding); + + ptrchr = s->filepos; + ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &ci->size, FALSE); + s->filepos = ptrchr; ci->childs = NULL; - if (!ferror(in)) - return ci; - - error: - camel_folder_summary_content_info_free(s, ci); - return NULL; + return ci; } static int content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci) { - CamelContentType *ct; + CamelContentType *ct=NULL; struct _camel_header_param *hp; io(printf("Saving content info\n")); ct = ci->type; + if (ct) { camel_folder_summary_encode_token(out, ct->type); camel_folder_summary_encode_token(out, ct->subtype); @@ -2070,14 +2482,23 @@ return camel_file_util_encode_uint32(out, ci->size); } + static void content_info_free(CamelFolderSummary *s, CamelMessageContentInfo *ci) { camel_content_type_unref(ci->type); - g_free(ci->id); - g_free(ci->description); - g_free(ci->encoding); - e_memchunk_free(s->content_info_chunks, ci); + + if (ci->needs_free) + { + token_free (ci->id); + token_free (ci->description); + token_free (ci->encoding); + } + + if (s != NULL) + g_slice_free1(s->content_info_size, ci); + else + g_slice_free (CamelMessageContentInfo, ci); } static char * @@ -2102,8 +2523,6 @@ CamelMessageContentInfo *info = NULL; CamelContentType *ct; int enc_id = -1, chr_id = -1, html_id = -1, idx_id = -1; - struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); - CamelMimeFilterCharset *mfc; CamelMessageContentInfo *part; d(printf("building content info\n")); @@ -2119,6 +2538,8 @@ /* check content type for indexing, then read body */ ct = camel_mime_parser_content_type(mp); /* update attachments flag as we go */ + + if (camel_content_type_is(ct, "application", "pgp-signature") #ifdef ENABLE_SMIME || camel_content_type_is(ct, "application", "x-pkcs7-signature") @@ -2127,74 +2548,7 @@ ) camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_SECURE, CAMEL_MESSAGE_SECURE); - if (p->index && camel_content_type_is(ct, "text", "*")) { - char *encoding; - const char *charset; - - d(printf("generating index:\n")); - - encoding = camel_content_transfer_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL)); - if (encoding) { - if (!g_ascii_strcasecmp(encoding, "base64")) { - d(printf(" decoding base64\n")); - if (p->filter_64 == NULL) - p->filter_64 = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_DEC); - else - camel_mime_filter_reset((CamelMimeFilter *)p->filter_64); - enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_64); - } else if (!g_ascii_strcasecmp(encoding, "quoted-printable")) { - d(printf(" decoding quoted-printable\n")); - if (p->filter_qp == NULL) - p->filter_qp = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_DEC); - else - camel_mime_filter_reset((CamelMimeFilter *)p->filter_qp); - enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_qp); - } else if (!g_ascii_strcasecmp (encoding, "x-uuencode")) { - d(printf(" decoding x-uuencode\n")); - if (p->filter_uu == NULL) - p->filter_uu = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_UU_DEC); - else - camel_mime_filter_reset((CamelMimeFilter *)p->filter_uu); - enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_uu); - } else { - d(printf(" ignoring encoding %s\n", encoding)); - } - g_free(encoding); - } - - charset = camel_content_type_param(ct, "charset"); - if (charset!=NULL - && !(g_ascii_strcasecmp(charset, "us-ascii")==0 - || g_ascii_strcasecmp(charset, "utf-8")==0)) { - d(printf(" Adding conversion filter from %s to UTF-8\n", charset)); - mfc = g_hash_table_lookup(p->filter_charset, charset); - if (mfc == NULL) { - mfc = camel_mime_filter_charset_new_convert(charset, "UTF-8"); - if (mfc) - g_hash_table_insert(p->filter_charset, g_strdup(charset), mfc); - } else { - camel_mime_filter_reset((CamelMimeFilter *)mfc); - } - if (mfc) { - chr_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)mfc); - } else { - w(g_warning("Cannot convert '%s' to 'UTF-8', message index may be corrupt", charset)); - } - } - /* we do charset conversions before this filter, which isn't strictly correct, - but works in most cases */ - if (camel_content_type_is(ct, "text", "html")) { - if (p->filter_html == NULL) - p->filter_html = camel_mime_filter_html_new(); - else - camel_mime_filter_reset((CamelMimeFilter *)p->filter_html); - html_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_html); - } - - /* and this filter actually does the indexing */ - idx_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_index); - } /* and scan/index everything */ while (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) ; @@ -2253,13 +2607,18 @@ { CamelDataWrapper *containee; int parts, i; - struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); + struct _CamelFolderSummaryPrivate *p; CamelMessageContentInfo *info = NULL, *child; CamelContentType *ct; - if (s->build_content) + if (s != NULL && s->build_content) info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_message(s, object); - + else + info = content_info_new_from_message(NULL, object); + + if (s != NULL) + p = _PRIVATE(s); + containee = camel_medium_get_content_object(CAMEL_MEDIUM(object)); if (containee == NULL) @@ -2304,7 +2663,7 @@ child->parent = info; my_list_append((struct _node **)&info->childs, (struct _node *)child); } - } else if (p->filter_stream + } else if (s != NULL && p->filter_stream && camel_content_type_is(ct, "text", "*")) { int html_id = -1, idx_id = -1; @@ -2649,7 +3008,6 @@ { "flagged", CAMEL_MESSAGE_FLAGGED }, { "seen", CAMEL_MESSAGE_SEEN }, { "attachments", CAMEL_MESSAGE_ATTACHMENTS }, - { "junk", CAMEL_MESSAGE_JUNK }, { "secure", CAMEL_MESSAGE_SECURE }, { NULL, 0 } }; @@ -2707,15 +3065,12 @@ { CamelMessageInfo *info; - if (s) { - CAMEL_SUMMARY_LOCK(s, alloc_lock); - if (s->message_info_chunks == NULL) - s->message_info_chunks = e_memchunk_new(32, s->message_info_size); - info = e_memchunk_alloc0(s->message_info_chunks); - CAMEL_SUMMARY_UNLOCK(s, alloc_lock); - } else { - info = g_malloc0(sizeof(CamelMessageInfoBase)); - } + if (s) + info = g_slice_alloc0(s->message_info_size); + else + info = (CamelMessageInfo *) g_slice_new0(CamelMessageInfoBase); + + ((CamelMessageInfoBase *)info)->flags = 0; info->refcount = 1; info->summary = s; @@ -2748,6 +3103,16 @@ } } +void * +camel_message_info_new_uid (CamelFolderSummary *summary, const char *uid) +{ + CamelMessageInfoBase *mi = (CamelMessageInfoBase *)camel_message_info_new(summary); + mi->uid = g_strdup (uid); + mi->flags |= CAMEL_MESSAGE_INFO_NEEDS_FREE; + mi->flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + return mi; +} + /** * camel_message_info_new_from_header: @@ -2780,6 +3145,8 @@ { CamelMessageInfo *mi = o; + /* camel_message_info_set_flags(mi, CAMEL_MESSAGE_FREED, CAMEL_MESSAGE_FREED); */ + g_return_if_fail(mi != NULL); if (mi->summary) { @@ -2795,8 +3162,8 @@ CAMEL_SUMMARY_UNLOCK(mi->summary, ref_lock); /* FIXME: this is kinda busted, should really be handled by message info free */ - if (mi->summary->build_content - && ((CamelMessageInfoBase *)mi)->content) { + if (/* mi->summary->build_content + && */((CamelMessageInfoBase *)mi)->content) { camel_folder_summary_content_info_free(mi->summary, ((CamelMessageInfoBase *)mi)->content); } @@ -2810,7 +3177,11 @@ } GLOBAL_INFO_UNLOCK(info); + if (((CamelMessageInfoBase *)mi)->content) + camel_folder_summary_content_info_free(NULL, ((CamelMessageInfoBase *)mi)->content); + message_info_free(NULL, mi); + } } @@ -2818,23 +3189,30 @@ message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi) { CamelMessageInfoBase *to, *from = (CamelMessageInfoBase *)mi; +#ifdef NON_TINYMAIL_FEATURES CamelFlag *flag; CamelTag *tag; - +#endif to = (CamelMessageInfoBase *)camel_message_info_new(s); to->flags = from->flags; to->size = from->size; + to->date_sent = from->date_sent; to->date_received = from->date_received; to->refcount = 1; /* NB: We don't clone the uid */ + to->flags |= CAMEL_MESSAGE_INFO_NEEDS_FREE; + to->flags &= ~CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + to->subject = camel_pstring_strdup(from->subject); to->from = camel_pstring_strdup(from->from); to->to = camel_pstring_strdup(from->to); to->cc = camel_pstring_strdup(from->cc); + +#ifdef NON_TINYMAIL_FEATURES to->mlist = camel_pstring_strdup(from->mlist); memcpy(&to->message_id, &from->message_id, sizeof(to->message_id)); @@ -2844,7 +3222,9 @@ to->references = g_malloc(len); memcpy(to->references, from->references, len); } +#endif +#ifdef NON_TINYMAIL_FEATURES flag = from->user_flags; while (flag) { camel_flag_set(&to->user_flags, flag->name, TRUE); @@ -2856,10 +3236,7 @@ camel_tag_set(&to->user_tags, tag->name, tag->value); tag = tag->next; } - - if (from->content) { - /* FIXME: copy content-infos */ - } +#endif return (CamelMessageInfo *)to; } @@ -2878,75 +3255,113 @@ { const CamelMessageInfo *mi = o; + if (mi == NULL || mi->refcount <=0) + return NULL; + if (mi->summary) return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->message_info_clone(mi->summary, mi); else return message_info_clone(NULL, mi); } + static const void * info_ptr(const CamelMessageInfo *mi, int id) { - switch (id) { - case CAMEL_MESSAGE_INFO_SUBJECT: - return ((const CamelMessageInfoBase *)mi)->subject; - case CAMEL_MESSAGE_INFO_FROM: - return ((const CamelMessageInfoBase *)mi)->from; - case CAMEL_MESSAGE_INFO_TO: - return ((const CamelMessageInfoBase *)mi)->to; - case CAMEL_MESSAGE_INFO_CC: - return ((const CamelMessageInfoBase *)mi)->cc; - case CAMEL_MESSAGE_INFO_MLIST: - return ((const CamelMessageInfoBase *)mi)->mlist; - case CAMEL_MESSAGE_INFO_MESSAGE_ID: - return &((const CamelMessageInfoBase *)mi)->message_id; - case CAMEL_MESSAGE_INFO_REFERENCES: - return ((const CamelMessageInfoBase *)mi)->references; - case CAMEL_MESSAGE_INFO_USER_FLAGS: - return ((const CamelMessageInfoBase *)mi)->user_flags; - case CAMEL_MESSAGE_INFO_USER_TAGS: - return ((const CamelMessageInfoBase *)mi)->user_tags; - default: - abort(); + const void *retval; + + g_static_rec_mutex_lock (&global_lock); + g_static_mutex_lock (&global_lock2); + + if (G_UNLIKELY (mi == NULL || mi->refcount <=0)) + retval = "Invalid refcount"; + if (G_UNLIKELY(((CamelMessageInfoBase*)mi)->flags & CAMEL_MESSAGE_FREED)) + retval = "Invalid"; + else switch (id) + { + case CAMEL_MESSAGE_INFO_SUBJECT: + retval = ((const CamelMessageInfoBase *)mi)->subject; + break; + case CAMEL_MESSAGE_INFO_FROM: + retval = ((const CamelMessageInfoBase *)mi)->from; + break; + case CAMEL_MESSAGE_INFO_TO: + retval = ((const CamelMessageInfoBase *)mi)->to; + break; + case CAMEL_MESSAGE_INFO_CC: + retval = ((const CamelMessageInfoBase *)mi)->cc; + break; + case CAMEL_MESSAGE_INFO_MESSAGE_ID: + retval = &((const CamelMessageInfoBase *)mi)->message_id; + break; } + + g_static_mutex_unlock (&global_lock2); + g_static_rec_mutex_unlock (&global_lock); + + return retval; } static guint32 info_uint32(const CamelMessageInfo *mi, int id) { - switch (id) { - case CAMEL_MESSAGE_INFO_FLAGS: - return ((const CamelMessageInfoBase *)mi)->flags; - case CAMEL_MESSAGE_INFO_SIZE: - return ((const CamelMessageInfoBase *)mi)->size; - default: - abort(); + guint32 retval; + + g_static_rec_mutex_lock (&global_lock); + + if (mi == NULL || mi->refcount <=0) + retval = 0; + else switch (id) + { + case CAMEL_MESSAGE_INFO_FLAGS: + retval = ((const CamelMessageInfoBase *)mi)->flags; + break; + case CAMEL_MESSAGE_INFO_SIZE: + retval = ((const CamelMessageInfoBase *)mi)->size; + break; } + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } static time_t info_time(const CamelMessageInfo *mi, int id) { - switch (id) { - case CAMEL_MESSAGE_INFO_DATE_SENT: - return ((const CamelMessageInfoBase *)mi)->date_sent; - case CAMEL_MESSAGE_INFO_DATE_RECEIVED: - return ((const CamelMessageInfoBase *)mi)->date_received; - default: - abort(); + time_t retval; + + g_static_rec_mutex_lock (&global_lock); + + if (mi == NULL || mi->refcount <=0) + retval = 0; + else switch (id) + { + case CAMEL_MESSAGE_INFO_DATE_SENT: + retval = ((const CamelMessageInfoBase *)mi)->date_sent; + break; + case CAMEL_MESSAGE_INFO_DATE_RECEIVED: + retval = ((const CamelMessageInfoBase *)mi)->date_received; + break; + default: + abort(); } + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } static gboolean info_user_flag(const CamelMessageInfo *mi, const char *id) { - return camel_flag_get(&((CamelMessageInfoBase *)mi)->user_flags, id); + return FALSE; } static const char * info_user_tag(const CamelMessageInfo *mi, const char *id) { - return camel_tag_get(&((CamelMessageInfoBase *)mi)->user_tags, id); + return NULL; } @@ -2962,10 +3377,26 @@ const void * camel_message_info_ptr(const CamelMessageInfo *mi, int id) { - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_ptr(mi, id); + const void * retval; + + g_static_rec_mutex_lock (&global_lock); + + if (mi==NULL || mi->refcount <= 0) + retval = NULL; else - return info_ptr(mi, id); + { + if (mi->summary) + if (((CamelObject*)mi->summary)->ref_count > 0 && CAMEL_IS_FOLDER_SUMMARY (mi->summary)) + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_ptr(mi, id); + else + retval = NULL; + else + retval = info_ptr(mi, id); + } + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } @@ -2981,10 +3412,26 @@ guint32 camel_message_info_uint32(const CamelMessageInfo *mi, int id) { - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_uint32(mi, id); + guint32 retval; + + g_static_rec_mutex_lock (&global_lock); + + if (mi == NULL || mi->refcount <=0) + retval = 0; else - return info_uint32(mi, id); + { + if (mi->summary) + if (CAMEL_IS_FOLDER_SUMMARY (mi->summary)) + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_uint32(mi, id); + else + retval = 0; + else + retval = info_uint32(mi, id); + } + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } @@ -2998,12 +3445,28 @@ * Returns the time_t data **/ time_t -camel_message_info_time(const CamelMessageInfo *mi, int id) +camel_message_info_time (const CamelMessageInfo *mi, int id) { - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_time(mi, id); - else - return info_time(mi, id); + time_t retval; + + g_static_rec_mutex_lock (&global_lock); + + if (mi == NULL || mi->refcount <=0) + retval = 0; + else + { + if (mi->summary) + if (CAMEL_IS_FOLDER_SUMMARY (mi->summary)) + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_time(mi, id); + else + retval = -1; + else + retval = info_time(mi, id); + } + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } @@ -3019,10 +3482,21 @@ gboolean camel_message_info_user_flag(const CamelMessageInfo *mi, const char *id) { + gboolean retval; + + g_static_rec_mutex_lock (&global_lock); + if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_user_flag(mi, id); + if (CAMEL_IS_FOLDER_SUMMARY (mi->summary)) + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_user_flag(mi, id); + else + retval = FALSE; else - return info_user_flag(mi, id); + retval = info_user_flag(mi, id); + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } @@ -3038,16 +3512,27 @@ const char * camel_message_info_user_tag(const CamelMessageInfo *mi, const char *id) { + const char * retval; + + g_static_rec_mutex_lock (&global_lock); + if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_user_tag(mi, id); + if (CAMEL_IS_FOLDER_SUMMARY (mi->summary)) + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_user_tag(mi, id); + else + retval = NULL; else - return info_user_tag(mi, id); + retval = info_user_tag(mi, id); + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } static gboolean info_set_flags(CamelMessageInfo *info, guint32 flags, guint32 set) { - guint32 old; + guint16 old; CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; /* TODO: locking? */ @@ -3060,7 +3545,7 @@ camel_folder_summary_touch(mi->summary); } - if (((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) && !((set & CAMEL_MESSAGE_JUNK_LEARN) && !(set & CAMEL_MESSAGE_JUNK))) + if ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) return FALSE; if (mi->summary && mi->summary->folder && mi->uid) { @@ -3088,10 +3573,21 @@ gboolean camel_message_info_set_flags(CamelMessageInfo *mi, guint32 flags, guint32 set) { + gboolean retval; + + g_static_rec_mutex_lock (&global_lock); + if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_flags(mi, flags, set); + if (CAMEL_IS_FOLDER_SUMMARY (mi->summary)) + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_flags(mi, flags, set); + else + retval = FALSE; else - return info_set_flags(mi, flags, set); + retval = info_set_flags(mi, flags, set); + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } static gboolean @@ -3100,7 +3596,11 @@ CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; int res; + g_static_rec_mutex_lock (&global_lock); + +#ifdef NON_TINYMAIL_FEATURES res = camel_flag_set(&mi->user_flags, name, value); +#endif /* TODO: check this item is still in the summary first */ if (mi->summary && res && mi->summary->folder && mi->uid) { @@ -3113,6 +3613,8 @@ camel_folder_change_info_free(changes); } + g_static_rec_mutex_unlock (&global_lock); + return res; } @@ -3130,10 +3632,18 @@ gboolean camel_message_info_set_user_flag(CamelMessageInfo *mi, const char *id, gboolean state) { + gboolean retval; + + g_static_rec_mutex_lock (&global_lock); + if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_user_flag(mi, id, state); + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_user_flag(mi, id, state); else - return info_set_user_flag(mi, id, state); + retval = info_set_user_flag(mi, id, state); + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } static gboolean @@ -3142,7 +3652,11 @@ CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; int res; + g_static_rec_mutex_lock (&global_lock); + +#ifdef NON_TINYMAIL_FEATURES res = camel_tag_set(&mi->user_tags, name, value); +#endif if (mi->summary && res && mi->summary->folder && mi->uid) { CamelFolderChangeInfo *changes = camel_folder_change_info_new(); @@ -3154,6 +3668,8 @@ camel_folder_change_info_free(changes); } + g_static_rec_mutex_unlock (&global_lock); + return res; } @@ -3171,10 +3687,18 @@ gboolean camel_message_info_set_user_tag(CamelMessageInfo *mi, const char *id, const char *val) { + gboolean retval; + + g_static_rec_mutex_lock (&global_lock); + if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_user_tag(mi, id, val); + retval = ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_user_tag(mi, id, val); else - return info_set_user_tag(mi, id, val); + retval = info_set_user_tag(mi, id, val); + + g_static_rec_mutex_unlock (&global_lock); + + return retval; } void @@ -3217,7 +3741,9 @@ printf("Subject: %s\n", camel_message_info_subject(mi)); printf("To: %s\n", camel_message_info_to(mi)); printf("Cc: %s\n", camel_message_info_cc(mi)); +#ifdef NON_TINYMAIL_FEATURES printf("mailing list: %s\n", camel_message_info_mlist(mi)); +#endif printf("From: %s\n", camel_message_info_from(mi)); printf("UID: %s\n", camel_message_info_uid(mi)); printf("Flags: %04x\n", camel_message_info_flags(mi)); @@ -3238,7 +3764,6 @@ klass->message_info_new_from_message = message_info_new_from_message; klass->message_info_load = message_info_load; klass->message_info_save = message_info_save; - klass->meta_message_info_save = meta_message_info_save; klass->message_info_free = message_info_free; klass->message_info_clone = message_info_clone; Only in .: camel-folder-summary.c.rej diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-summary.h ./camel-folder-summary.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-summary.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder-summary.h 2007-05-12 10:31:09.000000000 +0200 @@ -22,11 +22,12 @@ #ifndef _CAMEL_FOLDER_SUMMARY_H #define _CAMEL_FOLDER_SUMMARY_H + #include #include #include #include -#include + #define CAMEL_FOLDER_SUMMARY_TYPE camel_folder_summary_get_type () #define CAMEL_FOLDER_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_folder_summary_get_type (), CamelFolderSummary) @@ -58,34 +59,32 @@ char *description; char *encoding; /* this should be an enum?? */ guint32 size; + gboolean needs_free; }; /* system flag bits */ typedef enum _CamelMessageFlags { - CAMEL_MESSAGE_ANSWERED = 1<<0, - CAMEL_MESSAGE_DELETED = 1<<1, - CAMEL_MESSAGE_DRAFT = 1<<2, - CAMEL_MESSAGE_FLAGGED = 1<<3, - CAMEL_MESSAGE_SEEN = 1<<4, - - /* these aren't really system flag bits, but are convenience flags */ - CAMEL_MESSAGE_ATTACHMENTS = 1<<5, - CAMEL_MESSAGE_ANSWERED_ALL = 1<<6, - CAMEL_MESSAGE_JUNK = 1<<7, - CAMEL_MESSAGE_SECURE = 1<<8, - CAMEL_MESSAGE_USER_NOT_DELETABLE = 1<<9, - CAMEL_MESSAGE_HIDDEN = 1<<10, - - /* following flags are for the folder, and are not really permanent flags */ - CAMEL_MESSAGE_FOLDER_FLAGGED = 1<<16, /* for use by the folder implementation */ + CAMEL_MESSAGE_ANSWERED = 1<<0, /* used TNY_HEADER_FLAG_ANSWERED */ + CAMEL_MESSAGE_DELETED = 1<<1, /* used TNY_HEADER_FLAG_DELETED */ + CAMEL_MESSAGE_DRAFT = 1<<2, /* used TNY_HEADER_FLAG_DRAFT */ + CAMEL_MESSAGE_FLAGGED = 1<<3, /* used TNY_HEADER_FLAG_FLAGGED */ + CAMEL_MESSAGE_SEEN = 1<<4, /* used TNY_HEADER_FLAG_SEEN */ + CAMEL_MESSAGE_ATTACHMENTS = 1<<5, /* used TNY_HEADER_FLAG_ATTACHMENTS */ + CAMEL_MESSAGE_CACHED = 1<<6, /* used TNY_HEADER_FLAG_CACHED */ + CAMEL_MESSAGE_PARTIAL = 1<<7, /* used TNY_HEADER_FLAG_PARTIAL */ + CAMEL_MESSAGE_EXPUNGED = 1<<8, /* used TNY_HEADER_FLAG_EXPUNGED */ + CAMEL_MESSAGE_HIGH_PRIORITY = 1<<9|1<<10, /* used TNY_HEADER_FLAG_HIGH_PRIORITY */ + CAMEL_MESSAGE_NORMAL_PRIORITY = 0<<9|0<<10, /* used TNY_HEADER_FLAG_NORMAL_PRIORITY */ + CAMEL_MESSAGE_LOW_PRIORITY = 0<<9|1<<10, /* used TNY_HEADER_FLAG_LOW_PRIORITY */ + + /* internally used */ + CAMEL_MESSAGE_FOLDER_FLAGGED = 1<<12, /* internally used */ + CAMEL_MESSAGE_INFO_NEEDS_FREE = 1<<13,/* internally used */ + CAMEL_MESSAGE_INFO_UID_NEEDS_FREE = 1<<14, /* internally used */ + CAMEL_MESSAGE_FREED = 1<<15, /* internally used */ + CAMEL_MESSAGE_USER = 1<<16, /* free slot */ + CAMEL_MESSAGE_SECURE = 1<<17, /* free slot */ - /* flags after 1<<16 are used by camel providers, - if adding non permanent flags, add them to the end */ - - CAMEL_MESSAGE_JUNK_LEARN = 1<<30, /* used when setting CAMEL_MESSAGE_JUNK flag - to say that we request junk plugin - to learn that message as junk/non junk */ - CAMEL_MESSAGE_USER = 1<<31 /* supports user flags */ } CamelMessageFlags; /* Changes to system flags will NOT trigger a folder changed event */ @@ -114,11 +113,6 @@ } id; } CamelSummaryMessageID; -/* summary references is a fixed size array of references */ -typedef struct _CamelSummaryReferences { - int size; - CamelSummaryMessageID references[1]; -} CamelSummaryReferences; /* accessor id's */ enum { @@ -145,7 +139,6 @@ /* information about a given message, use accessors */ struct _CamelMessageInfo { CamelFolderSummary *summary; - guint32 refcount; /* ??? */ char *uid; }; @@ -153,48 +146,37 @@ /* For classes wishing to do the provided i/o, or for anonymous users, * they must subclass or use this messageinfo structure */ /* Otherwise they can do their own thing entirely */ -struct _CamelMessageInfoBase { - CamelFolderSummary *summary; - guint32 refcount; /* ??? */ - char *uid; - - const char *subject; - const char *from; - const char *to; - const char *cc; - const char *mlist; +/* on x86_32 */ +struct _CamelMessageInfoBase +{ + CamelFolderSummary *summary; /* 4 bytes */ + guint32 refcount; /* 4 bytes */ + char *uid; /* 4 bytes */ + const char *subject; /* 4 bytes */ + const char *from; /* 4 bytes */ + const char *to; /* 4 bytes */ + const char *cc; /* 4 bytes */ - guint32 flags; - guint32 size; - - time_t date_sent; - time_t date_received; + /* tree of content description - NULL if it is not available */ + CamelMessageContentInfo *content; /* 4 bytes */ + CamelSummaryMessageID message_id; /* 8 bytes */ - CamelSummaryMessageID message_id; - CamelSummaryReferences *references;/* from parent to root */ + guint32 flags; /* 4 bytes */ + guint32 size; /* 4 bytes */ - struct _CamelFlag *user_flags; - struct _CamelTag *user_tags; + time_t date_sent; /* 4 bytes */ + time_t date_received; /* 4 bytes */ - /* tree of content description - NULL if it is not available */ - CamelMessageContentInfo *content; + /* 56 bytes */ }; -/* probably do this as well, removing CamelFolderChangeInfo and interfaces -typedef struct _CamelChangeInfo CamelChangeInfo; -struct _CamelChangeInfo { - GPtrArray *added; - GPtrArray *removed; - GPtrArray *changed; - GPtrArray *recent; -}; -*/ typedef enum _CamelFolderSummaryFlags { CAMEL_SUMMARY_DIRTY = 1<<0, } CamelFolderSummaryFlags; + struct _CamelFolderSummary { CamelObject parent; @@ -214,32 +196,36 @@ guint32 message_info_size; guint32 content_info_size; - /* memory allocators (setup automatically) */ - struct _EMemChunk *message_info_chunks; - struct _EMemChunk *content_info_chunks; - char *summary_path; gboolean build_content; /* do we try and parse/index the content, or not? */ - GPtrArray *messages; /* CamelMessageInfo's */ - GHashTable *messages_uid; /* CamelMessageInfo's by uid */ + GPtrArray *messages, *expunged; /* CamelMessageInfo's */ + GHashTable *uidhash; struct _CamelFolder *folder; /* parent folder, for events */ struct _CamelFolderMetaSummary *meta_summary; /* Meta summary */ + + GMappedFile *file; + unsigned char *filepos; + GMutex *dump_lock, *hash_lock; + gboolean in_reload; + gint idx; + + void (*set_extra_flags_func) (CamelFolder *folder, CamelMessageInfoBase *mi); }; struct _CamelFolderSummaryClass { CamelObjectClass parent_class; /* load/save the global info */ - int (*summary_header_load)(CamelFolderSummary *, FILE *); + int (*summary_header_load)(CamelFolderSummary *); int (*summary_header_save)(CamelFolderSummary *, FILE *); /* create/save/load an individual message info */ CamelMessageInfo * (*message_info_new_from_header)(CamelFolderSummary *, struct _camel_header_raw *); CamelMessageInfo * (*message_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *); CamelMessageInfo * (*message_info_new_from_message)(CamelFolderSummary *, CamelMimeMessage *); - CamelMessageInfo * (*message_info_load)(CamelFolderSummary *, FILE *); + CamelMessageInfo * (*message_info_load)(CamelFolderSummary *, gboolean *must_add); int (*message_info_save)(CamelFolderSummary *, FILE *, CamelMessageInfo *); int (*meta_message_info_save)(CamelFolderSummary *, FILE *, FILE *, CamelMessageInfo *); @@ -250,7 +236,7 @@ CamelMessageContentInfo * (*content_info_new_from_header)(CamelFolderSummary *, struct _camel_header_raw *); CamelMessageContentInfo * (*content_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *); CamelMessageContentInfo * (*content_info_new_from_message)(CamelFolderSummary *, CamelMimePart *); - CamelMessageContentInfo * (*content_info_load)(CamelFolderSummary *, FILE *); + CamelMessageContentInfo * (*content_info_load)(CamelFolderSummary *); int (*content_info_save)(CamelFolderSummary *, FILE *, CamelMessageContentInfo *); void (*content_info_free)(CamelFolderSummary *, CamelMessageContentInfo *); @@ -265,16 +251,10 @@ gboolean (*info_user_flag)(const CamelMessageInfo *mi, const char *id); const char *(*info_user_tag)(const CamelMessageInfo *mi, const char *id); - /* set accessors for the modifyable bits */ -#if 0 - void (*info_set_ptr)(CamelMessageInfo *mi, int id, const void *val); - void (*info_set_uint32)(CamelMessageInfo *mi, int id, guint32 val); - void (*info_set_time)(CamelMessageInfo *mi, int id, time_t val); - void (*info_set_references)(CamelMessageInfo *mi, CamelSummaryReferences *); -#endif gboolean (*info_set_user_flag)(CamelMessageInfo *mi, const char *id, gboolean state); gboolean (*info_set_user_tag)(CamelMessageInfo *mi, const char *id, const char *val); gboolean (*info_set_flags)(CamelMessageInfo *mi, guint32 mask, guint32 set); + }; /* Meta-summary info */ @@ -289,8 +269,10 @@ CamelType camel_folder_summary_get_type (void); CamelFolderSummary *camel_folder_summary_new (struct _CamelFolder *folder); +unsigned char* +decode_uint32 (unsigned char *start, guint32 *dest, gboolean is_string); + void camel_folder_summary_set_filename(CamelFolderSummary *summary, const char *filename); -void camel_folder_summary_set_index(CamelFolderSummary *summary, CamelIndex *index); void camel_folder_summary_set_build_content(CamelFolderSummary *summary, gboolean state); guint32 camel_folder_summary_next_uid (CamelFolderSummary *summary); @@ -316,6 +298,7 @@ CamelMessageInfo *camel_folder_summary_add_from_message(CamelFolderSummary *summary, CamelMimeMessage *message); /* Just build raw summary items */ +CamelMessageInfo *camel_folder_summary_info_new_from_header_with_uid (CamelFolderSummary *s, struct _camel_header_raw *h, const gchar *uid); CamelMessageInfo *camel_folder_summary_info_new_from_header(CamelFolderSummary *summary, struct _camel_header_raw *headers); CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary *summary, CamelMimeParser *parser); CamelMessageInfo *camel_folder_summary_info_new_from_message(CamelFolderSummary *summary, CamelMimeMessage *message); @@ -341,7 +324,7 @@ /* basically like strings, but certain keywords can be compressed and de-cased */ int camel_folder_summary_encode_token(FILE *out, const char *str); -int camel_folder_summary_decode_token(FILE *in, char **str); +int camel_folder_summary_decode_token(CamelFolderSummary *s, char **str); /* message flag operations */ gboolean camel_flag_get(CamelFlag **list, const char *name); @@ -363,6 +346,8 @@ /* Summary may be null */ /* Use anonymous pointers to avoid tons of cast crap */ void *camel_message_info_new(CamelFolderSummary *summary); +void *camel_message_info_new_uid (CamelFolderSummary *summary, const char *uid); + void camel_message_info_ref(void *info); CamelMessageInfo *camel_message_info_new_from_header(CamelFolderSummary *summary, struct _camel_header_raw *header); void camel_message_info_free(void *info); @@ -379,7 +364,6 @@ #define camel_message_info_from(mi) ((const char *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_FROM)) #define camel_message_info_to(mi) ((const char *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_TO)) #define camel_message_info_cc(mi) ((const char *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_CC)) -#define camel_message_info_mlist(mi) ((const char *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_MLIST)) #define camel_message_info_flags(mi) camel_message_info_uint32((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_FLAGS) #define camel_message_info_size(mi) camel_message_info_uint32((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_SIZE) @@ -388,7 +372,6 @@ #define camel_message_info_date_received(mi) camel_message_info_time((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_DATE_RECEIVED) #define camel_message_info_message_id(mi) ((const CamelSummaryMessageID *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_MESSAGE_ID)) -#define camel_message_info_references(mi) ((const CamelSummaryReferences *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_REFERENCES)) #define camel_message_info_user_flags(mi) ((const CamelFlag *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_USER_FLAGS)) #define camel_message_info_user_tags(mi) ((const CamelTag *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_USER_TAGS)) @@ -404,6 +387,13 @@ void camel_message_info_dump (CamelMessageInfo *mi); +void camel_folder_summary_prepare_hash (CamelFolderSummary *summary); +void camel_folder_summary_kill_hash (CamelFolderSummary *summary); + +void camel_message_info_clear_normal_flags (CamelMessageInfo *min); +int camel_folder_summary_get_index_for (CamelFolderSummary *s, const char *uid); + + G_END_DECLS #endif /* ! _CAMEL_FOLDER_SUMMARY_H */ Only in .: camel-folder-summary.h.rej Only in .: camel-folder-summary.lo Only in .: camel-folder-summary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-thread.c ./camel-folder-thread.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-thread.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder-thread.c 2007-05-12 10:01:18.000000000 +0200 @@ -58,6 +58,7 @@ child->parent = node; } +#if 0 static void container_parent_child(CamelFolderThreadNode *parent, CamelFolderThreadNode *child) { @@ -99,6 +100,8 @@ printf("DAMN, we shouldn't be here!\n"); } +#endif + static void prune_empty(CamelFolderThread *thread, CamelFolderThreadNode **cp) @@ -118,8 +121,6 @@ if (c->child == NULL) { d(printf("removing empty node\n")); lastc->next = c->next; - m(memset(c, 0xfe, sizeof(*c))); - e_memchunk_free(thread->node_chunks, c); continue; } if (c->parent || c->child->next==0) { @@ -268,8 +269,6 @@ scan = scan->next; scan->next = c->child; clast->next = c->next; - m(memset(c, 0xee, sizeof(*c))); - e_memchunk_free(thread->node_chunks, c); continue; } if (c->message == NULL && container->message != NULL) { d(printf("container is non-empty parent\n")); @@ -296,7 +295,7 @@ remove_node(cp, container, &clast); remove_node(cp, c, &clast); - scan = e_memchunk_alloc0(thread->node_chunks); + scan = camel_folder_thread_node_new(thread); scan->root_subject = c->root_subject; scan->re = c->re && container->re; @@ -450,7 +449,9 @@ for (i=0;ilen;i++) { CamelMessageInfo *mi = summary->pdata[i]; const CamelSummaryMessageID *mid = camel_message_info_message_id(mi); +#ifdef NON_TINYMAIL_FEATURES const CamelSummaryReferences *references = camel_message_info_references(mi); +#endif if (mid->id.id) { c = g_hash_table_lookup(id_table, mid); @@ -459,22 +460,24 @@ /* if duplicate, just make out it is a no-id message, but try and insert it into the right spot in the tree */ d(printf("doing: (duplicate message id)\n")); - c = e_memchunk_alloc0(thread->node_chunks); + c = camel_folder_thread_node_new(thread); g_hash_table_insert(no_id_table, (void *)mi, c); } else if (!c) { d(printf("doing : %08x%08x (%s)\n", mid->id.part.hi, mid->id.part.lo, camel_message_info_subject(mi))); - c = e_memchunk_alloc0(thread->node_chunks); + c = camel_folder_thread_node_new(thread); g_hash_table_insert(id_table, (void *)mid, c); } } else { d(printf("doing : (no message id)\n")); - c = e_memchunk_alloc0(thread->node_chunks); + c = camel_folder_thread_node_new(thread); g_hash_table_insert(no_id_table, (void *)mi, c); } c->message = mi; c->order = i+1; child = c; + +#ifdef NON_TINYMAIL_FEATURES if (references) { int j; @@ -487,7 +490,7 @@ c = g_hash_table_lookup(id_table, &references->references[j]); if (c == NULL) { d(printf("not found\n")); - c = e_memchunk_alloc0(thread->node_chunks); + c = camel_folder_thread_node_new(thread); g_hash_table_insert(id_table, (void *)&references->references[j], c); } if (c!=child) @@ -495,6 +498,7 @@ child = c; } } +#endif } d(printf("\n\n")); @@ -547,8 +551,6 @@ /* and link the now 'real' node into the list */ newtop->next = child->next; c = newtop; - m(memset(child, 0xde, sizeof(*child))); - e_memchunk_free(thread->node_chunks, child); } else { c = child; } @@ -607,7 +609,7 @@ thread->refcount = 1; thread->subject = thread_subject; thread->tree = NULL; - thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode)); + thread->mem_chain = NULL; thread->folder = folder; camel_object_ref((CamelObject *)folder); @@ -682,9 +684,10 @@ g_hash_table_destroy(table); + g_slice_free_chain(CamelFolderThreadNode, thread->mem_chain, mem_chain); + thread->tree = NULL; - e_memchunk_destroy(thread->node_chunks); - thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode)); + thread->mem_chain = NULL; thread_summary(thread, all); g_ptr_array_free(thread->summary, TRUE); @@ -719,7 +722,7 @@ g_ptr_array_free(thread->summary, TRUE); camel_object_unref((CamelObject *)thread->folder); } - e_memchunk_destroy(thread->node_chunks); + g_slice_free_chain(CamelFolderThreadNode, thread->mem_chain, mem_chain); g_free(thread); } @@ -750,7 +753,7 @@ thread = g_malloc(sizeof(*thread)); thread->refcount = 1; thread->tree = NULL; - thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode)); + thread->mem_chain = NULL; thread->folder = NULL; thread->summary = NULL; @@ -798,8 +801,9 @@ g_hash_table_destroy(table); /* reset the tree, and rebuild fully */ + g_slice_free_chain(CamelFolderThreadNode, thread->mem_chain, mem_chain); thread->tree = NULL; - e_memchunk_empty(thread->node_chunks); + thread->mem_chain = NULL; thread_summary(thread, all); } @@ -836,7 +840,6 @@ rest = next->next; node->next = child; - e_memchunk_free(thread->node_chunks, next); next = child; do { lchild = child; @@ -853,7 +856,6 @@ node rest */ node->next = next->next; - e_memchunk_free(thread->node_chunks, next); next = node->next; } } else { @@ -878,3 +880,16 @@ } #endif + +CamelFolderThreadNode * +camel_folder_thread_node_new(CamelFolderThread *thread) +{ + CamelFolderThreadNode *node; + + node = g_slice_new0(CamelFolderThreadNode); + node->mem_chain = thread->mem_chain; + thread->mem_chain = node; + + return node; +} + diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-thread.h ./camel-folder-thread.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-folder-thread.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-folder-thread.h 2007-05-12 10:01:18.000000000 +0200 @@ -28,6 +28,7 @@ G_BEGIN_DECLS typedef struct _CamelFolderThreadNode { + struct _CamelFolderThreadNode *mem_chain; struct _CamelFolderThreadNode *next, *parent, *child; const CamelMessageInfo *message; char *root_subject; /* cached root equivalent subject */ @@ -40,7 +41,7 @@ guint32 subject : 1; struct _CamelFolderThreadNode *tree; - struct _EMemChunk *node_chunks; + struct _CamelFolderThreadNode *mem_chain; CamelFolder *folder; GPtrArray *summary; } CamelFolderThread; @@ -63,6 +64,8 @@ /* debugging function only */ int camel_folder_threaded_messages_dump(CamelFolderThreadNode *c); +CamelFolderThreadNode *camel_folder_thread_node_new(CamelFolderThread *thread); + G_END_DECLS #endif /* !_CAMEL_FOLDER_THREAD_H */ Only in .: camel-folder-thread.lo Only in .: camel-folder-thread.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-gpg-context.c ./camel-gpg-context.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-gpg-context.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-gpg-context.c 2007-05-12 10:01:18.000000000 +0200 @@ -400,7 +400,7 @@ if (gpg->diagbuf->len == 0) return NULL; - g_byte_array_append (gpg->diagbuf, "", 1); + g_byte_array_append (gpg->diagbuf, (guchar*)"", 1); } return (const char *) gpg->diagbuf->data; @@ -747,23 +747,20 @@ if (camel_debug("gpg:status")) printf ("status: %s\n", status); - if (strncmp (status, "[GNUPG:] ", 9) != 0) { - char *message; - message = g_locale_to_utf8(status, -1, NULL, NULL, NULL); + if (strncmp ((char*)status, "[GNUPG:] ", 9) != 0) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected GnuPG status message encountered:\n\n%s"), - message); - g_free(message); + status); return -1; } status += 9; - if (!strncmp (status, "USERID_HINT ", 12)) { + if (!strncmp ((char*)status, "USERID_HINT ", 12)) { char *hint, *user; status += 12; - status = next_token (status, &hint); + status = (const unsigned char *) next_token ((char*)status, &hint); if (!hint) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to parse gpg userid hint.")); @@ -776,18 +773,18 @@ goto recycle; } - if (gpg->utf8 || !(user = g_locale_to_utf8 (status, -1, &nread, &nwritten, NULL))) - user = g_strdup (status); + if (gpg->utf8 || !(user = g_locale_to_utf8 ((gchar*)status, -1, &nread, &nwritten, NULL))) + user = g_strdup ((gchar*)status); g_strstrip (user); g_hash_table_insert (gpg->userid_hint, hint, user); - } else if (!strncmp (status, "NEED_PASSPHRASE ", 16)) { + } else if (!strncmp ((char*)status, "NEED_PASSPHRASE ", 16)) { char *userid; status += 16; - status = next_token (status, &userid); + status = (const unsigned char *) next_token ((char*)status, &userid); if (!userid) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to parse gpg passphrase request.")); @@ -796,12 +793,12 @@ g_free (gpg->need_id); gpg->need_id = userid; - } else if (!strncmp (status, "NEED_PASSPHRASE_PIN ", 20)) { + } else if (!strncmp ((char*)status, "NEED_PASSPHRASE_PIN ", 20)) { char *userid; status += 20; - status = next_token (status, &userid); + status = (const unsigned char *)next_token ((char*)status, &userid); if (!userid) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to parse gpg passphrase request.")); @@ -810,7 +807,7 @@ g_free (gpg->need_id); gpg->need_id = userid; - } else if (!strncmp (status, "GET_HIDDEN ", 11)) { + } else if (!strncmp ((char*)status, "GET_HIDDEN ", 11)) { const char *name = NULL; char *prompt, *passwd; guint32 flags; @@ -822,14 +819,14 @@ else if (!name) name = ""; - if (!strncmp (status, "passphrase.pin.ask", 18)) { + if (!strncmp ((char*)status, "passphrase.pin.ask", 18)) { prompt = g_strdup_printf (_("You need a PIN to unlock the key for your\n" "SmartCard: \"%s\""), name); - } else if (!strncmp (status, "passphrase.enter", 16)) { + } else if (!strncmp ((char*)status, "passphrase.enter", 16)) { prompt = g_strdup_printf (_("You need a passphrase to unlock the key for\n" "user: \"%s\""), name); } else { - next_token (status, &prompt); + next_token ((char*)status, &prompt); camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected request from GnuPG for `%s'"), prompt); g_free (prompt); @@ -861,9 +858,9 @@ } g_free (prompt); - } else if (!strncmp (status, "GOOD_PASSPHRASE", 15)) { + } else if (!strncmp ((char*)status, "GOOD_PASSPHRASE", 15)) { gpg->bad_passwds = 0; - } else if (!strncmp (status, "BAD_PASSPHRASE", 14)) { + } else if (!strncmp ((char*)status, "BAD_PASSPHRASE", 14)) { gpg->bad_passwds++; camel_session_forget_password (gpg->session, NULL, NULL, gpg->need_id, ex); @@ -873,16 +870,13 @@ _("Failed to unlock secret key: 3 bad passphrases given.")); return -1; } - } else if (!strncmp (status, "UNEXPECTED ", 11)) { + } else if (!strncmp ((char*)status, "UNEXPECTED ", 11)) { /* this is an error */ - char *message; - message = g_locale_to_utf8(status+11, -1, NULL, NULL, NULL); camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected response from GnuPG: %s"), - message); - g_free(message); + status + 11); return -1; - } else if (!strncmp (status, "NODATA", 6)) { + } else if (!strncmp ((char*)status, "NODATA", 6)) { /* this is an error */ /* But we ignore it anyway, we should get other response codes to say why */ gpg->nodata = TRUE; @@ -890,55 +884,55 @@ /* check to see if we are complete */ switch (gpg->mode) { case GPG_CTX_MODE_SIGN: - if (!strncmp (status, "SIG_CREATED ", 12)) { + if (!strncmp ((char*)status, "SIG_CREATED ", 12)) { /* FIXME: save this state? */ } break; case GPG_CTX_MODE_VERIFY: - if (!strncmp (status, "TRUST_", 6)) { + if (!strncmp ((char*)status, "TRUST_", 6)) { status += 6; - if (!strncmp (status, "NEVER", 5)) { + if (!strncmp ((char*)status, "NEVER", 5)) { gpg->trust = GPG_TRUST_NEVER; - } else if (!strncmp (status, "MARGINAL", 8)) { + } else if (!strncmp ((char*)status, "MARGINAL", 8)) { gpg->trust = GPG_TRUST_MARGINAL; - } else if (!strncmp (status, "FULLY", 5)) { + } else if (!strncmp ((char*)status, "FULLY", 5)) { gpg->trust = GPG_TRUST_FULLY; - } else if (!strncmp (status, "ULTIMATE", 8)) { + } else if (!strncmp ((char*)status, "ULTIMATE", 8)) { gpg->trust = GPG_TRUST_ULTIMATE; - } else if (!strncmp (status, "UNDEFINED", 9)) { + } else if (!strncmp ((char*)status, "UNDEFINED", 9)) { gpg->trust = GPG_TRUST_UNDEFINED; } - } else if (!strncmp (status, "GOODSIG ", 8)) { + } else if (!strncmp ((char*)status, "GOODSIG ", 8)) { gpg->goodsig = TRUE; gpg->hadsig = TRUE; - } else if (!strncmp (status, "VALIDSIG ", 9)) { + } else if (!strncmp ((char*)status, "VALIDSIG ", 9)) { gpg->validsig = TRUE; - } else if (!strncmp (status, "BADSIG ", 7)) { + } else if (!strncmp ((char*)status, "BADSIG ", 7)) { gpg->badsig = FALSE; gpg->hadsig = TRUE; - } else if (!strncmp (status, "ERRSIG ", 7)) { + } else if (!strncmp ((char*)status, "ERRSIG ", 7)) { /* Note: NO_PUBKEY often comes after an ERRSIG */ gpg->errsig = FALSE; gpg->hadsig = TRUE; - } else if (!strncmp (status, "NO_PUBKEY ", 10)) { + } else if (!strncmp ((char*)status, "NO_PUBKEY ", 10)) { gpg->nopubkey = TRUE; } break; case GPG_CTX_MODE_ENCRYPT: - if (!strncmp (status, "BEGIN_ENCRYPTION", 16)) { + if (!strncmp ((char*)status, "BEGIN_ENCRYPTION", 16)) { /* nothing to do... but we know to expect data on stdout soon */ - } else if (!strncmp (status, "END_ENCRYPTION", 14)) { + } else if (!strncmp ((char*)status, "END_ENCRYPTION", 14)) { /* nothing to do, but we know the end is near? */ - } else if (!strncmp (status, "NO_RECP", 7)) { + } else if (!strncmp ((char*)status, "NO_RECP", 7)) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encrypt: No valid recipients specified.")); return -1; } break; case GPG_CTX_MODE_DECRYPT: - if (!strncmp (status, "BEGIN_DECRYPTION", 16)) { + if (!strncmp ((char*)status, "BEGIN_DECRYPTION", 16)) { /* nothing to do... but we know to expect data on stdout soon */ - } else if (!strncmp (status, "END_DECRYPTION", 14)) { + } else if (!strncmp ((char*)status, "END_DECRYPTION", 14)) { /* nothing to do, but we know the end is near? */ } break; Only in .: camel-gpg-context.lo Only in .: camel-gpg-context.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel.h ./camel.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel.h 2007-05-12 10:34:01.000000000 +0200 @@ -118,9 +118,9 @@ #include #include #include +#include #include #include -#include #include #include #include Only in .: camel.h.rej Only in .: camel-html-parser.lo Only in .: camel-html-parser.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-http-stream.c ./camel-http-stream.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-http-stream.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-http-stream.c 2007-05-12 10:01:18.000000000 +0200 @@ -268,7 +268,7 @@ /* parse the HTTP status code */ if (!g_ascii_strncasecmp (buffer, "HTTP/", 5)) { - token = http_next_token (buffer); + token = http_next_token ((const unsigned char *) buffer); http->statuscode = camel_header_decode_int (&token); return http->statuscode; } Only in .: camel-http-stream.lo Only in .: camel-http-stream.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-i18n.h ./camel-i18n.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-i18n.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-i18n.h 2007-05-12 10:43:53.000000000 +0200 @@ -29,9 +29,9 @@ #ifdef ENABLE_NLS # include -# ifdef CAMEL_EXPLICIT_TRANSLATION_DOMAIN +# ifdef TRANSDOM # undef _ -# define _(String) dgettext (CAMEL_EXPLICIT_TRANSLATION_DOMAIN, String) +# define _(String) dgettext (TRANSDOM, String) # else # define _(String) gettext (String) # endif @@ -42,12 +42,20 @@ # endif #else /* Stubs that do something close enough. */ -# define textdomain(String) (String) +# define textdomain(String) (String +#ifndef gettext # define gettext(String) (String) +#endif +#ifndef dgettext # define dgettext(Domain,Message) (Message) +#endif +#ifndef dcgettext # define dcgettext(Domain,Message,Type) (Message) +#endif # define bindtextdomain(Domain,Directory) (Domain) +#ifndef _ # define _(String) (String) +#endif # define N_(String) (String) #endif Only in .: camel-index.lo Only in .: camel-index.o Only in .: camel-internet-address.lo Only in .: camel-internet-address.o Only in .: camel-junk-plugin.lo Only in .: camel-junk-plugin.o Only in .: camel-list-utils.lo Only in .: camel-list-utils.o Only in .: camel-lite-1.2.pc Only in .: camel-lite.pc Only in .: camel-lite.pc.in Only in .: camel-lite-provider-1.2.pc Only in .: camel-lite-provider.pc Only in .: camel-lite-provider.pc.in Only in .: camel.lo Only in .: camel-lock-client.lo Only in .: camel-lock-client.o Only in .: camel-lock.lo Only in .: camel-lock.o Only in .: camel-medium.lo Only in .: camel-medium.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-basic.c ./camel-mime-filter-basic.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-basic.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-mime-filter-basic.c 2007-03-11 16:44:11.000000000 +0100 @@ -101,38 +101,38 @@ case CAMEL_MIME_FILTER_BASIC_BASE64_ENC: /* wont go to more than 2x size (overly conservative) */ camel_mime_filter_set_size(mf, len*2+6, FALSE); - newlen = camel_base64_encode_close(in, len, TRUE, mf->outbuf, &f->state, &f->save); + newlen = camel_base64_encode_close((unsigned char *)in, len, TRUE, (unsigned char*)mf->outbuf, &f->state, &f->save); g_assert(newlen <= len*2+6); break; case CAMEL_MIME_FILTER_BASIC_QP_ENC: /* *4 is definetly more than needed ... */ camel_mime_filter_set_size(mf, len*4+4, FALSE); - newlen = camel_quoted_encode_close(in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_quoted_encode_close((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, &f->save); g_assert(newlen <= len*4+4); break; case CAMEL_MIME_FILTER_BASIC_UU_ENC: /* won't go to more than 2 * (x + 2) + 62 */ camel_mime_filter_set_size (mf, (len + 2) * 2 + 62, FALSE); - newlen = camel_uuencode_close (in, len, mf->outbuf, f->uubuf, &f->state, &f->save); + newlen = camel_uuencode_close ((unsigned char *)in, len, (unsigned char*)mf->outbuf, f->uubuf, &f->state, (guint32*) &f->save); g_assert (newlen <= (len + 2) * 2 + 62); break; case CAMEL_MIME_FILTER_BASIC_BASE64_DEC: /* output can't possibly exceed the input size */ camel_mime_filter_set_size(mf, len, FALSE); - newlen = camel_base64_decode_step(in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_base64_decode_step((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, (guint32*) &f->save); g_assert(newlen <= len); break; case CAMEL_MIME_FILTER_BASIC_QP_DEC: /* output can't possibly exceed the input size, well unless its not really qp, then +2 max */ camel_mime_filter_set_size(mf, len+2, FALSE); - newlen = camel_quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_quoted_decode_step((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, (gint*) &f->save); g_assert(newlen <= len+2); break; case CAMEL_MIME_FILTER_BASIC_UU_DEC: if ((f->state & CAMEL_UUDECODE_STATE_BEGIN) && !(f->state & CAMEL_UUDECODE_STATE_END)) { /* "begin \n" has been found, so we can now start decoding */ camel_mime_filter_set_size (mf, len + 3, FALSE); - newlen = camel_uudecode_step (in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_uudecode_step ((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, (guint32*) &f->save); } else { newlen = 0; } @@ -164,31 +164,31 @@ case CAMEL_MIME_FILTER_BASIC_BASE64_ENC: /* wont go to more than 2x size (overly conservative) */ camel_mime_filter_set_size(mf, len*2+6, FALSE); - newlen = camel_base64_encode_step(in, len, TRUE, mf->outbuf, &f->state, &f->save); + newlen = camel_base64_encode_step((unsigned char *)in, len, TRUE, (unsigned char*)mf->outbuf, &f->state, (gint*)&f->save); g_assert(newlen <= len*2+6); break; case CAMEL_MIME_FILTER_BASIC_QP_ENC: /* *4 is overly conservative, but will do */ camel_mime_filter_set_size(mf, len*4+4, FALSE); - newlen = camel_quoted_encode_step(in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_quoted_encode_step((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, (gint*)&f->save); g_assert(newlen <= len*4+4); break; case CAMEL_MIME_FILTER_BASIC_UU_ENC: /* won't go to more than 2 * (x + 2) + 62 */ camel_mime_filter_set_size (mf, (len + 2) * 2 + 62, FALSE); - newlen = camel_uuencode_step (in, len, mf->outbuf, f->uubuf, &f->state, &f->save); + newlen = camel_uuencode_step ((unsigned char *)in, len, (unsigned char*)mf->outbuf, f->uubuf, &f->state, (guint32*)&f->save); g_assert (newlen <= (len + 2) * 2 + 62); break; case CAMEL_MIME_FILTER_BASIC_BASE64_DEC: /* output can't possibly exceed the input size */ camel_mime_filter_set_size(mf, len+3, FALSE); - newlen = camel_base64_decode_step(in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_base64_decode_step((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, (guint32*)&f->save); g_assert(newlen <= len+3); break; case CAMEL_MIME_FILTER_BASIC_QP_DEC: /* output can't possibly exceed the input size */ camel_mime_filter_set_size(mf, len + 2, FALSE); - newlen = camel_quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_quoted_decode_step((unsigned char *)in, len, (unsigned char*)mf->outbuf, &f->state, (gint*)&f->save); g_assert(newlen <= len + 2); break; case CAMEL_MIME_FILTER_BASIC_UU_DEC: @@ -230,7 +230,7 @@ if ((f->state & CAMEL_UUDECODE_STATE_BEGIN) && !(f->state & CAMEL_UUDECODE_STATE_END)) { /* "begin \n" has been found, so we can now start decoding */ camel_mime_filter_set_size (mf, len + 3, FALSE); - newlen = camel_uudecode_step (in, len, mf->outbuf, &f->state, &f->save); + newlen = camel_uudecode_step ((unsigned char*)in, len, (unsigned char*)mf->outbuf, &f->state, (guint32*)&f->save); } else { newlen = 0; } Only in .: camel-mime-filter-basic.lo Only in .: camel-mime-filter-basic.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-bestenc.c ./camel-mime-filter-bestenc.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-bestenc.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-mime-filter-bestenc.c 2007-03-11 16:44:11.000000000 +0100 @@ -102,7 +102,7 @@ f->startofline = FALSE; /* See rfc2045 section 2 for definitions of 7bit/8bit/binary */ - p = in; + p = (unsigned char *)in; pend = p + len; while (pflags & CAMEL_BESTENC_NO_FROM) && !f->hadfrom) { if (pend-p >= 5) { - f->hadfrom = strncmp(p, "From ", 5) == 0; + f->hadfrom = strncmp((char*)p, "From ", 5) == 0; } else if (pend-p == 0) { f->startofline = TRUE; } else { Only in .: camel-mime-filter-bestenc.lo Only in .: camel-mime-filter-bestenc.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-canon.c ./camel-mime-filter-canon.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-canon.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-mime-filter-canon.c 2007-05-12 10:01:18.000000000 +0200 @@ -80,8 +80,8 @@ flags = ((CamelMimeFilterCanon *)f)->flags; /* first, work out how much space we need */ - inptr = in; - inend = in+len; + inptr = (unsigned char *)in; + inend = (const unsigned char *) (in+len); while (inptr < inend) if (*inptr++ == '\n') lf++; @@ -93,7 +93,7 @@ camel_mime_filter_set_size(f, len+lf*3+4, FALSE); o = f->outbuf; - inptr = in; + inptr = (unsigned char *)in; start = inptr; starto = o; while (inptr < inend) { @@ -102,7 +102,7 @@ if (flags & CAMEL_MIME_FILTER_CANON_FROM && c == 'F') { inptr++; if (inptr < inend-4) { - if (strncmp(inptr, "rom ", 4) == 0) { + if (strncmp((char*)inptr, "rom ", 4) == 0) { strcpy(o, "=46rom "); inptr+=4; o+= 7; @@ -153,7 +153,7 @@ if (last) { *outlen = o - f->outbuf; } else { - camel_mime_filter_backup(f, start, inend - start); + camel_mime_filter_backup(f, (const char*)start, inend - start); *outlen = starto - f->outbuf; } Only in .: camel-mime-filter-canon.lo Only in .: camel-mime-filter-canon.o Only in .: camel-mime-filter-charset.lo Only in .: camel-mime-filter-charset.o Only in .: camel-mime-filter-crlf.lo Only in .: camel-mime-filter-crlf.o Only in .: camel-mime-filter-enriched.lo Only in .: camel-mime-filter-enriched.o Only in .: camel-mime-filter-from.lo Only in .: camel-mime-filter-from.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-gzip.c ./camel-mime-filter-gzip.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-gzip.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-mime-filter-gzip.c 2007-03-11 16:44:11.000000000 +0100 @@ -185,18 +185,18 @@ memcpy (filter->outbuf, priv->hdr.buf, 10); - priv->stream->next_out = filter->outbuf + 10; + priv->stream->next_out = (Bytef *)filter->outbuf + 10; priv->stream->avail_out = filter->outsize - 10; priv->state.zip.wrote_hdr = TRUE; } else { camel_mime_filter_set_size (filter, (len * 2) + 12, FALSE); - priv->stream->next_out = filter->outbuf; + priv->stream->next_out = (Bytef *)filter->outbuf; priv->stream->avail_out = filter->outsize; } - priv->stream->next_in = in; + priv->stream->next_in = (Bytef *)in; priv->stream->avail_in = len; do { @@ -210,7 +210,7 @@ n = filter->outsize - priv->stream->avail_out; camel_mime_filter_set_size (filter, n + (priv->stream->avail_in * 2) + 12, TRUE); priv->stream->avail_out = filter->outsize - n; - priv->stream->next_out = filter->outbuf + n; + priv->stream->next_out = (Bytef *)filter->outbuf + n; if (priv->stream->avail_in == 0) { guint32 val; @@ -229,13 +229,13 @@ } } else { if (priv->stream->avail_in > 0) - camel_mime_filter_backup (filter, priv->stream->next_in, priv->stream->avail_in); + camel_mime_filter_backup (filter, (const char *)priv->stream->next_in, priv->stream->avail_in); break; } } while (1); - priv->crc32 = crc32 (priv->crc32, in, len - priv->stream->avail_in); + priv->crc32 = crc32 (priv->crc32, (unsigned char*)in, len - priv->stream->avail_in); priv->isize += len - priv->stream->avail_in; *out = filter->outbuf; @@ -346,10 +346,10 @@ camel_mime_filter_set_size (filter, (len * 2) + 12, FALSE); - priv->stream->next_in = in; + priv->stream->next_in = (Bytef *)in; priv->stream->avail_in = len - 8; - priv->stream->next_out = filter->outbuf; + priv->stream->next_out = (Bytef *)filter->outbuf; priv->stream->avail_out = filter->outsize; do { @@ -368,12 +368,12 @@ n = filter->outsize - priv->stream->avail_out; camel_mime_filter_set_size (filter, n + (priv->stream->avail_in * 2) + 12, TRUE); priv->stream->avail_out = filter->outsize - n; - priv->stream->next_out = filter->outbuf + n; + priv->stream->next_out = (Bytef *)filter->outbuf + n; } else { priv->stream->avail_in += 8; if (priv->stream->avail_in > 0) - camel_mime_filter_backup (filter, priv->stream->next_in, priv->stream->avail_in); + camel_mime_filter_backup (filter, (char*)priv->stream->next_in, priv->stream->avail_in); break; } Only in .: camel-mime-filter-gzip.lo Only in .: camel-mime-filter-gzip.o Only in .: camel-mime-filter-html.lo Only in .: camel-mime-filter-html.o Only in .: camel-mime-filter-index.lo Only in .: camel-mime-filter-index.o Only in .: camel-mime-filter-linewrap.lo Only in .: camel-mime-filter-linewrap.o Only in .: camel-mime-filter.lo Only in .: camel-mime-filter.o Only in .: camel-mime-filter-pgp.lo Only in .: camel-mime-filter-pgp.o Only in .: camel-mime-filter-save.lo Only in .: camel-mime-filter-save.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-tohtml.c ./camel-mime-filter-tohtml.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-tohtml.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-mime-filter-tohtml.c 2007-05-12 10:00:17.000000000 +0200 @@ -60,10 +60,8 @@ { CONVERT_WEB_URLS, { "nntp://", "", camel_url_web_start, camel_url_web_end } }, { CONVERT_WEB_URLS, { "telnet://", "", camel_url_web_start, camel_url_web_end } }, { CONVERT_WEB_URLS, { "webcal://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "mailto:", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "callto:", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "h323:", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "sip:", "", camel_url_web_start, camel_url_web_end } }, + { CONVERT_WEB_URLS, { "callto://", "", camel_url_web_start, camel_url_web_end } }, + { CONVERT_WEB_URLS, { "h323://", "", camel_url_web_start, camel_url_web_end } }, { CONVERT_WEB_URLS, { "www.", "http://", camel_url_web_start, camel_url_web_end } }, { CONVERT_WEB_URLS, { "ftp.", "ftp://", camel_url_web_start, camel_url_web_end } }, { CONVERT_ADDRSPEC, { "@", "mailto:", camel_url_addrspec_start, camel_url_addrspec_end } }, Only in .: camel-mime-filter-tohtml.lo Only in .: camel-mime-filter-tohtml.o Only in .: camel-mime-filter-windows.lo Only in .: camel-mime-filter-windows.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-yenc.c ./camel-mime-filter-yenc.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-filter-yenc.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-mime-filter-yenc.c 2007-03-11 16:44:11.000000000 +0100 @@ -95,7 +95,7 @@ case CAMEL_MIME_FILTER_YENC_DIRECTION_ENCODE: /* won't go to more than 2 * (x + 2) + 62 */ camel_mime_filter_set_size (filter, (len + 2) * 2 + 62, FALSE); - newlen = camel_yencode_step (in, len, filter->outbuf, ¥c->state, + newlen = camel_yencode_step ((const unsigned char *)in, len, (unsigned char*)filter->outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= (len + 2) * 2 + 62); break; @@ -166,7 +166,7 @@ if ((yenc->state & CAMEL_MIME_YDECODE_STATE_DECODE) && !(yenc->state & CAMEL_MIME_YDECODE_STATE_END)) { /* all yEnc headers have been found so we can now start decoding */ camel_mime_filter_set_size (filter, len + 3, FALSE); - newlen = camel_ydecode_step (in, len, filter->outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); + newlen = camel_ydecode_step ((const unsigned char *)in, len, (unsigned char*)filter->outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= len + 3); } else { newlen = 0; @@ -190,7 +190,7 @@ case CAMEL_MIME_FILTER_YENC_DIRECTION_ENCODE: /* won't go to more than 2 * (x + 2) + 62 */ camel_mime_filter_set_size (filter, (len + 2) * 2 + 62, FALSE); - newlen = camel_yencode_close (in, len, filter->outbuf, ¥c->state, + newlen = camel_yencode_close ((const unsigned char *)in, len, (unsigned char*)filter->outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= (len + 2) * 2 + 62); break; @@ -198,7 +198,7 @@ if ((yenc->state & CAMEL_MIME_YDECODE_STATE_DECODE) && !(yenc->state & CAMEL_MIME_YDECODE_STATE_END)) { /* all yEnc headers have been found so we can now start decoding */ camel_mime_filter_set_size (filter, len + 3, FALSE); - newlen = camel_ydecode_step (in, len, filter->outbuf, ¥c->state, + newlen = camel_ydecode_step ((const unsigned char *)in, len, (unsigned char*)filter->outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= len + 3); } else { Only in .: camel-mime-filter-yenc.lo Only in .: camel-mime-filter-yenc.o Only in .: camel-mime-message.lo Only in .: camel-mime-message.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-parser.c ./camel-mime-parser.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-parser.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-mime-parser.c 2007-05-12 10:01:18.000000000 +0200 @@ -366,7 +366,7 @@ return NULL; if (array->len == 0 || array->data[array->len-1] != '\0') - g_byte_array_append(array, "", 1); + g_byte_array_append(array, (guchar*)"", 1); return (const char *) array->data; } @@ -1039,7 +1039,7 @@ } if (save) - g_byte_array_append(save, s->inptr, inptr-s->inptr); + g_byte_array_append(save, (guchar*)s->inptr, inptr-s->inptr); s->inptr = inptr; @@ -1712,11 +1712,11 @@ if (h->prestage > 0) { if (h->posttext == NULL) h->posttext = g_byte_array_new(); - g_byte_array_append(h->posttext, *databuffer, *datalength); + g_byte_array_append(h->posttext, (guchar*) *databuffer, *datalength); } else { if (h->pretext == NULL) h->pretext = g_byte_array_new(); - g_byte_array_append(h->pretext, *databuffer, *datalength); + g_byte_array_append(h->pretext, (guchar*) *databuffer, *datalength); } } } while (hb==h && *datalength>0); Only in .: camel-mime-parser.lo Only in .: camel-mime-parser.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-part.c ./camel-mime-part.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-part.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-mime-part.c 2007-05-12 10:01:18.000000000 +0200 @@ -341,7 +341,7 @@ void camel_mime_part_set_description (CamelMimePart *mime_part, const char *description) { - char *text = camel_header_encode_string (description); + char *text = camel_header_encode_string ((const unsigned char*)description); camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Description", text); Only in .: camel-mime-part.lo Only in .: camel-mime-part.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-part-utils.c ./camel-mime-part-utils.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-part-utils.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-mime-part-utils.c 2007-05-12 10:01:18.000000000 +0200 @@ -68,7 +68,7 @@ buffer = g_byte_array_new (); while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) { d(printf("appending o/p data: %d: %.*s\n", len, len, buf)); - g_byte_array_append (buffer, buf, len); + g_byte_array_append (buffer, (guchar*)buf, len); } d(printf("message part kept in memory!\n")); Only in .: camel-mime-part-utils.lo Only in .: camel-mime-part-utils.o Only in .: camel-mime-tables.c Only in .: camel-mime-tables.lo Only in .: camel-mime-tables.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-utils.c ./camel-mime-utils.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-mime-utils.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-mime-utils.c 2007-05-12 10:01:12.000000000 +0200 @@ -358,7 +358,7 @@ out = g_malloc (len * 4 / 3 + 5); outlen = camel_base64_encode_close ((unsigned char *)data, len, FALSE, - out, &state, &save); + out, &state, (gint*)&save); out[outlen] = '\0'; return (char *)out; } @@ -1034,13 +1034,13 @@ decword = g_alloca (tmplen); /* this will always be more-than-enough room */ switch(toupper(inptr[0])) { case 'Q': - inlen = quoted_decode(inptr+2, tmplen, decword); + inlen = quoted_decode((const unsigned char *)inptr+2, tmplen, (unsigned char*)decword); break; case 'B': { int state = 0; unsigned int save = 0; - inlen = camel_base64_decode_step((char *)inptr+2, tmplen, decword, &state, &save); + inlen = camel_base64_decode_step((unsigned char *)inptr+2, tmplen, (unsigned char*)decword, &state, &save); /* if state != 0 then error? */ break; } @@ -1332,7 +1332,7 @@ proclen = -1; p = inptr; i = 0; - while (p < (in+len) && convlen < (75 - strlen("=?utf-8?q?\?="))) { + while (p < (in+len) && convlen < (75 - strlen("=?utf-8?q\?\?="))) { unsigned char c = *p++; if (c >= 0xc0) @@ -1345,7 +1345,7 @@ else convlen += 3; } - if (proclen >= 0 && proclen < i && convlen < (75 - strlen("=?utf-8?q?\?="))) + if (proclen >= 0 && proclen < i && convlen < (75 - strlen("=?utf-8?q\?\?="))) proclen = i; /* well, we probably have broken utf8, just copy it anyway what the heck */ if (proclen == -1) { @@ -1382,7 +1382,7 @@ else *out++ = ' '; out += sprintf (out, "=?%s?Q?", type); - out += quoted_encode (buffer, enclen, out, safemask); + out += quoted_encode ((const unsigned char *)buffer, enclen, (unsigned char*)out, safemask); sprintf (out, "?="); d(printf("converted part = %s\n", ascii)); @@ -1416,7 +1416,7 @@ GString *out; char *outstr; - g_return_val_if_fail (g_utf8_validate (in, -1, NULL), NULL); + g_return_val_if_fail (g_utf8_validate ((const gchar*)in, -1, NULL), NULL); if (in == NULL) return NULL; @@ -1428,7 +1428,7 @@ inptr++; } if (*inptr == '\0') - return g_strdup (in); + return g_strdup ((gchar*)in); /* This gets each word out of the input, and checks to see what charset can be used to encode it. */ @@ -1443,7 +1443,7 @@ const char *newinptr; newinptr = g_utf8_next_char (inptr); - c = g_utf8_get_char (inptr); + c = g_utf8_get_char ((char*)inptr); if (newinptr == NULL || !g_unichar_validate (c)) { w(g_warning ("Invalid UTF-8 sequence encountered (pos %d, char '%c'): %s", (inptr-in), inptr[0], in)); @@ -1455,29 +1455,29 @@ /* we've reached the end of a 'word' */ if (word && !(last_was_encoded && encoding)) { /* output lwsp between non-encoded words */ - g_string_append_len (out, start, word - start); + g_string_append_len (out, (const gchar*)start, word - start); start = word; } switch (encoding) { case 0: - g_string_append_len (out, start, inptr - start); + g_string_append_len (out, (const gchar*)start, inptr - start); last_was_encoded = FALSE; break; case 1: if (last_was_encoded) g_string_append_c (out, ' '); - rfc2047_encode_word (out, start, inptr - start, "ISO-8859-1", CAMEL_MIME_IS_ESAFE); + rfc2047_encode_word (out, (const char *)start, inptr - start, "ISO-8859-1", CAMEL_MIME_IS_ESAFE); last_was_encoded = TRUE; break; case 2: if (last_was_encoded) g_string_append_c (out, ' '); - if (!(charset = camel_charset_best (start, inptr - start))) + if (!(charset = camel_charset_best ((const char*)start, inptr - start))) charset = "UTF-8"; - rfc2047_encode_word (out, start, inptr - start, charset, CAMEL_MIME_IS_ESAFE); + rfc2047_encode_word (out, (const char *)start, inptr - start, charset, CAMEL_MIME_IS_ESAFE); last_was_encoded = TRUE; break; } @@ -1499,32 +1499,32 @@ if (!(c < 256 && camel_mime_is_lwsp (c)) && !word) word = inptr; - inptr = newinptr; + inptr = (const unsigned char *)newinptr; } if (inptr - start) { if (word && !(last_was_encoded && encoding)) { - g_string_append_len (out, start, word - start); + g_string_append_len (out, (const gchar*)start, word - start); start = word; } switch (encoding) { case 0: - g_string_append_len (out, start, inptr - start); + g_string_append_len (out, (const gchar*)start, inptr - start); break; case 1: if (last_was_encoded) g_string_append_c (out, ' '); - rfc2047_encode_word (out, start, inptr - start, "ISO-8859-1", CAMEL_MIME_IS_ESAFE); + rfc2047_encode_word (out, (const char *)start, inptr - start, "ISO-8859-1", CAMEL_MIME_IS_ESAFE); break; case 2: if (last_was_encoded) g_string_append_c (out, ' '); - if (!(charset = camel_charset_best (start, inptr - start))) + if (!(charset = camel_charset_best ( (const char *)start, inptr - start))) charset = "UTF-8"; - rfc2047_encode_word (out, start, inptr - start, charset, CAMEL_MIME_IS_ESAFE); + rfc2047_encode_word (out, (const char *)start, inptr - start, charset, CAMEL_MIME_IS_ESAFE); break; } } @@ -1603,7 +1603,7 @@ const char *newinptr; newinptr = g_utf8_next_char (inptr); - c = g_utf8_get_char (inptr); + c = g_utf8_get_char ((char*)inptr); if (!g_unichar_validate (c)) { w(g_warning ("Invalid UTF-8 sequence encountered (pos %d, char '%c'): %s", @@ -1612,7 +1612,7 @@ continue; } - inptr = newinptr; + inptr = (const unsigned char *) newinptr; if (g_unichar_isspace (c)) { if (count > 0) { word = g_new0 (struct _phrase_word, 1); @@ -1748,28 +1748,28 @@ if (last_word && !(last_word->type == WORD_2047 && word->type == WORD_2047)) { /* one or both of the words are not encoded so we write the spaces out untouched */ len = word->start - last_word->end; - out = g_string_append_len (out, last_word->end, len); + out = g_string_append_len (out, (const gchar*) last_word->end, len); } switch (word->type) { case WORD_ATOM: - out = g_string_append_len (out, word->start, word->end - word->start); + out = g_string_append_len (out, (const gchar*) word->start, word->end - word->start); break; case WORD_QSTRING: - quote_word (out, TRUE, word->start, word->end - word->start); + quote_word (out, TRUE, (const char *) word->start, word->end - word->start); break; case WORD_2047: if (last_word && last_word->type == WORD_2047) { /* include the whitespace chars between these 2 words in the resulting rfc2047 encoded word. */ len = word->end - last_word->end; - start = last_word->end; + start = (const char *) last_word->end; /* encoded words need to be separated by linear whitespace */ g_string_append_c (out, ' '); } else { len = word->end - word->start; - start = word->start; + start = (const char *) word->start; } if (word->encoding == 1) { @@ -1959,11 +1959,12 @@ static char * hex_decode (const char *in, size_t len) { - const unsigned char *inend = in + len; + const unsigned char *inend = (const unsigned char *) (in + len); unsigned char *inptr, *outptr; char *outbuf; - outptr = outbuf = g_malloc (len + 1); + outbuf = (char*)g_malloc (len + 1); + outptr = (unsigned char *)outbuf; inptr = (unsigned char *) in; while (inptr < inend) { @@ -2210,12 +2211,13 @@ CamelContentType * camel_content_type_new(const char *type, const char *subtype) { - CamelContentType *t = g_malloc(sizeof(*t)); + CamelContentType *t = g_slice_new (CamelContentType); t->type = g_strdup(type); t->subtype = g_strdup(subtype); t->params = NULL; t->refcount = 1; + return t; } @@ -2248,7 +2250,7 @@ camel_header_param_list_free(ct->params); g_free(ct->type); g_free(ct->subtype); - g_free(ct); + g_slice_free (CamelContentType, ct); ct = NULL; } else { ct->refcount--; @@ -3217,15 +3219,15 @@ /* if we have really broken utf8 passed in, we just treat it as binary data */ - charset = camel_charset_best(in, strlen(in)); + charset = camel_charset_best((char*)in, strlen((char*)in)); if (charset == NULL) - return g_strdup(in); + return g_strdup((gchar*)in); if (g_ascii_strcasecmp(charset, "UTF-8") != 0) { - if ((outbuf = header_convert(charset, "UTF-8", in, strlen(in)))) + if ((outbuf = (unsigned char *)header_convert(charset, "UTF-8", (const char*)in, strlen((char*)in)))) inptr = outbuf; else - return g_strdup(in); + return g_strdup((gchar*)in); } /* FIXME: set the 'language' as well, assuming we can get that info...? */ @@ -3264,7 +3266,7 @@ continue; } - value = header_encode_param (p->value, &encoded); + value = header_encode_param ((unsigned char *)p->value, &encoded); if (!value) { w(g_warning ("appending parameter %s=%s violates rfc2184", p->name, p->value)); value = g_strdup (p->value); @@ -3785,7 +3787,7 @@ { unsigned char *p; - p = h->value; + p = (unsigned char *)h->value; while (p && *p) { if (!isascii(*p)) { w(g_warning("Appending header violates rfc: %s: %s", h->name, h->value)); @@ -3848,7 +3850,7 @@ camel_header_to_decode(value); } else if (!g_ascii_strcasecmp(name, "Content-type")) { printf("- Decoding content-type\n"); - camel_content_type_dump(camel_content_type_decode(value)); + camel_content_type_dump(camel_content_type_decode(value)); } else if (!g_ascii_strcasecmp(name, "MIME-Version")) { printf("- Decoding mime version\n"); camel_header_mime_decode(value); @@ -4251,7 +4253,7 @@ switch (a->type) { case CAMEL_HEADER_ADDRESS_NAME: if (encode) - text = camel_header_encode_phrase (a->name); + text = camel_header_encode_phrase ((unsigned char*)a->name); else text = a->name; if (text && *text) @@ -4263,7 +4265,7 @@ break; case CAMEL_HEADER_ADDRESS_GROUP: if (encode) - text = camel_header_encode_phrase (a->name); + text = camel_header_encode_phrase ((unsigned char*)a->name); else text = a->name; g_string_append_printf (out, "%s: ", text); Only in .: camel-mime-utils.lo Only in .: camel-mime-utils.o Only in .: camel-movemail.lo Only in .: camel-movemail.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-multipart.c ./camel-multipart.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-multipart.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-multipart.c 2007-05-12 10:01:18.000000000 +0200 @@ -363,12 +363,12 @@ bgen = g_strdup_printf ("%p:%lu:%lu", multipart, (unsigned long) getpid(), (unsigned long) time(0)); - md5_get_digest (bgen, strlen (bgen), digest); + md5_get_digest (bgen, strlen ((char*)bgen), (guchar*) digest); g_free (bgen); strcpy (bbuf, "=-"); p = bbuf + 2; state = save = 0; - p += camel_base64_encode_step (digest, 16, FALSE, p, &state, &save); + p += camel_base64_encode_step ((unsigned char *)digest, 16, FALSE, (unsigned char *)p, &state, &save); *p = '\0'; boundary = bbuf; Only in .: camel-multipart-encrypted.lo Only in .: camel-multipart-encrypted.o Only in .: camel-multipart.lo Only in .: camel-multipart.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-multipart-signed.c ./camel-multipart-signed.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-multipart-signed.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-multipart-signed.c 2007-05-12 10:01:18.000000000 +0200 @@ -409,7 +409,7 @@ if ((mps->content || mps->contentraw) && mps->signature) return 2; - if (mps->start1 == -1 && parse_content(mps) == -1) { + if (mps->start1 == -1 /*&& parse_content(mps) == -1*/) { if (dw->stream == NULL) return 0; else Only in .: camel-multipart-signed.lo Only in .: camel-multipart-signed.o Only in .: camel-net-utils.lo Only in .: camel-net-utils.o Only in .: camel-nntp-address.lo Only in .: camel-nntp-address.o Only in .: camel.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-object.c ./camel-object.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-object.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-object.c 2007-05-12 10:01:18.000000000 +0200 @@ -44,10 +44,8 @@ #define h(x) /* hooks */ /* I just mashed the keyboard for these... */ -#define CAMEL_OBJECT_MAGIC 0x77A344ED #define CAMEL_OBJECT_CLASS_MAGIC 0xEE26A997 #define CAMEL_INTERFACE_MAGIC 0xBCE137A7 -#define CAMEL_OBJECT_FINALISED_MAGIC 0x84AC365F #define CAMEL_OBJECT_CLASS_FINALISED_MAGIC 0x7621ABCD #define CAMEL_INTERFACE_FINALISED_MAGIC 0x7CB2FE71 @@ -134,11 +132,6 @@ /* ********************************************************************** */ -static pthread_mutex_t chunks_lock = PTHREAD_MUTEX_INITIALIZER; - -static EMemChunk *pair_chunks; -static EMemChunk *hook_chunks; -static unsigned int pair_id = 1; /* type-lock must be recursive, for atomically creating classes */ static GStaticRecMutex type_lock = G_STATIC_REC_MUTEX_INIT; @@ -146,14 +139,11 @@ static GMutex *ref_lock; static GHashTable *type_table; -static EMemChunk *type_chunks; /* fundamental types are accessed via global */ CamelType camel_object_type; CamelType camel_interface_type; -#define P_LOCK(l) (pthread_mutex_lock(&l)) -#define P_UNLOCK(l) (pthread_mutex_unlock(&l)) #define CLASS_LOCK(k) (g_mutex_lock((((CamelObjectClass *)k)->lock))) #define CLASS_UNLOCK(k) (g_mutex_unlock((((CamelObjectClass *)k)->lock))) #define REF_LOCK() (g_mutex_lock(ref_lock)) @@ -164,14 +154,17 @@ static struct _CamelHookPair * pair_alloc(void) { + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + static guint next_id = 1; CamelHookPair *pair; - P_LOCK(chunks_lock); - pair = e_memchunk_alloc(pair_chunks); - pair->id = pair_id++; - if (pair_id == 0) - pair_id = 1; - P_UNLOCK(chunks_lock); + pair = g_slice_new(CamelHookPair); + + g_static_mutex_lock(&mutex); + pair->id = next_id++; + if (next_id == 0) + next_id = 1; + g_static_mutex_unlock(&mutex); return pair; } @@ -179,33 +172,19 @@ static void pair_free(CamelHookPair *pair) { - g_assert(pair_chunks != NULL); - - P_LOCK(chunks_lock); - e_memchunk_free(pair_chunks, pair); - P_UNLOCK(chunks_lock); + g_slice_free (CamelHookPair, pair); } static struct _CamelHookList * hooks_alloc(void) { - CamelHookList *hooks; - - P_LOCK(chunks_lock); - hooks = e_memchunk_alloc(hook_chunks); - P_UNLOCK(chunks_lock); - - return hooks; + return g_slice_new0 (CamelHookList); } static void hooks_free(CamelHookList *hooks) { - g_assert(hook_chunks != NULL); - - P_LOCK(chunks_lock); - e_memchunk_free(hook_chunks, hooks); - P_UNLOCK(chunks_lock); + g_slice_free (CamelHookList, hooks); } /* not checked locked, who cares, only required for people that want to redefine root objects */ @@ -218,9 +197,6 @@ return; init = TRUE; - pair_chunks = e_memchunk_new(16, sizeof(CamelHookPair)); - hook_chunks = e_memchunk_new(16, sizeof(CamelHookList)); - type_chunks = e_memchunk_new(32, sizeof(CamelType)); type_table = g_hash_table_new(NULL, NULL); ref_lock = g_mutex_new(); } @@ -234,7 +210,6 @@ cobject_init(CamelObject *o, CamelObjectClass *klass) { o->klass = klass; - o->magic = CAMEL_OBJECT_MAGIC; o->ref_count = 1; o->flags = 0; } @@ -249,7 +224,6 @@ camel_object_free_hooks(o); - o->magic = CAMEL_OBJECT_FINALISED_MAGIC; o->klass = NULL; } @@ -474,7 +448,7 @@ switch(argv->argv[argv->argc].tag & CAMEL_ARG_TYPE) { case CAMEL_ARG_INT: case CAMEL_ARG_BOO: - if (camel_file_util_decode_uint32(fp, &argv->argv[argv->argc].ca_int) == -1) + if (camel_file_util_decode_uint32(fp, (guint32*) &argv->argv[argv->argc].ca_int) == -1) goto cleanup; break; case CAMEL_ARG_STR: @@ -583,7 +557,7 @@ res = 0; abort: - for (i=0;iargc;i++) { +/* for (i=0;iargc;i++) { CamelArg *arg = &argv->argv[i]; if ((argv->argv[i].tag & CAMEL_ARG_TYPE) == CAMEL_ARG_STR) @@ -598,7 +572,7 @@ if (meta) camel_object_free(obj, CAMEL_OBJECT_METADATA, meta); - +*/ return res; } @@ -747,7 +721,7 @@ size = offset + klass_size; - klass = g_malloc0(size); + klass = g_slice_alloc0(size); klass->klass_size = size; klass->klass_data = offset; @@ -765,12 +739,12 @@ return NULL; } - klass = g_malloc0(klass_size); + klass = g_slice_alloc (klass_size); klass->klass_size = klass_size; klass->object_size = object_size; klass->lock = g_mutex_new(); - klass->instance_chunks = e_memchunk_new(8, object_size); - + klass->hooks = NULL; + klass->parent = parent; if (parent) { klass->next = parent->child; @@ -851,20 +825,17 @@ CLASS_LOCK(type); - o = e_memchunk_alloc0(type->instance_chunks); - -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - if (type->instances) - type->instances->prev = o; - o->next = type->instances; - o->prev = NULL; - type->instances = o; -#endif + o = g_slice_alloc0 (type->object_size); CLASS_UNLOCK(type); camel_object_init(o, type, type); + if (o->flags & CAMEL_OBJECT_REF_DEBUG) + { + printf ("An object of the type that you are debugging got created\n"); + } + d(printf("%p: new %s()\n", o, o->klass->name)); return o; @@ -875,7 +846,14 @@ { register CamelObject *o = vo; - g_return_if_fail(CAMEL_IS_OBJECT(o)); + if (o->ref_count > 0) + g_return_if_fail(CAMEL_IS_OBJECT(o)); + + + if (o->flags & CAMEL_OBJECT_REF_DEBUG) + { + printf ("An object of the type that you are debugging got referenced\n"); + } REF_LOCK(); @@ -893,9 +871,13 @@ CamelHookList *hooks = NULL; g_return_if_fail(CAMEL_IS_OBJECT(o)); - klass = o->klass; + if (o->flags & CAMEL_OBJECT_REF_DEBUG) + { + printf ("An object of the type that you are debugging got unreferenced\n"); + } + if (o->hooks) hooks = camel_object_get_hooks(o); @@ -913,6 +895,11 @@ return; } + if (o->flags & CAMEL_OBJECT_REF_DEBUG) + { + printf ("An object of the type that you are debugging is about to be finalized\n"); + } + o->flags |= CAMEL_OBJECT_DESTROY; if (hooks) @@ -932,18 +919,13 @@ k = k->parent; } - o->magic = CAMEL_OBJECT_FINALISED_MAGIC; - CLASS_LOCK(klass); -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - if (o->prev) - o->prev->next = o->next; - else - klass->instances = o->next; - if (o->next) - o->next->prev = o->prev; -#endif - e_memchunk_free(klass->instance_chunks, o); + + memset (o, 0, klass->object_size); + o->flags |= CAMEL_OBJECT_DESTROYED; + + g_slice_free1 (klass->object_size, o); + CLASS_UNLOCK(klass); } @@ -969,72 +951,17 @@ return g_hash_table_lookup(type_table, name); } -static char * -desc_data(CamelObject *o, guint32 ok) -{ - char *what; - - if (o == NULL) - what = g_strdup("NULL OBJECT"); - else if (o->magic == ok) - what = NULL; - else if (o->magic == CAMEL_OBJECT_MAGIC) - what = g_strdup_printf("CLASS '%s'", ((CamelObjectClass *)o)->name); - else if (o->magic == CAMEL_OBJECT_CLASS_MAGIC) - what = g_strdup_printf("CLASS '%s'", ((CamelObjectClass *)o)->name); - else if (o->magic == CAMEL_INTERFACE_MAGIC) - what = g_strdup_printf("INTERFACE '%s'", ((CamelObjectClass *)o)->name); - else if (o->magic == CAMEL_OBJECT_FINALISED_MAGIC) - what = g_strdup_printf("finalised OBJECT"); - else if (o->magic == CAMEL_OBJECT_CLASS_FINALISED_MAGIC) - what = g_strdup_printf("finalised CLASS"); - else if (o->magic == CAMEL_INTERFACE_FINALISED_MAGIC) - what = g_strdup_printf("finalised INTERFACE"); - else - what = g_strdup_printf("junk data"); - - return what; -} - -#define check_magic(o, ctype, omagic) \ - ( ((CamelObject *)(o))->magic == (omagic) \ - && (ctype)->magic == CAMEL_OBJECT_CLASS_MAGIC) \ - ? 1 : check_magic_fail(o, ctype, omagic) - -static gboolean -check_magic_fail(void *o, CamelType ctype, guint32 omagic) -{ - char *what, *to; - - what = desc_data(o, omagic); - to = desc_data((CamelObject *)ctype, CAMEL_OBJECT_CLASS_MAGIC); - - if (what || to) { - if (what == NULL) { - if (omagic == CAMEL_OBJECT_MAGIC) - what = g_strdup_printf("OBJECT '%s'", ((CamelObject *)o)->klass->name); - else - what = g_strdup_printf("OBJECT '%s'", ((CamelObjectClass *)o)->name); - } - if (to == NULL) - to = g_strdup_printf("OBJECT '%s'", ctype->name); - g_warning("Trying to check %s is %s", what, to); - g_free(what); - g_free(to); - - return FALSE; - } - - return TRUE; -} gboolean camel_object_is(CamelObject *o, CamelType ctype) { CamelObjectClass *k; - g_return_val_if_fail(o != NULL, FALSE); - g_return_val_if_fail(check_magic(o, ctype, CAMEL_OBJECT_MAGIC), FALSE); + if (o == NULL) + return FALSE; + + if (o->flags & CAMEL_OBJECT_DESTROYED) + return FALSE; k = o->klass; while (k) { @@ -1050,7 +977,6 @@ camel_object_class_is(CamelObjectClass *k, CamelType ctype) { g_return_val_if_fail(k != NULL, FALSE); - g_return_val_if_fail(check_magic(k, ctype, CAMEL_OBJECT_CLASS_MAGIC), FALSE); while (k) { if (k == ctype) @@ -1065,7 +991,6 @@ camel_interface_is(CamelObjectClass *k, CamelType ctype) { g_return_val_if_fail(k != NULL, FALSE); - g_return_val_if_fail(check_magic(k, ctype, CAMEL_INTERFACE_MAGIC), FALSE); while (k) { if (k == ctype) @@ -1081,8 +1006,6 @@ { CamelObjectClass *k; - g_return_val_if_fail(check_magic(o, ctype, CAMEL_OBJECT_MAGIC), NULL); - k = o->klass; while (k) { if (k == ctype) @@ -1100,8 +1023,6 @@ { CamelObjectClass *r = k; - g_return_val_if_fail(check_magic(k, ctype, CAMEL_OBJECT_CLASS_MAGIC), NULL); - while (k) { if (k == ctype) return r; @@ -1118,8 +1039,6 @@ { CamelObjectClass *r = k; - g_return_val_if_fail(check_magic(k, ctype, CAMEL_INTERFACE_MAGIC), NULL); - while (k) { if (k == ctype) return r; @@ -1447,7 +1366,8 @@ int i, size; const char *prepname; - g_return_if_fail (CAMEL_IS_OBJECT (obj)); + if (obj->ref_count > 0) + g_return_if_fail (CAMEL_IS_OBJECT (obj)); g_return_if_fail (name); hook = co_find_pair(obj->klass, name); @@ -1848,7 +1768,7 @@ savename = camel_file_util_savename(file); dirname = g_path_get_dirname(savename); - g_mkdir_with_parents(dirname, 0777); + e_util_mkdir_hier(dirname, 0777); g_free(dirname); fp = g_fopen(savename, "wb"); if (fp != NULL) { @@ -1899,9 +1819,6 @@ object_class_dump_tree_rec(CamelType root, int depth) { char *p; -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - struct _CamelObject *o; -#endif p = alloca(depth*2+1); memset(p, ' ', depth*2); @@ -1919,22 +1836,7 @@ pair = pair->next; } } -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - o = root->instances; - while (o) { - printf("%s instance %p [%d]\n", p, o, o->ref_count); - /* todo: should lock hooks while it scans them */ - if (o->hooks) { - CamelHookPair *pair = o->hooks->list; - - while (pair) { - printf("%s hook '%s' func %p data %p\n", p, pair->name, pair->func.event, pair->data); - pair = pair->next; - } - } - o = o->next; - } -#endif + CLASS_UNLOCK(root); if (root->child) diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-object.h ./camel-object.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-object.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-object.h 2007-05-12 10:01:18.000000000 +0200 @@ -34,9 +34,6 @@ #include #include /* this is a @##$@#SF stupid header */ -/* turn on so that camel_object_class_dump_tree() dumps object instances as well */ -#define CAMEL_OBJECT_TRACK_INSTANCES - G_BEGIN_DECLS typedef struct _CamelObjectClass *CamelType; @@ -104,6 +101,8 @@ typedef enum _CamelObjectFlags { CAMEL_OBJECT_DESTROY = (1<<0), + CAMEL_OBJECT_DESTROYED = (1<<1), + CAMEL_OBJECT_REF_DEBUG = (1<<2), } CamelObjectFlags; /* returned by get::CAMEL_OBJECT_METADATA */ @@ -118,17 +117,11 @@ struct _CamelObject { struct _CamelObjectClass *klass; - guint32 magic; /* only really needed for debugging ... */ - /* current hooks on this object */ struct _CamelHookList *hooks; guint32 ref_count:24; guint32 flags:8; - -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - struct _CamelObject *next, *prev; -#endif }; struct _CamelObjectClass @@ -152,12 +145,6 @@ /* available hooks for this class */ struct _CamelHookPair *hooks; - /* memchunks for this type */ - struct _EMemChunk *instance_chunks; -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - struct _CamelObject *instances; -#endif - /* init class */ void (*klass_init)(struct _CamelObjectClass *); void (*klass_finalise)(struct _CamelObjectClass *); Only in .: camel-object.lo Only in .: camel-object.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-offline-folder.c ./camel-offline-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-offline-folder.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-offline-folder.c 2007-05-12 10:01:18.000000000 +0200 @@ -112,10 +112,11 @@ if (m->changes) { for (i = 0; i < m->changes->uid_added->len; i++) { - int pc = i * 100 / m->changes->uid_added->len; - camel_operation_progress (NULL, pc); - if ((message = camel_folder_get_message (m->folder, m->changes->uid_added->pdata[i], &mm->ex))) + camel_operation_progress (NULL, i, m->changes->uid_added->len); + /* TNY: Partial message retrieval here is always body only */ + /* TODO: Maybe detect what the original message was, if there was a message? */ + if ((message = camel_folder_get_message (m->folder, m->changes->uid_added->pdata[i], CAMEL_FOLDER_RECEIVE_PARTIAL, -1, &mm->ex))) camel_object_unref (message); } } else { @@ -264,10 +265,11 @@ } for (i = 0; i < uids->len; i++) { - int pc = i * 100 / uids->len; - message = camel_folder_get_message (folder, uids->pdata[i], ex); - camel_operation_progress (NULL, pc); + /* TNY: Partial message retrieval here is always body only */ + /* TODO: Maybe detect what the original message was, if there was a message? */ + message = camel_folder_get_message (folder, uids->pdata[i], CAMEL_FOLDER_RECEIVE_PARTIAL, -1, ex); + camel_operation_progress (NULL, i, uids->len); if (message == NULL) break; Only in .: camel-offline-folder.lo Only in .: camel-offline-folder.o Only in .: camel-offline-journal.lo Only in .: camel-offline-journal.o Only in .: camel-offline-store.lo Only in .: camel-offline-store.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-operation.c ./camel-operation.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-operation.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-operation.c 2007-05-12 10:01:18.000000000 +0200 @@ -46,7 +46,7 @@ struct _status_stack { guint32 flags; char *msg; - int pc; /* last pc reported */ + int sofar, oftotal; unsigned int stamp; /* last stamp reported */ }; @@ -514,12 +514,14 @@ s = g_malloc0(sizeof(*s)); s->msg = msg; s->flags = 0; + s->sofar = 0; + s->oftotal = 100; cc->lastreport = s; cc->status_stack = g_slist_prepend(cc->status_stack, s); UNLOCK(); - cc->status(cc, msg, CAMEL_OPERATION_START, cc->status_data); + cc->status(cc, msg, CAMEL_OPERATION_START, 100, cc->status_data); d(printf("start '%s'\n", msg, pc)); } @@ -578,17 +580,17 @@ /** * camel_operation_progress: * @cc: Operation to report to. - * @pc: Percent complete, 0 to 100. + * @sofar: Amount complete + * @oftotal: Max amount (or, amount when completed) * * Report progress on the current operation. If @cc is NULL, then the - * currently registered operation is used. @pc reports the current - * percentage of completion, which should be in the range of 0 to 100. + * currently registered operation is used. @ * * If the total percentage is not know, then use * camel_operation_progress_count(). **/ void -camel_operation_progress (CamelOperation *cc, int pc) +camel_operation_progress (CamelOperation *cc, int sofar, int oftotal) { unsigned int now; struct _status_stack *s; @@ -608,7 +610,8 @@ } s = cc->status_stack->data; - s->pc = pc; + s->sofar = sofar; + s->oftotal = oftotal; /* Transient messages dont start updating till 4 seconds after they started, then they update every second */ @@ -632,7 +635,7 @@ UNLOCK(); if (cc) { - cc->status(cc, msg, pc, cc->status_data); + cc->status(cc, msg, sofar, oftotal, cc->status_data); g_free(msg); } } @@ -646,7 +649,7 @@ void camel_operation_progress_count (CamelOperation *cc, int sofar) { - camel_operation_progress(cc, sofar); + camel_operation_progress(cc, sofar, 100); } /** @@ -664,7 +667,8 @@ struct _status_stack *s, *p; unsigned int now; char *msg = NULL; - int pc = 0; + int sofar = 0; + int oftotal = 100; if (cc == NULL) cc = co_getcc(); @@ -693,13 +697,15 @@ if (p->flags & CAMEL_OPERATION_TRANSIENT) { if (p->stamp + CAMEL_OPERATION_TRANSIENT_DELAY < now) { msg = g_strdup(p->msg); - pc = p->pc; + sofar = p->sofar; + oftotal = p->oftotal; cc->lastreport = p; break; } } else { msg = g_strdup(p->msg); - pc = p->pc; + sofar = p->sofar; + oftotal = p->oftotal; cc->lastreport = p; break; } @@ -709,7 +715,8 @@ g_free(s->msg); } else { msg = s->msg; - pc = CAMEL_OPERATION_END; + sofar = CAMEL_OPERATION_END; + oftotal = 100; cc->lastreport = s; } g_free(s); @@ -718,7 +725,7 @@ UNLOCK(); if (msg) { - cc->status(cc, msg, pc, cc->status_data); + cc->status(cc, msg, sofar, oftotal, cc->status_data); g_free(msg); } } diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-operation.h ./camel-operation.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-operation.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-operation.h 2007-05-12 10:01:18.000000000 +0200 @@ -28,7 +28,7 @@ typedef struct _CamelOperation CamelOperation; -typedef void (*CamelOperationStatusFunc)(struct _CamelOperation *op, const char *what, int pc, void *data); +typedef void (*CamelOperationStatusFunc)(struct _CamelOperation *op, const char *what, int sofar, int oftotal, void *data); typedef enum _camel_operation_status_t { CAMEL_OPERATION_START = -1, @@ -59,7 +59,7 @@ void camel_operation_start(CamelOperation *cc, char *what, ...); void camel_operation_start_transient(CamelOperation *cc, char *what, ...); -void camel_operation_progress(CamelOperation *cc, int pc); +void camel_operation_progress(CamelOperation *cc, int sofar, int oftotal); void camel_operation_progress_count(CamelOperation *cc, int sofar); void camel_operation_end(CamelOperation *cc); Only in .: camel-operation.lo Only in .: camel-operation.o Only in .: camel-partition-table.lo Only in .: camel-partition-table.o Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/: camel.pc.in diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-private.h ./camel-private.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-private.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-private.h 2007-05-12 10:01:18.000000000 +0200 @@ -84,6 +84,8 @@ (g_static_rec_mutex_lock(&((CamelService *)f)->priv->l)) #define CAMEL_SERVICE_REC_UNLOCK(f, l) \ (g_static_rec_mutex_unlock(&((CamelService *)f)->priv->l)) +#define CAMEL_SERVICE_REC_TRYLOCK(f, l) \ + (g_static_rec_mutex_trylock(&((CamelService *)f)->priv->l)) struct _CamelSessionPrivate { @@ -114,12 +116,9 @@ struct _CamelStreamFilter *filter_stream; - struct _CamelIndex *index; - GMutex *summary_lock; /* for the summary hashtable/array */ GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ GMutex *filter_lock; /* for accessing any of the filtering/indexing stuff, since we share them */ - GMutex *alloc_lock; /* for setting up and using allocators */ GMutex *ref_lock; /* for reffing/unreffing messageinfo's ALWAYS obtain before summary_lock */ }; @@ -130,7 +129,6 @@ struct _CamelStoreSummaryPrivate { GMutex *summary_lock; /* for the summary hashtable/array */ GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ - GMutex *alloc_lock; /* for setting up and using allocators */ GMutex *ref_lock; /* for reffing/unreffing messageinfo's ALWAYS obtain before summary_lock */ }; @@ -163,13 +161,19 @@ struct _CamelCertDBPrivate { GMutex *db_lock; /* for the db hashtable/array */ GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ - GMutex *alloc_lock; /* for setting up and using allocators */ GMutex *ref_lock; /* for reffing/unreffing certs */ }; #define CAMEL_CERTDB_LOCK(db, l) (g_mutex_lock (((CamelCertDB *) db)->priv->l)) #define CAMEL_CERTDB_UNLOCK(db, l) (g_mutex_unlock (((CamelCertDB *) db)->priv->l)) +#if !GLIB_CHECK_VERSION(2,8,0) +#define g_access access +#define g_chmod chmod +#define g_creat creat +#define g_chdir chdir +#endif + #ifdef G_OS_WIN32 int fsync (int fd); @@ -177,8 +181,8 @@ const char *_camel_get_libexecdir (void) G_GNUC_CONST; const char *_camel_get_providerdir (void) G_GNUC_CONST; -#undef EVOLUTION_LOCALEDIR -#define EVOLUTION_LOCALEDIR _camel_get_localedir () +#undef LOCALEDIR +#define LOCALEDIR _camel_get_localedir () #undef CAMEL_LIBEXECDIR #define CAMEL_LIBEXECDIR _camel_get_libexecdir () Only in .: camel-provider.lo Only in .: camel-provider.o Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/: camel-provider.pc.in diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-anonymous.c ./camel-sasl-anonymous.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-anonymous.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-sasl-anonymous.c 2007-05-12 10:01:18.000000000 +0200 @@ -137,7 +137,7 @@ } camel_object_unref (cia); ret = g_byte_array_new (); - g_byte_array_append (ret, sasl_anon->trace_info, strlen (sasl_anon->trace_info)); + g_byte_array_append (ret, (const guchar*)sasl_anon->trace_info, strlen (sasl_anon->trace_info)); break; case CAMEL_SASL_ANON_TRACE_OPAQUE: if (strchr (sasl_anon->trace_info, '@')) { @@ -147,7 +147,7 @@ return NULL; } ret = g_byte_array_new (); - g_byte_array_append (ret, sasl_anon->trace_info, strlen (sasl_anon->trace_info)); + g_byte_array_append (ret, (const guchar*)sasl_anon->trace_info, strlen (sasl_anon->trace_info)); break; case CAMEL_SASL_ANON_TRACE_EMPTY: ret = g_byte_array_new (); Only in .: camel-sasl-anonymous.lo Only in .: camel-sasl-anonymous.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl.c ./camel-sasl.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-sasl.c 2007-03-11 16:44:11.000000000 +0100 @@ -138,8 +138,8 @@ if (token) { token_binary = g_byte_array_new (); len = strlen (token); - g_byte_array_append (token_binary, token, len); - token_binary->len = camel_base64_decode_simple (token_binary->data, len); + g_byte_array_append (token_binary, (guchar *) token, len); + token_binary->len = camel_base64_decode_simple ((char *) token_binary->data, len); } else token_binary = NULL; @@ -149,7 +149,7 @@ if (!ret_binary) return NULL; - ret = camel_base64_encode_simple (ret_binary->data, ret_binary->len); + ret = camel_base64_encode_simple ((const char *) ret_binary->data, ret_binary->len); g_byte_array_free (ret_binary, TRUE); return ret; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-cram-md5.c ./camel-sasl-cram-md5.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-cram-md5.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-sasl-cram-md5.c 2007-05-12 10:01:18.000000000 +0200 @@ -134,11 +134,11 @@ /* lowercase hexify that bad-boy... */ for (s = digest, p = md5asc; p < md5asc + 32; s++, p += 2) - sprintf (p, "%.2x", *s); + sprintf ((char*)p, "%.2x", *s); ret = g_byte_array_new (); - g_byte_array_append (ret, sasl->service->url->user, strlen (sasl->service->url->user)); - g_byte_array_append (ret, " ", 1); + g_byte_array_append (ret, (const guchar*)sasl->service->url->user, strlen (sasl->service->url->user)); + g_byte_array_append (ret, (const guchar*)" ", 1); g_byte_array_append (ret, md5asc, 32); sasl->authenticated = TRUE; Only in .: camel-sasl-cram-md5.lo Only in .: camel-sasl-cram-md5.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-digest-md5.c ./camel-sasl-digest-md5.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-digest-md5.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-sasl-digest-md5.c 2007-05-12 10:01:18.000000000 +0200 @@ -546,7 +546,7 @@ /* lowercase hexify that bad-boy... */ for (s = digest, p = hex; p < hex + 32; s++, p += 2) - sprintf (p, "%.2x", *s); + sprintf ((char *) p, "%.2x", *s); } static char * @@ -568,22 +568,22 @@ /* compute A1 */ md5_init (&ctx); - md5_update (&ctx, resp->username, strlen (resp->username)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->realm, strlen (resp->realm)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, passwd, strlen (passwd)); + md5_update (&ctx, (const guchar*) resp->username, strlen (resp->username)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->realm, strlen (resp->realm)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) passwd, strlen (passwd)); md5_final (&ctx, digest); md5_init (&ctx); md5_update (&ctx, digest, 16); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->nonce, strlen (resp->nonce)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->cnonce, strlen (resp->cnonce)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->nonce, strlen (resp->nonce)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->cnonce, strlen (resp->cnonce)); if (resp->authzid) { - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->authzid, strlen (resp->authzid)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->authzid, strlen (resp->authzid)); } /* hexify A1 */ @@ -594,18 +594,18 @@ md5_init (&ctx); if (client) { /* we are calculating the client response */ - md5_update (&ctx, "AUTHENTICATE:", strlen ("AUTHENTICATE:")); + md5_update (&ctx, (const guchar*) "AUTHENTICATE:", strlen ("AUTHENTICATE:")); } else { /* we are calculating the server rspauth */ - md5_update (&ctx, ":", 1); + md5_update (&ctx, (const guchar*) ":", 1); } buf = digest_uri_to_string (resp->uri); - md5_update (&ctx, buf, strlen (buf)); + md5_update (&ctx, (const guchar*) buf, strlen (buf)); g_free (buf); if (resp->qop == QOP_AUTH_INT || resp->qop == QOP_AUTH_CONF) - md5_update (&ctx, ":00000000000000000000000000000000", 33); + md5_update (&ctx, (const guchar*) ":00000000000000000000000000000000", 33); /* now hexify A2 */ md5_final (&ctx, digest); @@ -613,17 +613,17 @@ /* compute KD */ md5_init (&ctx); - md5_update (&ctx, hex_a1, 32); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->nonce, strlen (resp->nonce)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->nc, 8); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->cnonce, strlen (resp->cnonce)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, qop_to_string (resp->qop), strlen (qop_to_string (resp->qop))); - md5_update (&ctx, ":", 1); - md5_update (&ctx, hex_a2, 32); + md5_update (&ctx, (const guchar*) hex_a1, 32); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->nonce, strlen (resp->nonce)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->nc, 8); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) resp->cnonce, strlen (resp->cnonce)); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx,(const guchar*) qop_to_string (resp->qop), strlen (qop_to_string (resp->qop))); + md5_update (&ctx, (const guchar*) ":", 1); + md5_update (&ctx, (const guchar*) hex_a2, 32); md5_final (&ctx, digest); digest_hex (digest, out); @@ -651,7 +651,7 @@ bgen = g_strdup_printf ("%p:%lu:%lu", resp, (unsigned long) getpid (), (unsigned long) time (0)); - md5_get_digest (bgen, strlen (bgen), digest); + md5_get_digest (bgen, strlen (bgen), (guchar*) digest); g_free (bgen); /* take our recommended 64 bits of entropy */ resp->cnonce = camel_base64_encode_simple (digest, 8); @@ -688,7 +688,7 @@ /* we don't really care about this... */ resp->authzid = NULL; - compute_response (resp, passwd, TRUE, resp->resp); + compute_response (resp, passwd, TRUE, (guchar*) resp->resp); return resp; } @@ -701,7 +701,7 @@ char *buf; buffer = g_byte_array_new (); - g_byte_array_append (buffer, "username=\"", 10); + g_byte_array_append (buffer, (guchar*) "username=\"", 10); if (resp->charset) { /* Encode the username using the requested charset */ char *username, *outbuf; @@ -734,61 +734,61 @@ if (cd != (iconv_t) -1) e_iconv_close (cd); - g_byte_array_append (buffer, username, strlen (username)); + g_byte_array_append (buffer, (guchar *) username, strlen (username)); g_free (username); } else { - g_byte_array_append (buffer, resp->username, strlen (resp->username)); + g_byte_array_append (buffer, (guchar *) resp->username, strlen (resp->username)); } - g_byte_array_append (buffer, "\",realm=\"", 9); - g_byte_array_append (buffer, resp->realm, strlen (resp->realm)); + g_byte_array_append (buffer, (guchar *) "\",realm=\"", 9); + g_byte_array_append (buffer,(guchar *) resp->realm, strlen (resp->realm)); - g_byte_array_append (buffer, "\",nonce=\"", 9); - g_byte_array_append (buffer, resp->nonce, strlen (resp->nonce)); + g_byte_array_append (buffer, (guchar *) "\",nonce=\"", 9); + g_byte_array_append (buffer, (guchar *) resp->nonce, strlen (resp->nonce)); - g_byte_array_append (buffer, "\",cnonce=\"", 10); - g_byte_array_append (buffer, resp->cnonce, strlen (resp->cnonce)); + g_byte_array_append (buffer, (guchar *) "\",cnonce=\"", 10); + g_byte_array_append (buffer, (guchar *) resp->cnonce, strlen (resp->cnonce)); - g_byte_array_append (buffer, "\",nc=", 5); - g_byte_array_append (buffer, resp->nc, 8); + g_byte_array_append (buffer, (guchar *) "\",nc=", 5); + g_byte_array_append (buffer,(guchar *) resp->nc, 8); - g_byte_array_append (buffer, ",qop=", 5); + g_byte_array_append (buffer, (guchar *) ",qop=", 5); str = qop_to_string (resp->qop); - g_byte_array_append (buffer, str, strlen (str)); + g_byte_array_append (buffer, (guchar *) str, strlen (str)); - g_byte_array_append (buffer, ",digest-uri=\"", 13); + g_byte_array_append (buffer, (guchar *) ",digest-uri=\"", 13); buf = digest_uri_to_string (resp->uri); - g_byte_array_append (buffer, buf, strlen (buf)); + g_byte_array_append (buffer, (guchar *) buf, strlen (buf)); g_free (buf); - g_byte_array_append (buffer, "\",response=", 11); - g_byte_array_append (buffer, resp->resp, 32); + g_byte_array_append (buffer, (guchar *) "\",response=", 11); + g_byte_array_append (buffer, (guchar *) resp->resp, 32); if (resp->maxbuf > 0) { - g_byte_array_append (buffer, ",maxbuf=", 8); + g_byte_array_append (buffer, (guchar *) ",maxbuf=", 8); buf = g_strdup_printf ("%u", resp->maxbuf); - g_byte_array_append (buffer, buf, strlen (buf)); + g_byte_array_append (buffer, (guchar *) buf, strlen (buf)); g_free (buf); } if (resp->charset) { - g_byte_array_append (buffer, ",charset=", 9); - g_byte_array_append (buffer, resp->charset, strlen (resp->charset)); + g_byte_array_append (buffer, (guchar *) ",charset=", 9); + g_byte_array_append (buffer, (guchar *) resp->charset, strlen ((char *) resp->charset)); } if (resp->cipher != CIPHER_INVALID) { str = cipher_to_string (resp->cipher); if (str) { - g_byte_array_append (buffer, ",cipher=\"", 9); - g_byte_array_append (buffer, str, strlen (str)); - g_byte_array_append (buffer, "\"", 1); + g_byte_array_append (buffer, (guchar *) ",cipher=\"", 9); + g_byte_array_append (buffer, (guchar *) str, strlen (str)); + g_byte_array_append (buffer, (guchar *) "\"", 1); } } if (resp->authzid) { - g_byte_array_append (buffer, ",authzid=\"", 10); - g_byte_array_append (buffer, resp->authzid, strlen (resp->authzid)); - g_byte_array_append (buffer, "\"", 1); + g_byte_array_append (buffer, (guchar *) ",authzid=\"", 10); + g_byte_array_append (buffer, (guchar *) resp->authzid, strlen (resp->authzid)); + g_byte_array_append (buffer, (guchar *) "\"", 1); } return buffer; @@ -821,7 +821,7 @@ return NULL; } - tokens = g_strndup (token->data, token->len); + tokens = g_strndup ((gchar *) token->data, token->len); priv->challenge = parse_server_challenge (tokens, &abort); g_free (tokens); if (!priv->challenge || abort) { @@ -855,7 +855,7 @@ break; case STATE_FINAL: if (token->len) - tokens = g_strndup (token->data, token->len); + tokens = g_strndup ((gchar *) token->data, token->len); else tokens = NULL; Only in .: camel-sasl-digest-md5.lo Only in .: camel-sasl-digest-md5.o Only in .: camel-sasl-gssapi.lo Only in .: camel-sasl-gssapi.o Only in .: camel-sasl-kerberos4.lo Only in .: camel-sasl-kerberos4.o Only in .: camel-sasl.lo diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-login.c ./camel-sasl-login.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-login.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-sasl-login.c 2007-05-12 10:01:18.000000000 +0200 @@ -121,11 +121,11 @@ switch (priv->state) { case LOGIN_USER: buf = g_byte_array_new (); - g_byte_array_append (buf, url->user, strlen (url->user)); + g_byte_array_append (buf, (guchar *) url->user, strlen (url->user)); break; case LOGIN_PASSWD: buf = g_byte_array_new (); - g_byte_array_append (buf, url->passwd, strlen (url->passwd)); + g_byte_array_append (buf, (guchar *) url->passwd, strlen (url->passwd)); sasl->authenticated = TRUE; break; Only in .: camel-sasl-login.lo Only in .: camel-sasl-login.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-ntlm.c ./camel-sasl-ntlm.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-ntlm.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-sasl-ntlm.c 2007-05-12 10:01:18.000000000 +0200 @@ -105,15 +105,15 @@ ret = g_byte_array_new (); if (!token || !token->len) { - g_byte_array_append (ret, NTLM_REQUEST, + g_byte_array_append (ret, (guchar *) NTLM_REQUEST, sizeof (NTLM_REQUEST) - 1); return ret; } memcpy (nonce, token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8); - ntlm_lanmanager_hash (sasl->service->url->passwd, hash); + ntlm_lanmanager_hash (sasl->service->url->passwd, (char *) hash); ntlm_calc_response (hash, nonce, lm_resp); - ntlm_nt_hash (sasl->service->url->passwd, hash); + ntlm_nt_hash (sasl->service->url->passwd, (char *) hash); ntlm_calc_response (hash, nonce, nt_resp); ret = g_byte_array_new (); @@ -125,17 +125,17 @@ NTLM_RESPONSE_FLAGS, sizeof (NTLM_RESPONSE_FLAGS) - 1); ntlm_set_string (ret, NTLM_RESPONSE_DOMAIN_OFFSET, - token->data + NTLM_CHALLENGE_DOMAIN_OFFSET, - atoi (token->data + NTLM_CHALLENGE_DOMAIN_LEN_OFFSET)); + (const char *) token->data + NTLM_CHALLENGE_DOMAIN_OFFSET, + atoi ((char *) token->data + NTLM_CHALLENGE_DOMAIN_LEN_OFFSET)); ntlm_set_string (ret, NTLM_RESPONSE_USER_OFFSET, sasl->service->url->user, strlen (sasl->service->url->user)); ntlm_set_string (ret, NTLM_RESPONSE_HOST_OFFSET, "UNKNOWN", sizeof ("UNKNOWN") - 1); ntlm_set_string (ret, NTLM_RESPONSE_LM_RESP_OFFSET, - lm_resp, sizeof (lm_resp)); + (const char *) lm_resp, sizeof (lm_resp)); ntlm_set_string (ret, NTLM_RESPONSE_NT_RESP_OFFSET, - nt_resp, sizeof (nt_resp)); + (const char *) nt_resp, sizeof (nt_resp)); sasl->authenticated = TRUE; return ret; @@ -177,10 +177,10 @@ memcpy (hash, LM_PASSWORD_MAGIC, 21); setup_schedule (lm_password, ks); - des (ks, hash); + des (ks, (unsigned char *) hash); setup_schedule (lm_password + 7, ks); - des (ks, hash + 8); + des (ks, (unsigned char *) hash + 8); } static void @@ -195,7 +195,7 @@ *p++ = '\0'; } - md4sum (buf, p - buf, hash); + md4sum (buf, p - buf, ( unsigned char *) hash); memset (hash + 16, 0, 5); g_free (buf); @@ -208,7 +208,7 @@ ba->data[offset + 1] = ba->data[offset + 3] = (len >> 8) & 0xFF; ba->data[offset + 4] = ba->len & 0xFF; ba->data[offset + 5] = (ba->len >> 8) & 0xFF; - g_byte_array_append (ba, data, len); + g_byte_array_append (ba, (guchar *) data, len); } Only in .: camel-sasl-ntlm.lo Only in .: camel-sasl-ntlm.o Only in .: camel-sasl.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-plain.c ./camel-sasl-plain.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-sasl-plain.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-sasl-plain.c 2007-05-12 10:01:18.000000000 +0200 @@ -97,10 +97,10 @@ /* FIXME: make sure these are "UTF8-SAFE" */ buf = g_byte_array_new (); - g_byte_array_append (buf, "", 1); - g_byte_array_append (buf, url->user, strlen (url->user)); - g_byte_array_append (buf, "", 1); - g_byte_array_append (buf, url->passwd, strlen (url->passwd)); + g_byte_array_append (buf, (guchar *) "", 1); + g_byte_array_append (buf,(guchar *) url->user, strlen (url->user)); + g_byte_array_append (buf,(guchar *) "", 1); + g_byte_array_append (buf, (guchar *) url->passwd, strlen (url->passwd)); sasl->authenticated = TRUE; Only in .: camel-sasl-plain.lo Only in .: camel-sasl-plain.o Only in .: camel-sasl-popb4smtp.lo Only in .: camel-sasl-popb4smtp.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-search-private.c ./camel-search-private.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-search-private.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-search-private.c 2007-05-12 10:01:18.000000000 +0200 @@ -248,7 +248,7 @@ puni = nuni = g_alloca (sizeof (gunichar) * strlen (needle)); - p = needle; + p = (const unsigned char *) needle; while ((u = camel_utf8_getc(&p))) *puni++ = g_unichar_tolower (u); @@ -379,7 +379,10 @@ /* from dan the man, if we have mixed case, perform a case-sensitive match, otherwise not */ p = (const unsigned char *)match; - while ((c = camel_utf8_getc(&p))) { + + c = camel_utf8_getc (&p); + while (c) + { if (g_unichar_isupper(c)) { switch (how) { case CAMEL_SEARCH_MATCH_EXACT: @@ -395,8 +398,9 @@ } return FALSE; } + c = camel_utf8_getc (&p); } - + switch (how) { case CAMEL_SEARCH_MATCH_EXACT: return camel_ustrcasecmp(value, match) == 0; @@ -510,7 +514,7 @@ camel_data_wrapper_write_to_stream (containee, CAMEL_STREAM (mem)); camel_stream_write (CAMEL_STREAM (mem), "", 1); - truth = regexec (pattern, mem->buffer->data, 0, NULL, 0) == 0; + truth = regexec (pattern, (char *) mem->buffer->data, 0, NULL, 0) == 0; camel_object_unref (mem); } @@ -622,14 +626,14 @@ word->word = g_strdup(wordin->words[i]->word); g_ptr_array_add(list, word); } else { - ptr = wordin->words[i]->word; + ptr = (const unsigned char *) wordin->words[i]->word; start = last = ptr; do { c = camel_utf8_getc(&ptr); if (c == 0 || !g_unichar_isalnum(c)) { if (last > start) { word = g_malloc0(sizeof(*word)); - word->word = g_strndup(start, last-start); + word->word = g_strndup((gchar *) start, last-start); word->type = type; g_ptr_array_add(list, word); all |= type; Only in .: camel-search-private.lo Only in .: camel-search-private.o Only in .: camel-seekable-stream.lo Only in .: camel-seekable-stream.o Only in .: camel-seekable-substream.lo Only in .: camel-seekable-substream.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-service.c ./camel-service.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-service.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-service.c 2007-05-12 10:01:18.000000000 +0200 @@ -93,7 +93,8 @@ camel_service_init (void *o, void *k) { CamelService *service = o; - + + service->data = NULL; service->priv = g_malloc0(sizeof(*service->priv)); g_static_rec_mutex_init(&service->priv->connect_lock); g_static_mutex_init(&service->priv->connect_op_lock); @@ -120,7 +121,8 @@ camel_url_free (service->url); if (service->session) camel_object_unref (service->session); - + service->data = NULL; + g_static_rec_mutex_free (&service->priv->connect_lock); g_static_mutex_free (&service->priv->connect_op_lock); diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-service.h ./camel-service.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-service.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-service.h 2007-05-12 10:01:18.000000000 +0200 @@ -68,6 +68,7 @@ CamelServiceConnectionStatus status; CamelOperation *connect_op; CamelURL *url; + gpointer data; }; typedef struct { Only in .: camel-service.lo Only in .: camel-service.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-session.c ./camel-session.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-session.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-session.c 2007-05-12 10:01:18.000000000 +0200 @@ -294,7 +294,7 @@ #endif return path; - if (g_mkdir_with_parents (path, S_IRWXU) == -1) { + if (e_util_mkdir_hier (path, S_IRWXU) == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create directory %s:\n%s"), path, g_strerror (errno)); @@ -336,7 +336,7 @@ * @session: a #CamelSession object * @service: the #CamelService this query is being made by * @domain: domain of password request. May be null to use the default. - * @prompt: prompt to provide to user + * @prompt: prompt to provide to user. May be null. * @item: an identifier, unique within this service, for the information * @flags: #CAMEL_SESSION_PASSWORD_REPROMPT, the prompt should force a reprompt * #CAMEL_SESSION_PASSWORD_SECRET, whether the password is secret @@ -352,6 +352,9 @@ * @prompt is a question to ask the user (if the application doesn't * already have the answer cached). If #CAMEL_SESSION_PASSWORD_SECRET * is set, the user's input will not be echoed back. + * This is a human-readable password question, possibly containing an untranslated error + * message directly from the server. This should be ignored by most implementations, + * so NULL is an acceptable value. * * If #CAMEL_SESSION_PASSWORD_STATIC is set, it means the password returned * will be stored statically by the caller automatically, for the current @@ -474,11 +477,11 @@ } static void -cs_thread_status(CamelOperation *op, const char *what, int pc, void *data) +cs_thread_status(CamelOperation *op, const char *what, int sofar, int oftotal, void *data) { CamelSessionThreadMsg *m = data; - CS_CLASS(m->session)->thread_status(m->session, m, what, pc); + CS_CLASS(m->session)->thread_status(m->session, m, what, sofar * 100 / oftotal); } static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size) Only in .: camel-session.lo Only in .: camel-session.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-smime-context.c ./camel-smime-context.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-smime-context.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-smime-context.c 2007-05-12 10:01:18.000000000 +0200 @@ -157,7 +157,7 @@ NULL, NULL, /* password callback */ NULL, NULL); /* decrypt key callback */ - NSS_CMSDecoder_Update(dec, istream->buffer->data, istream->buffer->len); + NSS_CMSDecoder_Update(dec, (char*) istream->buffer->data, istream->buffer->len); camel_object_unref(istream); cmsg = NSS_CMSDecoder_Finish(dec); @@ -401,7 +401,7 @@ goto fail; } - if (NSS_CMSEncoder_Update(enc, ((CamelStreamMem *)istream)->buffer->data, ((CamelStreamMem *)istream)->buffer->len) != SECSuccess) { + if (NSS_CMSEncoder_Update(enc, (char *) ((CamelStreamMem *)istream)->buffer->data, ((CamelStreamMem *)istream)->buffer->len) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to CMS encoder")); goto fail; @@ -717,7 +717,7 @@ NULL, NULL); /* decrypt key callback */ camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)sigpart), (CamelStream *)mem); - (void)NSS_CMSDecoder_Update(dec, mem->buffer->data, mem->buffer->len); + (void)NSS_CMSDecoder_Update(dec, (char *) mem->buffer->data, mem->buffer->len); cmsg = NSS_CMSDecoder_Finish(dec); if (cmsg == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Decoder failed")); @@ -853,7 +853,7 @@ /* FIXME: Canonicalise the input? */ mem = (CamelStreamMem *)camel_stream_mem_new(); camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, (CamelStream *)mem); - if (NSS_CMSEncoder_Update(enc, mem->buffer->data, mem->buffer->len) != SECSuccess) { + if (NSS_CMSEncoder_Update(enc, (char *) mem->buffer->data, mem->buffer->len) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); camel_object_unref(mem); camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to encoder")); @@ -936,7 +936,7 @@ NULL, NULL, NULL, NULL); /* decrypt key callback */ - if (NSS_CMSDecoder_Update(dec, istream->buffer->data, istream->buffer->len) != SECSuccess) { + if (NSS_CMSDecoder_Update(dec, (char *) istream->buffer->data, istream->buffer->len) != SECSuccess) { printf("decoder update failed\n"); } camel_object_unref(istream); Only in .: camel-smime-context.lo Only in .: camel-smime-context.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store.c ./camel-store.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-store.c 2007-05-12 10:00:17.000000000 +0200 @@ -84,6 +84,8 @@ static int store_setv (CamelObject *object, CamelException *ex, CamelArgV *args); static int store_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); +static GPtrArray* get_recent_messages (CamelStore *store, const char *folder_name, int *unseen, int *messages); + static void camel_store_class_init (CamelStoreClass *camel_store_class) { @@ -109,7 +111,8 @@ camel_store_class->subscribe_folder = subscribe_folder; camel_store_class->unsubscribe_folder = unsubscribe_folder; camel_store_class->noop = noop; - + camel_store_class->get_recent_messages = get_recent_messages; + /* virtual method overload */ camel_service_class->construct = construct; @@ -177,6 +180,29 @@ return camel_store_type; } + +GPtrArray* +camel_store_get_recent_messages (CamelStore *store, const char *folder_name, + int *unseen, int *messages) +{ + GPtrArray *ret; + + CAMEL_STORE_LOCK(store, folder_lock); + ret = CS_CLASS (store)->get_recent_messages (store, folder_name, unseen, messages); + CAMEL_STORE_UNLOCK(store, folder_lock); + + return ret; +} + +static GPtrArray* +get_recent_messages (CamelStore *store, const char *folder_name, int *unseen, int *messages) +{ + *unseen = 0; + *messages = 0; + return NULL; +} + + static int store_setv (CamelObject *object, CamelException *ex, CamelArgV *args) { @@ -713,7 +739,7 @@ g_free (vinfo->uri); } else { /* There wasn't a Trash/Junk folder so create a new folder entry */ - vinfo = g_new0 (CamelFolderInfo, 1); + vinfo = camel_folder_info_new (); g_assert(parent != NULL); @@ -858,6 +884,7 @@ ; } + /** * camel_folder_info_free: * @fi: a #CamelFolderInfo @@ -873,10 +900,25 @@ g_free (fi->name); g_free (fi->full_name); g_free (fi->uri); - g_free (fi); + g_slice_free (CamelFolderInfo, fi); } } + +/** + * camel_folder_info_new: + * + * Return value: a new empty CamelFolderInfo instance + **/ +CamelFolderInfo* +camel_folder_info_new (void) +{ + CamelFolderInfo *retval = g_slice_new0 (CamelFolderInfo); + retval->unread = 0; + retval->total = 0; + return retval; +} + static int folder_info_cmp (const void *ap, const void *bp) { @@ -945,7 +987,7 @@ CamelURL *url; char *sep; - pfi = g_new0 (CamelFolderInfo, 1); + pfi = camel_folder_info_new (); if (short_names) { pfi->name = strrchr (pname, separator); if (pfi->name) @@ -1088,7 +1130,9 @@ gboolean ret; g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); - g_return_val_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS, FALSE); + + if (! (store->flags & CAMEL_STORE_SUBSCRIPTIONS) ) + return FALSE; CAMEL_STORE_LOCK(store, folder_lock); @@ -1099,6 +1143,8 @@ return ret; } + + static void subscribe_folder(CamelStore *store, const char *folder_name, CamelException *ex) { diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store.h ./camel-store.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-store.h 2007-05-12 10:00:17.000000000 +0200 @@ -51,6 +51,8 @@ guint32 flags; guint32 unread; guint32 total; + guint32 local_size; + } CamelFolderInfo; /* Note: these are abstractions (duh), its upto the provider to make them make sense */ @@ -185,6 +187,10 @@ CamelException *ex); void (*noop) (CamelStore *store, CamelException *ex); + GPtrArray* (*get_recent_messages) (CamelStore *store, + const char *folder_name, + int *unseen, int *messages); + } CamelStoreClass; /* Standard Camel function */ @@ -228,6 +234,8 @@ void camel_store_free_folder_info_nop (CamelStore *store, CamelFolderInfo *fi); + +CamelFolderInfo *camel_folder_info_new (void); void camel_folder_info_free (CamelFolderInfo *fi); CamelFolderInfo *camel_folder_info_build (GPtrArray *folders, const char *namespace, @@ -253,6 +261,11 @@ const char *uri0, const char *uri1); +GPtrArray* camel_store_get_recent_messages (CamelStore *store, + const char *folder_name, + int *unseen, int *messages); + + typedef struct _CamelISubscribe CamelISubscribe; struct _CamelISubscribe { CamelInterface iface; Only in .: camel-store.lo Only in .: camel-store.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store-summary.c ./camel-store-summary.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store-summary.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-store-summary.c 2007-05-12 10:01:18.000000000 +0200 @@ -98,8 +98,6 @@ s->store_info_size = sizeof(CamelStoreInfo); - s->store_info_chunks = NULL; - s->version = CAMEL_STORE_SUMMARY_VERSION; s->flags = 0; s->count = 0; @@ -110,7 +108,6 @@ p->summary_lock = g_mutex_new(); p->io_lock = g_mutex_new(); - p->alloc_lock = g_mutex_new(); p->ref_lock = g_mutex_new(); } @@ -122,18 +119,19 @@ p = _PRIVATE(obj); + camel_store_summary_save (s); + camel_store_summary_clear(s); g_ptr_array_free(s->folders, TRUE); g_hash_table_destroy(s->folders_path); g_free(s->summary_path); - if (s->store_info_chunks) - e_memchunk_destroy(s->store_info_chunks); - + if (s->uri_base) + camel_url_free(s->uri_base); + g_mutex_free(p->summary_lock); g_mutex_free(p->io_lock); - g_mutex_free(p->alloc_lock); g_mutex_free(p->ref_lock); g_free(p); @@ -831,11 +829,7 @@ { CamelStoreInfo *info; - CAMEL_STORE_SUMMARY_LOCK(s, alloc_lock); - if (s->store_info_chunks == NULL) - s->store_info_chunks = e_memchunk_new(32, s->store_info_size); - info = e_memchunk_alloc0(s->store_info_chunks); - CAMEL_STORE_SUMMARY_UNLOCK(s, alloc_lock); + info = g_slice_alloc0(s->store_info_size); info->refcount = 1; return info; } @@ -944,7 +938,7 @@ { g_free(info->path); g_free(info->uri); - e_memchunk_free(s->store_info_chunks, info); + g_slice_free1(s->store_info_size, info); } static const char * diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store-summary.h ./camel-store-summary.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-store-summary.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-store-summary.h 2007-05-12 10:01:18.000000000 +0200 @@ -99,9 +99,6 @@ /* sizes of memory objects */ guint32 store_info_size; - /* memory allocators (setup automatically) */ - struct _EMemChunk *store_info_chunks; - char *summary_path; GPtrArray *folders; /* CamelStoreInfo's */ Only in .: camel-store-summary.lo Only in .: camel-store-summary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-stream-buffer.c ./camel-stream-buffer.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-stream-buffer.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-stream-buffer.c 2007-05-12 10:01:18.000000000 +0200 @@ -32,6 +32,7 @@ #include #include "camel-stream-buffer.h" +#include "camel-tcp-stream.h" static CamelStreamClass *parent_class = NULL; @@ -126,7 +127,7 @@ g_free(sbf->buf); } if (buf) { - sbf->buf = buf; + sbf->buf = (unsigned char*)buf; sbf->flags |= BUF_USER; } else { sbf->buf = g_malloc(size); @@ -253,7 +254,7 @@ bptr += bytes_read; } } else { - bytes_read = camel_stream_read(sbf->stream, sbf->buf, sbf->size); + bytes_read = camel_stream_read(sbf->stream, (char *)sbf->buf, sbf->size); if (bytes_read>0) { size_t bytes_used = bytes_read > n ? n : bytes_read; sbf->ptr = sbf->buf; @@ -312,7 +313,7 @@ /* if we've filled the buffer, write it out, reset buffer */ if (left == todo) { - if (stream_write_all(sbf->stream, sbf->buf, sbf->size) == -1) + if (stream_write_all(sbf->stream, (const char *)sbf->buf, sbf->size) == -1) return -1; sbf->ptr = sbf->buf; @@ -340,7 +341,7 @@ if ((sbf->mode & CAMEL_STREAM_BUFFER_MODE) == CAMEL_STREAM_BUFFER_WRITE) { size_t len = sbf->ptr - sbf->buf; - if (camel_stream_write (sbf->stream, sbf->buf, len) == -1) + if (camel_stream_write (sbf->stream, (const char *)sbf->buf, len) == -1) return -1; sbf->ptr = sbf->buf; @@ -391,8 +392,8 @@ int bytes_read; outptr = buf; - inptr = sbf->ptr; - inend = sbf->end; + inptr = (char*)sbf->ptr; + inend = (char*)sbf->end; outend = buf+max-1; /* room for NUL */ do { @@ -401,25 +402,71 @@ *outptr++ = c; if (c == '\n') { *outptr = 0; - sbf->ptr = inptr; + sbf->ptr = (unsigned char*) inptr; return outptr-buf; } } if (outptr == outend) break; - bytes_read = camel_stream_read (sbf->stream, sbf->buf, sbf->size); + bytes_read = camel_stream_read (sbf->stream, (char*)sbf->buf, sbf->size); if (bytes_read == -1) { if (buf == outptr) return -1; else bytes_read = 0; } - inptr = sbf->ptr = sbf->buf; - inend = sbf->end = sbf->buf + bytes_read; + sbf->ptr = sbf->buf; + sbf->end = sbf->buf + bytes_read; + inptr = (char*)sbf->ptr; + inend = (char*)sbf->end; + } while (bytes_read>0); + + sbf->ptr = (unsigned char*)inptr; + *outptr = 0; + + return (int)(outptr - buf); +} + + +int +camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max) +{ + register char *outptr, *inptr, *inend, c, *outend; + int bytes_read; + + outptr = buf; + inptr = (char*)sbf->ptr; + inend = (char*)sbf->end; + outend = buf+max-1; /* room for NUL */ + + do { + while (inptrptr = (unsigned char*) inptr; + return outptr-buf; + } + } + if (outptr == outend) + break; + + bytes_read = camel_tcp_stream_read_nb ((CamelTcpStream *)sbf->stream, (char*)sbf->buf, sbf->size); + if (bytes_read == -1) { + if (buf == outptr) + return -1; + else + bytes_read = 0; + } + sbf->ptr = sbf->buf; + sbf->end = sbf->buf + bytes_read; + inptr = (char*)sbf->ptr; + inend = (char*)sbf->end; } while (bytes_read>0); - sbf->ptr = inptr; + sbf->ptr = (unsigned char*)inptr; *outptr = 0; return (int)(outptr - buf); @@ -445,7 +492,7 @@ p = sbf->linebuf; while (1) { - nread = camel_stream_buffer_gets (sbf, p, sbf->linesize - (p - sbf->linebuf)); + nread = camel_stream_buffer_gets (sbf, (char*)p, sbf->linesize - (p - sbf->linebuf)); if (nread <=0) { if (p > sbf->linebuf) break; @@ -467,5 +514,5 @@ p--; p[0] = 0; - return g_strdup(sbf->linebuf); + return g_strdup((gchar*)sbf->linebuf); } diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-stream-buffer.h ./camel-stream-buffer.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-stream-buffer.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-stream-buffer.h 2007-05-12 10:01:18.000000000 +0200 @@ -94,6 +94,7 @@ int camel_stream_buffer_gets (CamelStreamBuffer *sbf, char *buf, unsigned int max); char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf); +int camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max); G_END_DECLS Only in .: camel-stream-buffer.lo Only in .: camel-stream-buffer.o Only in .: camel-stream-filter.lo Only in .: camel-stream-filter.o Only in .: camel-stream-fs.lo Only in .: camel-stream-fs.o Only in .: camel-stream-gzip.c Only in .: camel-stream-gzip.h Only in .: camel-stream-gzip.lo Only in .: camel-stream-gzip.o Only in .: camel-stream.lo Only in .: camel-stream-mem.lo Only in .: camel-stream-mem.o Only in .: camel-stream-null.lo Only in .: camel-stream-null.o Only in .: camel-stream.o Only in .: camel-stream-process.lo Only in .: camel-stream-process.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-stream-vfs.c ./camel-stream-vfs.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-stream-vfs.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-stream-vfs.c 2007-05-12 10:01:17.000000000 +0200 @@ -122,6 +122,7 @@ { CamelStreamVFS *stream_vfs; off_t offset; + GnomeVFSResult result; if (!handle) return NULL; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-string-utils.c ./camel-string-utils.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-string-utils.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-string-utils.c 2007-03-11 16:44:11.000000000 +0100 @@ -141,10 +141,15 @@ return c; } +#ifdef MEMDEBUG +static int cnt=0; +#endif + /* working stuff for pstrings */ static pthread_mutex_t pstring_lock = PTHREAD_MUTEX_INITIALIZER; static GHashTable *pstring_table = NULL; + /** * camel_pstring_add: * @str: string to add to the string pool @@ -184,6 +189,11 @@ g_free (str); } else { pstr = own ? str : g_strdup (str); + +#ifdef MEMDEBUG + cnt++; + printf ("%d\n", cnt); +#endif g_hash_table_insert (pstring_table, pstr, GINT_TO_POINTER (1)); } @@ -240,6 +250,10 @@ if (count == 0) { g_hash_table_remove(pstring_table, p); g_free(p); +#ifdef MEMDEBUG + cnt--; + printf ("%d\n", cnt); +#endif } else { g_hash_table_insert(pstring_table, p, GINT_TO_POINTER(count)); } Only in .: camel-string-utils.lo Only in .: camel-string-utils.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream.c ./camel-tcp-stream.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-tcp-stream.c 2007-03-11 16:44:11.000000000 +0100 @@ -40,6 +40,7 @@ static int tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); static struct sockaddr *tcp_get_local_address (CamelTcpStream *stream, socklen_t *len); static struct sockaddr *tcp_get_remote_address (CamelTcpStream *stream, socklen_t *len); +static ssize_t tcp_read_nb (CamelTcpStream *stream, char *buffer, size_t n); static void camel_tcp_stream_class_init (CamelTcpStreamClass *camel_tcp_stream_class) @@ -49,6 +50,7 @@ parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (CAMEL_STREAM_TYPE)); /* tcp stream methods */ + camel_tcp_stream_class->read_nb = tcp_read_nb; camel_tcp_stream_class->connect = tcp_connect; camel_tcp_stream_class->getsockopt = tcp_getsockopt; camel_tcp_stream_class->setsockopt = tcp_setsockopt; @@ -81,6 +83,12 @@ return type; } +static ssize_t +tcp_read_nb (CamelTcpStream *stream, char *buffer, size_t n) +{ + w(g_warning ("CamelTcpStream::read_nb called on default implementation")); + return -1; +} static int tcp_connect (CamelTcpStream *stream, struct addrinfo *host) @@ -181,6 +189,13 @@ return CTS_CLASS (stream)->get_local_address (stream, len); } +int +camel_tcp_stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n) +{ + return CTS_CLASS (stream)->read_nb (stream, buffer, n); +} + + static struct sockaddr * tcp_get_remote_address (CamelTcpStream *stream, socklen_t *len) { diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream.h ./camel-tcp-stream.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-tcp-stream.h 2007-05-12 10:01:18.000000000 +0200 @@ -106,6 +106,8 @@ struct sockaddr * (*get_local_address) (CamelTcpStream *stream, socklen_t *len); struct sockaddr * (*get_remote_address) (CamelTcpStream *stream, socklen_t *len); + ssize_t (*read_nb) (CamelTcpStream *stream, char *buffer, size_t n); + } CamelTcpStreamClass; /* Standard Camel function */ @@ -119,6 +121,8 @@ struct sockaddr *camel_tcp_stream_get_local_address (CamelTcpStream *stream, socklen_t *len); struct sockaddr *camel_tcp_stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); +int camel_tcp_stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); + G_END_DECLS #endif /* CAMEL_TCP_STREAM_H */ Only in .: camel-tcp-stream.lo Only in .: camel-tcp-stream.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream-openssl.c ./camel-tcp-stream-openssl.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream-openssl.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-tcp-stream-openssl.c 2007-05-12 10:23:33.000000000 +0200 @@ -1,6 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Authors: Jeffrey Stedfast + * Authors: + * Jeffrey Stedfast + * Philip Van Hoof * * Copyright 2001 Ximian, Inc. (www.ximian.com) * @@ -21,19 +23,23 @@ */ -#ifdef HAVE_CONFIG_H #include -#endif +#ifndef HAVE_NSS #ifdef HAVE_OPENSSL -#include -#include +#include "camel-tcp-stream-ssl.h" + #include -#include -#include #include #include +#include +#include +#include +#include + +#include "camel-session.h" +#include "camel-i18n.h" #include #include @@ -55,24 +61,25 @@ /* Returns the class for a CamelTcpStreamSSL */ #define CTSR_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so)) +static ssize_t stream_read_nb (CamelStream *stream, char *buffer, size_t n); static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); static int stream_flush (CamelStream *stream); static int stream_close (CamelStream *stream); -static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port); +static int stream_connect (CamelTcpStream *stream, struct addrinfo *host); static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data); static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); -static CamelTcpAddress *stream_get_local_address (CamelTcpStream *stream); -static CamelTcpAddress *stream_get_remote_address (CamelTcpStream *stream); +static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len); +static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); -static SSL *open_ssl_connection (CamelService *service, int sockfd, CamelTcpStreamSSL *openssl); +static SSL *open_ssl_connection (CamelSession *session, int sockfd, CamelTcpStreamSSL *openssl); struct _CamelTcpStreamSSLPrivate { int sockfd; SSL *ssl; - CamelService *service; + CamelSession *session; char *expected_host; gboolean ssl_mode; guint32 flags; @@ -94,6 +101,7 @@ camel_stream_class->flush = stream_flush; camel_stream_class->close = stream_close; + camel_tcp_stream_class->read_nb = stream_read_nb; camel_tcp_stream_class->connect = stream_connect; camel_tcp_stream_class->getsockopt = stream_getsockopt; camel_tcp_stream_class->setsockopt = stream_setsockopt; @@ -158,9 +166,10 @@ } + /** * camel_tcp_stream_ssl_new: - * @service: camel service + * @session: camel session * @expected_host: host that the stream is expecting to connect with. * @flags: flags * @@ -171,13 +180,13 @@ * Return value: a ssl stream (in ssl mode) **/ CamelStream * -camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host, guint32 flags) +camel_tcp_stream_ssl_new (struct _CamelSession *session, const char *expected_host, guint32 flags) { CamelTcpStreamSSL *stream; stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ())); - stream->priv->service = service; + stream->priv->session = session; stream->priv->expected_host = g_strdup (expected_host); stream->priv->ssl_mode = TRUE; stream->priv->flags = flags; @@ -188,7 +197,7 @@ /** * camel_tcp_stream_ssl_new_raw: - * @service: camel service + * @session: camel session * @expected_host: host that the stream is expecting to connect with. * @flags: flags * @@ -199,13 +208,13 @@ * Return value: a ssl-capable stream (in non ssl mode) **/ CamelStream * -camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host, guint32 flags) +camel_tcp_stream_ssl_new_raw (struct _CamelSession *session, const char *expected_host, guint32 flags) { CamelTcpStreamSSL *stream; stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ())); - stream->priv->service = service; + stream->priv->session = session; stream->priv->expected_host = g_strdup (expected_host); stream->priv->ssl_mode = FALSE; stream->priv->flags = flags; @@ -257,7 +266,7 @@ g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (stream), -1); if (stream->priv->sockfd != -1 && !stream->priv->ssl_mode) { - ssl = open_ssl_connection (stream->priv->service, stream->priv->sockfd, stream); + ssl = open_ssl_connection (stream->priv->session, stream->priv->sockfd, stream); if (ssl == NULL) { stream->priv->sockfd = -1; return -1; @@ -273,6 +282,58 @@ static ssize_t +stream_read_nb (CamelStream *stream, char *buffer, size_t n) +{ + CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); + SSL *ssl = openssl->priv->ssl; + ssize_t nread; + + int error, flags, fdmax; + struct timeval timeout; + fd_set rdset; + int res; + + flags = fcntl (openssl->priv->sockfd, F_GETFL); + fcntl (openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK); + + fdmax = openssl->priv->sockfd + 1; + + do { + FD_ZERO (&rdset); + FD_SET (openssl->priv->sockfd, &rdset); + nread = -1; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + res = select (fdmax, &rdset, 0, 0, &timeout); + + if (res == -1) + ; + else if (res == 0) + errno = ETIMEDOUT; + else { + + do { + if (ssl) { + nread = SSL_read (ssl, buffer, n); + if (nread < 0) + errno = ssl_errno (ssl, nread); + } else { + nread = read (openssl->priv->sockfd, buffer, n); + } + } while (0 && (nread < 0 && errno == EINTR)); + } + } while (0 && (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))); + + error = errno; + fcntl (openssl->priv->sockfd, F_SETFL, flags); + errno = error; + + + return nread; +} + + +static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); @@ -284,7 +345,7 @@ errno = EINTR; return -1; } - + cancel_fd = camel_operation_cancel_fd (NULL); if (cancel_fd == -1) { do { @@ -335,7 +396,7 @@ fcntl (openssl->priv->sockfd, F_SETFL, flags); errno = error; } - + return nread; } @@ -457,13 +518,9 @@ /* this is a 'cancellable' connect, cancellable from camel_operation_cancel etc */ /* returns -1 & errno == EINTR if the connection was cancelled */ static int -socket_connect (struct hostent *h, int port) +socket_connect (struct addrinfo *host) { -#ifdef ENABLE_IPv6 - struct sockaddr_in6 sin6; -#endif - struct sockaddr_in sin; - struct sockaddr *saddr; + struct sockaddr *saddr = host->ai_addr; struct timeval tv; socklen_t len; int cancel_fd; @@ -474,27 +531,8 @@ errno = EINTR; return -1; } - - /* setup connect, we do it using a nonblocking socket so we can poll it */ -#ifdef ENABLE_IPv6 - if (h->h_addrtype == AF_INET6) { - sin6.sin6_port = htons (port); - sin6.sin6_family = h->h_addrtype; - memcpy (&sin6.sin6_addr, h->h_addr, sizeof (sin6.sin6_addr)); - saddr = (struct sockaddr *) &sin6; - len = sizeof (sin6); - } else { -#endif - sin.sin_port = htons (port); - sin.sin_family = h->h_addrtype; - memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr)); - saddr = (struct sockaddr *) &sin; - len = sizeof (sin); -#ifdef ENABLE_IPv6 - } -#endif - - fd = socket (h->h_addrtype, SOCK_STREAM, 0); + + fd = socket (host->ai_family, SOCK_STREAM, 0); cancel_fd = camel_operation_cancel_fd (NULL); if (cancel_fd == -1) { @@ -639,11 +677,12 @@ { unsigned char md5sum[16], fingerprint[40], *f; CamelTcpStreamSSL *stream; - CamelService *service; + CamelSession *session; CamelCertDB *certdb = NULL; CamelCert *ccert = NULL; char *prompt, *cert_str; - int err, md5len, i; + int err, i; + unsigned int md5len; char buf[257]; X509 *cert; SSL *ssl; @@ -657,7 +696,7 @@ if (!stream) return FALSE; - service = stream->priv->service; + session = stream->priv->session; cert = X509_STORE_CTX_get_current_cert (ctx); err = X509_STORE_CTX_get_error (ctx); @@ -666,13 +705,13 @@ md5len = sizeof (md5sum); X509_digest (cert, EVP_md5 (), md5sum, &md5len); for (i = 0, f = fingerprint; i < 16; i++, f += 3) - sprintf (f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0'); + sprintf ((char *) f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0'); #define GET_STRING(name) X509_NAME_oneline (name, buf, 256) certdb = camel_certdb_get_default (); if (certdb) { - ccert = camel_certdb_get_cert (certdb, fingerprint); + ccert = camel_certdb_get_cert (certdb, (const char *) fingerprint); if (ccert) { if (ccert->trust != CAMEL_CERT_TRUST_UNKNOWN) { ok = ccert->trust != CAMEL_CERT_TRUST_NEVER; @@ -686,8 +725,8 @@ ccert = camel_certdb_cert_new (certdb); camel_cert_set_issuer (certdb, ccert, GET_STRING (X509_get_issuer_name (cert))); camel_cert_set_subject (certdb, ccert, GET_STRING (X509_get_subject_name (cert))); - camel_cert_set_hostname (certdb, ccert, stream->priv->expected_host); - camel_cert_set_fingerprint (certdb, ccert, fingerprint); + camel_cert_set_hostname (certdb, ccert, (const char *) stream->priv->expected_host); + camel_cert_set_fingerprint (certdb, ccert, (const char *) fingerprint); camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN); /* Add the certificate to our db */ @@ -703,11 +742,11 @@ GET_STRING (X509_get_subject_name (cert)), fingerprint, cert->valid ? _("GOOD") : _("BAD")); - prompt = g_strdup_printf (_("Bad certificate from %s:\n\n%s\n\n%s\n\n" - "Do you wish to accept anyway?"), - service->url->host, cert_str, x509_strerror (err)); + prompt = g_strdup_printf (_("Bad certificate\n\n%s\n\n%s\n\n" + "Do you wish to accept anyway?"), + cert_str, x509_strerror (err)); - ok = camel_session_alert_user (service->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE); + ok = camel_session_alert_user (session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE); g_free (prompt); if (ok && ccert) { @@ -724,7 +763,7 @@ } static SSL * -open_ssl_connection (CamelService *service, int sockfd, CamelTcpStreamSSL *openssl) +open_ssl_connection (CamelSession *session, int sockfd, CamelTcpStreamSSL *openssl) { SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; @@ -761,8 +800,7 @@ return ssl; } -static int -stream_connect (CamelTcpStream *stream, struct hostent *host, int port) +static int stream_connect_do (CamelTcpStream *stream, struct addrinfo *host) { CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); SSL *ssl = NULL; @@ -770,12 +808,12 @@ g_return_val_if_fail (host != NULL, -1); - fd = socket_connect (host, port); + fd = socket_connect (host); if (fd == -1) return -1; if (openssl->priv->ssl_mode) { - ssl = open_ssl_connection (openssl->priv->service, fd, openssl); + ssl = open_ssl_connection (openssl->priv->session, fd, openssl); if (!ssl) return -1; } @@ -786,6 +824,18 @@ return 0; } +static int +stream_connect (CamelTcpStream *stream, struct addrinfo *host) +{ + while (host) { + if (stream_connect_do (stream, host) == 0) + return 0; + host = host->ai_next; + } + + return -1; +} + static int get_sockopt_level (const CamelSockOptData *data) @@ -850,7 +900,7 @@ get_sockopt_level (data), optname, (void *) &data->value, - &optlen); + (socklen_t *) &optlen); } static int @@ -884,74 +934,27 @@ sizeof (data->value)); } -#ifdef ENABLE_IPv6 -#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in6)) -#else -#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in)) -#endif - -static CamelTcpAddress * -stream_get_local_address (CamelTcpStream *stream) -{ - unsigned char buf[MIN_SOCKADDR_BUFLEN]; -#ifdef ENABLE_IPv6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf; -#endif - struct sockaddr_in *sin = (struct sockaddr_in *) buf; - struct sockaddr *saddr = (struct sockaddr *) buf; - gpointer address; - socklen_t len; - int family; - - len = MIN_SOCKADDR_BUFLEN; - - if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1) - return NULL; - - if (saddr->sa_family == AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &sin->sin_addr; -#ifdef ENABLE_IPv6 - } else if (saddr->sa_family == AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &sin6->sin6_addr; -#endif - } else +static struct sockaddr * +stream_get_local_address (CamelTcpStream *stream, socklen_t *len) +{ + struct sockaddr *saddr = (struct sockaddr *) (malloc (*len)); + + if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, len) == -1) return NULL; - - return camel_tcp_address_new (family, sin->sin_port, len, address); + + return saddr; } -static CamelTcpAddress * -stream_get_remote_address (CamelTcpStream *stream) +static struct sockaddr * +stream_get_remote_address (CamelTcpStream *stream, socklen_t *len) { - unsigned char buf[MIN_SOCKADDR_BUFLEN]; -#ifdef ENABLE_IPv6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf; -#endif - struct sockaddr_in *sin = (struct sockaddr_in *) buf; - struct sockaddr *saddr = (struct sockaddr *) buf; - gpointer address; - socklen_t len; - int family; - - len = MIN_SOCKADDR_BUFLEN; - - if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1) - return NULL; - - if (saddr->sa_family == AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &sin->sin_addr; -#ifdef ENABLE_IPv6 - } else if (saddr->sa_family == AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &sin6->sin6_addr; -#endif - } else + struct sockaddr *saddr = (struct sockaddr *) (malloc (*len)); + + if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, len) == -1) return NULL; - - return camel_tcp_address_new (family, sin->sin_port, len, address); + + return saddr; } #endif /* HAVE_OPENSSL */ +#endif /* HAVE_NSS */ Only in .: camel-tcp-stream-openssl.c.rej diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream-raw.c ./camel-tcp-stream-raw.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream-raw.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-tcp-stream-raw.c 2007-05-12 10:24:11.000000000 +0200 @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -63,6 +64,12 @@ static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len); static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); +static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); + +static void signal_swallow( int num ) +{ + printf ("Connection troubles\n"); +} static void camel_tcp_stream_raw_class_init (CamelTcpStreamRawClass *camel_tcp_stream_raw_class) @@ -73,13 +80,16 @@ CAMEL_STREAM_CLASS (camel_tcp_stream_raw_class); parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ())); - + + signal( SIGPIPE, signal_swallow ); + /* virtual method overload */ camel_stream_class->read = stream_read; camel_stream_class->write = stream_write; camel_stream_class->flush = stream_flush; camel_stream_class->close = stream_close; + camel_tcp_stream_class->read_nb = stream_read_nb; camel_tcp_stream_class->connect = stream_connect; camel_tcp_stream_class->getsockopt = stream_getsockopt; camel_tcp_stream_class->setsockopt = stream_setsockopt; @@ -253,6 +263,14 @@ } static ssize_t +stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n) +{ + CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); + + return camel_read_socket_nb (raw->sockfd, buffer, n); +} + +static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); @@ -487,7 +505,7 @@ get_sockopt_level (data), optname, (void *) &data->value, - &optlen); + (socklen_t*) &optlen); } static int Only in .: camel-tcp-stream-raw.c.rej Only in .: camel-tcp-stream-raw.lo Only in .: camel-tcp-stream-raw.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream-ssl.c ./camel-tcp-stream-ssl.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-tcp-stream-ssl.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-tcp-stream-ssl.c 2007-05-12 10:32:23.000000000 +0200 @@ -86,6 +86,7 @@ static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len); static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); +static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); struct _CamelTcpStreamSSLPrivate { PRFileDesc *sockfd; @@ -94,6 +95,7 @@ char *expected_host; gboolean ssl_mode; guint32 flags; + gboolean accepted; }; static void @@ -111,7 +113,8 @@ camel_stream_class->write = stream_write; camel_stream_class->flush = stream_flush; camel_stream_class->close = stream_close; - + + camel_tcp_stream_class->read_nb = stream_read_nb; camel_tcp_stream_class->connect = stream_connect; camel_tcp_stream_class->getsockopt = stream_getsockopt; camel_tcp_stream_class->setsockopt = stream_setsockopt; @@ -336,6 +339,60 @@ static ssize_t +stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n) +{ + CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); + ssize_t nread; + PRSocketOptionData sockopts; + PRPollDesc pollfds[2]; + gboolean nonblock; + + /* get O_NONBLOCK options */ + sockopts.option = PR_SockOpt_Nonblocking; + PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); + sockopts.option = PR_SockOpt_Nonblocking; + nonblock = sockopts.value.non_blocking; + sockopts.value.non_blocking = TRUE; + PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); + + pollfds[0].fd = tcp_stream_ssl->priv->sockfd; + pollfds[0].in_flags = PR_POLL_READ; + + do { + PRInt32 res; + + pollfds[0].out_flags = 0; + pollfds[1].out_flags = 0; + nread = -1; + + res = PR_Poll(pollfds, 1, 0); + if (res == -1) + set_errno(PR_GetError()); + else if (res == 0) { +#ifdef ETIMEDOUT + errno = ETIMEDOUT; +#else + errno = EIO; +#endif + } else { + do { + nread = -1; + if (PR_Available (tcp_stream_ssl->priv->sockfd) != 0) + nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); + if (nread == -1) + set_errno (PR_GetError ()); + } while (0 && (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR)); + } + } while (0 && (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || + PR_GetError () == PR_IO_PENDING_ERROR || + PR_GetError () == PR_WOULD_BLOCK_ERROR))); + + /* restore O_NONBLOCK options */ + + return nread; +} + +static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); @@ -382,7 +439,8 @@ pollfds[1].out_flags = 0; nread = -1; - res = PR_Poll(pollfds, 2, IO_TIMEOUT); + res = PR_Poll(pollfds, 2, PR_TicksPerSecond () * 15 /*IO_TIMEOUT*/); + if (res == -1) set_errno(PR_GetError()); else if (res == 0) { @@ -469,7 +527,7 @@ pollfds[1].out_flags = 0; w = -1; - res = PR_Poll (pollfds, 2, IO_TIMEOUT); + res = PR_Poll (pollfds, 2, PR_TicksPerSecond () * 15 /*IO_TIMEOUT*/); if (res == -1) { set_errno(PR_GetError()); if (PR_GetError () == PR_PENDING_INTERRUPT_ERROR) @@ -658,7 +716,7 @@ int i; const char tohex[16] = "0123456789abcdef"; - md5_get_digest (cert->derCert.data, cert->derCert.len, md5sum); + md5_get_digest ((const gchar *) cert->derCert.data, cert->derCert.len, md5sum); for (i=0,f = fingerprint; i<16; i++) { unsigned int c = md5sum[i]; @@ -676,7 +734,7 @@ fingerprint[47] = 0; - return g_strdup(fingerprint); + return g_strdup((gchar*) fingerprint); } /* lookup a cert uses fingerprint to index an on-disk file */ @@ -731,7 +789,7 @@ close (fd); if (nread != st.st_size) { - g_warning ("cert size read truncated %s: %u != %ld", path, nread, st.st_size); + /* g_warning ("cert size read truncated %s: %u != %ld", path, nread, st.st_size); */ g_byte_array_free(ccert->rawcert, TRUE); ccert->rawcert = NULL; g_free(fingerprint); @@ -810,7 +868,7 @@ stream = camel_stream_fs_new_with_name (path, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (stream != NULL) { - if (camel_stream_write (stream, ccert->rawcert->data, ccert->rawcert->len) == -1) { + if (camel_stream_write (stream, (const char *) ccert->rawcert->data, ccert->rawcert->len) == -1) { g_warning ("Could not save cert: %s: %s", path, strerror (errno)); g_unlink (path); } @@ -861,11 +919,13 @@ CamelTcpStreamSSL *ssl; CERTCertificate *cert; SECStatus status = SECFailure; + struct _CamelTcpStreamSSLPrivate *priv; g_return_val_if_fail (data != NULL, SECFailure); g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (data), SECFailure); ssl = data; + priv = ssl->priv; cert = SSL_PeerCertificate (sockfd); if (cert == NULL) @@ -910,6 +970,8 @@ camel_certdb_cert_unref(certdb, ccert); camel_object_unref(certdb); + priv->accepted = accept; + return accept ? SECSuccess : SECFailure; #if 0 @@ -1057,19 +1119,22 @@ return NULL; SSL_OptionSet (ssl_fd, SSL_SECURITY, PR_TRUE); + if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL2) SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL2, PR_TRUE); else SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL2, PR_FALSE); + if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL3, PR_TRUE); else SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL3, PR_FALSE); + if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_TLS) SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_TRUE); else SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_FALSE); - + SSL_SetURL (ssl_fd, ssl->priv->expected_host); /*SSL_GetClientAuthDataHook (sslSocket, ssl_get_client_auth, (void *) certNickname);*/ Only in .: camel-tcp-stream-ssl.c.rej Only in .: camel-tcp-stream-ssl.lo Only in .: camel-tcp-stream-ssl.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-text-index.c ./camel-text-index.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-text-index.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-text-index.c 2007-05-12 10:01:18.000000000 +0200 @@ -1460,14 +1460,14 @@ return 0; } - ptr = buffer; - ptrend = buffer+len; + ptr = (const unsigned char *) buffer; + ptrend = (const unsigned char *) buffer+len; while ((c = camel_utf8_next(&ptr, ptrend))) { if (g_unichar_isalnum(c)) { c = g_unichar_tolower(c); - utf8len = g_unichar_to_utf8(c, utf8); + utf8len = g_unichar_to_utf8(c, (gchar *) utf8); utf8[utf8len] = 0; - g_string_append(p->buffer, utf8); + g_string_append(p->buffer, (gchar *) utf8); } else { if (p->buffer->len > 0 && p->buffer->len <= CAMEL_TEXT_INDEX_MAX_WORDLEN) { text_index_name_add_word(idn, p->buffer->str); Only in .: camel-text-index.lo Only in .: camel-text-index.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-transport.c ./camel-transport.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-transport.c 2007-04-20 13:25:00.000000000 +0200 +++ ./camel-transport.c 2007-03-11 16:44:11.000000000 +0100 @@ -66,7 +66,10 @@ camel_transport_finalize (CamelObject *object) { CamelTransport *xport = CAMEL_TRANSPORT (object); - + + g_mutex_lock (xport->priv->send_lock); + g_mutex_unlock (xport->priv->send_lock); + g_mutex_free (xport->priv->send_lock); g_free (xport->priv); } Only in .: camel-transport.lo Only in .: camel-transport.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-types.h ./camel-types.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-types.h 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-types.h 2007-05-12 10:00:17.000000000 +0200 @@ -62,6 +62,7 @@ typedef struct _CamelStore CamelStore; typedef struct _CamelStream CamelStream; typedef struct _CamelStreamNull CamelStreamNull; +typedef struct _CamelStreamGZip CamelStreamGZip; typedef struct _CamelStreamBuffer CamelStreamBuffer; typedef struct _CamelStreamDataWrapper CamelStreamDataWrapper; typedef struct _CamelStreamFilter CamelStreamFilter; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-uid-cache.c ./camel-uid-cache.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-uid-cache.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-uid-cache.c 2007-05-12 10:01:18.000000000 +0200 @@ -66,7 +66,7 @@ int fd, i; dirname = g_path_get_dirname (filename); - if (g_mkdir_with_parents (dirname, 0777) == -1) { + if (e_util_mkdir_hier (dirname, 0777) == -1) { g_free (dirname); return NULL; } Only in .: camel-uid-cache.lo Only in .: camel-uid-cache.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-url.c ./camel-url.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-url.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-url.c 2007-05-12 10:01:18.000000000 +0200 @@ -207,7 +207,9 @@ url->protocol = g_strdup (base->protocol); url->user = g_strdup (base->user); url->authmech = g_strdup (base->authmech); - url->passwd = g_strdup (base->passwd); + if (base->passwd) + url->passwd = g_strdup (base->passwd); + else url->passwd = NULL; url->host = g_strdup (base->host); url->port = base->port; @@ -330,7 +332,7 @@ #ifdef G_OS_WIN32 if (url->protocol && !strcmp(url->protocol, "file")) return g_filename_to_uri(url->path, url->host, NULL); -#endif +#endif /* G_OS_WIN32 */ str = g_string_sized_new (20); @@ -415,7 +417,8 @@ g_datalist_clear (&url->params); g_free (url->query); g_free (url->fragment); - + + memset (url, 0, sizeof (CamelURL)); g_free (url); } } @@ -705,11 +708,12 @@ { CamelURL *out; - out = g_malloc(sizeof(*out)); + out = g_malloc0(sizeof(*out)); out->protocol = g_strdup(in->protocol); out->user = g_strdup(in->user); out->authmech = g_strdup(in->authmech); - out->passwd = g_strdup(in->passwd); + if (in->passwd) + out->passwd = g_strdup(in->passwd); out->host = g_strdup(in->host); out->port = in->port; out->path = g_strdup(in->path); @@ -721,33 +725,3 @@ return out; } - -char * -camel_url_decode_path (const char *path) -{ - gchar **comps; - char *new_path = NULL; - GString *str; - int i = 0; - - if (!path) - return g_strdup(""); /* ??? or NULL? */ - - str = g_string_new (NULL); - - comps = g_strsplit (path, "/", -1); - while (comps[i]) { - camel_url_decode (comps[i]); - g_string_append (str, comps[i]); - g_string_append_c (str, '/'); - i++; - } - - /* Strip-off the trailing "/" */ - new_path = g_strndup (str->str, str->len-1); - - g_strfreev (comps); - g_string_free (str, TRUE); - - return new_path; -} Only in .: camel-url.lo Only in .: camel-url.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-url-scanner.c ./camel-url-scanner.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-url-scanner.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-url-scanner.c 2007-05-12 10:01:18.000000000 +0200 @@ -100,7 +100,7 @@ return TRUE; inptr = pos; - if (camel_utf8_getc_limit ((const unsigned char **) &inptr, inend) == 0xffff) + if (camel_utf8_getc_limit ((const unsigned char **) &inptr, (const unsigned char *) inend) == 0xffff) break; inlen = inend - inptr; @@ -180,7 +180,7 @@ int i; if (open_brace != NULL) - *open_brace == '\0'; + *open_brace = '\0'; if (so > 0) { for (i = 0; i < G_N_ELEMENTS (url_braces); i++) { Only in .: camel-url-scanner.lo Only in .: camel-url-scanner.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-utf8.c ./camel-utf8.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-utf8.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-utf8.c 2007-05-12 10:01:18.000000000 +0200 @@ -177,7 +177,7 @@ camel_utf8_putc(&p, c); *p = 0; - g_string_append(out, buffer); + g_string_append(out, (const char*) buffer); } static const char utf7_alphabet[] = @@ -363,10 +363,10 @@ while ( (c = camel_utf8_getc((const unsigned char **)&ptr)) ) { guint16 s = g_htons(c); - g_byte_array_append(work, (char *)&s, 2); + g_byte_array_append(work, (const unsigned char *)&s, 2); } - g_byte_array_append(work, "\000\000", 2); + g_byte_array_append(work, (const unsigned char *) "\000\000", 2); out = g_malloc(work->len); memcpy(out, work->data, work->len); g_byte_array_free(work, TRUE); Only in .: camel-utf8.lo Only in .: camel-utf8.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-vee-folder.c ./camel-vee-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-vee-folder.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-vee-folder.c 2007-05-12 10:01:18.000000000 +0200 @@ -60,7 +60,7 @@ static void vee_freeze(CamelFolder *folder); static void vee_thaw(CamelFolder *folder); -static CamelMimeMessage *vee_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); +static CamelMimeMessage *vee_get_message (CamelFolder *folder, const gchar *uid, gboolean full, CamelException *ex); static void vee_append_message(CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex); static void vee_transfer_messages_to(CamelFolder *source, GPtrArray *uids, CamelFolder *dest, GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex); @@ -385,11 +385,12 @@ md5_init(&ctx); tmp = camel_service_get_url((CamelService *)folder->parent_store); - md5_update(&ctx, tmp, strlen(tmp)); + md5_update(&ctx, (unsigned char*) tmp, strlen(tmp)); g_free(tmp); - md5_update(&ctx, folder->full_name, strlen(folder->full_name)); + md5_update(&ctx, (unsigned char*)folder->full_name, strlen(folder->full_name)); md5_final(&ctx, digest); - camel_base64_encode_close(digest, 6, FALSE, buffer, &state, &save); + + camel_base64_encode_close(digest, 6, FALSE, (unsigned char *) buffer, (int*) &state, (int*) &save); for (i=0;i<8;i++) { if (buffer[i] == '+') @@ -508,14 +509,14 @@ } static CamelMimeMessage * -vee_get_message(CamelFolder *folder, const char *uid, CamelException *ex) +vee_get_message(CamelFolder *folder, const char *uid, CamelFolderReceiveType type, gint param, CamelException *ex) { CamelVeeMessageInfo *mi; CamelMimeMessage *msg = NULL; mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); if (mi) { - msg = camel_folder_get_message(mi->real->summary->folder, camel_message_info_uid(mi)+8, ex); + msg = camel_folder_get_message(mi->real->summary->folder, camel_message_info_uid(mi)+8, type, param, ex); camel_message_info_free((CamelMessageInfo *)mi); } else { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, @@ -1336,6 +1337,7 @@ g_hash_table_insert(matches_hash, matches_changed->pdata[i], matches_changed->pdata[i]); } dd(printf("\n")); + for (i=0;ilen;i++) { uid = changed->pdata[i]; if (strlen(uid)+9 > vuidlen) { Only in .: camel-vee-folder.lo Only in .: camel-vee-folder.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-vee-store.c ./camel-vee-store.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-vee-store.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-vee-store.c 2007-05-12 10:01:18.000000000 +0200 @@ -147,7 +147,7 @@ const char *tmp; CamelURL *url; - fi = g_malloc0(sizeof(*fi)); + fi = camel_folder_info_new (); fi->full_name = g_strdup(name); tmp = strrchr(name, '/'); if (tmp == NULL) Only in .: camel-vee-store.lo Only in .: camel-vee-store.o Only in .: camel-vee-summary.lo Only in .: camel-vee-summary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-vtrash-folder.c ./camel-vtrash-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-vtrash-folder.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-vtrash-folder.c 2007-05-12 10:01:18.000000000 +0200 @@ -51,8 +51,6 @@ } vdata[] = { { CAMEL_VTRASH_NAME, N_("Trash"), "(match-all (system-flag \"Deleted\"))", CAMEL_MESSAGE_DELETED, CAMEL_FOLDER_IS_TRASH, N_("Cannot copy messages to the Trash folder") }, - { CAMEL_VJUNK_NAME, N_("Junk"), "(match-all (system-flag \"Junk\"))", CAMEL_MESSAGE_JUNK, CAMEL_FOLDER_IS_JUNK, - N_("Cannot copy messages to the Junk folder") }, }; static CamelVeeFolderClass *camel_vtrash_folder_parent; @@ -119,7 +117,7 @@ CamelFolder *folder = (CamelFolder *)object; int i; guint32 tag; - int unread = -1, deleted = 0, junked = 0, visible = 0, count = -1; + int unread = -1, deleted = 0, count = -1; for (i=0;iargc;i++) { CamelArgGet *arg = &args->argv[i]; @@ -131,8 +129,6 @@ switch (tag & CAMEL_ARG_TAG) { case CAMEL_FOLDER_ARG_UNREAD: case CAMEL_FOLDER_ARG_DELETED: - case CAMEL_FOLDER_ARG_JUNKED: - case CAMEL_FOLDER_ARG_VISIBLE: /* This is so we can get the values atomically, and also so we can calculate them only once */ if (unread == -1) { int j; @@ -148,10 +144,6 @@ unread++; if (flags & CAMEL_MESSAGE_DELETED) deleted++; - if (flags & CAMEL_MESSAGE_JUNK) - junked++; - if ((flags & (CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0) - visible++; camel_message_info_free(info); } } @@ -164,12 +156,6 @@ case CAMEL_FOLDER_ARG_DELETED: count = deleted; break; - case CAMEL_FOLDER_ARG_JUNKED: - count = junked; - break; - case CAMEL_FOLDER_ARG_VISIBLE: - count = visible; - break; } *arg->ca_int = count; Only in .: camel-vtrash-folder.lo Only in .: camel-vtrash-folder.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-win32.c ./camel-win32.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/camel-win32.c 2007-05-12 09:58:58.000000000 +0200 +++ ./camel-win32.c 2007-05-12 10:01:18.000000000 +0200 @@ -55,7 +55,7 @@ return; } - localedir = e_util_replace_prefix (E_DATA_SERVER_PREFIX, e_util_get_cp_prefix (), EVOLUTION_LOCALEDIR); + localedir = e_util_replace_prefix (E_DATA_SERVER_PREFIX, e_util_get_cp_prefix (), LOCALEDIR); libexecdir = e_util_replace_prefix (E_DATA_SERVER_PREFIX, e_util_get_prefix (), CAMEL_LIBEXECDIR); providerdir = e_util_replace_prefix (E_DATA_SERVER_PREFIX, e_util_get_prefix (), CAMEL_PROVIDERDIR); Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/: ChangeLog Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/: ChangeLog.pre-1-4 Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/: CODING.STYLE Only in .: .deps Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/: devel-docs Only in .: libcamel-lite-1.2.la Only in .: libcamel-lite-provider-1.2.la Only in .: .libs Only in .: Makefile diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/Makefile.am ./Makefile.am --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/Makefile.am 2007-05-12 09:58:58.000000000 +0200 +++ ./Makefile.am 2007-05-12 10:01:18.000000000 +0200 @@ -1,12 +1,10 @@ -## Process this file with automake to produce Makefile.in +SUBDIRS = . providers -SUBDIRS = . providers tests +AM_CFLAGS = -fPIC if OS_WIN32 -LIBCAMEL_PLATFORM_DEP_SOURCES = \ - camel-win32.c +LIBCAMEL_PLATFORM_DEP_SOURCES = camel-win32.c LIBCAMEL_PROVIDER_PLATFORM_DEP_SOURCES = -LOCK_HELPER = else LIBCAMEL_PLATFORM_DEP_SOURCES = \ camel-lock-client.c \ @@ -14,34 +12,38 @@ LIBCAMEL_PROVIDER_PLATFORM_DEP_SOURCES = \ camel-movemail.c \ camel-sasl-kerberos4.c -LOCK_HELPER = camel-lock-helper-1.2 endif %-$(API_VERSION).pc: %.pc cp $< $@ pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_in_files = camel.pc.in camel-provider.pc.in +pkgconfig_in_files = camel-lite.pc.in camel-lite-provider.pc.in pkgconfig_DATA = $(pkgconfig_in_files:.pc.in=-$(API_VERSION).pc) -libcamelincludedir = $(privincludedir)/camel -libcamel_providerincludedir = $(privincludedir)/camel - -camellibexecdir = $(libexecdir) -camellibexec_PROGRAMS = $(LOCK_HELPER) camel-index-control-1.2 - -lib_LTLIBRARIES = libcamel-1.2.la libcamel-provider-1.2.la - -INCLUDES = -I.. -I$(srcdir)/.. \ - -I$(top_srcdir)/intl \ - -DCAMEL_LIBEXECDIR=\""$(camellibexecdir)"\" \ - -DCAMEL_PROVIDERDIR=\""$(camel_providerdir)"\" \ - -DG_LOG_DOMAIN=\"camel\" \ - -DE_DATA_SERVER_PREFIX=\"$(prefix)\" \ - -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \ +libcamel_liteincludedir = $(includedir)/camel-lite/camel +libcamel_lite_providerincludedir = $(includedir)/camel-lite/camel +camel_litelibexecdir = $(libexecdir) + +lib_LTLIBRARIES = libcamel-lite-1.2.la libcamel-lite-provider-1.2.la + +INCLUDES = -I.. -I$(srcdir)/.. \ + -I$(top_srcdir)/intl \ + -DCAMEL_LIBEXECDIR=\""$(camel_litelibexecdir)"\" \ + -DCAMEL_PROVIDERDIR=\""$(camel_lite_providerdir)"\" \ + -DG_LOG_DOMAIN=\"camel-lite\" \ + -DTRANSDOM=\"$(GETTEXT_PACKAGE)\" \ + -DE_DATA_SERVER_PREFIX=\"$(prefix)\" \ + -DLOCALEDIR=\""$(localedir)"\" \ $(CAMEL_CFLAGS) -libcamel_provider_1_2_la_SOURCES = \ +if ENABLE_OPENSSL +SSL_FILE = camel-tcp-stream-openssl.c +else +SSL_FILE = camel-tcp-stream-ssl.c +endif + +libcamel_lite_provider_1_2_la_SOURCES = \ camel-cipher-context.c \ camel-digest-folder.c \ camel-digest-store.c \ @@ -76,9 +78,8 @@ camel-smime-context.c \ camel-store-summary.c \ camel-store.c \ - camel-tcp-stream-openssl.c \ + $(SSL_FILE) \ camel-tcp-stream-raw.c \ - camel-tcp-stream-ssl.c \ camel-tcp-stream.c \ camel-transport.c \ camel-uid-cache.c \ @@ -88,7 +89,7 @@ camel-vtrash-folder.c \ $(LIBCAMEL_PROVIDER_PLATFORM_DEP_SOURCES) -libcamel_providerinclude_HEADERS = \ +libcamel_lite_providerinclude_HEADERS = \ camel-cipher-context.h \ camel-digest-folder.h \ camel-digest-store.h \ @@ -139,16 +140,17 @@ camel-vee-summary.h \ camel-vtrash-folder.h -libcamel_provider_1_2_la_LDFLAGS = -version-info $(LIBCAMEL_CURRENT):$(LIBCAMEL_REVISION):$(LIBCAMEL_AGE) $(NO_UNDEFINED) +libcamel_lite_provider_1_2_la_LDFLAGS = -version-info $(LIBCAMEL_CURRENT):$(LIBCAMEL_REVISION):$(LIBCAMEL_AGE) $(NO_UNDEFINED) -libcamel_provider_1_2_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${API_VERSION}.la \ - libcamel-1.2.la \ +libcamel_lite_provider_1_2_la_LIBADD = \ + $(top_builddir)/libedataserver/libedataserver-${API_VERSION}.a \ + libcamel-lite-1.2.la \ $(CAMEL_LIBS) \ $(SOCKET_LIBS) \ - $(REGEX_LIBS) + $(REGEX_LIBS) \ + $(SSL_LIBS) -libcamel_1_2_la_SOURCES = \ +libcamel_lite_1_2_la_SOURCES = \ broken-date-parser.c \ camel-address.c \ camel-arg.c \ @@ -204,8 +206,8 @@ camel-stream-filter.c \ camel-stream-fs.c \ camel-stream-mem.c \ + camel-stream-gzip.c \ camel-stream-null.c \ - camel-stream-vfs.c \ camel-stream.c \ camel-string-utils.c \ camel-text-index.c \ @@ -215,7 +217,7 @@ camel.c \ $(LIBCAMEL_PLATFORM_DEP_SOURCES) -libcamelinclude_HEADERS = \ +libcamel_liteinclude_HEADERS = \ broken-date-parser.h \ camel-address.h \ camel-arg.h \ @@ -273,9 +275,9 @@ camel-stream-filter.h \ camel-stream-fs.h \ camel-stream-mem.h \ + camel-stream-gzip.h \ camel-stream-null.h \ camel-stream-process.h \ - camel-stream-vfs.h \ camel-stream.h \ camel-string-utils.h \ camel-text-index.h \ @@ -283,69 +285,21 @@ camel-url-scanner.h \ camel-url.h \ camel-utf8.h \ + camel-lock-helper.h \ camel.h -libcamel_1_2_la_LDFLAGS = -version-info $(LIBCAMEL_CURRENT):$(LIBCAMEL_REVISION):$(LIBCAMEL_AGE) $(NO_UNDEFINED) +libcamel_lite_1_2_la_LDFLAGS = -version-info 0:0:0 $(NO_UNDEFINED) -libcamel_1_2_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${API_VERSION}.la \ +libcamel_lite_1_2_la_LIBADD = \ + $(top_builddir)/libedataserver/libedataserver-${API_VERSION}.a \ $(CAMEL_LIBS) \ $(SOCKET_LIBS) \ - $(REGEX_LIBS) - - -camel_lock_helper_1_2_SOURCES = \ - camel-lock-helper.c \ - camel-lock-helper.h - -# NOTE: This needs to be cleaned up, it shouldn't link with all this crap, -# because it might be setuid. -camel_lock_helper_1_2_LDADD = \ - camel-lock.o \ - $(libcamel_1_2_la_LIBADD) - -camel_index_control_1_2_SOURCES = \ - camel-index-control.c - -camel_index_control_1_2_LDADD = \ - libcamel-1.2.la \ - $(libcamel_1_2_la_LIBADD) + $(REGEX_LIBS) \ + $(SSL_LIBS) camel-mime-tables.c: gentables.pl perl gentables.pl > $@ -install-exec-hook: - @if test -n "$(CAMEL_LOCK_HELPER_USER)"; then \ - if test `whoami` = root ; then \ - chown $(CAMEL_LOCK_HELPER_USER) $(DESTDIR)$(camellibexecdir)/camel-lock-helper-$(API_VERSION) ; \ - chmod u+s $(DESTDIR)$(camellibexecdir)/camel-lock-helper-$(API_VERSION) ; \ - else \ - echo '*** WARNING ***' ; \ - echo "Camel will not be able to open mbox files until you perform the following steps:" ; \ - echo " 1. Become root" ; \ - echo " 2. chown $(CAMEL_LOCK_HELPER_USER) $(DESTDIR)$(sbindir)/camel-lock-helper" ; \ - echo " 3. chmod u+s $(DESTDIR)$(sbindir)/camel-lock-helper" ; \ - echo '*** WARNING ***' ; \ - fi \ - else \ - echo "No user to chown to"; \ - fi - @if test -n "$(CAMEL_LOCK_HELPER_GROUP)"; then \ - if test `whoami` = root ; then \ - chgrp $(CAMEL_LOCK_HELPER_GROUP) $(DESTDIR)$(camellibexecdir)/camel-lock-helper-$(API_VERSION) ; \ - chmod g+s $(DESTDIR)$(camellibexecdir)/camel-lock-helper-$(API_VERSION) ; \ - else \ - echo '*** WARNING ***' ; \ - echo "Camel will not be able to open mbox files until you perform the following steps:" ; \ - echo " 1. Become root" ; \ - echo " 2. chgrp $(CAMEL_LOCK_HELPER_GROUP) $(DESTDIR)$(camellibexecdir)/camel-lock-helper-$(API_VERSION)" ; \ - echo " 3. chmod g+s $(DESTDIR)$(camellibexecdir)/camel-lock-helper-$(API_VERSION)" ; \ - echo '*** WARNING ***' ; \ - fi \ - else \ - echo "No user to chown to"; \ - fi - noinst_HEADERS = \ broken-date-parser.h \ camel-charset-map-private.h \ @@ -353,8 +307,6 @@ EXTRA_DIST = \ $(pkgconfig_in_files) \ - gentables.pl \ - ChangeLog.pre-1-4 \ - README + gentables.pl DISTCLEANFILES = $(pkgconfig_DATA) Only in .: Makefile.am.rej Only in .: Makefile.in Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers: .cvsignore Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers: groupwise Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers: hula diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-command.c ./providers/imap/camel-imap-command.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-command.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-command.c 2007-05-12 10:17:00.000000000 +0200 @@ -60,6 +60,10 @@ static char *imap_command_strdup_printf (CamelImapStore *store, const char *fmt, ...); + + + + /** * camel_imap_command: * @store: the IMAP store @@ -93,19 +97,24 @@ { va_list ap; char *cmd; - + CAMEL_SERVICE_REC_LOCK (store, connect_lock); - + if (fmt) { va_start (ap, fmt); cmd = imap_command_strdup_vprintf (store, fmt, ap); va_end (ap); } else { - camel_object_ref(folder); - if (store->current_folder) - camel_object_unref(store->current_folder); + + /* camel_object_ref(folder); + if (store->current_folder && CAMEL_IS_OBJECT (store->current_folder)) + camel_object_unref(store->current_folder); */ + store->current_folder = folder; - cmd = imap_command_strdup_printf (store, "SELECT %F", folder->full_name); + if (store->capabilities & IMAP_CAPABILITY_CONDSTORE) + cmd = imap_command_strdup_printf (store, "SELECT %F (CONDSTORE)", folder->full_name); + else + cmd = imap_command_strdup_printf (store, "SELECT %F", folder->full_name); } if (!imap_command_start (store, folder, cmd, ex)) { @@ -118,6 +127,7 @@ return imap_read_response (store, ex); } + /** * camel_imap_command_start: * @store: the IMAP store @@ -163,13 +173,15 @@ va_start (ap, fmt); cmd = imap_command_strdup_vprintf (store, fmt, ap); va_end (ap); - + CAMEL_SERVICE_REC_LOCK (store, connect_lock); + ok = imap_command_start (store, folder, cmd, ex); g_free (cmd); - + if (!ok) CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + return ok; } @@ -178,20 +190,43 @@ const char *cmd, CamelException *ex) { ssize_t nwritten; - - g_return_val_if_fail(store->ostream!=NULL, FALSE); - g_return_val_if_fail(store->istream!=NULL, FALSE); - + gchar *resp = NULL; + CamelException myex = CAMEL_EXCEPTION_INITIALISER; + gchar *full_cmd = NULL; + guint len = 0; + + if (store->ostream == NULL || ((CamelObject *)store->ostream)->ref_count <= 0) + { + if (store->has_login && !camel_service_connect ((CamelService*)store, ex)) + return FALSE; + } + + /* g_mutex_lock (store->stream_lock); */ + + if (store->ostream==NULL) return FALSE; + if (store->istream==NULL) return FALSE; + + /* g_mutex_unlock (store->stream_lock);*/ + + + /* Also read imap_update_summary and all of the IDLE crap */ + if (!store->dontdistridlehack) + camel_imap_store_stop_idle (store); + /* else + printf ("dont distr\n"); */ + /* Check for current folder */ - if (folder && folder != store->current_folder) { + if (folder && folder != store->current_folder) + { CamelImapResponse *response; CamelException internal_ex; - + response = camel_imap_command (store, folder, ex, NULL); if (!response) return FALSE; camel_exception_init (&internal_ex); - camel_imap_folder_selected (folder, response, &internal_ex); + /* g_print ("select\n"); */ + camel_imap_folder_selected (folder, response, &internal_ex, FALSE); camel_imap_response_free (store, response); if (camel_exception_is_set (&internal_ex)) { camel_exception_xfer (ex, &internal_ex); @@ -214,19 +249,51 @@ fprintf (stderr, "sending : %c%.5u %s\r\n", store->tag_prefix, store->command, mask); } - - nwritten = camel_stream_printf (store->ostream, "%c%.5u %s\r\n", - store->tag_prefix, store->command++, cmd); - - if (nwritten == -1) { + + /* g_mutex_lock (store->stream_lock); */ + + if (store->ostream==NULL || ((CamelObject *)store->ostream)->ref_count <= 0) + { /* g_mutex_unlock (store->stream_lock); */ return FALSE; } + if (store->istream==NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { /* g_mutex_unlock (store->stream_lock); */ return FALSE; } + + /* Read away whatever we got */ + while (camel_imap_store_readline_nb (store, &resp, &myex) > 0) + { + imap_debug ("unsolitcited: "); + imap_debug (resp); + imap_debug ("\n"); + + g_free (resp); + resp=NULL; + } + if (resp) + g_free (resp); + + full_cmd = g_strdup_printf ("%c%.5u %s\r\n", store->tag_prefix, + store->command++, cmd); + len = strlen (full_cmd); + + /* printf ("-> %s\n", full_cmd); */ + + nwritten = camel_stream_write (store->ostream, full_cmd, len); + + /* g_mutex_unlock (store->stream_lock); */ + + if (nwritten != len) + { + CamelException mex = CAMEL_EXCEPTION_INITIALISER; + if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); else camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, &mex); + camel_service_connect (CAMEL_SERVICE (store), &mex); + return FALSE; } @@ -253,7 +320,7 @@ camel_imap_command_continuation (CamelImapStore *store, const char *cmd, size_t cmdlen, CamelException *ex) { - if (!camel_imap_store_connected (store, ex)) + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, ex)) return NULL; g_return_val_if_fail(store->ostream!=NULL, NULL); @@ -268,6 +335,7 @@ camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno)); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return NULL; } @@ -275,6 +343,7 @@ return imap_read_response (store, ex); } + /** * camel_imap_command_response: * @store: the IMAP store @@ -301,7 +370,9 @@ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return CAMEL_IMAP_RESPONSE_ERROR; } - + + /* printf ("<-- %s\n", respbuf); */ + switch (*respbuf) { case '*': if (!g_ascii_strncasecmp (respbuf, "* BYE", 5)) { @@ -344,10 +415,67 @@ break; } *response = respbuf; - + if (type == CAMEL_IMAP_RESPONSE_ERROR || - type == CAMEL_IMAP_RESPONSE_TAGGED) + type == CAMEL_IMAP_RESPONSE_TAGGED) CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + + return type; +} + + +CamelImapResponseType +camel_imap_command_response_idle (CamelImapStore *store, char **response, + CamelException *ex) +{ + CamelImapResponseType type; + char *respbuf; + + if (camel_imap_store_readline (store, &respbuf, ex) < 0) + return CAMEL_IMAP_RESPONSE_ERROR; + + switch (*respbuf) { + case '*': + if (!g_ascii_strncasecmp (respbuf, "* BYE", 5)) { + /* Connection was lost, no more data to fetch */ + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Server unexpectedly disconnected: %s"), + _("Unknown error")); /* g_strerror (104)); FIXME after 1.0 is released */ + store->connected = FALSE; + g_free (respbuf); + respbuf = NULL; + type = CAMEL_IMAP_RESPONSE_ERROR; + break; + } + + /* Read the rest of the response. */ + type = CAMEL_IMAP_RESPONSE_UNTAGGED; + respbuf = imap_read_untagged (store, respbuf, ex); + if (!respbuf) + type = CAMEL_IMAP_RESPONSE_ERROR; + else if (!g_ascii_strncasecmp (respbuf, "* OK [ALERT]", 12) + || !g_ascii_strncasecmp (respbuf, "* NO [ALERT]", 12) + || !g_ascii_strncasecmp (respbuf, "* BAD [ALERT]", 13)) { + char *msg; + + /* for imap ALERT codes, account user@host */ + /* we might get a ']' from a BAD response since we +12, but who cares? */ + msg = g_strdup_printf(_("Alert from IMAP server %s@%s:\n%s"), + ((CamelService *)store)->url->user, ((CamelService *)store)->url->host, respbuf+12); + camel_session_alert_user(((CamelService *)store)->session, CAMEL_SESSION_ALERT_WARNING, msg, FALSE); + g_free(msg); + } else if (!g_ascii_strncasecmp (respbuf, "* BAD Invalid tag",17)) + type = CAMEL_IMAP_RESPONSE_ERROR; + break; + case '+': + type = CAMEL_IMAP_RESPONSE_CONTINUATION; + break; + default: + type = CAMEL_IMAP_RESPONSE_TAGGED; + break; + } + *response = respbuf; return type; } @@ -364,8 +492,9 @@ * we're still locked. This lock is owned by response * and gets unlocked when response is freed. */ + CAMEL_SERVICE_REC_LOCK (store, connect_lock); - + response = g_new0 (CamelImapResponse, 1); if (store->current_folder && camel_disco_store_status (CAMEL_DISCO_STORE (store)) != CAMEL_DISCO_STORE_RESYNCING) { response->folder = store->current_folder; @@ -383,7 +512,7 @@ } response->status = respbuf; - + /* Check for OK or continuation response. */ if (*respbuf == '+') return response; @@ -622,6 +751,7 @@ } g_free (response); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); } @@ -780,8 +910,9 @@ } else if (*p == 'G') { string = camel_utf8_utf7(string); } - - arglen = strlen (string); + + if (string) + arglen = strlen (string); g_ptr_array_add (args, string); if (imap_is_atom (string)) { len += arglen; Only in ./providers/imap: camel-imap-command.c.rej diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-command.h ./providers/imap/camel-imap-command.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-command.h 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-command.h 2007-05-12 10:01:04.000000000 +0200 @@ -74,6 +74,9 @@ char **respbuf, CamelException *ex); +CamelImapResponseType camel_imap_command_response_idle (CamelImapStore *store, char **response, + CamelException *ex); + G_END_DECLS #endif /* CAMEL_IMAP_COMMAND_H */ Only in ./providers/imap: camel-imap-command.lo Only in ./providers/imap: camel-imap-command.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-folder.c ./providers/imap/camel-imap-folder.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-folder.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-folder.c 2007-05-12 10:15:55.000000000 +0200 @@ -1,10 +1,15 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.c: class for an imap folder */ - -/* +/* camel-imap-folder.c: class for an imap folder + * + * This is the mmap version of camel-imap-folder.c which has a memory + * consumption reduced imap_update_summary implementation that will + * periodically instruct the mmap CamelFolderSummary instance to sync + * headers to disk. + * * Authors: * Dan Winship * Jeffrey Stedfast + * Philip Van Hoof * * Copyright (C) 2000, 2001 Ximian, Inc. * @@ -23,6 +28,11 @@ * USA */ +/* BODY always returns "textual data", which means a series of characters + no containing NUL, CR, or LF, of length <= 1000.*/ + +#define MAX_LINE_LEN 1024 + #include #include @@ -39,6 +49,7 @@ #include #include + #include "camel-data-wrapper.h" #include "camel-debug.h" #include "camel-disco-diary.h" @@ -71,6 +82,9 @@ #include "camel-imap-utils.h" #include "camel-imap-wrapper.h" + +#include + #define d(x) /* set to -1 for infinite size (suggested max command-line length is @@ -86,7 +100,8 @@ static void imap_finalize (CamelObject *object); static int imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args); -static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex); +static gboolean imap_rescan_condstore (CamelFolder *folder, int exists, const char *highestmodseq, CamelException *ex); +static gboolean imap_rescan (CamelFolder *folder, int exists, CamelException *ex); static void imap_refresh_info (CamelFolder *folder, CamelException *ex); static void imap_sync_online (CamelFolder *folder, CamelException *ex); static void imap_sync_offline (CamelFolder *folder, CamelException *ex); @@ -95,10 +110,11 @@ static void imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex); static void imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex); static void imap_rename (CamelFolder *folder, const char *new); +static void imap_set_push_email (CamelFolder *folder, gboolean setting); /* message manipulation */ static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, - CamelException *ex); + CamelFolderReceiveType type, gint param, CamelException *ex); static void imap_append_online (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex); @@ -132,6 +148,10 @@ static CamelObjectClass *parent_class; static GData *parse_fetch_response (CamelImapFolder *imap_folder, char *msg_att); +static void camel_imap_folder_changed_for_idle (CamelFolder *folder, int exists, + GArray *expunged, CamelException *ex); + +GPtrArray* _camel_imap_store_get_recent_messages (CamelImapStore *imap_store, const char *folder_name, int *messages, int *unseen, gboolean withthem); #ifdef G_OS_WIN32 /* The strtok() in Microsoft's C library is MT-safe (but still uses @@ -141,6 +161,8 @@ #define strtok_r(s,sep,lasts) (*(lasts)=strtok((s),(sep))) #endif + + static void camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) { @@ -152,6 +174,7 @@ /* virtual method overload */ ((CamelObjectClass *)camel_imap_folder_class)->getv = imap_getv; + camel_folder_class->set_push_email = imap_set_push_email; camel_folder_class->get_message = imap_get_message; camel_folder_class->rename = imap_rename; camel_folder_class->search_by_expression = imap_search_by_expression; @@ -178,12 +201,21 @@ camel_disco_folder_class->cache_message = imap_cache_message; } + static void camel_imap_folder_init (gpointer object, gpointer klass) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); CamelFolder *folder = CAMEL_FOLDER (object); - + + /* ((CamelObject *)folder)-> flags |= CAMEL_OBJECT_REF_DEBUG; */ + + imap_folder->idle_lock = g_new0 (GStaticRecMutex, 1); + g_static_rec_mutex_init (imap_folder->idle_lock); + imap_folder->stopping = FALSE; + imap_folder->in_idle = FALSE; + + imap_folder->do_push_email = TRUE; folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; @@ -229,7 +261,7 @@ const char *short_name; char *summary_file, *state_file; - if (g_mkdir_with_parents (folder_dir, S_IRWXU) != 0) { + if (e_util_mkdir_hier (folder_dir, S_IRWXU) != 0) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create directory %s: %s"), folder_dir, g_strerror (errno)); @@ -237,6 +269,10 @@ } folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); + imap_folder = CAMEL_IMAP_FOLDER (folder); + + imap_folder->folder_dir = g_strdup (folder_dir); + short_name = strrchr (folder_name, '/'); if (short_name) short_name++; @@ -244,7 +280,7 @@ short_name = folder_name; camel_folder_construct (folder, parent, folder_name, short_name); - summary_file = g_strdup_printf ("%s/summary", folder_dir); + summary_file = g_strdup_printf ("%s/summary.mmap", folder_dir); folder->summary = camel_imap_summary_new (folder, summary_file); g_free (summary_file); if (!folder->summary) { @@ -261,8 +297,8 @@ g_free(state_file); camel_object_state_read(folder); - imap_folder = CAMEL_IMAP_FOLDER (folder); imap_folder->cache = camel_imap_message_cache_new (folder_dir, folder->summary, ex); + if (!imap_folder->cache) { camel_object_unref (CAMEL_OBJECT (folder)); return NULL; @@ -278,15 +314,78 @@ folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK; } + if (imap_store->capabilities & IMAP_CAPABILITY_IDLE) + folder->folder_flags |= CAMEL_FOLDER_HAS_PUSHEMAIL_CAPABILITY; + imap_folder->search = camel_imap_search_new(folder_dir); return folder; } + +static void +put_highestmodseq (CamelImapFolder *imap_folder, const char *highestmodseq) +{ + char *filename = g_strdup_printf ("%s/highestmodseq", imap_folder->folder_dir); + FILE *file; + + file = fopen (filename, "w"); + g_free (filename); + + if (file != NULL) + { + fprintf (file, "%s", highestmodseq); + fclose (file); + } +} + +static char* +get_highestmodseq (CamelImapFolder *imap_folder) +{ + char *filename = g_strdup_printf ("%s/highestmodseq", imap_folder->folder_dir); + char *retval = NULL; + FILE *file; + + file = fopen (filename, "r"); + g_free (filename); + + if (file != NULL) + { + retval = g_malloc0 (25); /* a 64bit number must fit in it */ + fscanf (file, "%s", retval); + fclose (file); + } + + return retval; +} + /* Called with the store's connect_lock locked */ + + +/* +The assumption we have to make is that any folder can have been offline +before it got here to become selected. + +Which is nasty because that means that our IDLE code might not have kept it +synchronized. We might not have been notified by EXISTS, FETCH and EXPUNGE +unsolicited events (you can't assume that). + +We also can't assume the availability of HIGHESTMODSEQ (or CONDSTORE). Not +even if the IMAP service announced the condstore capability. That's because +condstore is to be enabled per mailbox! + +UIDNEXT might be incorrect, I have seen IMAP servers that simply get it wrong. + +Although it has been reported that Exchange's IMAP server sometimes gives to high +values for EXISTS, it's quite safe to assume that the EXISTS is going to be +correct on most servers. Just don't crash on sequences that don't exist remote. + +More documentation inline +*/ + void camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, - CamelException *ex) + CamelException *ex, gboolean idle) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary); @@ -294,13 +393,29 @@ CamelMessageInfo *info; guint32 perm_flags = 0; GData *fetch_data; - int i, count; - char *resp; - + int i, count, uidnext = -1; + char *resp, *phighestmodseq = NULL, *highestmodseq = NULL; + CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + gboolean removals = FALSE, condstore = FALSE, needtoput=FALSE, suc=FALSE; + count = camel_folder_summary_count (folder->summary); - - for (i = 0; i < response->untagged->len; i++) { + + /* With CONDSTORE this is the typical output. + * C: A142 SELECT INBOX (CONDSTORE) + * S: * 172 EXISTS + * S: * 1 RECENT + * S: * OK [UNSEEN 12] Message 12 is first unseen + * S: * OK [UIDVALIDITY 3857529045] UIDs valid + * S: * OK [UIDNEXT 4392] Predicted next UID + * S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) + * S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited + * S: * OK [HIGHESTMODSEQ 715194045007] + * S: A142 OK [READ-WRITE] SELECT completed, CONDSTORE is now enabled */ + + for (i = 0; i < response->untagged->len; i++) + { resp = response->untagged->pdata[i] + 2; + if (!g_ascii_strncasecmp (resp, "FLAGS ", 6) && !perm_flags) { resp += 6; folder->permanent_flags = imap_parse_flag_list (&resp); @@ -311,6 +426,44 @@ * even tho they do allow storing flags. *Sigh* So many fucking broken IMAP servers out there. */ if ((perm_flags = imap_parse_flag_list (&resp)) != 0) folder->permanent_flags = perm_flags; + } else if (!g_ascii_strncasecmp (resp, "OK [UIDNEXT ", 12)) { + char *marker = strchr (resp, ']'); + if (marker) *marker='\0'; + uidnext = strtoul (resp + 12, NULL, 10); + } else if (!g_ascii_strncasecmp (resp, "OK [HIGHESTMODSEQ ", 18)) + { + + /* So we have a HIGHESTMODSEQ, we are going to store this + * one assuming that our code that will follow is correct + * and that after that upcoming code, the local folder + * state will be in sync with that remote HIGHESTMODSEQ + * value. */ + + char *marker; + unsigned int len; + resp += 18; + + marker = strchr (resp, ']'); + + if (marker) + { + condstore = TRUE; + len = (unsigned int) (marker - resp); + + highestmodseq = g_strndup (resp, len); + phighestmodseq = get_highestmodseq (imap_folder); + + if (phighestmodseq !=NULL && !strcmp (phighestmodseq, highestmodseq)) + { + g_free (phighestmodseq); + phighestmodseq = NULL; + } else + needtoput = TRUE; + } else { + phighestmodseq = NULL; + highestmodseq = NULL; + } + } else if (!g_ascii_strncasecmp (resp, "OK [UIDVALIDITY ", 16)) { validity = strtoul (resp + 16, NULL, 10); } else if (isdigit ((unsigned char)*resp)) { @@ -319,8 +472,7 @@ if (!g_ascii_strncasecmp (resp, " EXISTS", 7)) { exists = num; /* Remove from the response so nothing - * else tries to interpret it. - */ + * else tries to interpret it. */ g_free (response->untagged->pdata[i]); g_ptr_array_remove_index (response->untagged, i--); } @@ -328,18 +480,31 @@ } if (camel_strstrcase (response->status, "OK [READ-ONLY]")) + { + folder->folder_flags |= CAMEL_FOLDER_IS_READONLY; imap_folder->read_only = TRUE; + } - if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) { + if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) + { + if (phighestmodseq != NULL) + g_free (phighestmodseq); + if (highestmodseq != NULL) + g_free (highestmodseq); + if (validity != imap_summary->validity) { camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID, _("Folder was destroyed and recreated on server.")); return; } - + /* FIXME: find missing UIDs ? */ return; } + + /* If there's no match on VALIDITY, we are dealing with a different + * folder. For example the folder got removed and re-created. We'll + * simply clear everyting and do things from scratch. */ if (!imap_summary->validity) imap_summary->validity = validity; @@ -351,82 +516,163 @@ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); imap_folder->need_rescan = FALSE; camel_imap_folder_changed (folder, exists, NULL, ex); + + if (phighestmodseq != NULL) + g_free (phighestmodseq); + if (highestmodseq != NULL) + g_free (highestmodseq); + return; } + + /* If we already had stuff locally, get the last one's UID . Store it in + * what we will start calling VAL */ - /* If we've lost messages, we have to rescan everything */ - if (exists < count) - imap_folder->need_rescan = TRUE; - else if (count != 0 && !imap_folder->need_rescan) { - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - - /* Similarly, if the UID of the highest message we - * know about has changed, then that indicates that - * messages have been both added and removed, so we - * have to rescan to find the removed ones. (We pass - * NULL for the folder since we know that this folder - * is selected, and we don't want camel_imap_command - * to worry about it.) - */ - response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count); - if (!response) - return; - uid = 0; - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - val = strtoul (resp + 2, &resp, 10); - if (val == 0) - continue; - if (!g_ascii_strcasecmp (resp, " EXISTS")) { - /* Another one?? */ - exists = val; - continue; - } - if (uid != 0 || val != count || g_ascii_strncasecmp (resp, " FETCH (", 8) != 0) - continue; - - fetch_data = parse_fetch_response (imap_folder, resp + 7); - uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10); - g_datalist_clear (&fetch_data); - } - camel_imap_response_free_without_processing (store, response); - + if (count > 0) + { info = camel_folder_summary_index (folder->summary, count - 1); val = strtoul (camel_message_info_uid (info), NULL, 10); camel_message_info_free(info); - if (uid == 0 || uid != val) - imap_folder->need_rescan = TRUE; + } else + val = -1; + + /* If we are going the CONDSTORE route and if (uidnext-1) is not the + * same as the last uid in our summary, it's very likely that expunges + * happened. This CONDSTORE code does not yet support expunges. + * Therefore we will simply use the old code. */ + + if (phighestmodseq != NULL && (val != uidnext-1)) + { + g_free (phighestmodseq); + phighestmodseq = NULL; + removals = TRUE; } + + /* If our local count isn't the same as the EXISTS, then our CONDSTORE + * implementation can't be used. Period. */ - /* Now rescan if we need to */ - if (imap_folder->need_rescan) { - imap_rescan (folder, exists, ex); - return; + if (exists != count) + { + if (phighestmodseq != NULL) + g_free (phighestmodseq); + phighestmodseq = NULL; + removals = TRUE; } - - /* If we don't need to rescan completely, but new messages - * have been added, find out about them. - */ - if (exists > count) + + if (removals) + imap_folder->need_rescan = TRUE; + else if (condstore && (store->capabilities & IMAP_CAPABILITY_CONDSTORE)) + imap_folder->need_rescan = FALSE; + + /* We still aren't certain. For example if at the end of the mailbox + * both an add and an expunge happened, then all of above figured out + * nothing meaningful. So we will compare the last local uid with the + * remote uid at the same sequence number (that's count, as the count + * is the index + 1). This is where we need the VAL thingy of above. */ + + if (!imap_folder->need_rescan) + { + int mval = 0; + + /* If the UID of the highest message we know about has changed, + * then that indicates that messages have been both added and + * removed, so we have to rescan to find the removed ones */ + + response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count); + if (response) { + uid = 0; + for (i = 0; i < response->untagged->len; i++) + { + resp = response->untagged->pdata[i]; + mval = strtoul (resp + 2, &resp, 10); + if (mval == 0) + continue; + if (!g_ascii_strcasecmp (resp, " EXISTS")) + { + /* Another one?? */ + exists = mval; + continue; + } + if (uid != 0 || mval != count || g_ascii_strncasecmp (resp, " FETCH (", 8) != 0) + continue; + + fetch_data = parse_fetch_response (imap_folder, resp + 7); + uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10); + g_datalist_clear (&fetch_data); + } + camel_imap_response_free_without_processing (store, response); + if (uid == 0 || uid != val) + imap_folder->need_rescan = TRUE; + } else + imap_folder->need_rescan = TRUE; + } + + /* Okay, it survived ALL checks and CONDSTORE is available too. Lucky we + * are, aren't we? So we use CONDSTORE. Note, however, that if condstore + * still finds removals (sequences don't match) or if anything goes wrong + * during the CONDSTORE code, that it'll set need_rescan TRUE and that + * as a result the lines below this if{} block will still happen. This is + * indeed on purpose and as a fall-back situation (our detection got it + * wrong) */ + + if (phighestmodseq) + { + if (!imap_folder->need_rescan) + suc = imap_rescan_condstore (folder, exists, phighestmodseq, ex); + g_free (phighestmodseq); + phighestmodseq = NULL; + } + + if (imap_folder->need_rescan) + suc = imap_rescan (folder, exists, ex); + else if (exists > count) camel_imap_folder_changed (folder, exists, NULL, ex); - - /* And we're done. */ + + if (highestmodseq != NULL && suc && needtoput) + put_highestmodseq (imap_folder, (const char *) highestmodseq); + + if (highestmodseq != NULL) + g_free (highestmodseq); + + if (idle) + camel_imap_folder_start_idle (folder); } -static void +static void imap_finalize (CamelObject *object) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); + CamelImapStore *store = CAMEL_IMAP_STORE (CAMEL_FOLDER(imap_folder)->parent_store); + + imap_folder->do_push_email = FALSE; + + imap_folder->stopping = TRUE; + + if (imap_folder->idle_signal > 0) + g_source_remove (imap_folder->idle_signal); + + if (!imap_folder->in_idle || imap_folder->idle_lock != NULL) + { + g_static_rec_mutex_free (imap_folder->idle_lock); + imap_folder->idle_lock = NULL; + } + + if (store->current_folder == (CamelFolder*) object) + store->current_folder = NULL; if (imap_folder->search) camel_object_unref (CAMEL_OBJECT (imap_folder->search)); if (imap_folder->cache) camel_object_unref (CAMEL_OBJECT (imap_folder->cache)); + if (imap_folder->folder_dir) + g_free (imap_folder->folder_dir); + #ifdef ENABLE_THREADS g_static_mutex_free(&imap_folder->priv->search_lock); g_static_rec_mutex_free(&imap_folder->priv->cache_lock); #endif + g_free(imap_folder->priv); } @@ -519,21 +765,20 @@ * should do it. */ CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock); - if (!camel_imap_store_connected(imap_store, ex)) + if (!camel_disco_store_check_online ((CamelDiscoStore*)imap_store, ex)) goto done; if (imap_store->current_folder != folder || g_ascii_strcasecmp(folder->full_name, "INBOX") == 0) { response = camel_imap_command (imap_store, folder, ex, NULL); if (response) { - camel_imap_folder_selected (folder, response, ex); + camel_imap_folder_selected (folder, response, ex, TRUE); camel_imap_response_free (imap_store, response); } } else if (imap_folder->need_rescan) { /* Otherwise, if we need a rescan, do it, and if not, just do * a NOOP to give the server a chance to tell us about new - * messages. - */ + * messages. */ imap_rescan (folder, camel_folder_summary_count (folder->summary), ex); } else { #if 0 @@ -542,10 +787,12 @@ if (g_ascii_strcasecmp(folder->full_name, "INBOX") == 0) { response = camel_imap_command (imap_store, folder, ex, "CHECK"); camel_imap_response_free (imap_store, response); + camel_imap_folder_start_idle (folder); } #endif response = camel_imap_command (imap_store, folder, ex, "NOOP"); camel_imap_response_free (imap_store, response); + camel_imap_folder_start_idle (folder); } si = camel_store_summary_path((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary, folder->full_name); @@ -564,10 +811,13 @@ done: CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock); - camel_folder_summary_save(folder->summary); + /* TNY TOCHECK: I think all situations are already saving the summary?! + * camel_folder_summary_save(folder->summary); */ + camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary); } +#if 0 static void flags_to_label(CamelFolder *folder, CamelImapMessageInfo *mi) { @@ -596,14 +846,198 @@ } mi->info.flags = (mi->info.flags & ~CAMEL_IMAP_MESSAGE_LABEL_MASK) | mask; + +#ifdef NON_TINYMAIL_FEATURES camel_tag_set(&mi->info.user_tags, "label", label); +#endif + } +} + +#endif + +static gboolean +imap_rescan_condstore (CamelFolder *folder, int exists, const char *highestmodseq, CamelException *ex) +{ + + /* So this is what we'll get. All the changes since highestmodseq. + * C: s100 UID FETCH 1:* (FLAGS) (CHANGEDSINCE 12345) + * S: * 1 FETCH (UID 4 MODSEQ (65402) FLAGS (\Seen)) + * S: * 2 FETCH (UID 6 MODSEQ (75403) FLAGS (\Deleted)) + * S: * 4 FETCH (UID 8 MODSEQ (29738) FLAGS ($NoJunk $AutoJunk $MDNSent)) + * S: s100 OK FETCH completed */ + + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + char *resp; + CamelImapResponseType type; + int summary_len, summary_got; + CamelMessageInfo *info; + CamelImapMessageInfo *iinfo; + gboolean ok, retval = TRUE; + CamelFolderChangeInfo *changes = NULL; + + imap_folder->need_rescan = FALSE; + + summary_len = camel_folder_summary_count (folder->summary); + if (summary_len == 0) { + if (exists) + camel_imap_folder_changed (folder, exists, NULL, ex); + return TRUE; + } + + camel_operation_start (NULL, _("Scanning for changed messages in %s"), folder->name); + ok = camel_imap_command_start (store, folder, ex, + "UID FETCH 1:* (FLAGS) (CHANGEDSINCE %s)", + highestmodseq); + if (!ok) { + + /* This probably means that the server doesn't understand + * CHANGEDSINCE, though it advertised support for CONDSTORE. + * But we are the client, we need to forgive! So we'll simply + * set need_rescan to TRUE and let the fallback stuff in the + * 'selected' method deal with it by launching imap_rescan. */ + + imap_folder->need_rescan = TRUE; + + /* TNY TODO: turn-off the CONDSTORE capability? */ + + camel_operation_end (NULL); + return FALSE; + } + + /* Highfive! everything is still up and running. It's still possible + * that things go wrong. But there's no need to stop then: we'll need + * to read-away what the server is sending anyway. So why not perform + * some work each time both the UID and the SEQUENCE match with what + * we have locally? + * + * If not, we simply set need_rescan TRUE and keep on going. This does, + * however, mean that we actually didn't really win traffic by using + * condstore. We even lost some. But being truly in sync is far more + * important. */ + + summary_got = 0; + while ((type = camel_imap_command_response (store, &resp, ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) + { + GData *data; + char *uid; + guint32 flags, seq; + + data = parse_fetch_response (imap_folder, resp); + g_free (resp); + + if (!data) + continue; + + uid = g_datalist_get_data (&data, "UID"); + flags = GPOINTER_TO_UINT (g_datalist_get_data (&data, "FLAGS")); + seq = GPOINTER_TO_UINT (g_datalist_get_data (&data, "SEQUENCE")); + + /* So basically: if the UID is not found locally, we have flags + * for a new message. That's cool, but not an error as the + * camel_imap_folder_changed will launch imap_update_summary + * who will deal with that. + * + * See, we wont find it if it's larger than the count of the + * local summary list. We don't even have to check that, right? + * + * We also check for negative sequences. No reason for that, + * it's just wrong (actually impossible since it's a unsigned + * int, but it's just for security-clarity here. Let it be, it + * doesn't hurt either) */ + + if (!uid || seq < 0 || seq-1 > summary_len) { + imap_folder->need_rescan = TRUE; + retval = FALSE; + g_datalist_clear (&data); + continue; + } + + info = camel_folder_summary_index (folder->summary, seq-1); + iinfo = (CamelImapMessageInfo *) info; + + + /* However, if we do find the message-info at that index then we + * we should also check whether the UID matches. If not, well .. + * that's not good eh. That means that we shouldn't have been + * using this CONDSTORE code in the first place! Bad luck, we + * just set need_rescan TRUE and let the selected metod launch + * the conventional imap_rescan later-on. Since we are receiving + * stuff anyway, and we need to read that away nonetheless, we + * just continue doing our stuff. */ + + if (info) + { + /* printf ("%s vs %s on %d\n", info->uid, uid, seq-1); */ + if (!strcmp (info->uid, uid)) + { + if (flags != iinfo->server_flags) + { + camel_folder_summary_touch (folder->summary); + guint32 server_set, server_cleared; + server_set = flags & ~iinfo->server_flags; + server_cleared = iinfo->server_flags & ~flags; + iinfo->info.flags = (iinfo->info.flags | server_set) & ~server_cleared; + iinfo->server_flags = flags; + if (changes == NULL) + changes = camel_folder_change_info_new(); + camel_folder_change_info_change_uid(changes, uid); + /* flags_to_label(folder, (CamelImapMessageInfo *)info); */ + } + camel_message_info_free (info); + } else { + imap_folder->need_rescan = TRUE; + retval = FALSE; + } + } else + retval = FALSE; + + camel_operation_progress (NULL, ++summary_got , summary_len); + g_datalist_clear (&data); } + + camel_operation_end (NULL); + + if (type == CAMEL_IMAP_RESPONSE_ERROR) + return FALSE; + + /* Free the final tagged response */ + if (resp) + g_free (resp); + + if (changes) + { + camel_object_trigger_event(CAMEL_OBJECT (folder), "folder_changed", changes); + camel_folder_change_info_free(changes); + } + + /* The thing with te if is that the selected folder will do imap_rescan + * anyway, that function will call the camel_imap_folder_changed too. + * There's no need to let this happen twice, so we filter it. + * + * However. If we were lucky and condstore succeeded without problems, + * then we must check for new messages of course. We can't have removals + * which is why it's set to NULL. If we had removals, then need_rescan + * has been set to TRUE. Right? Right! */ + + if (!imap_folder->need_rescan) + camel_imap_folder_changed (folder, exists, NULL, ex); + + return retval; } /* Called with the store's connect_lock locked */ -static void +static gboolean imap_rescan (CamelFolder *folder, int exists, CamelException *ex) { + gboolean retval = TRUE; + + /* Welcome to the most hairy code of Camel. On the left you + * have the bathroom where you can puke. On the right you have + * fresh water and soap to clean it up. In front of you, you have .. + * + * The code */ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); struct { @@ -622,10 +1056,12 @@ imap_folder->need_rescan = FALSE; summary_len = camel_folder_summary_count (folder->summary); - if (summary_len == 0) { + + if (summary_len == 0) + { if (exists) camel_imap_folder_changed (folder, exists, NULL, ex); - return; + return TRUE; } /* Check UIDs and flags of all messages we already know of. */ @@ -637,12 +1073,20 @@ camel_message_info_free(info); if (!ok) { camel_operation_end (NULL); - return; + return FALSE; } + /* Soo ... we allocate a matrix of the exact size of the local summary + * after we launched a command that asks for the flags of all messages + * until the last uid we have locally. Let's iterate them ... */ + new = g_malloc0 (summary_len * sizeof (*new)); summary_got = 0; - while ((type = camel_imap_command_response (store, &resp, ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) { + resp = NULL; + + while ((type = camel_imap_command_response (store, &resp, ex)) + == CAMEL_IMAP_RESPONSE_UNTAGGED) + { GData *data; char *uid; guint32 flags; @@ -656,40 +1100,66 @@ uid = g_datalist_get_data (&data, "UID"); flags = GPOINTER_TO_UINT (g_datalist_get_data (&data, "FLAGS")); - if (!uid || !seq || seq > summary_len) { + if (!uid || !seq || seq > summary_len || seq < 0) + { + retval = FALSE; g_datalist_clear (&data); continue; } - camel_operation_progress (NULL, ++summary_got * 100 / summary_len); + /* See, we are just storing them in that matrix. Nothing + * difficult here. */ + + camel_operation_progress (NULL, ++summary_got , summary_len); new[seq - 1].uid = g_strdup (uid); new[seq - 1].flags = flags; g_datalist_clear (&data); } camel_operation_end (NULL); - if (type == CAMEL_IMAP_RESPONSE_ERROR) { + + if (type == CAMEL_IMAP_RESPONSE_ERROR) + { for (i = 0; i < summary_len && new[i].uid; i++) g_free (new[i].uid); g_free (new); - return; + return FALSE; } /* Free the final tagged response */ - g_free (resp); + if (resp) + g_free (resp); /* If we find a UID in the summary that doesn't correspond to * the UID in the folder, then either: (a) it's a real UID, * but the message was deleted on the server, or (b) it's a * fake UID, and needs to be removed from the summary in order * to sync up with the server. So either way, we remove it - * from the summary. - */ + * from the summary. */ + removed = g_array_new (FALSE, FALSE, sizeof (int)); - for (i = 0; i < summary_len && new[i].uid; i++) { + for (i = 0; i < summary_len && new[i].uid; i++) + { info = camel_folder_summary_index (folder->summary, i); iinfo = (CamelImapMessageInfo *)info; - + + if (!info) + continue; + + /* This is where it gets hairy. It tries to mimic what an + * EXPUNGE would cause. That's because we will pass the removed + * sequences to the same handler for it (check below and in + * the code in imap-command and the IDLE stuff that handles + * EXPUNGE responses). + * + * Now. the consequences are that if at the very beginning of + * the remote mailbox a message got expunged, all local messages + * will be marked for removal caused by this. That's a terrible + * idea, but it is what it is .... */ + + /* TODO: recalculating rather than marking a lot perfectly fine + * material for removal */ + if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) { camel_message_info_free(info); seq = i + 1; @@ -699,8 +1169,12 @@ continue; } - /* Update summary flags */ - if (new[i].flags != iinfo->server_flags) { + + /* In case both the uid and the sequence are in match remote and + * locally, we can securely update the flags locally. */ + + if (new[i].flags != iinfo->server_flags) + { guint32 server_set, server_cleared; server_set = new[i].flags & ~iinfo->server_flags; @@ -712,14 +1186,15 @@ if (changes == NULL) changes = camel_folder_change_info_new(); camel_folder_change_info_change_uid(changes, new[i].uid); - flags_to_label(folder, (CamelImapMessageInfo *)info); + /* flags_to_label(folder, (CamelImapMessageInfo *)info); */ } camel_message_info_free(info); g_free (new[i].uid); } - if (changes) { + if (changes) + { camel_object_trigger_event(CAMEL_OBJECT (folder), "folder_changed", changes); camel_folder_change_info_free(changes); } @@ -730,11 +1205,9 @@ while (i < summary_len && new[i].uid) g_free (new[i++].uid); g_free (new); - - /* Remove any leftover cached summary messages. (Yes, we - * repeatedly add the same number to the removed array. - * See RFC2060 7.4.1) - */ + + /* Remove any leftover cached summary messages. (Yes, we repeatedly add + * the same number to the removed array. See RFC2060 7.4.1) */ for (i = seq; i <= summary_len; i++) g_array_append_val (removed, seq); @@ -742,6 +1215,8 @@ /* And finally update the summary. */ camel_imap_folder_changed (folder, exists, removed, ex); g_array_free (removed, TRUE); + + return retval; } /* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */ @@ -751,8 +1226,7 @@ * If no messages match, returns %NULL. Otherwise, returns an array of * CamelMessageInfo and sets *@set to a message set corresponding the * UIDs of the matched messages (up to @UID_SET_LIMIT bytes). The - * caller must free the infos, the array, and the set string. - */ + * caller must free the infos, the array, and the set string. */ static GPtrArray * get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set) { @@ -836,8 +1310,7 @@ /* Find a message with changed flags, find all of the other * messages like it, sync them as a group, mark them as - * updated, and continue. - */ + * updated, and continue.*/ max = camel_folder_summary_count (folder->summary); for (i = 0; i < max; i++) { if (!(info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i))) @@ -865,7 +1338,7 @@ continue; /* Make sure we're connected before issuing commands */ - if (!camel_imap_store_connected(store, ex)) { + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, ex)) { g_free(set); break; } @@ -916,6 +1389,7 @@ imap_sync_offline (folder, ex); CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + /* camel_imap_folder_start_idle (folder); */ } static int @@ -948,8 +1422,7 @@ camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]); camel_folder_change_info_remove_uid (changes, uids->pdata[i]); /* We intentionally don't remove it from the cache because - * the cached data may be useful in replaying a COPY later. - */ + * the cached data may be useful in replaying a COPY later. */ } camel_folder_summary_save (folder->summary); @@ -1004,6 +1477,9 @@ } CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + + camel_imap_folder_start_idle (folder); + } static void @@ -1026,8 +1502,7 @@ /* If we don't have UID EXPUNGE we need to avoid expunging any * of the wrong messages. So we search for deleted messages, * and any that aren't in our to-expunge list get temporarily - * marked un-deleted. - */ + * marked un-deleted. */ CAMEL_SERVICE_REC_LOCK (store, connect_lock); @@ -1080,8 +1555,7 @@ } } else { /* Empty SEARCH result, meaning nothing is marked deleted - * on server. - */ + * on server. */ keep_uids = NULL; mark_uids = uids; @@ -1109,6 +1583,7 @@ return; } camel_imap_response_free (store, response); + } } @@ -1132,7 +1607,6 @@ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return; } - camel_imap_response_free (store, response); } if (mark_uids != uids) @@ -1170,6 +1644,9 @@ g_free (result); CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + + camel_imap_folder_start_idle (folder); + } static gchar * @@ -1290,7 +1767,7 @@ } /* send the rest of our data - the mime message */ - response2 = camel_imap_command_continuation (store, ba->data, ba->len, ex); + response2 = camel_imap_command_continuation (store, (const char *) ba->data, ba->len, ex); g_byte_array_free (ba, TRUE); /* free it only after message is sent. This may cause more FETCHes. */ @@ -1355,6 +1832,9 @@ camel_folder_summary_count (folder->summary) == count) imap_refresh_info (folder, ex); CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + + camel_imap_folder_start_idle (folder); + } static void @@ -1429,7 +1909,8 @@ mi = camel_folder_summary_uid (source->summary, uid); g_return_if_fail (mi != NULL); - message = camel_folder_get_message (source, uid, NULL); + /* TNY TODO: detect whether or not to persist partial message retrieval */ + message = camel_folder_get_message (source, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); if (message) { camel_imap_summary_add_offline (dest->summary, destuid, message, mi); @@ -1552,9 +2033,7 @@ CamelFolder *dest, GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex) { - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); int count; - /* Sync message flags if needed. */ imap_sync_online (source, ex); if (camel_exception_is_set (ex)) @@ -1570,13 +2049,17 @@ return; /* Make the destination notice its new messages */ - if (store->current_folder != dest || + + /*if (store->current_folder != dest || camel_folder_summary_count (dest->summary) == count) - camel_folder_refresh_info (dest, ex); - + camel_folder_refresh_info (dest, ex); */ + /* FIXME */ if (transferred_uids) *transferred_uids = NULL; + + camel_imap_folder_start_idle (source); + } static void @@ -1629,8 +2112,11 @@ !isdigit (*(unsigned char *)(uids->pdata[i])) && !camel_exception_is_set (ex)) { uid = uids->pdata[i]; - message = camel_folder_get_message (source, uid, NULL); + + /* TNY TODO: detect whether or not to persist partial message retrieval */ + message = camel_folder_get_message (source, uid, CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); if (!message) { + i++; /* Message must have been expunged */ continue; } @@ -1708,7 +2194,7 @@ static CamelMimeMessage *get_message (CamelImapFolder *imap_folder, const char *uid, CamelMessageContentInfo *ci, - CamelException *ex); + CamelFolderReceiveType type, gint param, CamelException *ex); struct _part_spec_stack { struct _part_spec_stack *parent; @@ -1829,7 +2315,8 @@ strcpy(spec, part_spec); g_free(part_spec); - stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, ex); + /* TNY TODO: partial message retrieval exception */ + stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); if (stream) { ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (body_mp), stream); camel_object_unref (CAMEL_OBJECT (stream)); @@ -1866,7 +2353,8 @@ num = 1; while (ci) { sprintf (child_spec + speclen, "%d.MIME", num++); - stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, FALSE, ex); + /* TNY TODO: partial message retrieval exception */ + stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, TRUE, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); if (stream) { int ret; @@ -1922,7 +2410,8 @@ return (CamelDataWrapper *) body_mp; } else if (camel_content_type_is (ci->type, "message", "rfc822")) { - content = (CamelDataWrapper *) get_message (imap_folder, uid, ci->childs, ex); + /* TNY TODO: partial message retrieval exception */ + content = (CamelDataWrapper *) get_message (imap_folder, uid, ci->childs, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); g_free (part_spec); return content; } else { @@ -1946,7 +2435,7 @@ static CamelMimeMessage * get_message (CamelImapFolder *imap_folder, const char *uid, CamelMessageContentInfo *ci, - CamelException *ex) + CamelFolderReceiveType type, gint param, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (CAMEL_FOLDER (imap_folder)->parent_store); CamelDataWrapper *content; @@ -1960,7 +2449,8 @@ section_text = g_strdup_printf ("%s%s%s", part_spec, *part_spec ? "." : "", store->server_level >= IMAP_LEVEL_IMAP4REV1 ? "HEADER" : "0"); - stream = camel_imap_folder_fetch_data (imap_folder, uid, section_text, FALSE, ex); + /* TNY: partial message retrieval */ + stream = camel_imap_folder_fetch_data (imap_folder, uid, section_text, FALSE, type, param, ex); g_free (section_text); g_free(part_spec); if (!stream) @@ -2000,14 +2490,14 @@ static CamelMimeMessage * get_message_simple (CamelImapFolder *imap_folder, const char *uid, - CamelStream *stream, CamelException *ex) + CamelStream *stream, CamelFolderReceiveType type, gint param, CamelException *ex) { CamelMimeMessage *msg; int ret; if (!stream) { stream = camel_imap_folder_fetch_data (imap_folder, uid, "", - FALSE, ex); + FALSE, type, param, ex); if (!stream) return NULL; } @@ -2046,7 +2536,7 @@ } static CamelMimeMessage * -imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) +imap_get_message (CamelFolder *folder, const char *uid, CamelFolderReceiveType type, gint param, CamelException *ex) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); @@ -2064,8 +2554,12 @@ /* If its cached in full, just get it as is, this is only a shortcut, since we get stuff from the cache anyway. It affects a busted connection though. */ - if ( (stream = camel_imap_folder_fetch_data(imap_folder, uid, "", TRUE, NULL)) - && (msg = get_message_simple(imap_folder, uid, stream, ex))) + if ( (stream = camel_imap_folder_fetch_data (imap_folder, uid, "", TRUE, type, param, NULL)) + && (msg = get_message_simple(imap_folder, uid, stream, type, param, ex))) + goto done; + + + if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_OFFLINE) goto done; /* All this mess is so we silently retry a fetch if we fail with @@ -2080,7 +2574,7 @@ || store->braindamaged || mi->info.size < IMAP_SMALL_BODY_SIZE || (!content_info_incomplete(mi->info.content) && !mi->info.content->childs)) { - msg = get_message_simple (imap_folder, uid, NULL, ex); + msg = get_message_simple (imap_folder, uid, NULL, type, param, ex); } else { if (content_info_incomplete (mi->info.content)) { /* For larger messages, fetch the structure and build a message @@ -2094,7 +2588,7 @@ int i; CAMEL_SERVICE_REC_LOCK(store, connect_lock); - if (!camel_imap_store_connected(store, ex)) { + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, ex)) { CAMEL_SERVICE_REC_UNLOCK(store, connect_lock); camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("This message is not currently available")); @@ -2129,7 +2623,8 @@ camel_imap_response_free (store, response); } else { - camel_exception_clear(ex); + /* camel_exception_clear(ex); */ + goto fail; } } @@ -2146,21 +2641,24 @@ * let the mailer's "bad MIME" code handle it. */ if (content_info_incomplete (mi->info.content)) - msg = get_message_simple (imap_folder, uid, NULL, ex); + msg = get_message_simple (imap_folder, uid, NULL, type, param, ex); else - msg = get_message (imap_folder, uid, mi->info.content, ex); + msg = get_message (imap_folder, uid, mi->info.content, type, param, ex); } } while (msg == NULL && retry < 2 && camel_exception_get_id(ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE); -done: /* FIXME, this shouldn't be done this way. */ - if (msg) - camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", store->base_url); +done: + camel_message_info_free(&mi->info); + return msg; + fail: camel_message_info_free(&mi->info); + if (msg && CAMEL_IS_OBJECT (msg)) + camel_object_unref (CAMEL_OBJECT (msg)); - return msg; + return NULL; } static void @@ -2170,7 +2668,8 @@ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (disco_folder); CamelStream *stream; - stream = camel_imap_folder_fetch_data (imap_folder, uid, "", FALSE, ex); + /* TNY TODO: partial message retrieval exception */ + stream = camel_imap_folder_fetch_data (imap_folder, uid, "", FALSE, CAMEL_FOLDER_RECEIVE_FULL, -1, ex); if (stream) camel_object_unref (CAMEL_OBJECT (stream)); } @@ -2224,7 +2723,7 @@ return TRUE; } -static time_t +time_t decode_internaldate (const unsigned char *in) { const unsigned char *inptr = in; @@ -2235,7 +2734,7 @@ memset ((void *) &tm, 0, sizeof (struct tm)); - tm.tm_mday = strtoul (inptr, (char **) &buf, 10); + tm.tm_mday = strtoul ((char *) inptr, (char **) &buf, 10); if (buf == inptr || *buf != '-') return (time_t) -1; @@ -2244,7 +2743,7 @@ return (time_t) -1; for (n = 0; n < 12; n++) { - if (!g_ascii_strncasecmp (inptr, tm_months[n], 3)) + if (!g_ascii_strncasecmp ((gchar *) inptr, tm_months[n], 3)) break; } @@ -2255,7 +2754,7 @@ inptr += 4; - n = strtoul (inptr, (char **) &buf, 10); + n = strtoul ((char *) inptr, (char **) &buf, 10); if (buf == inptr || *buf != ' ') return (time_t) -1; @@ -2269,7 +2768,7 @@ tm.tm_min = min; tm.tm_sec = sec; - n = strtol (inptr, NULL, 10); + n = strtol ((char *) inptr, NULL, 10); date = e_mktime_utc (&tm); @@ -2281,9 +2780,52 @@ return date; } -static void -add_message_from_data (CamelFolder *folder, GPtrArray *messages, - int first, GData *data) + +static CamelImapMessageInfo* +message_from_data (CamelFolder *folder, GData *data) +{ + CamelMimeMessage *msg; + CamelStream *stream; + CamelImapMessageInfo *mi; + const char *idate; + gint size = 0; + + stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); + if (!stream) + return NULL; + + msg = camel_mime_message_new (); + if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) { + camel_object_unref (CAMEL_OBJECT (msg)); + return NULL; + } + + mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (folder->summary, msg); + camel_object_unref (CAMEL_OBJECT (msg)); + + size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE")); + if (size) + mi->info.size = size; + + /* TNY TODO: This is a hack! But else we need to parse + * BODYSTRUCTURE (and I'm lazy). It needs fixing though. */ + if (size > 102400) + ((CamelMessageInfoBase *)mi)->flags |= CAMEL_MESSAGE_ATTACHMENTS; + /* ... it does */ + + if ((idate = g_datalist_get_data (&data, "INTERNALDATE"))) + mi->info.date_received = decode_internaldate ((const unsigned char *) idate); + + if (mi->info.date_received == -1) + mi->info.date_received = mi->info.date_sent; + + return mi; +} + +#if 0 +static void +add_message_from_data (CamelFolder *folder, GPtrArray *messages, + int first, GData *data) { CamelMimeMessage *msg; CamelStream *stream; @@ -2308,327 +2850,856 @@ } mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (folder->summary, msg); + camel_object_unref (CAMEL_OBJECT (msg)); if ((idate = g_datalist_get_data (&data, "INTERNALDATE"))) - mi->info.date_received = decode_internaldate (idate); + mi->info.date_received = decode_internaldate ((const unsigned char *) idate); if (mi->info.date_received == -1) mi->info.date_received = mi->info.date_sent; - + messages->pdata[seq - first] = mi; + + return; } +#endif + +/* #define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE " */ + +#ifdef NON_TINYMAIL_FEATURES +#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE X-PRIORITY X-MSMAIL-PRIORITY" +#else +#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT MESSAGE-ID X-PRIORITY X-MSMAIL-PRIORITY X-MS-HAS-ATTACH CONTENT-TYPE" +#endif -#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE " /* FIXME: this needs to be kept in sync with camel-mime-utils.c's list of mailing-list headers and so might be best if this were auto-generated? */ -#define MAILING_LIST_HEADERS "X-MAILING-LIST X-LOOP LIST-ID LIST-POST MAILING-LIST ORIGINATOR X-LIST SENDER RETURN-PATH X-BEENTHERE " +#define MAILING_LIST_HEADERS " X-MAILING-LIST X-LOOP LIST-ID LIST-POST MAILING-LIST ORIGINATOR X-LIST SENDER RETURN-PATH X-BEENTHERE" + + +static guint32 +imap_get_uids (CamelFolder *folder, CamelImapStore *store, CamelException *ex, GPtrArray *needheaders, int size) +{ + char *resp = NULL; + CamelImapResponseType type; + guint32 cnt = 0; + gchar *uid, *str; + + while ((type = camel_imap_command_response (store, &resp, ex)) == + CAMEL_IMAP_RESPONSE_UNTAGGED) + { + str = strstr (resp, "SEARCH"); + + if (str) + { + str+=7; + uid = strtok (str, " "); + + while (uid != NULL) + { + if (uid) + g_ptr_array_add (needheaders, g_strdup (uid)); + uid = strtok (NULL, " "); + cnt++; + } + } + + g_free (resp); + resp=NULL; + } + if (type == CAMEL_IMAP_RESPONSE_TAGGED && resp) + g_free (resp); + + if (type == CAMEL_IMAP_RESPONSE_ERROR) + { + if (resp) + g_free (resp); + camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, + _("Connection canceled")); + cnt = 0; + } + + return cnt; + +} static void imap_update_summary (CamelFolder *folder, int exists, CamelFolderChangeInfo *changes, CamelException *ex) { - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders; - guint32 flags, uidval; - int i, seq, first, size, got; - CamelImapResponseType type; - GString *header_spec = NULL; - CamelImapMessageInfo *mi, *info; - CamelStream *stream; - char *uid, *resp; - GData *data; - - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) { - if (store->headers == IMAP_FETCH_ALL_HEADERS) - header_spec = g_string_new ("HEADER"); - else { - gchar *temp; - header_spec = g_string_new ("HEADER.FIELDS ("); - header_spec = g_string_append (header_spec, CAMEL_MESSAGE_INFO_HEADERS); - if (store->headers == IMAP_FETCH_MAILING_LIST_HEADERS) - header_spec = g_string_append (header_spec, MAILING_LIST_HEADERS); - if (store->custom_headers) - header_spec = g_string_append (header_spec, store->custom_headers); - - temp = g_strdup(header_spec->str); - temp = g_strstrip (temp); - header_spec = g_string_new (temp); - g_free (temp); - header_spec = g_string_append (header_spec, ")"); - } - } else - header_spec = g_string_new ("0"); + CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + GPtrArray *needheaders; + guint32 flags; + int seq=0; + CamelImapResponseType type; + const char *header_spec; + CamelImapMessageInfo *mi; + char *resp; + GData *data; + gboolean more = TRUE, oosync = FALSE, oldrescval = imap_folder->need_rescan; + unsigned int nextn, cnt=0, tcnt=0, ucnt=0, ineed = 0, allhdrs = 0; - d(printf("Header is : %s", header_spec->str)); - - /* Figure out if any of the new messages are already cached (which - * may be the case if we're re-syncing after disconnected operation). - * If so, get their UIDs, FLAGS, and SIZEs. If not, get all that - * and ask for the headers too at the same time. - */ + if (!store->ostream || !store->istream) + return; + + if (store->server_level >= IMAP_LEVEL_IMAP4REV1) + header_spec = "HEADER.FIELDS (" CAMEL_MESSAGE_INFO_HEADERS ")"; + else + header_spec = "0"; + + if( g_getenv ("TNY_IMAP_FETCH_ALL_HEADERS") ) + header_spec = "HEADER"; + + nextn = 0; + if (folder->summary) + nextn = camel_folder_summary_count (folder->summary); + if (nextn <= 0) { + camel_folder_summary_load (folder->summary); + nextn = camel_folder_summary_count (folder->summary); + } + + ineed = (exists - nextn); + nextn = 1; + tcnt = 0; + + camel_operation_start (NULL, _("Fetching summary information for new messages in folder")); + + camel_folder_summary_prepare_hash (folder->summary); + + store->dontdistridlehack = TRUE; + + while (more) + { + gboolean did_hack = FALSE; + gint hcnt = 0; + CamelFolderChangeInfo *mchanges; + + imap_folder->need_rescan = TRUE; + camel_folder_summary_save (folder->summary); seq = camel_folder_summary_count (folder->summary); - first = seq + 1; - if (seq > 0) { - mi = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, seq - 1); - uidval = strtoul(camel_message_info_uid (mi), NULL, 10); - camel_message_info_free(&mi->info); - } else - uidval = 0; - - size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS); - got = 0; + if (!camel_imap_command_start (store, folder, ex, - "UID FETCH %d:* (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])", - uidval + 1, header_spec->str)) { - g_string_free (header_spec, TRUE); + "UID SEARCH %d:%d ALL", seq + 1, seq + 1 + nextn)) + { if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting UIDs (1)"); + camel_operation_end (NULL); return; } + + more = FALSE; + needheaders = g_ptr_array_new (); + cnt = imap_get_uids (folder, store, ex, needheaders, (exists - seq)); + + if (cnt == 0 && camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) + { + if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting UIDs (1,1)"); + + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); + g_ptr_array_free (needheaders, TRUE); + camel_operation_end (NULL); + more = FALSE; + camel_folder_summary_kill_hash (folder->summary); + store->dontdistridlehack = FALSE; return; } - camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name); - - /* Parse the responses. We can't add a message to the summary - * until we've gotten its headers, and there's no guarantee - * the server will send the responses in a useful order... - */ - fetch_data = g_ptr_array_new (); - messages = g_ptr_array_new (); - while ((type = camel_imap_command_response (store, &resp, ex)) == - CAMEL_IMAP_RESPONSE_UNTAGGED) { - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq < first) { - g_datalist_clear (&data); - continue; - } - - if (g_datalist_get_data (&data, "FLAGS")) - got += IMAP_PRETEND_SIZEOF_FLAGS; - if (g_datalist_get_data (&data, "RFC822.SIZE")) - got += IMAP_PRETEND_SIZEOF_SIZE; - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (stream) { - got += IMAP_PRETEND_SIZEOF_HEADERS; - - /* Use the stream now so we don't tie up many - * many fds if we're fetching many many messages. - */ - add_message_from_data (folder, messages, first, data); - g_datalist_set_data (&data, "BODY_PART_STREAM", NULL); + + tcnt += cnt; + + /* Figure out whether we need more */ + more = (cnt < (exists - seq)); + /* If we received less than what we asked for, yet need more */ + if ((cnt < nextn) && more) + { + if (!camel_imap_command_start (store, folder, ex, + "UID SEARCH %d:* ALL", seq + 1 + cnt)) + { if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting UIDs (2)"); + camel_operation_end (NULL); + store->dontdistridlehack = FALSE; return; } + cnt = imap_get_uids (folder, store, ex, needheaders, (exists - seq) - cnt); + + if (cnt == 0 && camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) + { + if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting UIDs (2,1)"); + + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); + g_ptr_array_free (needheaders, TRUE); + camel_operation_end (NULL); + more = FALSE; + camel_folder_summary_kill_hash (folder->summary); + store->dontdistridlehack = FALSE; + return; } - - camel_operation_progress (NULL, got * 100 / size); - g_ptr_array_add (fetch_data, data); - } - camel_operation_end (NULL); - - if (type == CAMEL_IMAP_RESPONSE_ERROR) - goto lose; - - /* Free the final tagged response */ - g_free (resp); - - /* Figure out which headers we still need to fetch. */ - needheaders = g_ptr_array_new (); - size = got = 0; - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - if (g_datalist_get_data (&data, "BODY_PART_LEN")) - continue; - - uid = g_datalist_get_data (&data, "UID"); - if (uid) { - g_ptr_array_add (needheaders, uid); - size += IMAP_PRETEND_SIZEOF_HEADERS; + + tcnt += cnt; + /* If we still received too few */ + if (tcnt < (exists - seq)) + { + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); + g_ptr_array_free (needheaders, TRUE); + needheaders = g_ptr_array_new (); + if (!camel_imap_command_start (store, folder, ex, + "UID SEARCH 1:* ALL")) + { if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting UIDs (3)"); + camel_folder_summary_kill_hash (folder->summary); + camel_operation_end (NULL); + store->dontdistridlehack = FALSE; return; } + camel_folder_summary_clear (folder->summary); + tcnt = cnt = imap_get_uids (folder, store, ex, needheaders, (exists - seq) - tcnt); + + if (cnt == 0 && camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) + { + if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting UIDs (3,1)"); + + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); + g_ptr_array_free (needheaders, TRUE); + camel_operation_end (NULL); + more = FALSE; + camel_folder_summary_kill_hash (folder->summary); + store->dontdistridlehack = FALSE; + return; + } } + camel_operation_end (NULL); + more = FALSE; + did_hack = TRUE; } - - /* And fetch them */ - if (needheaders->len) { - char *uidset; + + nextn = (nextn < 1000) ? nextn+nextn+25 : 1000; + + if (needheaders->len) + { int uid = 0; - + char *uidset; + + ucnt = 0; qsort (needheaders->pdata, needheaders->len, - sizeof (void *), uid_compar); - - camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name); - - while (uid < needheaders->len) { + sizeof (void *), uid_compar); + + mchanges = camel_folder_change_info_new (); + + while (uid < needheaders->len) + { uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid); if (!camel_imap_command_start (store, folder, ex, - "UID FETCH %s BODY.PEEK[%s]", - uidset, header_spec->str)) { + "UID FETCH %s (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])", + uidset, header_spec)) + { + if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting headers (1)"); + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); g_ptr_array_free (needheaders, TRUE); camel_operation_end (NULL); g_free (uidset); - g_string_free (header_spec, TRUE); - goto lose; + more = FALSE; + camel_folder_summary_kill_hash (folder->summary); + store->dontdistridlehack = FALSE; + return; } g_free (uidset); - + + resp = NULL; while ((type = camel_imap_command_response (store, &resp, ex)) - == CAMEL_IMAP_RESPONSE_UNTAGGED) { + == CAMEL_IMAP_RESPONSE_UNTAGGED) + { + gchar *muid; + guint32 sequence, curlen; + data = parse_fetch_response (imap_folder, resp); - g_free (resp); + g_free (resp); resp = NULL; + if (!data) continue; - - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (stream) { - add_message_from_data (folder, messages, first, data); - got += IMAP_PRETEND_SIZEOF_HEADERS; - camel_operation_progress (NULL, got * 100 / size); + + mi = message_from_data (folder, data); + + if (mi) + { + flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS")); + if (flags) + { + mi->server_flags = flags; + mi->info.flags |= flags; + /* flags_to_label(folder, mi); */ + } + + muid = g_datalist_get_data (&data, "UID"); + if (muid) + { + if (mi->info.uid && mi->info.flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE) + g_free (mi->info.uid); + mi->info.uid = g_strdup (muid); + mi->info.flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + } + + ucnt++; + + allhdrs++; + camel_operation_progress (NULL, allhdrs , ineed); + sequence = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); + curlen = camel_folder_summary_count (folder->summary); + + if (sequence > 0 && sequence <= exists && sequence != curlen) + { + int r; + if (curlen > sequence) + { + for (r = curlen-1; r >= sequence -1; r--) + { + g_warning ("Problem with your local summary store (too much), correcting: curlen=%d, r=%d, seq=%d\n", curlen, r, sequence); + CamelMessageInfo *ri = g_ptr_array_index (folder->summary->messages, r); + if (ri) { + /* camel_folder_change_info_remove_uid (mchange, camel_message_info_uid (mi)); */ + ((CamelMessageInfoBase*)ri)->flags |= CAMEL_MESSAGE_EXPUNGED; + ((CamelMessageInfoBase*)ri)->flags |= CAMEL_MESSAGE_FREED; + camel_folder_summary_remove (folder->summary, ri); + } + } + } else { + for (r=0; r < sequence - curlen - 1; r++) + { + CamelMessageInfo *ni = camel_message_info_clone (mi); + if (ni) { + g_warning ("Problem with your local summary store (too few), correcting: curlen=%d, r=%d, seq=%d\n", curlen, r, sequence); + camel_folder_summary_add (folder->summary, (CamelMessageInfo *)ni); + /* camel_folder_change_info_add_uid (mchanges, camel_message_info_uid (ni)); */ + } + } + } + oosync = TRUE; + } + + camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi); + + /* printf ("Change: %s!\n", camel_message_info_uid (mi)); */ + camel_folder_change_info_add_uid (mchanges, camel_message_info_uid (mi)); + if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT)) + camel_folder_change_info_recent_uid(mchanges, camel_message_info_uid (mi)); } + + if (did_hack) { + hcnt++; + if (hcnt > 1000) { + camel_folder_summary_save (folder->summary); + camel_folder_summary_prepare_hash (folder->summary); + hcnt = 0; + } + } + g_datalist_clear (&data); } - - if (type == CAMEL_IMAP_RESPONSE_ERROR) { + + if (resp != NULL) + g_free (resp); + + if (type == CAMEL_IMAP_RESPONSE_ERROR) + { + if (!camel_operation_cancel_check (NULL)) + g_warning ("IMAP error getting headers (2)"); + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); g_ptr_array_free (needheaders, TRUE); camel_operation_end (NULL); - goto lose; + more = FALSE; + camel_folder_summary_kill_hash (folder->summary); + store->dontdistridlehack = FALSE; + return; } + } - g_string_free (header_spec, TRUE); - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - } - - /* Now finish up summary entries (fix UIDs, set flags and size) */ - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; + - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq >= first + messages->len) { - g_datalist_clear (&data); - continue; + if (camel_folder_change_info_changed (mchanges)) { + camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", mchanges); + /* printf ("Changes!\n"); */ } - - mi = messages->pdata[seq - first]; - if (mi == NULL) { - CamelMessageInfo *pmi = NULL; - int j; - - /* This is a kludge around a bug in Exchange - * 5.5 that sometimes claims multiple messages - * have the same UID. See bug #17694 for - * details. The "solution" is to create a fake - * message-info with the same details as the - * previously valid message. Yes, the user - * will have a clone in his/her message-list, - * but at least we don't crash. - */ - - /* find the previous valid message info */ - for (j = seq - first - 1; j >= 0; j--) { - pmi = messages->pdata[j]; - if (pmi != NULL) - break; - } - - if (pmi == NULL) { - /* Server response is *really* fucked up, - I guess we just pretend it never happened? */ - continue; + camel_folder_change_info_free (mchanges); + + } + + if (ucnt < needheaders->len) + g_warning ("Problem while receiving headers from IMAP " + "(I didn't receive enough headers %d vs %d)\n", + ucnt, needheaders->len); + + g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL); + g_ptr_array_free (needheaders, TRUE); + + } /* more */ + + if (oosync) + imap_folder->need_rescan = TRUE; + + camel_folder_summary_save (folder->summary); + camel_folder_summary_kill_hash (folder->summary); + camel_operation_end (NULL); + + imap_folder->need_rescan = oldrescval; + store->dontdistridlehack = FALSE; + +} + +typedef struct { + guint32 id; + guint32 flags; +} FetchIdleResponse; + +typedef struct { + guint32 exists; + guint32 recent; + GArray *expunged; + GPtrArray *fetch; + gboolean fetch_happened; + CamelFolder *folder; +} IdleResponse; + +static void +process_idle_response (IdleResponse *idle_resp) +{ + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + + idle_debug ("process_idle_response\n"); + + if (!idle_resp) + return; + + if (idle_resp->fetch && idle_resp->folder) + { + CamelMessageInfo *info; + CamelImapMessageInfo *iinfo; + CamelFolderChangeInfo *changes = NULL; + + guint i=0; + for (i=0; i < idle_resp->fetch->len; i++) + { + FetchIdleResponse *fid = idle_resp->fetch->pdata[i]; + info = camel_folder_summary_index (idle_resp->folder->summary, fid->id); + iinfo = (CamelImapMessageInfo *) info; + + if (info) + { + if (fid->flags != iinfo->server_flags) + { + camel_folder_summary_touch (idle_resp->folder->summary); + guint32 server_set, server_cleared; + server_set = fid->flags & ~iinfo->server_flags; + server_cleared = iinfo->server_flags & ~fid->flags; + iinfo->info.flags = (iinfo->info.flags | server_set) & ~server_cleared; + iinfo->server_flags = fid->flags; + if (changes == NULL) + changes = camel_folder_change_info_new(); + camel_folder_change_info_change_uid(changes, info->uid); + } + camel_message_info_free (info); } - - mi = (CamelImapMessageInfo *)camel_message_info_clone(pmi); } - - uid = g_datalist_get_data (&data, "UID"); - if (uid) - mi->info.uid = g_strdup (uid); - flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS")); - if (flags) { - ((CamelImapMessageInfo *)mi)->server_flags = flags; - /* "or" them in with the existing flags that may - * have been set by summary_info_new_from_message. - */ - mi->info.flags |= flags; - flags_to_label(folder, mi); + + if (changes) + { + if (camel_folder_change_info_changed (changes)) + camel_object_trigger_event (CAMEL_OBJECT (idle_resp->folder), "folder_changed", changes); + camel_folder_change_info_free (changes); + camel_folder_summary_save (idle_resp->folder->summary); } - size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE")); - if (size) - mi->info.size = size; - - g_datalist_clear (&data); + } - g_ptr_array_free (fetch_data, TRUE); - - /* And add the entries to the summary, etc. */ - for (i = 0; i < messages->len; i++) { - mi = messages->pdata[i]; - if (!mi) { - g_warning ("No information for message %d", i + first); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Incomplete server response: no information provided for message %d"), - i + first); - break; - } - uid = (char *)camel_message_info_uid(mi); - if (uid[0] == 0) { - g_warning("Server provided no uid: message %d", i + first); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Incomplete server response: no UID provided for message %d"), - i + first); - break; + + camel_imap_folder_changed_for_idle (idle_resp->folder, idle_resp->exists, + idle_resp->expunged, &ex); + +} + +static void +read_idle_response (CamelFolder *folder, char *resp, IdleResponse *idle_resp) +{ + char *ptr = strchr (resp, '*'); + + idle_debug ("read_idle_response\n"); + + if (ptr && strstr (resp, "EXISTS") != NULL) + idle_resp->exists = strtoul (resp + 1, NULL, 10); + + if (ptr && strstr (resp, "RECENT") != NULL) + idle_resp->recent = strtoul (resp + 1, NULL, 10); + + if (ptr && strstr (resp, "FETCH") != NULL) + { + char *fptr = resp; + + FetchIdleResponse *fid = g_slice_new0 (FetchIdleResponse); + fid->id = strtoul (resp + 1, NULL, 10); + fptr += 9; + fid->flags = imap_parse_flag_list (&fptr); + + if (idle_resp->fetch == NULL) + idle_resp->fetch = g_ptr_array_new (); + g_ptr_array_add (idle_resp->fetch, fid); + } + + if (ptr && strstr (resp, "EXPUNGE") != NULL) + { + guint32 id = strtoul (resp + 1, NULL, 10); + + if (idle_resp->expunged == NULL) + idle_resp->expunged = g_array_new (FALSE, FALSE, sizeof (int)); + g_array_append_val (idle_resp->expunged, id); + } +} + +static IdleResponse* +idle_response_new (CamelFolder *folder) +{ + IdleResponse *idle_resp = g_slice_new0 (IdleResponse); + + idle_debug ("idle_response_new\n"); + + idle_resp->folder = folder; + camel_object_ref (CAMEL_OBJECT (folder)); + return idle_resp; +} + +static void +idle_response_free (IdleResponse *idle_resp) +{ + idle_debug ("idle_response_free\n"); + + guint i=0; + + if (idle_resp->expunged) + g_array_free (idle_resp->expunged, TRUE); + + if (idle_resp->fetch) + for (i=0 ;i < idle_resp->fetch->len; i++) + g_slice_free (FetchIdleResponse, idle_resp->fetch->pdata[i]); + + if (idle_resp->folder) + camel_object_unref (CAMEL_OBJECT (idle_resp->folder)); + + g_slice_free (IdleResponse, idle_resp); +} + +static void +idle_real_start (CamelImapStore *store) +{ + idle_debug ("idle_real_start\n"); + + g_mutex_lock (store->stream_lock); + store->idle_prefix = g_strdup_printf ("%c%.5u", + store->tag_prefix, store->command++); + camel_stream_printf (store->ostream, "%s IDLE\r\n", + store->idle_prefix); + g_mutex_unlock (store->stream_lock); + +} + +static IdleResponse* +idle_deal_with_stuff (CamelFolder *folder, CamelImapStore *store, gboolean *had_err, gboolean *had_lock) +{ + IdleResponse *idle_resp = NULL; + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + char *resp = NULL; + int nwritten; + CamelImapResponseType type; + gboolean hlock = FALSE; + + idle_debug ("idle_deal_with_stuff\n"); + + if (!folder || !CAMEL_IS_IMAP_FOLDER (folder)) + return NULL; + if (!store || !CAMEL_IS_IMAP_STORE (store)) + return NULL; + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex)) + return NULL; + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return NULL; + if (store->ostream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return NULL; + + hlock = CAMEL_SERVICE_REC_TRYLOCK (store, connect_lock); + + if (hlock) + { + if (store->current_folder) + { + resp = NULL; + while (camel_imap_store_readline_nb (store, &resp, &ex) > 0) + { + /* printf ("resp: %s\n", resp); */ + if (strchr (resp, '*') != NULL && (strstr (resp, "EXISTS") || + strstr (resp, "FETCH")|| strstr (resp, "EXPUNGE") || + strstr (resp, "RECENT"))) + { + if (!idle_resp) + idle_resp = idle_response_new (folder); + read_idle_response (folder, resp, idle_resp); + } + g_free (resp); resp=NULL; } - info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid); - if (info) { - for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) { - if (folder->summary->messages->pdata[seq] == info) - break; + if (resp) + g_free (resp); + + g_mutex_lock (store->stream_lock); + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex)) + { g_mutex_unlock (store->stream_lock); return NULL; } + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { g_mutex_unlock (store->stream_lock); return NULL; } + if (store->ostream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { g_mutex_unlock (store->stream_lock); return NULL; } + if (store->ostream && CAMEL_IS_STREAM (store->ostream)) { + idle_debug ("Sending DONE in idle_deal_with_stuff (nb)\n"); + nwritten = camel_stream_printf (store->ostream, "DONE\r\n"); + } + g_mutex_unlock (store->stream_lock); + + if (nwritten == -1) + goto outofhere; + + resp = NULL; + while ((type = camel_imap_command_response_idle (store, &resp, &ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) + { + /* printf ("D resp: %s\n", resp); */ + if (strchr (resp, '*') != NULL && (strstr (resp, "EXISTS") || + strstr (resp, "FETCH") || strstr (resp, "EXPUNGE") || + strstr (resp, "RECENT"))) + { + if (!idle_resp) + idle_resp = idle_response_new (folder); + read_idle_response (folder, resp, idle_resp); } - - g_warning("Message already present? %s", camel_message_info_uid(mi)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unexpected server response: Identical UIDs provided for messages %d and %d"), - seq + 1, i + first); - - camel_message_info_free(&info->info); - break; + g_free (resp); resp=NULL; + } + + if (type == CAMEL_IMAP_RESPONSE_ERROR) + *had_err = TRUE; + + if (resp) + g_free (resp); + + } else { + g_mutex_lock (store->stream_lock); + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex)) + { g_mutex_unlock (store->stream_lock); return NULL; } + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { g_mutex_unlock (store->stream_lock); return NULL; } + if (store->ostream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { g_mutex_unlock (store->stream_lock); return NULL; } + if (store->ostream && CAMEL_IS_STREAM (store->ostream)) { + idle_debug ("Sending DONE in idle_deal_with_stuff (b)\n"); + nwritten = camel_stream_printf (store->ostream, "DONE\r\n"); + } + g_mutex_unlock (store->stream_lock); + if (nwritten == -1) + goto outofhere; + resp = NULL; + while ((type = camel_imap_command_response_idle (store, &resp, &ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) + { g_free (resp); resp=NULL; } + if (resp) + g_free (resp); + } + +outofhere: + + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + } + + *had_lock = hlock; + + return idle_resp; +} + +void +camel_imap_folder_stop_idle (CamelFolder *folder) +{ + CamelImapStore *store; + IdleResponse *idle_resp = NULL; + gboolean had_err = FALSE; + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + + idle_debug ("camel_imap_folder_stop_idle\n"); + + if (!folder || !CAMEL_IS_IMAP_FOLDER (folder)) + return; + + store = CAMEL_IMAP_STORE (folder->parent_store); + + if (!store || !CAMEL_IS_IMAP_STORE (store)) + return; + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex)) + return; + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return; + if (store->ostream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return; + + g_static_rec_mutex_lock (((CamelImapFolder *)folder)->idle_lock); + + if ((store->capabilities & IMAP_CAPABILITY_IDLE) && store->idle_prefix) + { + gboolean had_lock = FALSE; + g_free (store->idle_prefix); + store->idle_prefix = NULL; + + if (store->idle_signal > 0) + g_source_remove (store->idle_signal); + + idle_resp = idle_deal_with_stuff (folder, store, &had_err, &had_lock); + + /* Outside of the lock of course */ + if (idle_resp && !had_err) + process_idle_response (idle_resp); + + /* idle_real_start (store); */ + + if (idle_resp) + idle_response_free (idle_resp); + } + + g_static_rec_mutex_unlock (((CamelImapFolder *)folder)->idle_lock); +} + +static void +idle_timeout_checker_destroy (gpointer data) +{ + idle_debug ("idle_timeout_checker_destroy\n"); + + return; +} + +static gboolean +idle_timeout_checker (gpointer data) +{ + CamelFolder *folder = (CamelFolder *) data; + CamelImapFolder *imap_folder; + CamelImapStore *store; + gboolean had_err = FALSE, hadlock = FALSE; + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + + ((CamelImapFolder *)folder)->in_idle = TRUE; + + idle_debug ("idle_timeout_checker\n"); + + if ((!folder) || ((((CamelObject *)data)->ref_count <= 0) && (!CAMEL_IS_IMAP_FOLDER (folder)))) + return FALSE; + + store = CAMEL_IMAP_STORE (folder->parent_store); + if (!(store->capabilities & IMAP_CAPABILITY_IDLE)) + return FALSE; + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex)) + return FALSE; + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return FALSE; + if (store->ostream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return FALSE; + + g_static_rec_mutex_lock (((CamelImapFolder *)folder)->idle_lock); + + + imap_folder = CAMEL_IMAP_FOLDER (folder); + if (!imap_folder->do_push_email) + { + g_static_rec_mutex_unlock (((CamelImapFolder *)folder)->idle_lock); + return FALSE; + } + + if (store->idle_prefix != NULL) + { + gboolean had_lock = FALSE; + IdleResponse *idle_resp = idle_deal_with_stuff (folder, store, &had_err,&hadlock); + + if (idle_resp && !had_err) + process_idle_response (idle_resp); + + if (hadlock) + idle_real_start (store); + + if (idle_resp) + idle_response_free (idle_resp); + } + + g_static_rec_mutex_unlock (((CamelImapFolder *)folder)->idle_lock); + + if (((CamelImapFolder *)folder)->stopping) + { + g_static_rec_mutex_free (((CamelImapFolder *)folder)->idle_lock); + ((CamelImapFolder *)folder)->idle_lock = NULL; + ((CamelImapFolder *)folder)->in_idle = FALSE; + return FALSE; + } + + ((CamelImapFolder *)folder)->in_idle = FALSE; + + return TRUE; +} + + +void +camel_imap_folder_start_idle (CamelFolder *folder) +{ + CamelImapStore *store; + CamelImapFolder *imap_folder = (CamelImapFolder *) folder; + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + + idle_debug ("camel_imap_folder_start_idle\n"); + + if (!folder || !CAMEL_IS_IMAP_FOLDER (folder)) + return; + + store = CAMEL_IMAP_STORE (folder->parent_store); + if (!store || !CAMEL_IS_IMAP_STORE (store)) + return; + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex)) + return; + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return; + if (store->ostream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + return; + + g_static_rec_mutex_lock (((CamelImapFolder *)folder)->idle_lock); + + if (store->capabilities & IMAP_CAPABILITY_IDLE) + { + if (store->current_folder && !store->idle_prefix) + { + folder->folder_flags |= CAMEL_FOLDER_HAS_PUSHEMAIL_CAPABILITY; + + idle_real_start (store); + + store->idle_signal = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 5 * 1000, + idle_timeout_checker, folder, idle_timeout_checker_destroy); + + imap_folder->idle_signal = store->idle_signal; } - - camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi); - camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); - - if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT)) - camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi)); } - for ( ; i < messages->len; i++) { - if ((mi = messages->pdata[i])) - camel_message_info_free(&mi->info); - } - - g_ptr_array_free (messages, TRUE); - - return; - - lose: - if (fetch_data) { - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - g_datalist_clear (&data); - } - g_ptr_array_free (fetch_data, TRUE); + g_static_rec_mutex_unlock (((CamelImapFolder *)folder)->idle_lock); + +} + + +static void +imap_set_push_email (CamelFolder *folder, gboolean setting) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + + if (imap_folder->do_push_email && !setting) { + imap_folder->do_push_email = setting; + camel_imap_folder_stop_idle (folder); } - if (messages) { - for (i = 0; i < messages->len; i++) { - if (messages->pdata[i]) - camel_message_info_free(messages->pdata[i]); - } - g_ptr_array_free (messages, TRUE); + + if (!imap_folder->do_push_email && setting) { + imap_folder->do_push_email = setting; + camel_imap_folder_start_idle (folder); } -} + return; +} /* Called with the store's connect_lock locked */ void camel_imap_folder_changed (CamelFolder *folder, int exists, @@ -2643,9 +3714,11 @@ if (expunged) { int i, id; - for (i = 0; i < expunged->len; i++) { + for (i = 0; i < expunged->len; i++) + { id = g_array_index (expunged, int, i); info = camel_folder_summary_index (folder->summary, id - 1); + if (info == NULL) { /* FIXME: danw: does this mean that the summary is corrupt? */ /* I guess a message that we never retrieved got expunged? */ @@ -2653,9 +3726,71 @@ } camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); + + CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); + camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info)); + CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); + + ((CamelMessageInfoBase *)info)->flags |= CAMEL_MESSAGE_EXPUNGED; + + camel_folder_summary_remove (folder->summary, info); + camel_message_info_free(info); + } + } + + len = camel_folder_summary_count (folder->summary); + + if (exists > len) { + camel_imap_folder_stop_idle (folder); + imap_update_summary (folder, exists, changes, ex); + /* camel_imap_folder_start_idle (folder); will happen later? */ + } + + if (camel_folder_change_info_changed (changes)) + camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes); + + camel_folder_change_info_free (changes); + camel_folder_summary_save (folder->summary); +} + + +static void +camel_imap_folder_changed_for_idle (CamelFolder *folder, int exists, + GArray *expunged, CamelException *ex) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + CamelFolderChangeInfo *changes; + CamelMessageInfo *info; + int len; + + /* printf ("FOR IDLE: %d vs %d\n", exists, camel_folder_summary_count (folder->summary)); */ + + changes = camel_folder_change_info_new (); + if (expunged) { + int i, id; + + for (i = 0; i < expunged->len; i++) + { + const char *uid; + + id = g_array_index (expunged, int, i); + info = camel_folder_summary_index (folder->summary, id - 1); + + if (info == NULL) { + /* FIXME: danw: does this mean that the summary is corrupt? */ + /* I guess a message that we never retrieved got expunged? */ + continue; + } + + uid = camel_message_info_uid (info); + camel_folder_change_info_remove_uid (changes, uid); + CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info)); CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); + + ((CamelMessageInfoBase *)info)->flags |= CAMEL_MESSAGE_EXPUNGED; + camel_folder_summary_remove (folder->summary, info); camel_message_info_free(info); } @@ -2688,95 +3823,554 @@ } } +static void +handle_freeup (CamelImapStore *store, gint nread, CamelException *ex) +{ + if (nread <= 0) + { + if (errno == EINTR) + camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); + else + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Server unexpectedly disconnected: %s"), + g_strerror (errno)); + + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + } +} + CamelStream * camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid, const char *section_text, gboolean cache_only, - CamelException *ex) + CamelFolderReceiveType type, gint param, CamelException *ex) { CamelFolder *folder = CAMEL_FOLDER (imap_folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - CamelStream *stream; - GData *fetch_data; - char *found_uid; - int i; - - /* EXPUNGE responses have to modify the cache, which means - * they have to grab the cache_lock while holding the - * connect_lock. - - * Because getting the service lock may cause MUCH unecessary - * delay when we already have the data locally, we do the - * locking separately. This could cause a race - * getting the same data from the cache, but that is only - * an inefficiency, and bad luck. - */ + CamelImapStore *store = NULL; + CamelStream *stream = NULL; + gboolean connected = FALSE, idle_rt = FALSE; + CamelException tex = CAMEL_EXCEPTION_INITIALISER; + ssize_t nread = 0; gboolean amcon = FALSE; + CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); - stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex); - if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) { - camel_exception_clear (ex); - stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex); + + connected = camel_disco_store_check_online(CAMEL_DISCO_STORE (folder->parent_store), &tex); + + if (connected && ((type & CAMEL_FOLDER_RECEIVE_FULL) && camel_imap_message_cache_is_partial (imap_folder->cache, uid))) + camel_imap_message_cache_remove (imap_folder->cache, uid); + else if (connected && ((type & CAMEL_FOLDER_RECEIVE_PARTIAL || type & CAMEL_FOLDER_RECEIVE_SIZE_LIMITED) + && !camel_imap_message_cache_is_partial (imap_folder->cache, uid))) + camel_imap_message_cache_remove (imap_folder->cache, uid); + else + { + stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex); + if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) + { + camel_exception_clear (ex); + stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex); + } } CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); - + if (stream || cache_only) return stream; - camel_exception_clear(ex); - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); - - if (!camel_imap_store_connected(store, ex)) { + if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (folder->parent_store), ex)) + { camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("This message is not currently available")); CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return NULL; } - camel_exception_clear (ex); - if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) { - response = camel_imap_command (store, folder, ex, - "UID FETCH %s RFC822.PEEK", - uid); - } else { - response = camel_imap_command (store, folder, ex, - "UID FETCH %s BODY.PEEK[%s]", - uid, section_text); + + store = CAMEL_IMAP_STORE (camel_object_new (CAMEL_IMAP_STORE_TYPE)); + + camel_service_construct (CAMEL_SERVICE (store), + camel_service_get_session (CAMEL_SERVICE (folder->parent_store)), + camel_service_get_provider (CAMEL_SERVICE (folder->parent_store)), + CAMEL_SERVICE (folder->parent_store)->url, ex); + + if (camel_exception_is_set (ex)) + { + g_critical ("Severe interal error while trying to construct a new connection\n"); + camel_object_unref (store); + return NULL; } - /* We won't need the connect_lock again after this. */ - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - if (!response) { + + camel_operation_start (NULL, _("Preparing to get message")); + + amcon = camel_service_connect (CAMEL_SERVICE (store), ex); + + if (!amcon || camel_exception_is_set (ex) || !camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) + { + camel_object_unref (store); + camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("This message is not currently available" + " (can't let a new connection go online)")); CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); return NULL; } - - for (i = 0; i < response->untagged->len; i++) { - fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]); - found_uid = g_datalist_get_data (&fetch_data, "UID"); - stream = g_datalist_get_data (&fetch_data, "BODY_PART_STREAM"); - if (found_uid && stream && !strcmp (uid, found_uid)) - break; - - g_datalist_clear (&fetch_data); - stream = NULL; + camel_exception_clear (ex); + + camel_operation_end (NULL); + + camel_operation_start (NULL, _("Retrieving message")); + + CAMEL_SERVICE_REC_LOCK(store, connect_lock); + + CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); + + if (type & CAMEL_FOLDER_RECEIVE_FULL) + stream = camel_imap_message_cache_insert (imap_folder->cache, + uid, section_text, "", 0, NULL); + else /* CAMEL_FOLDER_RECEIVE_PARTIAL, CAMEL_FOLDER_RECEIVE_SIZE_LIMITED or any */ + stream = camel_imap_message_cache_insert (imap_folder->cache, + uid, "", "", 0, NULL); + + if (stream == NULL) + stream = camel_stream_mem_new (); + + if (type & CAMEL_FOLDER_RECEIVE_FULL) + { + camel_imap_message_cache_set_partial (imap_folder->cache, uid, FALSE); + + if (store->capabilities & IMAP_CAPABILITY_BINARY) + { + gchar line[MAX_LINE_LEN]; + gboolean err = FALSE; + char two_bytes[2]; + char t_str [1024]; + int f = 0; + ssize_t hread = 1; + gint length=0, rec=0; + char *pos, *ppos; + + nread = 1; + + /* Stops idle */ + camel_imap_command_start (store, folder, ex, + "UID FETCH %s BINARY.PEEK[%s]", uid, section_text); + + g_mutex_lock (store->stream_lock); + + two_bytes [0] = ' '; + + /* a01 uid fetch 1 BINARY.PEEK[] + * * 1 FETCH (UID 1 BINARY[] {24693}\r\n + * Subject: Testing.... + * )\r\n + * a01 OK .... \r\n */ + + /* Read the length in the "\*.*[~|]{}" */ + while (two_bytes[0] != '\n' && f < 1023 && nread > 0) + { + nread = camel_stream_read (store->ostream, two_bytes, 1); + line [f] = two_bytes [0]; +/* printf ("%c%c", two_bytes[0], two_bytes[1]); */ + f++; + } + line[f] = '\0'; +/* printf ("\n"); */ + + /* The first line is very unlikely going to consume 1023 bytes */ + if (f > 1023 || nread <= 0) { + g_warning ("BINARY: Long first line, UID=%s", uid); + goto berrorhander; + } + + /* If the line doesn't start with "* " */ + if (*line != '*' || *(line + 1) != ' ') + { err = TRUE; g_warning ("BINARY: Line doesn't start with \"* \", UID=%s (%s)", uid, line); goto berrorhander; } + pos = strchr (line, '{'); + + /* If we don't find a '{' character */ + if (!pos) + { err = TRUE; g_warning ("BINARY: Line doesn't contain a {, UID=%s (%s)", uid, line); goto berrorhander; } + + /* Set the '}' character to \0 */ + ppos = strchr (pos, '}'); + if (ppos) + *ppos = '\0'; + else /* If we didn't find it */ + { err = TRUE; g_warning ("BINARY: Line doesn't contain a }, UID=%s (%s)", uid, line); goto berrorhander; } + + length = strtol (pos + 1, NULL, 10); + + /* If strtol failed (it's important enough to check this) */ + if (errno == ERANGE) + { err = TRUE; g_warning ("BINARY: strtol failed, UID=%s (%s)", uid, line); goto berrorhander; } + + /* Until we have reached the length, read 1024 at the time */ + while (hread > 0 && rec < length) + { + int wread = (length - rec); + if (wread < 1 || wread > 1024) + wread = 1024; + hread = camel_stream_read (store->ostream, t_str, wread); + if (hread > 0) + { + /* And write them too */ + camel_stream_write (stream, t_str, hread); + rec += hread; + camel_operation_progress (NULL, rec, length); + } else { + if (hread != 0) { + g_warning ("BINARY: read failed, UID=%s", uid); + err = TRUE; + goto berrorhander; + } + } + } + + + camel_stream_reset (stream); + + /* Read away the last two lines */ + for (f = 0; f < 2; f++) { + nread = 1; two_bytes[0] = 'x'; + while (two_bytes[0] != '\n' && nread > 0) + nread = camel_stream_read (store->ostream, two_bytes, 1); + } +berrorhander: + g_mutex_unlock (store->stream_lock); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + /* Starts idle */ + camel_imap_folder_start_idle ((CamelFolder *) imap_folder); + idle_rt = TRUE; + + if (err) + goto errorhander; + } else + { + gboolean err=FALSE; + gchar line [MAX_LINE_LEN]; + guint linenum = 0; + CamelStreamBuffer *server_stream; + gchar *tag; + guint taglen; + gboolean isnextdone = FALSE, hadr = FALSE; + guint tread = 0, exread = 0; + + nread = 0; + + /* Stops idle */ + if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) + camel_imap_command_start (store, folder, ex, + "UID FETCH %s RFC822.PEEK", uid); + else + camel_imap_command_start (store, folder, ex, + "UID FETCH %s BODY.PEEK[%s]", uid, section_text); + + tag = g_strdup_printf ("%c%.5u", store->tag_prefix, store->command-1); + taglen = strlen (tag); + + g_mutex_lock (store->stream_lock); + server_stream = (CamelStreamBuffer*) store->istream; + + if (!server_stream) + err = TRUE; + else + store->command++; + + if (server_stream) + while ((nread = camel_stream_buffer_gets (server_stream, line, MAX_LINE_LEN) > 0)) + { + gint llen = 0; + + /* It might be the line before the last line + * TNY TODO: why no check for (linenum != 0) then ? */ + + if (line[0] == ')' && (line[1] == '\n' || (line[1] == '\r' && line[2] == '\n'))) + { + if (line[1] == '\r') + hadr = TRUE; + isnextdone = TRUE; + continue; + } + + /* It's the first line */ + if (linenum == 0 && (line [0] != '*' || line[1] != ' ')) + { err=TRUE; break; } + else if (linenum == 0) + { + char *pos, *ppos; + pos = strchr (line, '{'); + if (pos) { + ppos = strchr (pos, '}'); + if (ppos) { + *ppos = '\0'; + exread = strtol (pos + 1, NULL, 10); + } + } + linenum++; + continue; + } + + /* It's the last line (isnextdone will be ignored if that is the case) */ + if (!strncmp (line, tag, taglen)) + break; + + camel_seekable_stream_seek (CAMEL_SEEKABLE_STREAM (stream), 0, CAMEL_STREAM_END); + + if (isnextdone) + { + if (hadr) + camel_stream_write (stream, ")\n", 2); + else + camel_stream_write (stream, ")\r\n", 3); + + hadr = FALSE; + isnextdone = FALSE; + } + + llen = strlen (line); + camel_stream_write (stream, line, llen); + linenum++; + tread += llen; + + camel_operation_progress (NULL, tread, exread); + + memset (line, 0, MAX_LINE_LEN); + } + + g_mutex_unlock (store->stream_lock); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + /* Starts idle */ + camel_imap_folder_start_idle ((CamelFolder *) imap_folder); + idle_rt = TRUE; + + if (nread <= 0) + err = TRUE; + + if (tag) + g_free (tag); + + if (err) + goto errorhander; + + camel_stream_reset (stream); + + } /* NON-BINARY */ + + } else + { + + /* Partial message retrieval feature gets the message like this: + { HEADER boundary 1.HEADER 1 boundary } */ + + char *boundary = NULL; + int t = 0, boundary_len = 0; + const gchar *infos[2] = { "HEADER", /*"1.HEADER",*/ "1" }; + + camel_imap_message_cache_set_partial (imap_folder->cache, uid, TRUE); + + for (t=0; t < 2; t++) + { + gboolean err=FALSE; + gchar line[MAX_LINE_LEN]; + guint linenum = 0; + CamelStreamBuffer *server_stream; + gchar *tag; + guint taglen; + gboolean isnextdone = FALSE; + guint tread = 0, exread = 0; + + nread = 0; + + /* Stops idle */ + camel_imap_command_start (store, folder, ex, + "UID FETCH %s BODY.PEEK[%s]", uid, infos[t]); + + tag = g_strdup_printf ("%c%.5u", store->tag_prefix, store->command-1); + taglen = strlen (tag); + + g_mutex_lock (store->stream_lock); + + if (!store->istream || ((CamelObject *)store->istream)->ref_count <= 0) + { + err = TRUE; + nread = -1; + goto rerrorhandler; + } + + if (!store->ostream || ((CamelObject *)store->ostream)->ref_count <= 0) + { + err = TRUE; + nread = -1; + goto rerrorhandler; + } + + if (camel_imap_store_restore_stream_buffer (store)) + server_stream = store->istream ? CAMEL_STREAM_BUFFER (store->istream) : NULL; + else server_stream = NULL; + + if (server_stream == NULL) + err = TRUE; + else + store->command++; + + if (server_stream) + while ((nread = camel_stream_buffer_gets (server_stream, line, MAX_LINE_LEN) > 0)) + { + gint llen = 0; + + /* It might be the line before the last line */ + if (line[0] == ')' && (line[1] == '\n' || (line[1] == '\r' && line[2] == '\n'))) + { isnextdone = TRUE; continue; } + + /* It's the first line */ + if (linenum == 0 && (line [0] != '*' || line[1] != ' ')) + { err=TRUE; break; } + else if (linenum == 0) + { + char *pos, *ppos; + pos = strchr (line, '{'); + if (pos) { + ppos = strchr (pos, '}'); + if (ppos) { + *ppos = '\0'; + exread = strtol (pos + 1, NULL, 10); + } + } + linenum++; + continue; + } + + + /* It's the last line */ + if (!strncmp (line, tag, taglen)) + { + if ((t == 0 || t == 1 /* 2 */) && boundary_len > 0) + { + camel_seekable_stream_seek (CAMEL_SEEKABLE_STREAM (stream), 0, CAMEL_STREAM_END); + camel_stream_write (stream, "\n--", 3); + camel_stream_write (stream, boundary, boundary_len); + camel_stream_write (stream, "\n", 1); + } + break; + } + + if (t == 0 && boundary_len == 0 && !boundary) + { + CamelContentType *ct = NULL; + const char *bound=NULL; + char *pstr = (char*)strcasestr (line, "Content-Type:"); + + /* If it's the Content-Type line (TODO: use BODYSTRUCTURE for this) */ + + if (pstr) + { + pstr = strchr (pstr, ':'); + if (pstr) + { + pstr++; + ct = camel_content_type_decode(pstr); + } + } + + if (ct) + { + bound = camel_content_type_param(ct, "boundary"); + if (bound) + { + boundary_len = strlen (bound); + if (boundary_len > 0) + boundary = g_strdup (bound); + else + boundary_len = 0; + } + } + } + + camel_seekable_stream_seek (CAMEL_SEEKABLE_STREAM (stream), 0, CAMEL_STREAM_END); + + if (isnextdone) + { + camel_stream_write (stream, ")\n", 2); + isnextdone = FALSE; + } + + llen = strlen (line); + camel_stream_write (stream, line, llen); + + tread += llen; + camel_operation_progress (NULL, tread, exread); + + linenum++; + memset (line, 0, MAX_LINE_LEN); + } +rerrorhandler: + g_mutex_unlock (store->stream_lock); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + /* Starts idle */ + camel_imap_store_start_idle (store); + idle_rt = TRUE; + + if (nread <= 0) + err = TRUE; + + if (tag) + g_free (tag); + + if (err) + { + if (boundary_len > 0) + g_free (boundary); + goto errorhander; + } + } + + if (boundary_len > 0) + g_free (boundary); + + camel_stream_reset (stream); } - camel_imap_response_free (store, response); + CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); - if (!stream) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not find message body in FETCH response.")); - } else { - camel_object_ref (CAMEL_OBJECT (stream)); - g_datalist_clear (&fetch_data); - } - + + CAMEL_SERVICE_REC_UNLOCK(store, connect_lock); + + camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL); + camel_object_unref (CAMEL_OBJECT (store)); + + camel_operation_end (NULL); + return stream; + +errorhander: + + if (!idle_rt) + camel_imap_folder_start_idle ((CamelFolder *) imap_folder); + + CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); + camel_imap_message_cache_remove (imap_folder->cache, uid); + + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Could not find message body in FETCH response.")); + + handle_freeup (store, nread, ex); + + if (stream && ((CamelObject *)stream)->ref_count > 0) + camel_object_unref (CAMEL_OBJECT (stream)); + + if (store) + { + + CAMEL_SERVICE_REC_UNLOCK(store, connect_lock); + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + camel_object_unref (CAMEL_OBJECT (store)); + } + + camel_operation_end (NULL); + + return NULL; } + + + + static GData * parse_fetch_response (CamelImapFolder *imap_folder, char *response) { @@ -2784,7 +4378,7 @@ char *start, *part_spec = NULL, *body = NULL, *uid = NULL, *idate = NULL; gboolean cache_header = TRUE, header = FALSE; size_t body_len = 0; - + if (*response != '(') { long seq; @@ -2886,6 +4480,13 @@ g_datalist_set_data_full (&data, "INTERNALDATE", idate, g_free); response += len + 1; } + } else if (!g_ascii_strncasecmp (response, "MODSEQ ", 7)) { + char *marker = strchr (response + 7, ')'); + if (marker) + response = marker + 1; + + if (!marker) + g_warning ("Unexpected MODSEQ format: %s", response); } else { g_warning ("Unexpected FETCH response from server: (%s", response); break; Only in ./providers/imap: camel-imap-folder.c.rej diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-folder.h ./providers/imap/camel-imap-folder.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-folder.h 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-folder.h 2007-05-12 10:01:04.000000000 +0200 @@ -41,7 +41,7 @@ struct _CamelImapFolder { CamelDiscoFolder parent_object; - struct _CamelImapFolderPrivate *priv; + struct _CamelImapFolderPrivate *priv; CamelFolderSearch *search; CamelImapMessageCache *cache; @@ -49,12 +49,16 @@ unsigned int need_rescan:1; unsigned int need_refresh:1; unsigned int read_only:1; + gchar *folder_dir; + gboolean do_push_email, stopping, in_idle; + guint idle_signal; + GStaticRecMutex *idle_lock; }; typedef struct { CamelDiscoFolderClass parent_class; - /* Virtual methods */ + /* Virtual methods */ } CamelImapFolderClass; @@ -67,7 +71,7 @@ void camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, - CamelException *ex); + CamelException *ex, gboolean idle); void camel_imap_folder_changed (CamelFolder *folder, int exists, GArray *expunged, CamelException *ex); @@ -76,11 +80,17 @@ const char *uid, const char *section_text, gboolean cache_only, - CamelException *ex); + CamelFolderReceiveType type, gint param, CamelException *ex); + +time_t decode_internaldate (const unsigned char *in); /* Standard Camel function */ CamelType camel_imap_folder_get_type (void); +void camel_imap_folder_stop_idle (CamelFolder *folder); +void camel_imap_folder_start_idle (CamelFolder *folder); + + G_END_DECLS #endif /* CAMEL_IMAP_FOLDER_H */ Only in ./providers/imap: camel-imap-folder.lo Only in ./providers/imap: camel-imap-folder.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-message-cache.c ./providers/imap/camel-imap-message-cache.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-message-cache.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-message-cache.c 2007-05-12 10:01:04.000000000 +0200 @@ -170,6 +170,9 @@ cache->parts = g_hash_table_new (g_str_hash, g_str_equal); cache->cached = g_hash_table_new (NULL, NULL); deletes = g_ptr_array_new (); + + camel_folder_summary_prepare_hash (summary); + while ((dname = g_dir_read_name (dir))) { if (!isdigit (dname[0])) continue; @@ -188,6 +191,7 @@ g_free (uid); } g_dir_close (dir); + camel_folder_summary_kill_hash (summary); while (deletes->len) { g_unlink (deletes->pdata[0]); @@ -329,6 +333,59 @@ return insert_finish (cache, uid, path, key, stream); } +void +camel_imap_message_cache_set_flags (const gchar *folder_dir, CamelMessageInfoBase *mi) +{ + char mystring [512]; + snprintf (mystring, 512, "%s/%s.", folder_dir, mi->uid); + if (g_file_test (mystring, G_FILE_TEST_IS_REGULAR)) + { + mi->flags |= CAMEL_MESSAGE_CACHED; + snprintf (mystring, 512, "%s/%s.partial", folder_dir, mi->uid); + if (g_file_test (mystring, G_FILE_TEST_IS_REGULAR)) + mi->flags |= CAMEL_MESSAGE_PARTIAL; + else + mi->flags &= ~CAMEL_MESSAGE_PARTIAL; + } else { + mi->flags &= ~CAMEL_MESSAGE_CACHED; + mi->flags &= ~CAMEL_MESSAGE_PARTIAL; + } +} + +gboolean +camel_imap_message_cache_is_partial (CamelImapMessageCache *cache, const char *uid) +{ + gchar *path = g_strdup_printf ("%s/%s.ispartial", cache->path, uid); + gboolean retval = FALSE; + + retval = g_file_test (path, G_FILE_TEST_IS_REGULAR); + + g_free (path); + + return retval; +} + +void +camel_imap_message_cache_set_partial (CamelImapMessageCache *cache, const char *uid, gboolean partial) +{ + gchar *path = g_strdup_printf ("%s/%s.ispartial", cache->path, uid); + int fd; + + if (!partial) + { + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + g_unlink (path); + } else { + if (!g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + fd = g_open (path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600); + if (fd) close (fd); + } + } + + g_free (path); +} + /** * camel_imap_message_cache_insert_stream: * @cache: the cache @@ -429,6 +486,12 @@ return stream; } + if (!g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + g_free (path); + return NULL; + } + stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0); if (stream) { cache_put (cache, uid, key, stream); diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-message-cache.h ./providers/imap/camel-imap-message-cache.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-message-cache.h 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-message-cache.h 2007-05-12 10:01:04.000000000 +0200 @@ -86,6 +86,12 @@ const char *part_spec, CamelException *ex); +gboolean camel_imap_message_cache_is_partial (CamelImapMessageCache *cache, + const char *uid); + +void camel_imap_message_cache_set_partial (CamelImapMessageCache *cache, + const char *uid, gboolean partial); + void camel_imap_message_cache_remove (CamelImapMessageCache *cache, const char *uid); @@ -97,6 +103,9 @@ const char *dest_uid, CamelException *ex); +void camel_imap_message_cache_set_flags (const gchar *folder_dir, CamelMessageInfoBase *mi); + + /* Standard Camel function */ CamelType camel_imap_message_cache_get_type (void); Only in ./providers/imap: camel-imap-message-cache.lo Only in ./providers/imap: camel-imap-message-cache.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-provider.c ./providers/imap/camel-imap-provider.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-provider.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-provider.c 2007-05-12 10:01:04.000000000 +0200 @@ -87,7 +87,7 @@ CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, + /* CAMEL_URL_NEED_USER | */ CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, imap_conf_entries, Only in ./providers/imap: camel-imap-provider.lo Only in ./providers/imap: camel-imap-provider.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-search.c ./providers/imap/camel-imap-search.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-search.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-search.c 2007-05-12 10:01:03.000000000 +0200 @@ -185,11 +185,11 @@ md5_init(&ctx); for (i=0;itype == ESEXP_RES_STRING) - md5_update(&ctx, argv[i]->value.string, strlen(argv[i]->value.string)); + md5_update(&ctx, (const guchar *) argv[i]->value.string, strlen(argv[i]->value.string)); } md5_final(&ctx, digest); - camel_base64_encode_close(digest, 12, FALSE, hash, &state, &save); + camel_base64_encode_close(digest, 12, FALSE, (unsigned char *) hash, (int *) &state, (int *) &save); for (i=0;i<16;i++) { if (hash[i] == '+') @@ -328,7 +328,7 @@ /* TODO: Handle multiple search terms */ /* This handles multiple search words within a single term */ - words = camel_search_words_split (mr->terms[0]); + words = camel_search_words_split ((const unsigned char *) mr->terms[0]); search = g_string_new (""); g_string_append_printf (search, "UID %d:%d", mr->lastuid + 1, is->lastuid); for (i = 0; i < words->len; i++) { Only in ./providers/imap: camel-imap-search.lo Only in ./providers/imap: camel-imap-search.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-store.c ./providers/imap/camel-imap-store.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-store.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-store.c 2007-05-12 10:00:49.000000000 +0200 @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #include "camel/camel-debug.h" #include "camel/camel-disco-diary.h" @@ -49,6 +52,8 @@ #include "camel/camel-stream-fs.h" #include "camel/camel-stream-process.h" #include "camel/camel-stream.h" +#include "camel/camel-stream-mem.h" +#include "camel/camel-mime-message.h" #include "camel/camel-string-utils.h" #include "camel/camel-tcp-stream-raw.h" #include "camel/camel-tcp-stream-ssl.h" @@ -63,6 +68,10 @@ #include "camel-imap-summary.h" #include "camel-imap-utils.h" +#if !GLIB_CHECK_VERSION (2, 8, 0) +#define g_access access +#endif + #define d(x) /* Specified in RFC 2060 */ @@ -128,6 +137,40 @@ static void imap_forget_folder(CamelImapStore *imap_store, const char *folder_name, CamelException *ex); static void imap_set_server_level (CamelImapStore *store); +static GPtrArray* imap_get_recent_messages (CamelStore *store, const char *folder_name, int *unseen, int *messages); + +static void let_idle_die (CamelImapStore *imap_store) +{ + if (imap_store->idle_signal > 0) + g_source_remove (imap_store->idle_signal); + + if (imap_store->idle_prefix) + { + g_free (imap_store->idle_prefix); + imap_store->idle_prefix=NULL; + g_mutex_lock (imap_store->stream_lock); + idle_debug ("Sending DONE in let_idle_die\n"); + camel_stream_printf (imap_store->ostream, "DONE\r\n"); + g_mutex_unlock (imap_store->stream_lock); + } + +} + +void +camel_imap_store_stop_idle (CamelImapStore *store) +{ + if (store->current_folder && CAMEL_IS_IMAP_FOLDER (store->current_folder)) + camel_imap_folder_stop_idle (store->current_folder); +} + + +void +camel_imap_store_start_idle (CamelImapStore *store) +{ + if (store->current_folder && CAMEL_IS_IMAP_FOLDER (store->current_folder)) + camel_imap_folder_start_idle (store->current_folder); +} + static void camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class) { @@ -162,7 +205,8 @@ camel_store_class->noop = imap_noop; camel_store_class->get_trash = imap_get_trash; camel_store_class->get_junk = imap_get_junk; - + camel_store_class->get_recent_messages = imap_get_recent_messages; + camel_disco_store_class->can_work_offline = can_work_offline; camel_disco_store_class->connect_online = imap_connect_online; camel_disco_store_class->connect_offline = imap_connect_offline; @@ -189,6 +233,8 @@ CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); CamelDiscoStore *disco = CAMEL_DISCO_STORE (object); + let_idle_die (imap_store); + /* This frees current_folder, folders, authtypes, streams, and namespace. */ camel_service_disconnect((CamelService *)imap_store, TRUE, NULL); @@ -207,18 +253,24 @@ disco->diary = NULL; } - if (imap_store->custom_headers) - g_free (imap_store->custom_headers); + + g_mutex_free (imap_store->stream_lock); + } static void camel_imap_store_init (gpointer object, gpointer klass) { CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); - + + imap_store->dontdistridlehack = FALSE; + imap_store->idle_signal = 0; + imap_store->idle_prefix = NULL; imap_store->istream = NULL; imap_store->ostream = NULL; - + imap_store->stream_lock = g_mutex_new (); + imap_store->has_login = FALSE; + imap_store->dir_sep = '\0'; imap_store->current_folder = NULL; imap_store->connected = FALSE; @@ -293,17 +345,6 @@ if (camel_url_get_param (url, "filter_junk_inbox")) imap_store->parameters |= IMAP_PARAM_FILTER_JUNK_INBOX; - imap_store->headers = IMAP_FETCH_MAILING_LIST_HEADERS; - if (camel_url_get_param (url, "all_headers")) - imap_store->headers = IMAP_FETCH_ALL_HEADERS; - else if (camel_url_get_param (url, "basic_headers")) - imap_store->headers = IMAP_FETCH_MINIMAL_HEADERS; - - if (camel_url_get_param (url, "imap_custom_headers")) { - imap_store->custom_headers = g_strdup(camel_url_get_param (url, "imap_custom_headers")); - } - - /* setup journal*/ path = g_strdup_printf ("%s/journal", imap_store->storage_path); disco_store->diary = camel_disco_diary_new (disco_store, path, ex); @@ -335,6 +376,8 @@ } } + + static int imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args) { @@ -484,6 +527,9 @@ { "XGWEXTENSIONS", IMAP_CAPABILITY_XGWEXTENSIONS }, { "XGWMOVE", IMAP_CAPABILITY_XGWMOVE }, { "LOGINDISABLED", IMAP_CAPABILITY_LOGINDISABLED }, + { "CONDSTORE", IMAP_CAPABILITY_CONDSTORE }, + { "IDLE", IMAP_CAPABILITY_IDLE }, + { "BINARY", IMAP_CAPABILITY_BINARY }, { NULL, 0 } }; @@ -560,9 +606,37 @@ #ifdef HAVE_SSL #define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) +#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) #endif +gboolean +camel_imap_store_restore_stream_buffer (CamelImapStore *store) +{ + if (store->istream == NULL || !CAMEL_IS_STREAM_BUFFER (store->istream)) + { + if (store->ostream && CAMEL_IS_STREAM (store->ostream)) + { + /* This is a recoverable situation. It's strange though */ + store->istream = camel_stream_buffer_new (store->ostream, CAMEL_STREAM_BUFFER_READ); + } else { + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + g_mutex_unlock (store->stream_lock); + camel_operation_uncancel (NULL); + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, &ex); + camel_exception_clear (&ex); + g_warning ("Something terrible happened with your connection.\nTrying to recover. (%s)\n", + g_strerror (errno)); + camel_service_connect (CAMEL_SERVICE (store), &ex); + if (camel_exception_is_set (&ex)) + g_warning ("Connection recovery failed: %s", + camel_exception_get_description (&ex)); + g_mutex_lock (store->stream_lock); + return FALSE; + } + } + return TRUE; +} + static gboolean connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, CamelException *ex) { @@ -573,8 +647,10 @@ gboolean force_imap4 = FALSE; gboolean clean_quit = TRUE; char *buf; - + gboolean not_ssl = TRUE; + if (ssl_mode != MODE_CLEAR) { + not_ssl = FALSE; #ifdef HAVE_SSL if (ssl_mode == MODE_TLS) { tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); @@ -606,10 +682,12 @@ return FALSE; } - + + g_mutex_lock (store->stream_lock); store->ostream = tcp_stream; store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ); - + g_mutex_unlock (store->stream_lock); + store->connected = TRUE; store->preauthed = FALSE; store->command = 0; @@ -625,7 +703,10 @@ camel_tcp_stream_setsockopt((CamelTcpStream *)tcp_stream, &sockopt); /* Read the greeting, if any, and deal with PREAUTH */ - if (camel_imap_store_readline (store, &buf, ex) < 0) { + if (camel_imap_store_readline (store, &buf, ex) < 0) + { + + g_mutex_lock (store->stream_lock); if (store->istream) { camel_object_unref (store->istream); store->istream = NULL; @@ -635,7 +716,8 @@ camel_object_unref (store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; return FALSE; @@ -672,10 +754,20 @@ force_imap4 = TRUE; } + + /* Tinymail hack: always use IMAP4, not IMAP4rev1 (sorry) */ + + /* force_imap4 = TRUE; */ + store->braindamaged = TRUE; + + /* end of hack :) */ + g_free (buf); /* get the imap server capabilities */ - if (!imap_get_capability (service, ex)) { + if (!imap_get_capability (service, ex)) + { + g_mutex_lock (store->stream_lock); if (store->istream) { camel_object_unref (store->istream); store->istream = NULL; @@ -685,7 +777,8 @@ camel_object_unref (store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; return FALSE; } @@ -695,9 +788,12 @@ store->server_level = IMAP_LEVEL_IMAP4; } - if (ssl_mode != MODE_TLS) { + if (not_ssl || ssl_mode != MODE_TLS) { + /* we're done */ + return TRUE; + } #ifdef HAVE_SSL @@ -713,10 +809,15 @@ clean_quit = FALSE; response = camel_imap_command (store, NULL, ex, "STARTTLS"); - if (!response) { + if (!response) + { + g_mutex_lock (store->stream_lock); camel_object_unref (store->istream); camel_object_unref (store->ostream); - store->istream = store->ostream = NULL; + store->istream = NULL; + store->ostream = NULL; + g_mutex_unlock (store->stream_lock); + return FALSE; } @@ -738,7 +839,10 @@ /* rfc2595, section 4 states that after a successful STLS command, the client MUST discard prior CAPA responses */ - if (!imap_get_capability (service, ex)) { + if (!imap_get_capability (service, ex)) + { + + g_mutex_lock (store->stream_lock); if (store->istream) { camel_object_unref (store->istream); store->istream = NULL; @@ -748,7 +852,8 @@ camel_object_unref (store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; return FALSE; @@ -771,7 +876,8 @@ if (response) camel_imap_response_free_without_processing (store, response); } - + + g_mutex_lock (store->stream_lock); if (store->istream) { camel_object_unref (store->istream); store->istream = NULL; @@ -781,7 +887,8 @@ camel_object_unref (store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; return FALSE; @@ -887,16 +994,20 @@ return FALSE; } g_free (full_cmd); - + + g_mutex_lock (store->stream_lock); store->ostream = cmd_stream; store->istream = camel_stream_buffer_new (cmd_stream, CAMEL_STREAM_BUFFER_READ); - + g_mutex_unlock (store->stream_lock); + store->connected = TRUE; store->preauthed = FALSE; store->command = 0; /* Read the greeting, if any, and deal with PREAUTH */ - if (camel_imap_store_readline (store, &buf, ex) < 0) { + if (camel_imap_store_readline (store, &buf, ex) < 0) + { + g_mutex_lock (store->stream_lock); if (store->istream) { camel_object_unref (store->istream); store->istream = NULL; @@ -906,7 +1017,8 @@ camel_object_unref (store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; return FALSE; } @@ -915,7 +1027,9 @@ g_free (buf); /* get the imap server capabilities */ - if (!imap_get_capability (service, ex)) { + if (!imap_get_capability (service, ex)) + { + g_mutex_lock (store->stream_lock); if (store->istream) { camel_object_unref (store->istream); store->istream = NULL; @@ -925,7 +1039,8 @@ camel_object_unref (store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; return FALSE; } @@ -949,12 +1064,13 @@ { NULL, "imap", IMAP_PORT, MODE_CLEAR }, }; + static gboolean connect_to_server_wrapper (CamelService *service, CamelException *ex) { const char *ssl_mode; struct addrinfo hints, *ai; - int mode, ret, i; + int mode = -1, ret, i; char *serv; const char *port; @@ -1003,6 +1119,12 @@ return ret; } +gboolean +camel_imap_service_connect (CamelService *service, CamelException *ex) +{ + return connect_to_server_wrapper (service, ex); +} + extern CamelServiceAuthType camel_imap_password_authtype; static GList * @@ -1015,12 +1137,13 @@ if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) return NULL; - + CAMEL_SERVICE_REC_LOCK (store, connect_lock); connected = store->istream != NULL && store->connected; if (!connected) connected = connect_to_server_wrapper (service, ex); CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + if (!connected) return NULL; @@ -1046,11 +1169,9 @@ const char *name; CamelFolderInfo *fi; - fi = g_malloc0(sizeof(*fi)); - + fi = camel_folder_info_new (); fi->full_name = g_strdup(folder_name); - fi->unread = -1; - fi->total = -1; + url = camel_url_new (imap_store->base_url, NULL); g_free (url->path); @@ -1132,23 +1253,11 @@ g_free (folder_dir); goto event; } - camel_object_unref (summary); - - g_unlink (summary_file); - g_free (summary_file); - - summary_file = g_strdup_printf ("%s/summary-meta", folder_dir); - summary = camel_imap_summary_new (NULL, summary_file); - if (!summary) { - g_free (summary_file); - g_free (folder_dir); - goto event; - } cache = camel_imap_message_cache_new (folder_dir, summary, ex); if (cache) camel_imap_message_cache_clear (cache); - + camel_object_unref (cache); camel_object_unref (summary); @@ -1397,6 +1506,14 @@ if (authtype) authenticated = try_auth (store, authtype->authproto, ex); else { + + if (!service->url->passwd) + { + camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, + _("You did not enter a password.")); + return FALSE; + } + response = camel_imap_command (store, NULL, ex, "LOGIN %S %S", service->url->user, @@ -1414,9 +1531,17 @@ "to IMAP server.\n%s\n\n"), camel_exception_get_description (ex)); camel_exception_clear (ex); - } + } else + if (!imap_get_capability (service, ex)) + { + errbuf = g_strdup_printf (_("Unable to authenticate " + "to IMAP server.\n%s\n\n"), + camel_exception_get_description (ex)); + camel_exception_clear (ex); + return FALSE; + } } - + return TRUE; } @@ -1438,11 +1563,14 @@ size_t len; CamelImapStoreNamespace *ns; + let_idle_die (store); + CAMEL_SERVICE_REC_LOCK (store, connect_lock); + if (!connect_to_server_wrapper (service, ex) || !imap_auth_loop (service, ex)) { CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - camel_service_disconnect (service, TRUE, NULL); + /* camel_service_disconnect (service, TRUE, NULL); */ return FALSE; } @@ -1559,6 +1687,7 @@ done: + /* save any changes we had */ camel_store_summary_save((CamelStoreSummary *)store->summary); @@ -1566,7 +1695,9 @@ if (camel_exception_is_set (ex)) camel_service_disconnect (service, TRUE, NULL); - + else + store->has_login = TRUE; + return !camel_exception_is_set (ex); } @@ -1576,9 +1707,11 @@ CamelImapStore *store = CAMEL_IMAP_STORE (service); CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service); + let_idle_die (store); + if (!disco_store->diary) return FALSE; - + store->connected = !camel_exception_is_set (ex); return store->connected; } @@ -1588,6 +1721,9 @@ { CamelImapStore *store = CAMEL_IMAP_STORE (service); + let_idle_die (store); + + g_mutex_lock (store->stream_lock); if (store->istream) { camel_stream_close(store->istream); camel_object_unref(store->istream); @@ -1599,13 +1735,13 @@ camel_object_unref(store->ostream); store->ostream = NULL; } - + g_mutex_unlock (store->stream_lock); + store->connected = FALSE; - if (store->current_folder) { - camel_object_unref (store->current_folder); - store->current_folder = NULL; - } - + /* if (store->current_folder && CAMEL_IS_OBJECT (store->current_folder)) + camel_object_unref (store->current_folder); */ + store->current_folder = NULL; + if (store->authtypes) { g_hash_table_foreach_remove (store->authtypes, free_key, NULL); @@ -1626,7 +1762,9 @@ { CamelImapStore *store = CAMEL_IMAP_STORE (service); CamelImapResponse *response; - + + let_idle_die (store); + if (store->connected && clean) { response = camel_imap_command (store, NULL, NULL, "LOGOUT"); camel_imap_response_free (store, response); @@ -1666,11 +1804,11 @@ CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock); - if (!camel_imap_store_connected(imap_store, ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)store, ex)) goto done; current_folder = imap_store->current_folder; - if (current_folder && imap_summary_is_dirty (current_folder->summary)) { + if (current_folder && CAMEL_IS_IMAP_FOLDER (current_folder) && imap_summary_is_dirty (current_folder->summary)) { /* let's sync the flags instead. NB: must avoid folder lock */ ((CamelFolderClass *)((CamelObject *)current_folder)->klass)->sync(current_folder, FALSE, ex); } else { @@ -1762,10 +1900,12 @@ struct imap_status_item *items, *item, *tail; CamelImapResponse *response; char *status, *name, *p; - - /* FIXME: we assume the server is STATUS-capable */ - - response = camel_imap_command (imap_store, NULL, NULL, + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + + if (!(imap_store->capabilities & IMAP_CAPABILITY_STATUS)) + return NULL; + + response = camel_imap_command (imap_store, NULL, &ex, "STATUS %F (%s)", folder_name, type); @@ -1846,6 +1986,266 @@ return items; } +static void +camel_imap_store_set_status_for (CamelImapStore *imap_store, const char *folder_name, guint32 messages, guint32 unseen, guint32 uidnext) +{ + char *storage_path, *folder_dir, *filename; + FILE *file = NULL; + + storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); + folder_dir = imap_path_to_physical (storage_path, folder_name); + g_free(storage_path); + filename = g_strdup_printf ("%s/status", folder_dir); + g_free (folder_dir); + + file = fopen (filename, "w"); + g_free (filename); + + if (file != NULL) + { + fprintf (file, "%d %d %d", messages, unseen, uidnext); + fclose (file); + } + + return; +} + +static void +camel_imap_store_get_status_for (CamelImapStore *imap_store, const char *folder_name, guint32 *messages, guint32 *unseen, guint32 *uidnext) +{ + char *storage_path, *folder_dir, *filename; + FILE *file = NULL; + int nmessages, nunseen, nuidnext; + + storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); + folder_dir = imap_path_to_physical (storage_path, folder_name); + g_free(storage_path); + filename = g_strdup_printf ("%s/status", folder_dir); + g_free (folder_dir); + + file = fopen (filename, "r"); + g_free (filename); + + if (file != NULL) + { + fscanf (file, "%i %i %i", &nmessages, &nunseen, &nuidnext); + *messages = nmessages; + *unseen = nunseen; + *uidnext = nuidnext; + fclose (file); + } + + return; +} + +static CamelMessageInfo* +parse_message_header (char *response) +{ + CamelMessageInfoBase *mi = NULL; + char *uid = NULL, *idate = NULL; + size_t body_len = 0; + guint32 flags = 0, size = 0; + + if (*response != '(') { + long seq; + + if (*response != '*' || *(response + 1) != ' ') + return NULL; + seq = strtol (response + 2, &response, 10); + if (seq == 0) + return NULL; + if (g_ascii_strncasecmp (response, " FETCH (", 8) != 0) + return NULL; + response += 7; + } + + do { + response++; + if (!g_ascii_strncasecmp (response, "FLAGS ", 6)) { + response += 6; + flags = imap_parse_flag_list (&response); + } else if (!g_ascii_strncasecmp (response, "RFC822.SIZE ", 12)) { + response += 12; + size = strtoul (response, &response, 10); + } else if (!g_ascii_strncasecmp (response, "BODY[", 5) || + !g_ascii_strncasecmp (response, "RFC822 ", 7)) + { + char *p, *body; + if (*response == 'B') { + response += 5; + p = strchr (response, ']'); + if (!p || *(p + 1) != ' ') + break; + response = p + 2; + } else + response += 7; + + body = imap_parse_nstring ((const char **) &response, &body_len); + if (!response) + break; + if (body) + { + CamelMimeMessage *msg = camel_mime_message_new (); + CamelStream *stream = camel_stream_mem_new_with_buffer (body, body_len); + g_free (body); + + if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) { + camel_object_unref (CAMEL_OBJECT (msg)); + break; + } + + mi = (CamelMessageInfoBase *) camel_folder_summary_info_new_from_message (NULL, msg); + camel_object_unref (CAMEL_OBJECT (msg)); + } + } else if (!g_ascii_strncasecmp (response, "UID ", 4)) { + int len = strcspn (response + 4, " )"); + uid = g_strndup (response + 4, len); + response += 4 + len; + } else if (!g_ascii_strncasecmp (response, "INTERNALDATE ", 13)) { + int len; response += 13; + if (*response == '"') { + response++; + len = strcspn (response, "\""); + idate = g_strndup (response, len); + response += len + 1; + } + } else { + g_warning ("Unexpected FETCH response from server: (%s", response); + break; + } + } while (response && *response != ')'); + + if (mi) + { + mi->flags |= flags; + if (uid) { + if (mi->uid && (mi->flags & CAMEL_MESSAGE_INFO_UID_NEEDS_FREE)) + g_free (mi->uid); + + mi->uid = uid; + mi->flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; + } + if (idate) { + mi->date_received = decode_internaldate ((const unsigned char *) idate); + g_free (idate); + } + mi->size = size; + } + + return (CamelMessageInfo *) mi; +} + +GPtrArray* +_camel_imap_store_get_recent_messages (CamelImapStore *imap_store, const char *folder_name, int *unseen, int *messages, gboolean withthem) +{ + guint32 uidnext=-1; + struct imap_status_item *items, *item; + guint ounseen, omessages, ouidnext; + GPtrArray *retval = NULL; + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + CamelImapResponse *response; + CamelException tex = CAMEL_EXCEPTION_INITIALISER; + + if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (imap_store), &ex)) + return NULL; + +/* + Example: C: A042 STATUS blurdybloop (UIDNEXT MESSAGES) + S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292) + S: A042 OK STATUS completed +*/ + + camel_operation_uncancel (NULL); + + + /* On for example courier, the selected's STATUS is cached (kill that cache) */ + if (withthem) + { + response = camel_imap_command (imap_store, NULL, &tex, + "SELECT"/*, folder_name*/); + +printf ("SELECT %s\n", folder_name); + + if (response) + camel_imap_response_free (imap_store, response); + } + + item = items = get_folder_status (imap_store, folder_name, "MESSAGES UNSEEN UIDNEXT"); + while (item != NULL) { + if (!g_ascii_strcasecmp (item->name, "MESSAGES")) + *messages = item->value; + if (!g_ascii_strcasecmp (item->name, "UNSEEN")) + *unseen = item->value; + if (!g_ascii_strcasecmp (item->name, "UIDNEXT")) + uidnext = item->value; + item = item->next; + } + imap_status_item_free (items); +printf ("%d %d %d\n", *messages, *unseen, uidnext); + + if (withthem) + { + camel_imap_store_get_status_for (imap_store, folder_name, &omessages, &ounseen, &ouidnext); + + if (ouidnext != uidnext) + { + CamelImapResponseType type; + char *resp; + + camel_exception_clear (&tex); + + if (!camel_imap_command_start (imap_store, NULL, &tex, + "UID FETCH %d:* (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER])", ouidnext-1)) + goto done; + + while ((type = camel_imap_command_response (imap_store, &resp, &tex)) + == CAMEL_IMAP_RESPONSE_UNTAGGED) + { + if (resp) + { + CamelMessageInfo *mi = parse_message_header (resp); + g_free (resp); + + if (mi) + { + if (retval == NULL) + retval = g_ptr_array_new (); + g_ptr_array_add (retval, mi); + } + } + } + + /* Restore the original folder selection */ + if (imap_store->current_folder != NULL && imap_store->current_folder->full_name != NULL) + { + response = camel_imap_command (imap_store, NULL, &tex, + "SELECT %F", imap_store->current_folder->full_name); + if (response) + camel_imap_response_free (imap_store, response); + } + } + } + +done: + + camel_imap_store_set_status_for (imap_store, folder_name, *messages, *unseen, uidnext); + + return retval; +} + +static GPtrArray* +imap_get_recent_messages (CamelStore *store, const char *folder_name, int *unseen, int *messages) +{ + GPtrArray *retval = NULL; + CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); + + CAMEL_SERVICE_REC_LOCK(imap_store, connect_lock); + retval = _camel_imap_store_get_recent_messages (imap_store, folder_name, unseen, messages, TRUE); + CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock); + + return retval; +} + static CamelFolder * get_folder_online (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) { @@ -1863,7 +2263,7 @@ CAMEL_SERVICE_REC_LOCK(imap_store, connect_lock); - if (!camel_imap_store_connected(imap_store, ex)) { + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) { CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock); return NULL; } @@ -1872,9 +2272,10 @@ folder_name = "INBOX"; if (imap_store->current_folder) { - camel_object_unref (imap_store->current_folder); + /* camel_object_unref (imap_store->current_folder); */ imap_store->current_folder = NULL; } + response = camel_imap_command (imap_store, NULL, ex, "SELECT %F", folder_name); if (!response) { char *folder_real, *parent_name, *parent_real; @@ -1931,7 +2332,7 @@ for (i = 0; i < response->untagged->len; i++) { resp = response->untagged->pdata[i]; - if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone)) + if (!imap_parse_list_response (imap_store, resp, (int *) &flags, NULL, &thisone)) continue; if (!strcmp (parent_name, thisone)) { @@ -2038,13 +2439,13 @@ CamelException local_ex; imap_store->current_folder = new_folder; - camel_object_ref (new_folder); + /* camel_object_ref (new_folder); */ camel_exception_init (&local_ex); - camel_imap_folder_selected (new_folder, response, &local_ex); + camel_imap_folder_selected (new_folder, response, &local_ex, TRUE); if (camel_exception_is_set (&local_ex)) { camel_exception_xfer (ex, &local_ex); - camel_object_unref (imap_store->current_folder); + /* camel_object_unref (imap_store->current_folder); */ imap_store->current_folder = NULL; camel_object_unref (new_folder); new_folder = NULL; @@ -2095,7 +2496,7 @@ CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock); - if (!camel_imap_store_connected(imap_store, ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) goto fail; /* make sure this folder isn't currently SELECTed */ @@ -2104,8 +2505,9 @@ goto fail; camel_imap_response_free_without_processing (imap_store, response); - if (imap_store->current_folder) - camel_object_unref (imap_store->current_folder); + /*if (imap_store->current_folder) + camel_object_unref (imap_store->current_folder);*/ + /* no need to actually create a CamelFolder for INBOX */ imap_store->current_folder = NULL; @@ -2195,7 +2597,7 @@ CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock); - if (!camel_imap_store_connected(imap_store, ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) goto fail; /* make sure this folder isn't currently SELECTed - it's @@ -2206,8 +2608,8 @@ goto fail; camel_imap_response_free_without_processing (imap_store, response); - if (imap_store->current_folder) - camel_object_unref (imap_store->current_folder); + /*if (imap_store->current_folder) + camel_object_unref (imap_store->current_folder); */ /* no need to actually create a CamelFolder for INBOX */ imap_store->current_folder = NULL; @@ -2426,7 +2828,8 @@ flags = (flags & ~CAMEL_FOLDER_SUBSCRIBED) | (si->info.flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED); - fi = g_new0 (CamelFolderInfo, 1); + fi = camel_folder_info_new (); + fi->full_name = g_strdup(camel_store_info_path(imap_store->summary, si)); if (!g_ascii_strcasecmp(fi->full_name, "inbox")) { flags |= CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_TYPE_INBOX; @@ -2451,9 +2854,6 @@ fi->uri = camel_url_to_string (url, 0); camel_url_free (url); - fi->total = -1; - fi->unread = -1; - return fi; } @@ -2525,29 +2925,68 @@ /* We do a LIST followed by LSUB, and merge the results. LSUB may not be a strict subset of LIST for some servers, so we can't use either or separately */ + + /* TNY TODO! It used to loop until 2, but I think it's just wrong to + merge with LSUB?! (It doesn't make any sense) */ + present = g_hash_table_new(folder_hash, folder_eq); - for (j=0;j<2;j++) { + + for (j=0;j<2;j++) + { response = camel_imap_command (imap_store, NULL, ex, "%s \"\" %G", j==1 ? "LSUB" : "LIST", pattern); if (!response) goto fail; - for (i = 0; i < response->untagged->len; i++) { + for (i = 0; i < response->untagged->len; i++) + { list = response->untagged->pdata[i]; fi = parse_list_response_as_folder_info (imap_store, list); - if (fi) { + + if (fi) + { + if (FALSE && j == 0) + { + struct imap_status_item *item, *items; + item = items = get_folder_status (imap_store, fi->full_name, "MESSAGES UNSEEN"); + while (item != NULL) + { + if (!g_ascii_strcasecmp (item->name, "MESSAGES")) + fi->total = item->value; + if (!g_ascii_strcasecmp (item->name, "UNSEEN")) + fi->unread = item->value; + item = item->next; + } + imap_status_item_free (items); + } + hfi = g_hash_table_lookup(present, fi->full_name); - if (hfi == NULL) { - if (j==1) { + + if (hfi == NULL) + { + if (j == 1) + { + /* It's in LSUB but not in LIST? */ + fi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; if ((fi->flags & (CAMEL_IMAP_FOLDER_MARKED | CAMEL_IMAP_FOLDER_UNMARKED))) imap_store->capabilities |= IMAP_CAPABILITY_useful_lsub; } - g_hash_table_insert(present, fi->full_name, fi); + + if (j == 0) /* From the LSUB we don't add folders */ + g_hash_table_insert(present, fi->full_name, fi); + else + camel_folder_info_free(fi); } else { if (j == 1) hfi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; + + if (j == 0) + { + hfi->unread = fi->unread; + hfi->total = fi->total; + } camel_folder_info_free(fi); } } @@ -2559,17 +2998,22 @@ /* FIXME: we need to emit folder_create/subscribed/etc events for any new folders */ count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;isummary, i); if (si == NULL) continue; - if (imap_match_pattern(imap_store->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si))) { - if ((fi = g_hash_table_lookup(present, camel_store_info_path(imap_store->summary, si))) != NULL) { - if (((fi->flags ^ si->flags) & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) { + if (imap_match_pattern(imap_store->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si))) + { + if ((fi = g_hash_table_lookup(present, camel_store_info_path(imap_store->summary, si))) != NULL) + { + if (((fi->flags ^ si->flags) & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) si->flags = (si->flags & ~CAMEL_FOLDER_SUBSCRIBED) | (fi->flags & CAMEL_FOLDER_SUBSCRIBED); - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } + si->unread = fi->unread; + si->total = fi->total; + camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); } else { camel_store_summary_remove((CamelStoreSummary *)imap_store->summary, si); count--; @@ -2608,17 +3052,120 @@ } #endif + +static int +isdir (char *name) +{ + struct stat st; + if (stat (name, &st)) + return 0; + return S_ISDIR (st.st_mode); +} + +static char *ignored_names[] = { ".", "..", "subfolders", NULL }; + +int +ignorent (char *name) +{ + char **p; + for (p = ignored_names; *p; p++) + if (strcmp (name, *p) == 0) + return 1; + return 0; +} + + +void +my_du (char *name, int *my_size) +{ + DIR *dir; + struct dirent *ent; + + chdir (name); + dir = opendir (name); + + if (!dir) + return; + + while ((ent = readdir (dir))) + { + if (!ignorent (ent->d_name)) + { + char *p = g_strdup_printf ("%s/%s", name, ent->d_name); + if (isdir (p)) + my_du (p, my_size); + else + { + struct stat st; + if (stat (p, &st) == 0) + *my_size += st.st_size; + } + g_free (p); + } + } + + closedir (dir); +} + static void fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) { CamelFolder *folder; + CamelImapStore *imap_store = (CamelImapStore *) store; + gint msize = 0; + char *storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); + char *folder_dir = imap_path_to_physical (storage_path, fi->full_name); + + g_free(storage_path); + my_du (folder_dir, &msize); folder = camel_object_bag_peek(store->folders, fi->full_name); - if (folder) { + + if (folder) + { fi->unread = camel_folder_get_unread_message_count(folder); fi->total = camel_folder_get_message_count(folder); camel_object_unref(folder); + + } else if ((fi->unread == -1) || (fi->total == -1)) { + + + /* This code reads the beginning of the summary.mmap file for + * the length and unread-count of the folder. It makes it + * possible to read the total and unread values of the + * CamelFolderInfo structure without having to read the entire + * folder in (mmap it) + * It's called by get_folder_info_offline and therefore also by + * get_folder_info_online for each node in the tree. */ + + gchar *spath = g_strdup_printf ("%s/summary.mmap", folder_dir); + FILE *f = fopen (spath, "r"); + g_free (spath); + + if (f) { + + gint tsize = ((sizeof (guint32) * 5) + sizeof (time_t)); + char *buffer = malloc (tsize), *ptr; + guint32 version, a; + a = fread (buffer, 1, tsize, f); + if (a == tsize) + { + ptr = buffer; + version = g_ntohl(get_unaligned_u32(ptr)); + ptr += 16; + if (fi->total == -1) + fi->total = g_ntohl(get_unaligned_u32(ptr)); + ptr += 4; + if (fi->unread == -1 && (version < 0x100 && version >= 13)) + fi->unread = g_ntohl(get_unaligned_u32(ptr)); + } + g_free (buffer); + fclose (f); + } } + + fi->local_size = msize; + g_free (folder_dir); } struct _refresh_msg { @@ -2636,7 +3183,7 @@ CAMEL_SERVICE_REC_LOCK(m->store, connect_lock); - if (!camel_imap_store_connected((CamelImapStore *)m->store, &m->ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)m->store, &m->ex)) goto done; if (store->namespace && store->namespace[0]) { @@ -2718,7 +3265,7 @@ CAMEL_SERVICE_REC_LOCK(store, connect_lock); - if (!camel_imap_store_connected((CamelImapStore *)store, ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) goto fail; if (top[0] == 0) { @@ -2814,8 +3361,7 @@ /* folder_info_build will insert parent nodes as necessary and mark * them as noselect, which is information we actually don't have at * the moment. So let it do the right thing by bailing out if it's - * not a folder we're explicitly interested in. - */ + * not a folder we're explicitly interested in. */ for (i=0;isummary);i++) { CamelStoreInfo *si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i); @@ -2828,17 +3374,26 @@ || (include_inbox && !g_ascii_strcasecmp (camel_imap_store_info_full_name(imap_store->summary, si), "INBOX"))) && ((imap_store->parameters & IMAP_PARAM_SUBSCRIPTIONS) == 0 || (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) == 0 - || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED))) { + || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED))) + { + fi = imap_build_folder_info(imap_store, camel_store_info_path((CamelStoreSummary *)imap_store->summary, si)); + fi->flags = si->flags; fi->unread = si->unread; fi->total = si->total; - fi->flags = si->flags; + + if (fi->unread == 0 || fi->total == 0) + { + fi->unread = -1; + fi->total = -1; + } + /* HACK: some servers report noinferiors for all folders (uw-imapd) We just translate this into nochildren, and let the imap layer enforce it. See create folder */ if (fi->flags & CAMEL_FOLDER_NOINFERIORS) fi->flags = (fi->flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_NOCHILDREN; - + /* blah, this gets lost somewhere, i can't be bothered finding out why */ if (!g_ascii_strcasecmp(fi->full_name, "inbox")) fi->flags = (fi->flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_INBOX; @@ -2852,6 +3407,11 @@ camel_url_free (url); } else { fill_fi((CamelStore *)imap_store, fi, 0); + if (fi->unread == -1) + fi->unread = 0; + + if (fi->total == -1) + fi->total = 0; } g_ptr_array_add (folders, fi); } @@ -2863,6 +3423,8 @@ g_ptr_array_free (folders, TRUE); g_free(name); + camel_store_summary_save ((CamelStoreSummary *)imap_store->summary); + return fi; } @@ -2894,7 +3456,7 @@ CAMEL_SERVICE_REC_LOCK(store, connect_lock); - if (!camel_imap_store_connected (imap_store, ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) goto done; response = camel_imap_command (imap_store, NULL, ex, @@ -2902,7 +3464,7 @@ if (!response) goto done; camel_imap_response_free (imap_store, response); - + si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); if (si) { if ((si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) { @@ -2938,7 +3500,7 @@ CAMEL_SERVICE_REC_LOCK(store, connect_lock); - if (!camel_imap_store_connected (imap_store, ex)) + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) goto done; response = camel_imap_command (imap_store, NULL, ex, @@ -3017,28 +3579,36 @@ * close the connection. We can't expect a read to have any * meaning if we reconnect, so always set an exception. */ - - if (!camel_imap_store_connected (store, ex)) + + if (!camel_disco_store_check_online((CamelDiscoStore *)store, ex)) return -1; - + + g_mutex_lock (store->stream_lock); + camel_imap_store_restore_stream_buffer (store); stream = CAMEL_STREAM_BUFFER (store->istream); - + ba = g_byte_array_new (); while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) { - g_byte_array_append (ba, linebuf, nread); + g_byte_array_append (ba, (const guchar*) linebuf, nread); if (linebuf[nread - 1] == '\n') break; } - + g_mutex_unlock (store->stream_lock); + if (nread <= 0) { if (errno == EINTR) + { + CamelException mex = CAMEL_EXCEPTION_INITIALISER; camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); - else + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + camel_service_connect (CAMEL_SERVICE (store), &mex); + } else { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Server unexpectedly disconnected: %s"), g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + } + g_byte_array_free (ba, TRUE); return -1; } @@ -3057,7 +3627,55 @@ nread--; } - *dest = ba->data; + *dest = (char *) ba->data; + g_byte_array_free (ba, FALSE); + + return nread; +} + + +ssize_t +camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex) +{ + CamelStreamBuffer *stream; + char linebuf[1024] = {0}; + GByteArray *ba; + ssize_t nread; + + g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1); + g_return_val_if_fail (dest, -1); + + *dest = NULL; + + g_mutex_lock (store->stream_lock); + if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { + g_mutex_unlock (store->stream_lock); + return -1; + } + stream = CAMEL_STREAM_BUFFER (store->istream); + ba = g_byte_array_new (); + while ((nread = camel_tcp_stream_buffer_gets_nb (stream, linebuf, sizeof (linebuf))) > 0) + { + g_byte_array_append (ba, (const guchar*) linebuf, nread); + if (linebuf[nread - 1] == '\n') + break; + } + g_mutex_unlock (store->stream_lock); + + if (nread <= 0) { + g_byte_array_free (ba, TRUE); + return -1; + } + + nread = ba->len - 1; + ba->data[nread] = '\0'; + if (ba->data[nread - 1] == '\r') { + ba->data[nread - 1] = '\0'; + nread--; + } + + *dest = (char *) ba->data; g_byte_array_free (ba, FALSE); return nread; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-store.h ./providers/imap/camel-imap-store.h --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-store.h 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-store.h 2007-05-12 10:11:29.000000000 +0200 @@ -25,6 +25,22 @@ #ifndef CAMEL_IMAP_STORE_H #define CAMEL_IMAP_STORE_H 1 +/* #define IDLE_DEBUG 1 */ +/* #define IMAP_DEBUG 1 */ + +#ifdef IDLE_DEBUG +#define idle_debug(o) printf ("%s\n", o) +#else +#define idle_debug(o) +#endif + +#ifdef IMAP_DEBUG +#define imap_debug(o) printf ("%s\n", o) +#else +#define imap_debug(o) +#endif + + #include "camel-imap-types.h" #include #include @@ -98,6 +114,9 @@ #define IMAP_CAPABILITY_XGWEXTENSIONS (1 << 9) #define IMAP_CAPABILITY_XGWMOVE (1 << 10) #define IMAP_CAPABILITY_LOGINDISABLED (1 << 11) +#define IMAP_CAPABILITY_CONDSTORE (1 << 12) +#define IMAP_CAPABILITY_IDLE (1 << 13) +#define IMAP_CAPABILITY_BINARY (1 << 14) #define IMAP_PARAM_OVERRIDE_NAMESPACE (1 << 0) #define IMAP_PARAM_CHECK_ALL (1 << 1) @@ -106,15 +125,12 @@ #define IMAP_PARAM_FILTER_JUNK_INBOX (1 << 4) #define IMAP_PARAM_SUBSCRIPTIONS (1 << 5) -#define IMAP_FETCH_ALL_HEADERS 1 -#define IMAP_FETCH_MAILING_LIST_HEADERS 2 /* Fetches Minimal and Mailing List Headers. Default behavior */ -#define IMAP_FETCH_MINIMAL_HEADERS 3 - struct _CamelImapStore { CamelDiscoStore parent_object; CamelStream *istream; CamelStream *ostream; + GMutex *stream_lock; struct _CamelImapStoreSummary *summary; @@ -140,9 +156,9 @@ GHashTable *authtypes; time_t refresh_stamp; - - guint32 headers; - char *custom_headers; + gchar *idle_prefix; + guint idle_signal; + gboolean dontdistridlehack, has_login; }; typedef struct { @@ -157,7 +173,14 @@ gboolean camel_imap_store_connected (CamelImapStore *store, CamelException *ex); +ssize_t camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex); ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex); +gboolean camel_imap_service_connect (CamelService *service, CamelException *ex); + +gboolean camel_imap_store_restore_stream_buffer (CamelImapStore *store); + +void camel_imap_store_stop_idle (CamelImapStore *store); +void camel_imap_store_start_idle (CamelImapStore *store); G_END_DECLS Only in ./providers/imap: camel-imap-store.h.rej Only in ./providers/imap: camel-imap-store.lo Only in ./providers/imap: camel-imap-store.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-store-summary.c ./providers/imap/camel-imap-store-summary.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-store-summary.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-store-summary.c 2007-05-12 10:01:04.000000000 +0200 @@ -468,27 +468,44 @@ guint32 sep = '/'; ns = g_malloc0(sizeof(*ns)); - if (camel_file_util_decode_string(in, &ns->path) == -1 - || camel_file_util_decode_string(in, &ns->full_name) == -1 - || camel_file_util_decode_uint32(in, &sep) == -1) { - namespace_free(s, ns); - ns = NULL; - } else { - ns->sep = sep; - } + + if (camel_file_util_decode_string(in, &ns->path) == -1) + goto nserror; + + if (camel_file_util_decode_string(in, &ns->full_name) == -1) + goto nserror; + + if (camel_file_util_decode_uint32(in, &sep) == -1) + goto nserror; + + ns->sep = sep; return ns; + + nserror: + + namespace_free(s, ns); + return NULL; } static int namespace_save(CamelStoreSummary *s, FILE *in, CamelImapStoreNamespace *ns) { - if (camel_file_util_encode_string(in, ns->path) == -1 - || camel_file_util_encode_string(in, ns->full_name) == -1 - || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) - return -1; + if (camel_file_util_encode_string(in, ns->path) == -1) + goto serr; + + if (camel_file_util_encode_string(in, ns->full_name) == -1) + goto serr; + + if (camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) + goto serr; return 0; + + serr: + printf ("Error happend while writing\n"); + return -1; + } static int Only in ./providers/imap: camel-imap-store-summary.lo Only in ./providers/imap: camel-imap-store-summary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-summary.c ./providers/imap/camel-imap-summary.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-summary.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-summary.c 2007-05-12 10:09:12.000000000 +0200 @@ -33,19 +33,21 @@ #include "camel-file-utils.h" +#include "camel-imap-message-cache.h" #include "camel-imap-summary.h" #include "camel-imap-utils.h" +#include "camel-imap-folder.h" #define CAMEL_IMAP_SUMMARY_VERSION (3) -static int summary_header_load (CamelFolderSummary *, FILE *); +static int summary_header_load (CamelFolderSummary *); static int summary_header_save (CamelFolderSummary *, FILE *); -static CamelMessageInfo *message_info_load (CamelFolderSummary *s, FILE *in); +static CamelMessageInfo *message_info_load (CamelFolderSummary *s, gboolean *must_add); static int message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info); static gboolean info_set_user_tag(CamelMessageInfo *info, const char *name, const char *value); -static CamelMessageContentInfo *content_info_load (CamelFolderSummary *s, FILE *in); +static CamelMessageContentInfo *content_info_load (CamelFolderSummary *s); static int content_info_save (CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *info); @@ -108,10 +110,18 @@ } static void +camel_imap_summary_set_extra_flags (CamelFolder *folder, CamelMessageInfoBase *mi) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + camel_imap_message_cache_set_flags (imap_folder->folder_dir, mi); +} + +static void camel_imap_summary_init (CamelImapSummary *obj) { CamelFolderSummary *s = (CamelFolderSummary *)obj; + s->set_extra_flags_func = camel_imap_summary_set_extra_flags; /* subclasses need to set the right instance data sizes */ s->message_info_size = sizeof(CamelImapMessageInfo); s->content_info_size = sizeof(CamelImapMessageContentInfo); @@ -146,31 +156,31 @@ } static int -summary_header_load (CamelFolderSummary *s, FILE *in) +summary_header_load (CamelFolderSummary *s) { CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s); - if (camel_imap_summary_parent->summary_header_load (s, in) == -1) + if (camel_imap_summary_parent->summary_header_load (s) == -1) return -1; /* Legacy version */ - if (s->version == 0x30c) - return camel_file_util_decode_uint32(in, &ims->validity); + if (s->version == 0x30c) { + unsigned char* ptrchr = s->filepos; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &ims->validity, FALSE); + s->filepos = ptrchr; + return 0; + } /* Version 1 */ - if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1) - return -1; + ims->version = g_ntohl(get_unaligned_u32(s->filepos)); s->filepos += 4; if (ims->version == 2) { /* Version 2: for compat with version 2 of the imap4 summary files */ int have_mlist; - - if (camel_file_util_decode_fixed_int32 (in, &have_mlist) == -1) - return -1; + have_mlist = g_ntohl(get_unaligned_u32(s->filepos)); s->filepos += 4; } - - if (camel_file_util_decode_fixed_int32(in, &ims->validity) == -1) - return -1; + + ims->validity = g_ntohl(get_unaligned_u32(s->filepos)); s->filepos += 4; if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) { g_warning("Unkown summary version\n"); @@ -207,25 +217,22 @@ } static CamelMessageInfo * -message_info_load (CamelFolderSummary *s, FILE *in) +message_info_load (CamelFolderSummary *s, gboolean *must_add) { CamelMessageInfo *info; CamelImapMessageInfo *iinfo; - info = camel_imap_summary_parent->message_info_load (s, in); - if (info) { - iinfo = (CamelImapMessageInfo *)info; - - if (camel_file_util_decode_uint32 (in, &iinfo->server_flags) == -1) - goto error; + info = camel_imap_summary_parent->message_info_load (s, must_add); + iinfo = (CamelImapMessageInfo*)info; + if (info) { + unsigned char* ptrchr = s->filepos; + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &iinfo->server_flags, FALSE); + s->filepos = ptrchr; label_to_flags(iinfo); } return info; -error: - camel_message_info_free(info); - return NULL; } static int @@ -253,10 +260,16 @@ } static CamelMessageContentInfo * -content_info_load (CamelFolderSummary *s, FILE *in) +content_info_load (CamelFolderSummary *s) { - if (fgetc (in)) - return camel_imap_summary_parent->content_info_load (s, in); + guint32 doit; + unsigned char* ptrchr = s->filepos; + + ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &doit, FALSE); + s->filepos = ptrchr; + + if (doit == 1) + return camel_imap_summary_parent->content_info_load (s); else return camel_folder_summary_content_info_new (s); } @@ -266,10 +279,10 @@ CamelMessageContentInfo *info) { if (info->type) { - fputc (1, out); + camel_file_util_encode_uint32 (out, 1); return camel_imap_summary_parent->content_info_save (s, out, info); } else - return fputc (0, out); + return camel_file_util_encode_uint32 (out, 0); } void @@ -278,8 +291,10 @@ const CamelMessageInfo *info) { CamelImapMessageInfo *mi; +#ifdef NON_TINYMAIL_FEATURES const CamelFlag *flag; const CamelTag *tag; +#endif /* Create summary entry */ mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (summary, message); @@ -287,6 +302,7 @@ /* Copy flags 'n' tags */ mi->info.flags = camel_message_info_flags(info); +#ifdef NON_TINYMAIL_FEATURES flag = camel_message_info_user_flags(info); while (flag) { camel_message_info_set_user_flag((CamelMessageInfo *)mi, flag->name, TRUE); @@ -297,8 +313,10 @@ camel_message_info_set_user_tag((CamelMessageInfo *)mi, tag->name, tag->value); tag = tag->next; } +#endif - mi->info.size = camel_message_info_size(info); + mi->info.size = ((CamelMessageInfoBase *)info)->size; + mi->info.flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; mi->info.uid = g_strdup (uid); label_to_flags(mi); @@ -313,7 +331,9 @@ CamelImapMessageInfo *mi; mi = camel_message_info_clone(info); + mi->info.uid = g_strdup(uid); + mi->info.flags |= CAMEL_MESSAGE_INFO_UID_NEEDS_FREE; label_to_flags(mi); Only in ./providers/imap: camel-imap-summary.c.rej Only in ./providers/imap: camel-imap-summary.lo Only in ./providers/imap: camel-imap-summary.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-utils.c ./providers/imap/camel-imap-utils.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-utils.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-utils.c 2007-05-12 10:00:49.000000000 +0200 @@ -125,7 +125,7 @@ } /* decode IMAP's modified UTF-7 into UTF-8 */ - node->prefix = imap_mailbox_decode (astring, len); + node->prefix = imap_mailbox_decode ((const unsigned char *) astring, len); g_free (astring); if (!node->prefix) { g_free (node); @@ -375,7 +375,6 @@ if (folder) { char *astring; - char *mailbox; /* get the folder name */ word = imap_next_word (word); @@ -385,7 +384,9 @@ *folder = astring; - mailbox = imap_mailbox_decode (astring, strlen (astring)); + char *mailbox; + + mailbox = imap_mailbox_decode ((const unsigned char *) astring, strlen (astring)); g_free (astring); if (!mailbox) return FALSE; @@ -480,8 +481,6 @@ g_string_append (gstr, "\\Flagged "); if (flags & CAMEL_MESSAGE_SEEN) g_string_append (gstr, "\\Seen "); - if (flags & CAMEL_MESSAGE_JUNK) - g_string_append (gstr, "Junk "); if (flags & CAMEL_IMAP_MESSAGE_LABEL1) g_string_append(gstr, "$Label1 "); if (flags & CAMEL_IMAP_MESSAGE_LABEL2) @@ -555,9 +554,7 @@ else if (!g_ascii_strncasecmp (flag_list, "\\Recent", len)) flags |= CAMEL_IMAP_MESSAGE_RECENT; else if (!g_ascii_strncasecmp(flag_list, "\\*", len)) - flags |= CAMEL_MESSAGE_USER|CAMEL_MESSAGE_JUNK|CAMEL_IMAP_MESSAGE_LABEL_MASK; - else if (!g_ascii_strncasecmp(flag_list, "Junk", len)) - flags |= CAMEL_MESSAGE_JUNK; + flags |= CAMEL_MESSAGE_USER|CAMEL_IMAP_MESSAGE_LABEL_MASK; else if (!g_ascii_strncasecmp(flag_list, "$Label1", len)) flags |= CAMEL_IMAP_MESSAGE_LABEL1; else if (!g_ascii_strncasecmp(flag_list, "$Label2", len)) @@ -967,7 +964,7 @@ /* size */ size = strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; + inptr = (const char *) p; if (camel_content_type_is (ctype, "message", "rfc822")) { /* body_type_msg */ @@ -990,14 +987,14 @@ /* lines */ strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; + inptr = (const char *) p; } else if (camel_content_type_is (ctype, "text", "*")) { if (*inptr++ != ' ') goto exception; /* lines */ strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; + inptr = (const char *) p; } else { /* body_type_basic */ } Only in ./providers/imap: camel-imap-utils.lo Only in ./providers/imap: camel-imap-utils.o diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-wrapper.c ./providers/imap/camel-imap-wrapper.c --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/camel-imap-wrapper.c 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/camel-imap-wrapper.c 2007-05-12 10:01:04.000000000 +0200 @@ -141,9 +141,10 @@ if (data_wrapper->offline) { CamelStream *datastream; + /* TNY TODO: partial message retrieval exception */ datastream = camel_imap_folder_fetch_data ( imap_wrapper->folder, imap_wrapper->uid, - imap_wrapper->part_spec, FALSE, NULL); + imap_wrapper->part_spec, FALSE, CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); if (!datastream) { CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); #ifdef ENETUNREACH @@ -188,8 +189,9 @@ imap_wrapper->part = part; /* Try the cache. */ + /* TNY TODO: Partial message retrieval exception */ stream = camel_imap_folder_fetch_data (imap_folder, uid, part_spec, - TRUE, NULL); + TRUE, CAMEL_FOLDER_RECEIVE_FULL, -1, NULL); if (stream) { imap_wrapper_hydrate (imap_wrapper, stream); camel_object_unref (stream); Only in ./providers/imap: camel-imap-wrapper.lo Only in ./providers/imap: camel-imap-wrapper.o Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap: ChangeLog Only in ./providers/imap: .deps Only in ./providers/imap: libcamelimap.la Only in ./providers/imap: .libs Only in ./providers/imap: Makefile diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/Makefile.am ./providers/imap/Makefile.am --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/Makefile.am 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/Makefile.am 2007-05-12 10:01:04.000000000 +0200 @@ -12,6 +12,7 @@ $(CAMEL_CFLAGS) \ $(GNOME_INCLUDEDIR) \ $(GTK_INCLUDEDIR) \ + -DTRANSDOM=\"$(GETTEXT_PACKAGE)\" \ -DG_LOG_DOMAIN=\"camel-imap-provider\" libcamelimap_la_SOURCES = \ @@ -42,9 +43,8 @@ libcamelimap_la_LDFLAGS = -avoid-version -module $(NO_UNDEFINED) libcamelimap_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${API_VERSION}.la \ - $(top_builddir)/camel/libcamel-provider-1.2.la \ - $(top_builddir)/camel/libcamel-1.2.la \ + $(top_builddir)/camel/libcamel-lite-provider-1.2.la \ + $(top_builddir)/camel/libcamel-lite-1.2.la \ $(CAMEL_LIBS) EXTRA_DIST = libcamelimap.urls Only in ./providers/imap: Makefile.am.rej Only in ./providers/imap: Makefile.in diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/all-wcprops ./providers/imap/.svn/all-wcprops --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/all-wcprops 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/.svn/all-wcprops 2007-05-12 10:49:08.000000000 +0200 @@ -1,155 +1,155 @@ K 25 svn:wc:ra_dav:version-url -V 67 -/svn/evolution-data-server/!svn/ver/7736/trunk/camel/providers/imap +V 83 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap END -camel-imap-store-summary.h +camel-imap-store.c K 25 svn:wc:ra_dav:version-url -V 94 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-store-summary.h +V 102 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c END -camel-imap-store.c +camel-imap-store-summary.h K 25 svn:wc:ra_dav:version-url -V 86 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-store.c +V 110 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store-summary.h END camel-imap-summary.c K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-summary.c +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-summary.c END camel-imap-utils.c K 25 svn:wc:ra_dav:version-url -V 86 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-utils.c +V 102 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-utils.c END camel-imap-store.h K 25 svn:wc:ra_dav:version-url -V 86 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-store.h +V 102 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h END camel-imap-summary.h K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-summary.h +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-summary.h END -ChangeLog +.svnignore K 25 svn:wc:ra_dav:version-url -V 77 -/svn/evolution-data-server/!svn/ver/7736/trunk/camel/providers/imap/ChangeLog +V 94 +/svn/tinymail/!svn/ver/1019/trunk/libtinymail-camel/camel-lite/camel/providers/imap/.svnignore END -camel-imap-utils.h +camel-imap-search.c K 25 svn:wc:ra_dav:version-url -V 86 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-utils.h +V 103 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-search.c END -camel-imap-search.c +camel-imap-utils.h K 25 svn:wc:ra_dav:version-url -V 87 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-search.c +V 102 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-utils.h END camel-imap-types.h K 25 svn:wc:ra_dav:version-url -V 86 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-types.h +V 102 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-types.h END camel-imap-search.h K 25 svn:wc:ra_dav:version-url -V 87 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-search.h +V 103 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-search.h END camel-imap-folder.c K 25 svn:wc:ra_dav:version-url -V 87 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-folder.c +V 103 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c END camel-imap-command.c K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-command.c +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c END -libcamelimap.urls +camel-imap-private.h K 25 svn:wc:ra_dav:version-url -V 85 -/svn/evolution-data-server/!svn/ver/1352/trunk/camel/providers/imap/libcamelimap.urls +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-private.h END -camel-imap-private.h +libcamelimap.urls K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-private.h +V 101 +/svn/tinymail/!svn/ver/1014/trunk/libtinymail-camel/camel-lite/camel/providers/imap/libcamelimap.urls END camel-imap-folder.h K 25 svn:wc:ra_dav:version-url -V 87 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-folder.h +V 103 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.h END camel-imap-wrapper.c K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-wrapper.c +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-wrapper.c END camel-imap-command.h K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-command.h +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.h END camel-imap-message-cache.c K 25 svn:wc:ra_dav:version-url -V 94 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-message-cache.c +V 110 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-message-cache.c END Makefile.am K 25 svn:wc:ra_dav:version-url -V 79 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/Makefile.am +V 95 +/svn/tinymail/!svn/ver/1078/trunk/libtinymail-camel/camel-lite/camel/providers/imap/Makefile.am END camel-imap-wrapper.h K 25 svn:wc:ra_dav:version-url -V 88 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-wrapper.h +V 104 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-wrapper.h END camel-imap-store-summary.c K 25 svn:wc:ra_dav:version-url -V 94 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-store-summary.c +V 110 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store-summary.c END .cvsignore K 25 svn:wc:ra_dav:version-url -V 78 -/svn/evolution-data-server/!svn/ver/1187/trunk/camel/providers/imap/.cvsignore +V 94 +/svn/tinymail/!svn/ver/1014/trunk/libtinymail-camel/camel-lite/camel/providers/imap/.cvsignore END camel-imap-provider.c K 25 svn:wc:ra_dav:version-url -V 89 -/svn/evolution-data-server/!svn/ver/7736/trunk/camel/providers/imap/camel-imap-provider.c +V 105 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-provider.c END camel-imap-message-cache.h K 25 svn:wc:ra_dav:version-url -V 94 -/svn/evolution-data-server/!svn/ver/7720/trunk/camel/providers/imap/camel-imap-message-cache.h +V 110 +/svn/tinymail/!svn/ver/1943/trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-message-cache.h END diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/dir-prop-base ./providers/imap/.svn/dir-prop-base --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/dir-prop-base 2007-05-12 09:58:49.000000000 +0200 +++ ./providers/imap/.svn/dir-prop-base 2007-04-22 11:56:49.000000000 +0200 @@ -1,16 +1,9 @@ K 10 svn:ignore -V 72 -.deps -Makefile +V 33 Makefile.in .libs .deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov +Makefile END diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/entries ./providers/imap/.svn/entries --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/entries 2007-05-12 09:58:59.000000000 +0200 +++ ./providers/imap/.svn/entries 2007-05-12 10:49:08.000000000 +0200 @@ -1,15 +1,15 @@ 8 dir -7738 -http://svn.gnome.org/svn/evolution-data-server/trunk/camel/providers/imap -http://svn.gnome.org/svn/evolution-data-server +1943 +https://svn.tinymail.org/svn/tinymail/trunk/libtinymail-camel/camel-lite/camel/providers/imap +https://svn.tinymail.org/svn/tinymail -2007-05-11T18:31:18.634404Z -7736 -sragavan +2007-05-12T08:30:21.902504Z +1943 +pvanhoof has-props svn:special svn:externals svn:needs-lock @@ -24,7 +24,7 @@ -d0434b6f-c725-0410-8785-fd8a057797ef +d4f517bd-a70b-0410-9f68-c17655437c52 camel-imap-store.c file @@ -32,12 +32,11 @@ -2007-05-12T07:58:53.000000Z -7eba60014db1dcb95b1af27475e7e02d -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:00:49.000000Z +77ad4eae29652d3119273c87cd426634 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-store-summary.h file @@ -45,12 +44,11 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:00:49.000000Z af4ec743c60bf3ad2be944a0f15a89c0 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-summary.c file @@ -58,12 +56,11 @@ -2007-05-12T07:58:53.000000Z -9bbd0f7518d5201fed7fce809f631179 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:09:12.000000Z +f642efa760729841b01fd61a02f8f7cf +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-utils.c file @@ -71,12 +68,11 @@ -2007-05-12T07:58:53.000000Z -8a8bcf82411207058954ade2160908cf -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:00:49.000000Z +5eb9aa62a9871744cf2e85e8af385e19 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-store.h file @@ -84,12 +80,11 @@ -2007-05-12T07:58:53.000000Z -2877ca95c846448546109c271133bd7c -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:11:29.000000Z +30f84c1dfa2bea8a78b4f10fe30b9957 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-summary.h file @@ -97,24 +92,23 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:01:01.000000Z 6c3ac8d793ee95f5cdce563463cb207e -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof -ChangeLog +.svnignore file -2007-05-12T07:58:53.000000Z -64fa7e5386bd253cde04fb5078c38400 -2007-05-11T18:31:18.634404Z -7736 -sragavan +2007-03-11T15:44:08.000000Z +349bfb6574e6f84ca228f148c7fb1129 +2006-10-16T23:45:03.608857Z +1019 +pvanhoof camel-imap-search.c file @@ -122,12 +116,11 @@ -2007-05-12T07:58:53.000000Z -858d42167939c33a671302f10d4c20a6 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:03.000000Z +4102a31b17553d02a902ff487fb8dd17 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-utils.h file @@ -135,12 +128,11 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:01:03.000000Z 6b137f9debb71b87550f833e9ff30663 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-types.h file @@ -148,12 +140,11 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:01:03.000000Z 5f3bda53f01f40f5787096d96a995609 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-search.h file @@ -161,12 +152,11 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:01:03.000000Z f5321638abadbde77b286b5c9f4d28c9 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-folder.c file @@ -174,12 +164,11 @@ -2007-05-12T07:58:53.000000Z -a5b37dd33a064724fd52c95f1aa16dce -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:15:55.000000Z +a0ed8ca02615043b0fab2b1cd809cec2 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-command.c file @@ -187,12 +176,11 @@ -2007-05-12T07:58:53.000000Z -6fc11cfb17e2cb41bf7ed7043245a141 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:17:00.000000Z +4acd760158d31d6a41e1748dbc802bc4 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-private.h file @@ -200,12 +188,11 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:01:04.000000Z e68703f00e6e4d1fd4f700c42703c457 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof libcamelimap.urls file @@ -213,11 +200,11 @@ -2007-04-20T11:24:56.000000Z +2007-03-11T15:44:08.000000Z 626a2232193e7dcca9e18cc90922f9a8 -2001-03-27T05:22:44.000000Z -1352 -danw +2006-10-16T23:10:20.309538Z +1014 +pvanhoof camel-imap-folder.h file @@ -225,12 +212,11 @@ -2007-05-12T07:58:53.000000Z -aba96eea2c77565797bb951813eca925 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:04.000000Z +b80eec9804afd5c0dab8a71653abf459 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-wrapper.c file @@ -238,12 +224,11 @@ -2007-05-12T07:58:53.000000Z -ee5b3e0dcdccb857cff11d810d6909fe -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:04.000000Z +1806282273e06f6eaefad72aea2166da +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-command.h file @@ -251,12 +236,11 @@ -2007-05-12T07:58:53.000000Z -e6c274c76599459792e012221514a520 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:04.000000Z +4dfdf651e9517d44de2a61635c408c6e +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-message-cache.c file @@ -264,12 +248,11 @@ -2007-05-12T07:58:53.000000Z -9021592367ed3acc210bd1518ca60662 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:04.000000Z +2c96b3481340f2b66d17fec8419fe739 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof Makefile.am file @@ -277,11 +260,11 @@ -2007-05-12T07:58:53.000000Z -996091003d0f5318b57a5d1c29b7f4c6 -2007-04-28T01:42:04.098476Z -7720 -mbarnes +2007-05-12T08:01:04.000000Z +ba0afda4913b41290bf774beb5796930 +2006-10-30T14:48:07.262395Z +1078 +pvanhoof camel-imap-wrapper.h file @@ -289,12 +272,11 @@ -2007-05-12T07:58:53.000000Z +2007-05-12T08:01:04.000000Z 43043fc0422276c8a92f482ad4f5446a -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-store-summary.c file @@ -302,12 +284,11 @@ -2007-05-12T07:58:53.000000Z -9096fbb1f97a5f412d8d96d492b0e583 -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:04.000000Z +1805027ff12abe812e058100e2fd24fa +2007-05-12T08:30:21.902504Z +1943 +pvanhoof .cvsignore file @@ -315,11 +296,11 @@ -2007-04-20T11:24:56.000000Z +2007-03-11T15:44:08.000000Z 8ed39a9d365e0613ec1d61142135e223 -2001-01-22T11:57:29.000000Z -1187 -zucchi +2006-10-16T23:10:20.309538Z +1014 +pvanhoof camel-imap-provider.c file @@ -327,12 +308,11 @@ -2007-05-12T07:58:53.000000Z -cf5bf7aaeb1268e2971b2fd5975da83a -2007-05-11T18:31:18.634404Z -7736 -sragavan -has-props +2007-05-12T08:01:04.000000Z +91499d3da894df288e2bcac03cf04092 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof camel-imap-message-cache.h file @@ -340,10 +320,9 @@ -2007-05-12T07:58:53.000000Z -bb57d0d57e49300c7bc58f32d045f4be -2007-04-28T01:42:04.098476Z -7720 -mbarnes -has-props +2007-05-12T08:01:04.000000Z +2f303f7978077de6735392d6a99e45c9 +2007-05-12T08:30:21.902504Z +1943 +pvanhoof Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-command.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-command.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-folder.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-folder.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-message-cache.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-message-cache.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-private.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-provider.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-search.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-search.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-store.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-store.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-store-summary.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-store-summary.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-summary.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-summary.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-types.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-utils.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-utils.h.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-wrapper.c.svn-base Only in /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/prop-base: camel-imap-wrapper.h.svn-base diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/text-base/camel-imap-command.c.svn-base ./providers/imap/.svn/text-base/camel-imap-command.c.svn-base --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/text-base/camel-imap-command.c.svn-base 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/.svn/text-base/camel-imap-command.c.svn-base 2007-05-12 10:17:00.000000000 +0200 @@ -60,6 +60,10 @@ static char *imap_command_strdup_printf (CamelImapStore *store, const char *fmt, ...); + + + + /** * camel_imap_command: * @store: the IMAP store @@ -93,19 +97,24 @@ { va_list ap; char *cmd; - + CAMEL_SERVICE_REC_LOCK (store, connect_lock); - + if (fmt) { va_start (ap, fmt); cmd = imap_command_strdup_vprintf (store, fmt, ap); va_end (ap); } else { - camel_object_ref(folder); - if (store->current_folder) - camel_object_unref(store->current_folder); + + /* camel_object_ref(folder); + if (store->current_folder && CAMEL_IS_OBJECT (store->current_folder)) + camel_object_unref(store->current_folder); */ + store->current_folder = folder; - cmd = imap_command_strdup_printf (store, "SELECT %F", folder->full_name); + if (store->capabilities & IMAP_CAPABILITY_CONDSTORE) + cmd = imap_command_strdup_printf (store, "SELECT %F (CONDSTORE)", folder->full_name); + else + cmd = imap_command_strdup_printf (store, "SELECT %F", folder->full_name); } if (!imap_command_start (store, folder, cmd, ex)) { @@ -118,6 +127,7 @@ return imap_read_response (store, ex); } + /** * camel_imap_command_start: * @store: the IMAP store @@ -163,13 +173,15 @@ va_start (ap, fmt); cmd = imap_command_strdup_vprintf (store, fmt, ap); va_end (ap); - + CAMEL_SERVICE_REC_LOCK (store, connect_lock); + ok = imap_command_start (store, folder, cmd, ex); g_free (cmd); - + if (!ok) CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + return ok; } @@ -178,20 +190,43 @@ const char *cmd, CamelException *ex) { ssize_t nwritten; - - g_return_val_if_fail(store->ostream!=NULL, FALSE); - g_return_val_if_fail(store->istream!=NULL, FALSE); - + gchar *resp = NULL; + CamelException myex = CAMEL_EXCEPTION_INITIALISER; + gchar *full_cmd = NULL; + guint len = 0; + + if (store->ostream == NULL || ((CamelObject *)store->ostream)->ref_count <= 0) + { + if (store->has_login && !camel_service_connect ((CamelService*)store, ex)) + return FALSE; + } + + /* g_mutex_lock (store->stream_lock); */ + + if (store->ostream==NULL) return FALSE; + if (store->istream==NULL) return FALSE; + + /* g_mutex_unlock (store->stream_lock);*/ + + + /* Also read imap_update_summary and all of the IDLE crap */ + if (!store->dontdistridlehack) + camel_imap_store_stop_idle (store); + /* else + printf ("dont distr\n"); */ + /* Check for current folder */ - if (folder && folder != store->current_folder) { + if (folder && folder != store->current_folder) + { CamelImapResponse *response; CamelException internal_ex; - + response = camel_imap_command (store, folder, ex, NULL); if (!response) return FALSE; camel_exception_init (&internal_ex); - camel_imap_folder_selected (folder, response, &internal_ex); + /* g_print ("select\n"); */ + camel_imap_folder_selected (folder, response, &internal_ex, FALSE); camel_imap_response_free (store, response); if (camel_exception_is_set (&internal_ex)) { camel_exception_xfer (ex, &internal_ex); @@ -214,19 +249,51 @@ fprintf (stderr, "sending : %c%.5u %s\r\n", store->tag_prefix, store->command, mask); } - - nwritten = camel_stream_printf (store->ostream, "%c%.5u %s\r\n", - store->tag_prefix, store->command++, cmd); - - if (nwritten == -1) { + + /* g_mutex_lock (store->stream_lock); */ + + if (store->ostream==NULL || ((CamelObject *)store->ostream)->ref_count <= 0) + { /* g_mutex_unlock (store->stream_lock); */ return FALSE; } + if (store->istream==NULL || ((CamelObject *)store->istream)->ref_count <= 0) + { /* g_mutex_unlock (store->stream_lock); */ return FALSE; } + + /* Read away whatever we got */ + while (camel_imap_store_readline_nb (store, &resp, &myex) > 0) + { + imap_debug ("unsolitcited: "); + imap_debug (resp); + imap_debug ("\n"); + + g_free (resp); + resp=NULL; + } + if (resp) + g_free (resp); + + full_cmd = g_strdup_printf ("%c%.5u %s\r\n", store->tag_prefix, + store->command++, cmd); + len = strlen (full_cmd); + + /* printf ("-> %s\n", full_cmd); */ + + nwritten = camel_stream_write (store->ostream, full_cmd, len); + + /* g_mutex_unlock (store->stream_lock); */ + + if (nwritten != len) + { + CamelException mex = CAMEL_EXCEPTION_INITIALISER; + if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); else camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, &mex); + camel_service_connect (CAMEL_SERVICE (store), &mex); + return FALSE; } @@ -253,7 +320,7 @@ camel_imap_command_continuation (CamelImapStore *store, const char *cmd, size_t cmdlen, CamelException *ex) { - if (!camel_imap_store_connected (store, ex)) + if (!camel_disco_store_check_online ((CamelDiscoStore*)store, ex)) return NULL; g_return_val_if_fail(store->ostream!=NULL, NULL); @@ -268,6 +335,7 @@ camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno)); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return NULL; } @@ -275,6 +343,7 @@ return imap_read_response (store, ex); } + /** * camel_imap_command_response: * @store: the IMAP store @@ -301,7 +370,9 @@ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return CAMEL_IMAP_RESPONSE_ERROR; } - + + /* printf ("<-- %s\n", respbuf); */ + switch (*respbuf) { case '*': if (!g_ascii_strncasecmp (respbuf, "* BYE", 5)) { @@ -344,10 +415,67 @@ break; } *response = respbuf; - + if (type == CAMEL_IMAP_RESPONSE_ERROR || - type == CAMEL_IMAP_RESPONSE_TAGGED) + type == CAMEL_IMAP_RESPONSE_TAGGED) CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); + + return type; +} + + +CamelImapResponseType +camel_imap_command_response_idle (CamelImapStore *store, char **response, + CamelException *ex) +{ + CamelImapResponseType type; + char *respbuf; + + if (camel_imap_store_readline (store, &respbuf, ex) < 0) + return CAMEL_IMAP_RESPONSE_ERROR; + + switch (*respbuf) { + case '*': + if (!g_ascii_strncasecmp (respbuf, "* BYE", 5)) { + /* Connection was lost, no more data to fetch */ + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Server unexpectedly disconnected: %s"), + _("Unknown error")); /* g_strerror (104)); FIXME after 1.0 is released */ + store->connected = FALSE; + g_free (respbuf); + respbuf = NULL; + type = CAMEL_IMAP_RESPONSE_ERROR; + break; + } + + /* Read the rest of the response. */ + type = CAMEL_IMAP_RESPONSE_UNTAGGED; + respbuf = imap_read_untagged (store, respbuf, ex); + if (!respbuf) + type = CAMEL_IMAP_RESPONSE_ERROR; + else if (!g_ascii_strncasecmp (respbuf, "* OK [ALERT]", 12) + || !g_ascii_strncasecmp (respbuf, "* NO [ALERT]", 12) + || !g_ascii_strncasecmp (respbuf, "* BAD [ALERT]", 13)) { + char *msg; + + /* for imap ALERT codes, account user@host */ + /* we might get a ']' from a BAD response since we +12, but who cares? */ + msg = g_strdup_printf(_("Alert from IMAP server %s@%s:\n%s"), + ((CamelService *)store)->url->user, ((CamelService *)store)->url->host, respbuf+12); + camel_session_alert_user(((CamelService *)store)->session, CAMEL_SESSION_ALERT_WARNING, msg, FALSE); + g_free(msg); + } else if (!g_ascii_strncasecmp (respbuf, "* BAD Invalid tag",17)) + type = CAMEL_IMAP_RESPONSE_ERROR; + break; + case '+': + type = CAMEL_IMAP_RESPONSE_CONTINUATION; + break; + default: + type = CAMEL_IMAP_RESPONSE_TAGGED; + break; + } + *response = respbuf; return type; } @@ -364,8 +492,9 @@ * we're still locked. This lock is owned by response * and gets unlocked when response is freed. */ + CAMEL_SERVICE_REC_LOCK (store, connect_lock); - + response = g_new0 (CamelImapResponse, 1); if (store->current_folder && camel_disco_store_status (CAMEL_DISCO_STORE (store)) != CAMEL_DISCO_STORE_RESYNCING) { response->folder = store->current_folder; @@ -383,7 +512,7 @@ } response->status = respbuf; - + /* Check for OK or continuation response. */ if (*respbuf == '+') return response; @@ -622,6 +751,7 @@ } g_free (response); + CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); } @@ -780,8 +910,9 @@ } else if (*p == 'G') { string = camel_utf8_utf7(string); } - - arglen = strlen (string); + + if (string) + arglen = strlen (string); g_ptr_array_add (args, string); if (imap_is_atom (string)) { len += arglen; diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/text-base/camel-imap-command.h.svn-base ./providers/imap/.svn/text-base/camel-imap-command.h.svn-base --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/text-base/camel-imap-command.h.svn-base 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/.svn/text-base/camel-imap-command.h.svn-base 2007-05-12 10:01:04.000000000 +0200 @@ -74,6 +74,9 @@ char **respbuf, CamelException *ex); +CamelImapResponseType camel_imap_command_response_idle (CamelImapStore *store, char **response, + CamelException *ex); + G_END_DECLS #endif /* CAMEL_IMAP_COMMAND_H */ diff -ru /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/text-base/camel-imap-folder.c.svn-base ./providers/imap/.svn/text-base/camel-imap-folder.c.svn-base --- /home/pvanhoof/repos/gnome/evolution-data-server/camel/providers/imap/.svn/text-base/camel-imap-folder.c.svn-base 2007-05-12 09:58:53.000000000 +0200 +++ ./providers/imap/.svn/text-base/camel-imap-folder.c.svn-base 2007-05-12 10:15:55.000000000 +0200 @@ -1,10 +1,15 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.c: class for an imap folder */ - -/* +/* camel-imap-folder.c: class for an imap folder + * + * This is the mmap version of camel-imap-folder.c which has a memory + * consumption reduced imap_update_summary implementation that will + * periodically instruct the mmap CamelFolderSummary instance to sync + * headers to disk. + * * Authors: * Dan Winship * Jeffrey Stedfast + * Philip Van Hoof * * Copyright (C) 2000, 2001 Ximian, Inc. * @@ -23,6 +28,11 @@ * USA */ +/* BODY always returns "textual data", which means a series of characters + no containing NUL, CR, or LF, of length <= 1000.*/ + +#define MAX_LINE_LEN 1024 + #include #include @@ -39,6 +49,7 @@ #include #include + #include "camel-data-wrapper.h" #include "camel-debug.h" #include "camel-disco-diary.h" @@ -71,6 +82,9 @@ #include "camel-imap-utils.h" #include "camel-imap-wrapper.h" + +#include + #define d(x) /* set to -1 for infinite size (suggested max command-line length is @@ -86,7 +100,8 @@ static void imap_finalize (CamelObject *object); static int imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args); -static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex); +static gboolean imap_rescan_condstore (CamelFolder *folder, int exists, const char *highestmodseq, CamelException *ex); +static gboolean imap_rescan (CamelFolder *folder, int exists, CamelException *ex); static void imap_refresh_info (CamelFolder *folder, CamelException *ex); static void imap_sync_online (CamelFolder *folder, CamelException *ex); static void imap_sync_offline (CamelFolder *folder, CamelException *ex); @@ -95,10 +110,11 @@ static void imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex); static void imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex); static void imap_rename (CamelFolder *folder, const char *new); +static void imap_set_push_email (CamelFolder *folder, gboolean setting); /* message manipulation */ static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, - CamelException *ex); + CamelFolderReceiveType type, gint param, CamelException *ex); static void imap_append_online (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex); @@ -132,6 +148,10 @@ static CamelObjectClass *parent_class; static GData *parse_fetch_response (CamelImapFolder *imap_folder, char *msg_att); +static void camel_imap_folder_changed_for_idle (CamelFolder *folder, int exists, + GArray *expunged, CamelException *ex); + +GPtrArray* _camel_imap_store_get_recent_messages (CamelImapStore *imap_store, const char *folder_name, int *messages, int *unseen, gboolean withthem); #ifdef G_OS_WIN32 /* The strtok() in Microsoft's C library is MT-safe (but still uses @@ -141,6 +161,8 @@ #define strtok_r(s,sep,lasts) (*(lasts)=strtok((s),(sep))) #endif + + static void camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) { @@ -152,6 +174,7 @@ /* virtual method overload */ ((CamelObjectClass *)camel_imap_folder_class)->getv = imap_getv; + camel_folder_class->set_push_email = imap_set_push_email; camel_folder_class->get_message = imap_get_message; camel_folder_class->rename = imap_rename; camel_folder_class->search_by_expression = imap_search_by_expression; @@ -178,12 +201,21 @@ camel_disco_folder_class->cache_message = imap_cache_message; } + static void camel_imap_folder_init (gpointer object, gpointer klass) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); CamelFolder *folder = CAMEL_FOLDER (object); - + + /* ((CamelObject *)folder)-> flags |= CAMEL_OBJECT_REF_DEBUG; */ + + imap_folder->idle_lock = g_new0 (GStaticRecMutex, 1); + g_static_rec_mutex_init (imap_folder->idle_lock); + imap_folder->stopping = FALSE; + imap_folder->in_idle = FALSE; + + imap_folder->do_push_email = TRUE; folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; @@ -229,7 +261,7 @@ const char *short_name; char *summary_file, *state_file; - if (g_mkdir_with_parents (folder_dir, S_IRWXU) != 0) { + if (e_util_mkdir_hier (folder_dir, S_IRWXU) != 0) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create directory %s: %s"), folder_dir, g_strerror (errno)); @@ -237,6 +269,10 @@ } folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); + imap_folder = CAMEL_IMAP_FOLDER (folder); + + imap_folder->folder_dir = g_strdup (folder_dir); + short_name = strrchr (folder_name, '/'); if (short_name) short_name++; @@ -244,7 +280,7 @@ short_name = folder_name; camel_folder_construct (folder, parent, folder_name, short_name); - summary_file = g_strdup_printf ("%s/summary", folder_dir); + summary_file = g_strdup_printf ("%s/summary.mmap", folder_dir); folder->summary = camel_imap_summary_new (folder, summary_file); g_free (summary_file); if (!folder->summary) { @@ -261,8 +297,8 @@ g_free(state_file); camel_object_state_read(folder); - imap_folder = CAMEL_IMAP_FOLDER (folder); imap_folder->cache = camel_imap_message_cache_new (folder_dir, folder->summary, ex); + if (!imap_folder->cache) { camel_object_unref (CAMEL_OBJECT (folder)); return NULL; @@ -278,15 +314,78 @@ folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK; } + if (imap_store->capabilities & IMAP_CAPABILITY_IDLE) + folder->folder_flags |= CAMEL_FOLDER_HAS_PUSHEMAIL_CAPABILITY; + imap_folder->search = camel_imap_search_new(folder_dir); return folder; } + +static void +put_highestmodseq (CamelImapFolder *imap_folder, const char *highestmodseq) +{ + char *filename = g_strdup_printf ("%s/highestmodseq", imap_folder->folder_dir); + FILE *file; + + file = fopen (filename, "w"); + g_free (filename); + + if (file != NULL) + { + fprintf (file, "%s", highestmodseq); + fclose (file); + } +} + +static char* +get_highestmodseq (CamelImapFolder *imap_folder) +{ + char *filename = g_strdup_printf ("%s/highestmodseq", imap_folder->folder_dir); + char *retval = NULL; + FILE *file; + + file = fopen (filename, "r"); + g_free (filename); + + if (file != NULL) + { + retval = g_malloc0 (25); /* a 64bit number must fit in it */ + fscanf (file, "%s", retval); + fclose (file); + } + + return retval; +} + /* Called with the store's connect_lock locked */ + + +/* +The assumption we have to make is that any folder can have been offline +before it got here to become selected. + +Which is nasty because that means that our IDLE code might not have kept it +synchronized. We might not have been notified by EXISTS, FETCH and EXPUNGE +unsolicited events (you can't assume that). + +We also can't assume the availability of HIGHESTMODSEQ (or CONDSTORE). Not +even if the IMAP service announced the condstore capability. That's because +condstore is to be enabled per mailbox! + +UIDNEXT might be incorrect, I have seen IMAP servers that simply get it wrong. + +Although it has been reported that Exchange's IMAP server sometimes gives to high +values for EXISTS, it's quite safe to assume that the EXISTS is going to be +correct on most servers. Just don't crash on sequences that don't exist remote. + +More documentation inline +*/ + void camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, - CamelException *ex) + CamelException *ex, gboolean idle) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary); @@ -294,13 +393,29 @@ CamelMessageInfo *info; guint32 perm_flags = 0; GData *fetch_data; - int i, count; - char *resp; - + int i, count, uidnext = -1; + char *resp, *phighestmodseq = NULL, *highestmodseq = NULL; + CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + gboolean removals = FALSE, condstore = FALSE, needtoput=FALSE, suc=FALSE; + count = camel_folder_summary_count (folder->summary); - - for (i = 0; i < response->untagged->len; i++) { + + /* With CONDSTORE this is the typical output. + * C: A142 SELECT INBOX (CONDSTORE) + * S: * 172 EXISTS + * S: * 1 RECENT + * S: * OK [UNSEEN 12] Message 12 is first unseen + * S: * OK [UIDVALIDITY 3857529045] UIDs valid + * S: * OK [UIDNEXT 4392] Predicted next UID + * S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) + * S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited + * S: * OK [HIGHESTMODSEQ 715194045007] + * S: A142 OK [READ-WRITE] SELECT completed, CONDSTORE is now enabled */ + + for (i = 0; i < response->untagged->len; i++) + { resp = response->untagged->pdata[i] + 2; + if (!g_ascii_strncasecmp (resp, "FLAGS ", 6) && !perm_flags) { resp += 6; folder->permanent_flags = imap_parse_flag_list (&resp); @@ -311,6 +426,44 @@ * even tho they do allow storing flags. *Sigh* So many fucking broken IMAP servers out there. */ if ((perm_flags = imap_parse_flag_list (&resp)) != 0) folder->permanent_flags = perm_flags; + } else if (!g_ascii_strncasecmp (resp, "OK [UIDNEXT ", 12)) { + char *marker = strchr (resp, ']'); + if (marker) *marker='\0'; + uidnext = strtoul (resp + 12, NULL, 10); + } else if (!g_ascii_strncasecmp (resp, "OK [HIGHESTMODSEQ ", 18)) + { + + /* So we have a HIGHESTMODSEQ, we are going to store this + * one assuming that our code that will follow is correct + * and that after that upcoming code, the local folder + * state will be in sync with that remote HIGHESTMODSEQ + * value. */ + + char *marker; + unsigned int len; + resp += 18; + + marker = strchr (resp, ']'); + + if (marker) + { + condstore = TRUE; + len = (unsigned int) (marker - resp); + + highestmodseq = g_strndup (resp, len); + phighestmodseq = get_highestmodseq (imap_folder); + + if (phighestmodseq !=NULL && !strcmp (phighestmodseq, highestmodseq)) + { + g_free (phighestmodseq); + phighestmodseq = NULL; + } else + needtoput = TRUE; + } else { + phighestmodseq = NULL; + highestmodseq = NULL; + } + } else if (!g_ascii_strncasecmp (resp, "OK [UIDVALIDITY ", 16)) { validity = strtoul (resp + 16, NULL, 10); } else if (isdigit ((unsigned char)*resp)) { @@ -319,8 +472,7 @@ if (!g_ascii_strncasecmp (resp, " EXISTS", 7)) { exists = num; /* Remove from the response so nothing - * else tries to interpret it. - */ + * else tries to interpret it. */ g_free (response->untagged->pdata[i]); g_ptr_array_remove_index (response->untagged, i--); } @@ -328,18 +480,31 @@ } if (camel_strstrcase (response->status, "OK [READ-ONLY]")) + { + folder->folder_flags |= CAMEL_FOLDER_IS_READONLY; imap_folder->read_only = TRUE; + } - if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) { + if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) + { + if (phighestmodseq != NULL) + g_free (phighestmodseq); + if (highestmodseq != NULL) + g_free (highestmodseq); + if (validity != imap_summary->validity) { camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID, _("Folder was destroyed and recreated on server.")); return; } - + /* FIXME: find missing UIDs ? */ return; } + + /* If there's no match on VALIDITY, we are dealing with a different + * folder. For example the folder got removed and re-created. We'll + * simply clear everyting and do things from scratch. */ if (!imap_summary->validity) imap_summary->validity = validity; @@ -351,82 +516,163 @@ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); imap_folder->need_rescan = FALSE; camel_imap_folder_changed (folder, exists, NULL, ex); + + if (phighestmodseq != NULL) + g_free (phighestmodseq); + if (highestmodseq != NULL) + g_free (highestmodseq); + return; } + + /* If we already had stuff locally, get the last one's UID . Store it in + * what we will start calling VAL */ - /* If we've lost messages, we have to rescan everything */ - if (exists < count) - imap_folder->need_rescan = TRUE; - else if (count != 0 && !imap_folder->need_rescan) { - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - - /* Similarly, if the UID of the highest message we - * know about has changed, then that indicates that - * messages have been both added and removed, so we - * have to rescan to find the removed ones. (We pass - * NULL for the folder since we know that this folder - * is selected, and we don't want camel_imap_command - * to worry about it.) - */ - response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count); - if (!response) - return; - uid = 0; - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - val = strtoul (resp + 2, &resp, 10); - if (val == 0) - continue; - if (!g_ascii_strcasecmp (resp, " EXISTS")) { - /* Another one?? */ - exists = val; - continue; - } - if (uid != 0 || val != count || g_ascii_strncasecmp (resp, " FETCH (", 8) != 0) - continue; - - fetch_data = parse_fetch_response (imap_folder, resp + 7); - uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10); - g_datalist_clear (&fetch_data); - } - camel_imap_response_free_without_processing (store, response); - + if (count > 0) + { info = camel_folder_summary_index (folder->summary, count - 1); val = strtoul (camel_message_info_uid (info), NULL, 10); camel_message_info_free(info); - if (uid == 0 || uid != val) - imap_folder->need_rescan = TRUE; + } else + val = -1; + + /* If we are going the CONDSTORE route and if (uidnext-1) is not the + * same as the last uid in our summary, it's very likely that expunges + * happened. This CONDSTORE code does not yet support expunges. + * Therefore we will simply use the old code. */ + + if (phighestmodseq != NULL && (val != uidnext-1)) + { + g_free (phighestmodseq); + phighestmodseq = NULL; + removals = TRUE; } + + /* If our local count isn't the same as the EXISTS, then our CONDSTORE + * implementation can't be used. Period. */ - /* Now rescan if we need to */ - if (imap_folder->need_rescan) { - imap_rescan (folder, exists, ex); - return; + if (exists != count) + { + if (phighestmodseq != NULL) + g_free (phighestmodseq); + phighestmodseq = NULL; + removals = TRUE; } - - /* If we don't need to rescan completely, but new messages - * have been added, find out about them. - */ - if (exists > count) + + if (removals) + imap_folder->need_rescan = TRUE; + else if (condstore && (store->capabilities & IMAP_CAPABILITY_CONDSTORE)) + imap_folder->need_rescan = FALSE; + + /* We still aren't certain. For example if at the end of the mailbox + * both an add and an expunge happened, then all of above figured out + * nothing meaningful. So we will compare the last local uid with the + * remote uid at the same sequence number (that's count, as the count + * is the index + 1). This is where we need the VAL thingy of above. */ + + if (!imap_folder->need_rescan) + { + int mval = 0; + + /* If the UID of the highest message we know about has changed, + * then that indicates that messages have been both added and + * removed, so we have to rescan to find the removed ones */ + + response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count); + if (response) { + uid = 0; + for (i = 0; i < response->untagged->len; i++) + { + resp = response->untagged->pdata[i]; + mval = strtoul (resp + 2, &resp, 10); + if (mval == 0) + continue; + if (!g_ascii_strcasecmp (resp, " EXISTS")) + { + /* Another one?? */ + exists = mval; + continue; + } + if (uid != 0 || mval != count || g_ascii_strncasecmp (resp, " FETCH (", 8) != 0) + continue; + + fetch_data = parse_fetch_response (imap_folder, resp + 7); + uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10); + g_datalist_clear (&fetch_data); + } + camel_imap_response_free_without_processing (store, response); + if (uid == 0 || uid != val) + imap_folder->need_rescan = TRUE; + } else + imap_folder->need_rescan = TRUE; + } + + /* Okay, it survived ALL checks and CONDSTORE is available too. Lucky we + * are, aren't we? So we use CONDSTORE. Note, however, that if condstore + * still finds removals (sequences don't match) or if anything goes wrong + * during the CONDSTORE code, that it'll set need_rescan TRUE and that + * as a result the lines below this if{} block will still happen. This is + * indeed on purpose and as a fall-back situation (our detection got it + * wrong) */ + + if (phighestmodseq) + { + if (!imap_folder->need_rescan) + suc = imap_rescan_condstore (folder, exists, phighestmodseq, ex); + g_free (phighestmodseq); + phighestmodseq = NULL; + } + + if (imap_folder->need_rescan) + suc = imap_rescan (folder, exists, ex); + else if (exists > count) camel_imap_folder_changed (folder, exists, NULL, ex); - - /* And we're done. */ + + if (highestmodseq != NULL && suc && needtoput) + put_highestmodseq (imap_folder, (const char *) highestmodseq); + + if (highestmodseq != NULL) + g_free (highestmodseq); + + if (idle) + camel_imap_folder_start_idle (folder); } -static void +static void imap_finalize (CamelObject *object) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); + CamelImapStore *store = CAMEL_IMAP_STORE (CAMEL_FOLDER(imap_folder)->parent_store); + + imap_folder->do_push_email = FALSE; + + imap_folder->stopping = TRUE; + + if (imap_folder->idle_signal > 0) + g_source_remove (imap_folder->idle_signal); + + if (!imap_folder->in_idle || imap_folder->idle_lock != NULL) + { + g_static_rec_mutex_free (imap_folder->idle_lock); + imap_folder->idle_lock = NULL; + } + + if (store->current_folder == (CamelFolder*) object) + store->current_folder = NULL; if (imap_folder->search) camel_object_unref (CAMEL_OBJECT (imap_folder->search)); if (imap_folder->cache) camel_object_unref (CAMEL_OBJECT (imap_folder->cache)); + if (imap_folder->folder_dir) + g_free (imap_folder->folder_dir); + #ifdef ENABLE_THREADS g_static_mutex_free(&imap_folder->priv->search_lock); g_static_rec_mutex_free(&imap_folder->priv->cache_lock); #endif + g_free(imap_folder->priv); } @@ -519,21 +765,20 @@ * should do it. */ CAMEL_SERVI