diff options
22 files changed, 654 insertions, 279 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index bc2909c56e..43b31ae2d7 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,139 @@ +2000-11-30 Not Zed <NotZed@HelixCode.com> + + * providers/local/camel-mbox-folder.c (mbox_get_message): Remove + assertion that content is there, when it no longer can be. + + * camel-folder-summary.h: Removed pos/bodypos/endpos from + camelmeessagecontentinfo. + (CamelMessageFlags): Added an attachments flag. + + * providers/local/camel-local-summary.h: Added load virtual + function. + + * tests/lib/folders.c (test_message_info): Accessors. + (test_folder_message): " + + * camel-folder-thread.c (get_root_subject): Fix accessors. + (dump_tree_rec): " + + * camel-folder-search.c (camel_folder_search_execute_expression): + Accessors for messageinfo. + (search_match_all): " + (search_header_contains): " + (search_header_contains): " + (search_body_contains): " + (camel_folder_search_execute_expression): Use mepool_strdup. + + * providers/local/camel-mbox-summary.c (summary_update): Accessors + for messageinfo. + (mbox_summary_sync_full): " + + * providers/local/camel-mh-summary.c (remove_summary): Accessors + for messageinfo. + (mh_summary_check): " + (mh_summary_sync_message): " + (mh_summary_sync): " + + * providers/local/camel-mh-folder.c (mh_append_message): Use + accessor for uid. + + * providers/local/camel-local-summary.c + (local_summary_decode_x_evolution): Use accessor to uid. + (local_summary_encode_x_evolution): Likewise. + (message_info_new): And here. + (camel_local_summary_load): Call virtual load function. + (local_summary_load): Default load function, load summary. + (camel_local_summary_load): Check file exists before trying to + load. + (camel_local_summary_construct): Turn off building content info! + (CAMEL_LOCAL_SUMMARY_VERSION): Bump, since we dont build content + info anymore. + (camel_local_summary_load): After a successful load/check, do a + save too so we dont have to go through it again randomly. + + * providers/nntp/camel-nntp-utils.c (get_XOVER_headers): Use + accessors for messageinfo. + + * providers/nntp/camel-nntp-folder.c (nntp_folder_get_uids): Use + accessors for uid. + + * providers/imap/camel-imap-folder.c (imap_refresh_info): Use + accessor for uid. + (imap_sync): Likewise. + (imap_get_uids): Likewise. + (imap_update_summary): And here. + + * providers/vee/camel-vee-folder.c (vfolder_remove_match): Use + accessor for uid. + (vfolder_add_match): Handle estrv stuff. + (vfolder_change_match): Accessor for uid. + (get_real_message): " + (vee_get_uids): " + (vee_folder_build): " + estrv. + (vee_folder_build_folder): " + + * providers/local/camel-maildir-folder.c (maildir_append_message): + Use acccessors for uid's. + (maildir_get_message): Here too. + + * providers/local/camel-maildir-summary.c + (camel_maildir_summary_init): Setup the string count for us. + (message_info_new): Access the string array directly. + (message_info_free): No need to free string if using array. + (camel_maildir_summary_info_to_name): Use accessor to get to uid. + (remove_summary): And here. + (maildir_summary_check): Likewise. + (maildir_summary_sync): And here. + (maildir_summary_load): Load up a cache of uid->filename mappings + before loading the actual summary file. This saves us having to + waste the diskspace storing the filenames in the summary itself, + and also helps us sync the summary better on load. + (message_info_load): If we have the load_map setup, and the uid + exists, then set the filename cache from it, and update the flags + from the name, incase our summary mismatches it. + + * camel-folder-summary.c (camel_folder_summary_init): Setup string + count for compressed info record. An optional compile mode which + stores all strings for a given messageinfo into a packed array, + which should save 36-50 bytes/record. + (camel_folder_summary_info_new): Init the string array. + (message_info_new): Set the string array items, as required. + (message_info_load): And here too. + (message_info_save): Use accessors to get to strings. + (message_info_free): Free strings as one. + (camel_message_info_dup_to): Handle packed array case. + (camel_folder_summary_add): Use accessors. And pack the strv + before storing it. + (summary_assign_uid): New function to assign a unique uid to a + message, if it doesn't have one. + (camel_folder_summary_add): Call assign_uid instead of doing it + ourselves. + (camel_folder_summary_info_new_from_parser): " + (camel_folder_summary_info_new_from_message): " + (camel_folder_summary_encode_string): constify. + (camel_folder_summary_encode_token): " + (summary_build_content_info_message): Fix accessors to messageinfo. + (CAMEL_FOLDER_SUMMARY_VERSION): Bumped, for removal of + contentinfo->pos data. + (camel_folder_summary_info_new_from_parser): Calculate the size + based on the parser position, not the removed contentinfo stuff. + (camel_folder_summary_info_new_from_message): Remove size stuff. + (camel_folder_summary_offset_content): Removed, no longer means anything. + (content_info_new): + (content_info_load): + (content_info_save): + (summary_build_content_info): Remove stuff for contentinfo->pos*. + (summary_build_content_info): Take a msginfo argument, set + attachments flag if we find any attachments. + (summary_build_content_info_message): set attachments flag if we + find any attachments. + (camel_folder_summary_info_new_from_parser): Always scan the + content info, even if we dont save it. + (camel_folder_summary_info_new_from_message): And here too. + (summary_build_content_info): Only create the contentinfo stuff if + we have it turned on, otherwise just parse and discard. + (summary_build_content_info_message): Likewise. + 2000-11-29 Jeffrey Stedfast <fejj@helixcode.com> * camel-store.c (camel_store_get_folder): Updated the gtk-doc diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index 8bd1e90b24..0376dd9fef 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -118,7 +118,7 @@ camel_folder_search_finalize (CamelObject *obj) /* yeah, this is a gtk object */ if (search->sexp) - gtk_object_unref(search->sexp); + gtk_object_unref((GtkObject *)search->sexp); g_free(search->last_search); g_hash_table_foreach(p->mempool_hash, free_mempool, obj); @@ -323,19 +323,16 @@ camel_folder_search_execute_expression(CamelFolderSearch *search, const char *ex } for (i=0;i<search->summary->len;i++) { CamelMessageInfo *info = g_ptr_array_index(search->summary, i); - if (g_hash_table_lookup(results, info->uid)) { - char *s = e_mempool_alloc(pool, strlen(info->uid) + 1); - strcpy(s, info->uid); - g_ptr_array_add(matches, s); + char *uid = (char *)camel_message_info_uid(info); + if (g_hash_table_lookup(results, uid)) { + g_ptr_array_add(matches, e_mempool_strdup(pool, uid)); } } g_hash_table_destroy(results); } else { for (i=0;i<r->value.ptrarray->len;i++) { - char *s = e_mempool_alloc(pool, strlen(g_ptr_array_index(r->value.ptrarray, i)) + 1); d(printf("adding match: %s\n", (char *)g_ptr_array_index(r->value.ptrarray, i))); - strcpy(s, g_ptr_array_index(r->value.ptrarray, i)); - g_ptr_array_add(matches, s); + g_ptr_array_add(matches, e_mempool_strdup(pool, g_ptr_array_index(r->value.ptrarray, i))); } } e_sexp_result_free(r); @@ -441,13 +438,13 @@ search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFold r1 = e_sexp_term_eval(f, argv[0]); if (r1->type == ESEXP_RES_BOOL) { if (r1->value.bool) - g_ptr_array_add(r->value.ptrarray, search->current->uid); + g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(search->current)); } else { g_warning("invalid syntax, matches require a single bool result"); } e_sexp_result_free(r1); } else { - g_ptr_array_add(r->value.ptrarray, search->current->uid); + g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(search->current)); } search->current = NULL; @@ -467,13 +464,13 @@ search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFold r1 = e_sexp_term_eval(f, argv[0]); if (r1->type == ESEXP_RES_BOOL) { if (r1->value.bool) - g_ptr_array_add(r->value.ptrarray, search->current->uid); + g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(search->current)); } else { g_warning("invalid syntax, matches require a single bool result"); } e_sexp_result_free(r1); } else { - g_ptr_array_add(r->value.ptrarray, search->current->uid); + g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(search->current)); } } search->current = NULL; @@ -492,24 +489,25 @@ search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, C /* are we inside a match-all? */ if (search->current && argc>1 && argv[0]->type == ESEXP_RES_STRING) { - char *headername, *header = NULL; + char *headername; + const char *header = NULL; char strbuf[32]; int i; /* only a subset of headers are supported .. */ headername = argv[0]->value.string; if (!strcasecmp(headername, "subject")) { - header = search->current->subject; + header = camel_message_info_subject(search->current); } else if (!strcasecmp(headername, "date")) { /* FIXME: not a very useful form of the date */ sprintf(strbuf, "%d", (int)search->current->date_sent); header = strbuf; } else if (!strcasecmp(headername, "from")) { - header = search->current->from; + header = camel_message_info_from(search->current); } else if (!strcasecmp(headername, "to")) { - header = search->current->to; + header = camel_message_info_to(search->current); } else if (!strcasecmp(headername, "cc")) { - header = search->current->cc; + header = camel_message_info_cc(search->current); } else { g_warning("Performing query on unknown header: %s", headername); } @@ -519,7 +517,7 @@ search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, C for (i=1;i<argc && !truth;i++) { if (argv[i]->type == ESEXP_RES_STRING && e_utf8_strstrcase (header, argv[i]->value.string)) { - r(printf("%s got a match with %s of %s\n", search->current->uid, header, argv[i]->value.string)); + r(printf("%s got a match with %s of %s\n", camel_message_info_uid(search->current), header, argv[i]->value.string)); truth = TRUE; break; } @@ -661,7 +659,8 @@ search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, Cam if (search->body_index) { for (i=0;i<argc && !truth;i++) { if (argv[i]->type == ESEXP_RES_STRING) { - truth = ibex_find_name(search->body_index, search->current->uid, argv[i]->value.string); + truth = ibex_find_name(search->body_index, (char *)camel_message_info_uid(search->current), + argv[i]->value.string); } else { g_warning("Invalid type passed to body-contains match function"); } @@ -669,7 +668,7 @@ search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, Cam } else if (search->folder) { /* we do a 'slow' direct search */ if (build_match_regex(&pattern, argc, argv) == 0) { - truth = match_message(search->folder, search->current->uid, &pattern); + truth = match_message(search->folder, camel_message_info_uid(search->current), &pattern); regfree(&pattern); } } else { @@ -713,8 +712,8 @@ search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, Cam for (i=0;i<search->summary->len;i++) { CamelMessageInfo *info = g_ptr_array_index(search->summary, i); - if (match_message(search->folder, info->uid, &pattern)) - g_ptr_array_add(r->value.ptrarray, info->uid); + if (match_message(search->folder, camel_message_info_uid(info), &pattern)) + g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(info)); } } /* else? we could always get the summary from the folder, but then we need to free it later somehow */ diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index 12e276245d..4879d547ee 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -53,7 +53,7 @@ extern int strdup_count, malloc_count, free_count; #endif -#define CAMEL_FOLDER_SUMMARY_VERSION (10) +#define CAMEL_FOLDER_SUMMARY_VERSION (11) struct _CamelFolderSummaryPrivate { GHashTable *filter_charset; /* CamelMimeFilterCharset's indexed by source charset */ @@ -95,7 +95,7 @@ static void content_info_free(CamelFolderSummary *, CamelMessageConten static char *next_uid_string(CamelFolderSummary *s); -static CamelMessageContentInfo * summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp); +static CamelMessageContentInfo * summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimeParser *mp); static CamelMessageContentInfo * summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimePart *object); static void camel_folder_summary_class_init (CamelFolderSummaryClass *klass); @@ -144,6 +144,10 @@ camel_folder_summary_init (CamelFolderSummary *s) s->message_info_chunks = NULL; s->content_info_chunks = NULL; +#ifdef DOESTRV + s->message_info_strings = CAMEL_MESSAGE_INFO_LAST; +#endif + s->version = CAMEL_FOLDER_SUMMARY_VERSION; s->flags = 0; s->time = 0; @@ -247,8 +251,7 @@ void camel_folder_summary_set_filename(CamelFolderSummary *s, const char *name) * 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. * - * Also see :set_build_content(), which must be enabled to perform - * body indexing. + * Unlike earlier behaviour, build_content need not be set to perform indexing. **/ void camel_folder_summary_set_index(CamelFolderSummary *s, ibex *index) { @@ -265,8 +268,6 @@ void camel_folder_summary_set_index(CamelFolderSummary *s, ibex *index) * Set a flag to tell the summary to build the content info summary * (CamelMessageInfo.content). The default is not to build content info * summaries. - * - * This flag must also be set to on to perform indexing, see :set_index(). **/ void camel_folder_summary_set_build_content(CamelFolderSummary *s, gboolean state) { @@ -503,6 +504,25 @@ camel_folder_summary_save(CamelFolderSummary *s) return 0; } +static void +summary_assign_uid(CamelFolderSummary *s, CamelMessageInfo *info) +{ + const char *uid; + + uid = camel_message_info_uid(info); + if (uid == NULL || uid[0] == 0) { + camel_message_info_set_uid(info, camel_folder_summary_next_uid_string(s)); + uid = camel_message_info_uid(info); + } + + while (g_hash_table_lookup(s->messages_uid, uid)) { + g_warning("Trying to insert message with clashing uid (%s). new uid re-assigned", camel_message_info_uid(info)); + camel_message_info_set_uid(info, camel_folder_summary_next_uid_string(s)); + uid = camel_message_info_uid(info); + info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; + } +} + /** * camel_folder_summary_add: * @s: @@ -520,18 +540,16 @@ void camel_folder_summary_add(CamelFolderSummary *s, CamelMessageInfo *info) if (info == NULL) return; - if (info->uid == NULL) - info->uid = camel_folder_summary_next_uid_string(s); + summary_assign_uid(s, info); - while (g_hash_table_lookup(s->messages_uid, info->uid)) { - g_warning("Trying to insert message with clashing uid (%s). new uid re-assigned", info->uid); - g_free(info->uid); - info->uid = camel_folder_summary_next_uid_string(s); - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - } +#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_hash_table_insert(s->messages_uid, info->uid, info); + g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); s->flags |= CAMEL_SUMMARY_DIRTY; } @@ -636,9 +654,11 @@ CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary * char *buffer; int len; struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); + off_t start; /* 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) != HSCAN_EOF) { info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_parser(s, mp); @@ -646,30 +666,18 @@ CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary * /* 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 (info->uid == NULL) - info->uid = camel_folder_summary_next_uid_string(s); - - while (g_hash_table_lookup(s->messages_uid, info->uid)) { - g_free(info->uid); - info->uid = camel_folder_summary_next_uid_string(s); - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - } + summary_assign_uid(s, info); if (p->index) { if (p->filter_index == NULL) p->filter_index = camel_mime_filter_index_new_ibex(p->index); - camel_mime_filter_index_set_name(p->filter_index, info->uid); - ibex_unindex(p->index, info->uid); + camel_mime_filter_index_set_name(p->filter_index, (char *)camel_message_info_uid(info)); + ibex_unindex(p->index, (char *)camel_message_info_uid(info)); } - /* build the content info, if we're supposed to */ - if (s->build_content) { - info->content = summary_build_content_info(s, mp); - if (info->content->pos != -1) - info->size = info->content->endpos - info->content->pos; - } else { - camel_mime_parser_drop_step(mp); - } + /* always scan the content info, even if we dont save it */ + info->content = summary_build_content_info(s, info, mp); + info->size = camel_mime_parser_tell(mp) - start; } return info; } @@ -692,24 +700,14 @@ CamelMessageInfo *camel_folder_summary_info_new_from_message(CamelFolderSummary /* 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 (info->uid == NULL) - info->uid = camel_folder_summary_next_uid_string(s); - - while (g_hash_table_lookup(s->messages_uid, info->uid)) { - g_free(info->uid); - info->uid = camel_folder_summary_next_uid_string(s); - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - } + summary_assign_uid(s, info); if (p->index) - ibex_unindex(p->index, info->uid); + ibex_unindex(p->index, (char *)camel_message_info_uid(info)); - /* build the content info, if we're supposed to */ - if (s->build_content) { - info->content = summary_build_content_info_message(s, info, (CamelMimePart *)msg); - if (info->content->pos != -1) - info->size = info->content->endpos - info->content->pos; - } + info->content = summary_build_content_info_message(s, info, (CamelMimePart *)msg); + /* FIXME: calculate the size as part of build_content_info_message */ + /* info->size = ... */ return info; } @@ -794,7 +792,7 @@ camel_folder_summary_clear(CamelFolderSummary *s) **/ void camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info) { - g_hash_table_remove(s->messages_uid, info->uid); + g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); g_ptr_array_remove(s->messages, info); camel_folder_summary_info_free(s, info); s->flags |= CAMEL_SUMMARY_DIRTY; @@ -1089,7 +1087,7 @@ token_search_cmp(char *key, char **index) * Return value: -1 on error. **/ int -camel_folder_summary_encode_token(FILE *out, char *str) +camel_folder_summary_encode_token(FILE *out, const char *str) { io(printf("Encoding token: '%s'\n", str)); @@ -1195,7 +1193,7 @@ camel_folder_summary_decode_token(FILE *in, char **str) * Return value: -1 on error. **/ int -camel_folder_summary_encode_string(FILE *out, char *str) +camel_folder_summary_encode_string(FILE *out, const char *str) { register int len; @@ -1256,26 +1254,6 @@ camel_folder_summary_decode_string(FILE *in, char **str) return 0; } -/** - * camel_folder_summary_offset_content: - * @content: - * @offset: - * - * Offset the content info @content by @offset characters. - **/ -void -camel_folder_summary_offset_content(CamelMessageContentInfo *content, off_t offset) -{ - content->pos += offset; - content->bodypos += offset; - content->endpos += offset; - content = content->childs; - while (content) { - camel_folder_summary_offset_content(content, offset); - content = content->next; - } -} - static struct _node * my_list_append(struct _node **list, struct _node *n) { @@ -1454,6 +1432,9 @@ camel_folder_summary_info_new(CamelFolderSummary *s) s->message_info_chunks = e_memchunk_new(32, s->message_info_size); mi = e_memchunk_alloc(s->message_info_chunks); memset(mi, 0, s->message_info_size); +#ifdef DOESTRV + mi->strings = e_strv_new(s->message_info_strings); +#endif return mi; } @@ -1481,10 +1462,21 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) mi = camel_folder_summary_info_new(s); +#ifdef DOESTRV + msgid = camel_folder_summary_format_string(h, "subject"); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, msgid); + msgid = camel_folder_summary_format_address(h, "from"); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_FROM, msgid); + msgid = camel_folder_summary_format_address(h, "to"); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_TO, msgid); + msgid = camel_folder_summary_format_address(h, "cc"); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_CC, msgid); +#else mi->subject = camel_folder_summary_format_string(h, "subject"); mi->from = camel_folder_summary_format_address(h, "from"); mi->to = camel_folder_summary_format_address(h, "to"); mi->cc = camel_folder_summary_format_address(h, "cc"); +#endif mi->user_flags = NULL; mi->user_tags = NULL; mi->date_sent = header_decode_date(header_raw_find(&h, "date", NULL), NULL); @@ -1533,11 +1525,29 @@ message_info_load(CamelFolderSummary *s, FILE *in) CamelMessageInfo *mi; guint count; int i; +#ifdef DOESTRV + char *tmp; +#endif mi = camel_folder_summary_info_new(s); io(printf("Loading message info\n")); - +#ifdef DOESTRV + camel_folder_summary_decode_string(in, &tmp); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_UID, tmp); + camel_folder_summary_decode_uint32(in, &mi->flags); + camel_folder_summary_decode_uint32(in, &mi->size); + camel_folder_summary_decode_time_t(in, &mi->date_sent); + camel_folder_summary_decode_time_t(in, &mi->date_received); + camel_folder_summary_decode_string(in, &tmp); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, tmp); + camel_folder_summary_decode_string(in, &tmp); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_FROM, tmp); + camel_folder_summary_decode_string(in, &tmp); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_TO, tmp); + camel_folder_summary_decode_string(in, &tmp); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_CC, tmp); +#else camel_folder_summary_decode_string(in, &mi->uid); camel_folder_summary_decode_uint32(in, &mi->flags); camel_folder_summary_decode_uint32(in, &mi->size); @@ -1547,6 +1557,7 @@ message_info_load(CamelFolderSummary *s, FILE *in) camel_folder_summary_decode_string(in, &mi->from); camel_folder_summary_decode_string(in, &mi->to); camel_folder_summary_decode_string(in, &mi->cc); +#endif mi->content = NULL; camel_folder_summary_decode_fixed_int32(in, &mi->message_id.id.part.hi); @@ -1593,15 +1604,15 @@ message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) io(printf("Saving message info\n")); - camel_folder_summary_encode_string(out, mi->uid); + camel_folder_summary_encode_string(out, camel_message_info_uid(mi)); camel_folder_summary_encode_uint32(out, mi->flags); camel_folder_summary_encode_uint32(out, mi->size); camel_folder_summary_encode_time_t(out, mi->date_sent); camel_folder_summary_encode_time_t(out, mi->date_received); - camel_folder_summary_encode_string(out, mi->subject); - camel_folder_summary_encode_string(out, mi->from); - camel_folder_summary_encode_string(out, mi->to); - camel_folder_summary_encode_string(out, mi->cc); + camel_folder_summary_encode_string(out, camel_message_info_subject(mi)); + camel_folder_summary_encode_string(out, camel_message_info_from(mi)); + camel_folder_summary_encode_string(out, camel_message_info_to(mi)); + camel_folder_summary_encode_string(out, camel_message_info_cc(mi)); camel_folder_summary_encode_fixed_int32(out, mi->message_id.id.part.hi); camel_folder_summary_encode_fixed_int32(out, mi->message_id.id.part.lo); @@ -1639,11 +1650,15 @@ message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) static void message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) { +#ifdef DOESTRV + e_strv_destroy(mi->strings); +#else g_free(mi->uid); g_free(mi->subject); g_free(mi->from); g_free(mi->to); g_free(mi->cc); +#endif g_free(mi->references); camel_flag_list_free(&mi->user_flags); camel_tag_list_free(&mi->user_tags); @@ -1661,9 +1676,6 @@ content_info_new(CamelFolderSummary *s, struct _header_raw *h) ci->description = header_decode_string(header_raw_find(&h, "content-description", NULL)); ci->encoding = header_content_encoding_decode(header_raw_find(&h, "content-transfer-encoding", NULL)); - ci->pos = -1; - ci->bodypos = -1; - ci->endpos = -1; return ci; } @@ -1678,10 +1690,6 @@ content_info_load(CamelFolderSummary *s, FILE *in) io(printf("Loading content info\n")); ci = content_info_alloc(s); - - camel_folder_summary_decode_off_t(in, &ci->pos); - camel_folder_summary_decode_off_t(in, &ci->bodypos); - camel_folder_summary_decode_off_t(in, &ci->endpos); camel_folder_summary_decode_token(in, &type); camel_folder_summary_decode_token(in, &subtype); @@ -1716,10 +1724,6 @@ content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci) io(printf("Saving content info\n")); - camel_folder_summary_encode_off_t(out, ci->pos); - camel_folder_summary_encode_off_t(out, ci->bodypos); - camel_folder_summary_encode_off_t(out, ci->endpos); - ct = ci->type; if (ct) { camel_folder_summary_encode_token(out, ct->type); @@ -1764,7 +1768,7 @@ next_uid_string(CamelFolderSummary *s) */ static CamelMessageContentInfo * -summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) +summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimeParser *mp) { int state, len; char *buffer; @@ -1782,15 +1786,17 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) state = camel_mime_parser_step(mp, &buffer, &len); body = camel_mime_parser_tell(mp); - info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_parser(s, mp); - - info->pos = camel_mime_parser_tell_start_headers(mp); - info->bodypos = body; + if (s->build_content) + info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_parser(s, mp); switch(state) { case HSCAN_HEADER: /* check content type for indexing, then read body */ ct = camel_mime_parser_content_type(mp); + /* update attachments flag as we go */ + if (!header_content_type_is(ct, "text", "*")) + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; + if (p->index && header_content_type_is(ct, "text", "*")) { char *encoding; const char *charset; @@ -1846,25 +1852,29 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) break; case HSCAN_MULTIPART: d(printf("Summarising multipart\n")); + /* update attachments flag as we go */ + ct = camel_mime_parser_content_type(mp); + if (header_content_type_is(ct, "multipart", "mixed")) + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; + while (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_MULTIPART_END) { camel_mime_parser_unstep(mp); - part = summary_build_content_info(s, mp); + part = summary_build_content_info(s, msginfo, mp); if (part) { part->parent = info; my_list_append((struct _node **)&info->childs, (struct _node *)part); - } else { - g_error("Parsing failed: could not build part of a multipart"); } } break; case HSCAN_MESSAGE: d(printf("Summarising message\n")); - part = summary_build_content_info(s, mp); + /* update attachments flag as we go */ + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; + + part = summary_build_content_info(s, msginfo, mp); if (part) { part->parent = info; my_list_append((struct _node **)&info->childs, (struct _node *)part); - } else { - g_error("Parsing failed: no content of a message?"); } state = camel_mime_parser_step(mp, &buffer, &len); if (state != HSCAN_MESSAGE_END) { @@ -1874,8 +1884,6 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) break; } - info->endpos = camel_mime_parser_tell(mp); - d(printf("finished building content info\n")); return info; @@ -1890,7 +1898,8 @@ summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msgi struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); CamelMessageContentInfo *info = NULL, *child; - info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_message(s, object); + if (s->build_content) + info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_message(s, object); containee = camel_medium_get_content_object(CAMEL_MEDIUM(object)); @@ -1900,6 +1909,13 @@ summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msgi /* TODO: I find it odd that get_part and get_content_object do not add a reference, probably need fixing for multithreading */ + /* check for attachments */ + if (gmime_content_field_is_type(CAMEL_DATA_WRAPPER(containee)->mime_type, "multipart", "*")) { + if (gmime_content_field_is_type(CAMEL_DATA_WRAPPER(containee)->mime_type, "multipart", "mixed")) + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; + } else if (!gmime_content_field_is_type(CAMEL_DATA_WRAPPER(containee)->mime_type, "text", "*")) + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; + /* using the object types is more accurate than using the mime/types */ if (CAMEL_IS_MULTIPART(containee)) { parts = camel_multipart_get_number(CAMEL_MULTIPART(containee)); @@ -1925,7 +1941,7 @@ summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msgi CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new(); camel_data_wrapper_write_to_stream(containee, (CamelStream *)mem); - ibex_index_buffer(p->index, msginfo->uid, mem->buffer->data, mem->buffer->len, NULL); + ibex_index_buffer(p->index, (char *)camel_message_info_uid(msginfo), mem->buffer->data, mem->buffer->len, NULL); camel_object_unref((CamelObject *)mem); } @@ -2145,11 +2161,20 @@ camel_message_info_dup_to(const CamelMessageInfo *from, CamelMessageInfo *to) to->date_received = from->date_received; /* Copy strings */ +#ifdef DOESTRV + to->strings = e_strv_new(CAMEL_MESSAGE_INFO_LAST); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_SUBJECT, camel_message_info_subject(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_FROM, camel_message_info_from(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_TO, camel_message_info_to(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_CC, camel_message_info_cc(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_UID, camel_message_info_uid(from)); +#else to->subject = g_strdup(from->subject); to->from = g_strdup(from->from); to->to = g_strdup(from->to); to->cc = g_strdup(from->cc); to->uid = g_strdup(from->uid); +#endif memcpy(&to->message_id, &from->message_id, sizeof(from->message_id)); /* Copy structures */ @@ -2192,11 +2217,15 @@ camel_message_info_dup_to(const CamelMessageInfo *from, CamelMessageInfo *to) void camel_message_info_free(CamelMessageInfo *mi) { +#ifdef DOESTRV + e_strv_destroy(mi->strings); +#else g_free(mi->uid); g_free(mi->subject); g_free(mi->from); g_free(mi->to); g_free(mi->cc); +#endif g_free(mi->references); camel_flag_list_free(&mi->user_flags); camel_tag_list_free(&mi->user_tags); @@ -2205,18 +2234,18 @@ camel_message_info_free(CamelMessageInfo *mi) } #ifdef DOESTRV -const char *camel_message_info_string(CamelMessageInfo *mi, int type) +const char *camel_message_info_string(const CamelMessageInfo *mi, int type) { - if (mi->strings == NULL || type >= CAMEL_MESSAGE_INFO_STRING_COUNT) + if (mi->strings == NULL) return ""; return e_strv_get(mi->strings, type); } -void camel_message_info_set_string(CamelMessageInfo *mi, int type, const char *str) +void camel_message_info_set_string(CamelMessageInfo *mi, int type, char *str) { g_assert(mi->strings != NULL); - mi->strings = e_strv_set(mi->strings, type, str); + mi->strings = e_strv_set_ref_free(mi->strings, type, str); } #endif @@ -2254,11 +2283,11 @@ message_info_dump(CamelMessageInfo *mi) return; } - printf("Subject: %s\n", mi->subject); - printf("To: %s\n", mi->to); - printf("Cc: %s\n", mi->cc); - printf("From: %s\n", mi->from); - printf("UID: %s\n", mi->uid); + printf("Subject: %s\n", camel_message_info_subject(mi)); + printf("To: %s\n", camel_message_info_to(to)); + printf("Cc: %s\n", camel_message_info_cc(cc)); + printf("From: %s\n", camel_message_info_from(from)); + printf("UID: %s\n", camel_message_info_uid(uid)); printf("Flags: %04x\n", mi->flags & 0xffff); content_info_dump(mi->content, 0); } diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h index 19f17855bc..defba693fc 100644 --- a/camel/camel-folder-summary.h +++ b/camel/camel-folder-summary.h @@ -47,14 +47,6 @@ typedef struct _CamelMessageContentInfo { char *id; char *description; char *encoding; - - /* NOTE: The fields below are to be deprecated, and eventually removed */ - - /* information about where this object lives in the stream. - if pos is -1 these are all invalid */ - off_t pos; - off_t bodypos; - off_t endpos; } CamelMessageContentInfo; /* system flag bits */ @@ -64,6 +56,8 @@ enum _CamelMessageFlags { CAMEL_MESSAGE_DRAFT = 1<<2, CAMEL_MESSAGE_FLAGGED = 1<<3, CAMEL_MESSAGE_SEEN = 1<<4, + CAMEL_MESSAGE_ATTACHMENTS = 1<<5, + /* 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_USER = 1<<31 /* supports user flags */ @@ -98,15 +92,17 @@ typedef struct _CamelSummaryReferences { CamelSummaryMessageID references[1]; } CamelSummaryReferences; +#define DOESTRV + #ifdef DOESTRV /* string array indices */ enum { + CAMEL_MESSAGE_INFO_UID, CAMEL_MESSAGE_INFO_SUBJECT, CAMEL_MESSAGE_INFO_FROM, CAMEL_MESSAGE_INFO_TO, CAMEL_MESSAGE_INFO_CC, - CAMEL_MESSAGE_INFO_UID, - CAMEL_MESSAGE_INFO_STRING_COUNT, + CAMEL_MESSAGE_INFO_LAST, }; #endif @@ -114,7 +110,7 @@ enum { typedef struct { /* public fields */ #ifdef DOESTRV - EStrv *strings; /* all strings packed into a single compact array */ + struct _EStrv *strings; /* all strings packed into a single compact array */ #else gchar *subject; gchar *from; @@ -158,7 +154,10 @@ struct _CamelFolderSummary { /* sizes of memory objects */ guint32 message_info_size; guint32 content_info_size; - + +#ifdef DOESTRV + guint32 message_info_strings; +#endif /* memory allocators (setup automatically) */ struct _EMemChunk *message_info_chunks; struct _EMemChunk *content_info_chunks; @@ -243,9 +242,6 @@ int camel_folder_summary_count(CamelFolderSummary *); CamelMessageInfo *camel_folder_summary_index(CamelFolderSummary *, int); CamelMessageInfo *camel_folder_summary_uid(CamelFolderSummary *, const char *uid); -/* shift content ... */ -void camel_folder_summary_offset_content(CamelMessageContentInfo *content, off_t offset); - /* summary formatting utils */ char *camel_folder_summary_format_address(struct _header_raw *h, const char *name); char *camel_folder_summary_format_string(struct _header_raw *h, const char *name); @@ -259,11 +255,11 @@ int camel_folder_summary_encode_time_t(FILE *out, time_t value); int camel_folder_summary_decode_time_t(FILE *in, time_t *dest); int camel_folder_summary_encode_off_t(FILE *out, off_t value); int camel_folder_summary_decode_off_t(FILE *in, off_t *dest); -int camel_folder_summary_encode_string(FILE *, char *); -int camel_folder_summary_decode_string(FILE *, char **); +int camel_folder_summary_encode_string(FILE *out, const char *str); +int camel_folder_summary_decode_string(FILE *in, char **); /* basically like strings, but certain keywords can be compressed and de-cased */ -int camel_folder_summary_encode_token(FILE *, char *); +int camel_folder_summary_encode_token(FILE *, const char *); int camel_folder_summary_decode_token(FILE *, char **); /* message flag operations */ @@ -286,19 +282,33 @@ void camel_message_info_free(CamelMessageInfo *mi); /* accessors */ #ifdef DOESTRV -const char *camel_message_info_string(CamelMessageInfo *mi, int type); -#define camel_message_info_subject(x) camel_message_info_string(m, CAMEL_MESSAGE_INFO_SUBJECT) -#define camel_message_info_from(x) camel_message_info_string(m, CAMEL_MESSAGE_INFO_FROM) -#define camel_message_info_to(x) camel_message_info_string(m, CAMEL_MESSAGE_INFO_TO) -#define camel_message_info_cc(x) camel_message_info_string(m, CAMEL_MESSAGE_INFO_CC) -#define camel_message_info_uid(x) camel_message_info_string(m, CAMEL_MESSAGE_INFO_UID) - -void camel_message_info_set_string(CamelMessageInfo *mi, int type, const char *str); -#define camel_message_info_set_subject(x, s) camel_message_info_string(m, CAMEL_MESSAGE_INFO_SUBJECT, s) -#define camel_message_info_set_from(x, s) camel_message_info_string(m, CAMEL_MESSAGE_INFO_FROM, s) -#define camel_message_info_set_to(x, s) camel_message_info_string(m, CAMEL_MESSAGE_INFO_TO, s) -#define camel_message_info_set_cc(x, s) camel_message_info_string(m, CAMEL_MESSAGE_INFO_CC, s) -#define camel_message_info_set_uid(x, s) camel_message_info_string(m, CAMEL_MESSAGE_INFO_UID, s) +const char *camel_message_info_string(const CamelMessageInfo *mi, int type); +#define camel_message_info_subject(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_SUBJECT) +#define camel_message_info_from(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_FROM) +#define camel_message_info_to(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_TO) +#define camel_message_info_cc(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_CC) +#define camel_message_info_uid(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_UID) + +void camel_message_info_set_string(CamelMessageInfo *mi, int type, char *str); +#define camel_message_info_set_subject(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_SUBJECT, s) +#define camel_message_info_set_from(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_FROM, s) +#define camel_message_info_set_to(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_TO, s) +#define camel_message_info_set_cc(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_CC, s) +#define camel_message_info_set_uid(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_UID, s) + +#else + +#define camel_message_info_subject(x) (((CamelMessageInfo *)(x))->subject?((CamelMessageInfo *)(x))->subject:"") +#define camel_message_info_from(x) (((CamelMessageInfo *)(x))->from?((CamelMessageInfo *)(x))->from:"") +#define camel_message_info_to(x) (((CamelMessageInfo *)(x))->to?((CamelMessageInfo *)(x))->to:"") +#define camel_message_info_cc(x) (((CamelMessageInfo *)(x))->cc?((CamelMessageInfo *)(x))->cc:"") +#define camel_message_info_uid(x) (((CamelMessageInfo *)(x))->uid?((CamelMessageInfo *)(x))->uid:"") + +#define camel_message_info_set_subject(x, s) (g_free(((CamelMessageInfo *)(x))->subject),((CamelMessageInfo *)(x))->subject = (s)) +#define camel_message_info_set_from(x, s) (g_free(((CamelMessageInfo *)(x))->from),((CamelMessageInfo *)(x))->from = (s)) +#define camel_message_info_set_to(x, s) (g_free(((CamelMessageInfo *)(x))->to),((CamelMessageInfo *)(x))->to = (s)) +#define camel_message_info_set_cc(x, s) (g_free(((CamelMessageInfo *)(x))->cc),((CamelMessageInfo *)(x))->cc = (s)) +#define camel_message_info_set_uid(x, s) (g_free(((CamelMessageInfo *)(x))->uid),((CamelMessageInfo *)(x))->uid = (s)) #endif #endif /* ! _CAMEL_FOLDER_SUMMARY_H */ diff --git a/camel/camel-folder-thread.c b/camel/camel-folder-thread.c index b105d18ae4..4b6a72053e 100644 --- a/camel/camel-folder-thread.c +++ b/camel/camel-folder-thread.c @@ -149,13 +149,13 @@ get_root_subject(CamelFolderThreadNode *c, int *re) s = NULL; *re = FALSE; if (c->message) - s = c->message->subject; + s = (char *)camel_message_info_subject(c->message); else { /* one of the children will always have a message */ scan = c->child; while (scan) { if (scan->message) { - s = scan->message->subject; + s = (char *)camel_message_info_subject(scan->message); break; } scan = scan->next; @@ -319,7 +319,7 @@ dump_tree_rec(struct _tree_info *info, CamelFolderThreadNode *c, int depth) g_hash_table_insert(info->visited, c, c); } if (c->message) { - printf("%s %p Subject: %s <%.8s>\n", p, c, c->message->subject, c->message->message_id.id.hash); + printf("%s %p Subject: %s <%.8s>\n", p, c, camel_message_info_subject(c->message), c->message->message_id.id.hash); count += 1; } else { printf("%s %p <empty>\n", p, c); diff --git a/camel/camel-folder.c b/camel/camel-folder.c index d50323f3a4..126b3e56c0 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -1143,7 +1143,7 @@ change_info_add_uid(CamelFolderChangeInfo *info, GPtrArray *uids, const char *ui if (copy) g_ptr_array_add(uids, e_mempool_strdup(info->uid_pool, uid)); else - g_ptr_array_add(uids, uid); + g_ptr_array_add(uids, (char *)uid); } static void diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index a4b8b459de..892eb71d50 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -300,7 +300,7 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex) if (!new[i].uid) continue; - if (strcmp (info->uid, new[i].uid) != 0) { + if (strcmp (camel_message_info_uid(info), new[i].uid) != 0) { camel_folder_summary_remove (imap_folder->summary, info); folder_changed = TRUE; @@ -314,7 +314,7 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex) info->flags = new[i].flags; camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", - info->uid); + (char *)camel_message_info_uid(info)); } g_free (new[i].uid); @@ -366,7 +366,7 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) response = camel_imap_command ( store, folder, ex, "UID STORE %s FLAGS.SILENT %s", - info->uid, flags); + camel_message_info_uid(info), flags); g_free (flags); if (!response) return; @@ -547,7 +547,7 @@ imap_get_uids (CamelFolder *folder) for (i = 0; i < count; i++) { info = camel_folder_summary_index (imap_folder->summary, i); - array->pdata[i] = g_strdup (info->uid); + array->pdata[i] = g_strdup (camel_message_info_uid(info)); } return array; @@ -697,7 +697,8 @@ imap_update_summary (CamelFolder *folder, int first, int last, */ info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(imap_folder->summary)))->message_info_new(imap_folder->summary, h); header_raw_clear (&h); - info->uid = g_strndup (uid, q - uid); + uid = g_strndup(uid, q-uid); + camel_message_info_set_uid(info, uid); /* now lets grab the FLAGS */ if (!(flags = strstr (headers->pdata[i], "FLAGS "))) { diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c index 787b482169..c1c3256865 100644 --- a/camel/providers/local/camel-local-folder.c +++ b/camel/providers/local/camel-local-folder.c @@ -367,7 +367,7 @@ local_get_uids(CamelFolder *folder) for (i = 0; i < count; i++) { CamelMessageInfo *info = camel_folder_summary_index(CAMEL_FOLDER_SUMMARY(local_folder->summary), i); - array->pdata[i] = g_strdup(info->uid); + array->pdata[i] = g_strdup(camel_message_info_uid(info)); } return array; diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c index 83b0e6313b..5e47ee35c3 100644 --- a/camel/providers/local/camel-local-summary.c +++ b/camel/providers/local/camel-local-summary.c @@ -35,7 +35,7 @@ #define io(x) #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ -#define CAMEL_LOCAL_SUMMARY_VERSION (0x100) +#define CAMEL_LOCAL_SUMMARY_VERSION (0x200) struct _CamelLocalSummaryPrivate { }; @@ -59,6 +59,7 @@ static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo static int local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi); static char *local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi); +static int local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); static int local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); static int local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); static CamelMessageInfo *local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); @@ -105,6 +106,7 @@ camel_local_summary_class_init(CamelLocalSummaryClass *klass) sklass->message_info_save = message_info_save;*/ /*sklass->message_info_free = message_info_free;*/ + klass->load = local_summary_load; klass->check = local_summary_check; klass->sync = local_summary_sync; klass->add = local_summary_add; @@ -140,20 +142,42 @@ camel_local_summary_finalise(CamelObject *obj) void camel_local_summary_construct(CamelLocalSummary *new, const char *filename, const char *local_name, ibex *index) { - camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), TRUE); + camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), FALSE); camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY(new), filename); new->folder_path = g_strdup(local_name); new->index = index; } +static int +local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) +{ + return camel_folder_summary_load((CamelFolderSummary *)cls); +} + /* load/check the summary */ int camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) { - if (forceindex || camel_folder_summary_load((CamelFolderSummary *)cls) == -1) { + struct stat st; + CamelFolderSummary *s = (CamelFolderSummary *)cls; + + d(printf("Loading summary ...\n")); + + if (forceindex + || stat(s->summary_path, &st) == -1 + || ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) { camel_folder_summary_clear((CamelFolderSummary *)cls); } - return camel_local_summary_check(cls, NULL, ex); + + if (camel_local_summary_check(cls, NULL, ex) == 0) { + if (camel_folder_summary_save(s) == -1) + g_warning("Could not save summary for %s: %s", cls->folder_path, strerror(errno)); + if (cls->index && ibex_save(cls->index) == -1) + g_warning("Could not sync index for %s: %s", cls->folder_path, strerror(errno)); + + return 0; + } + return -1; } char * @@ -322,7 +346,8 @@ camel_local_summary_write_headers(int fd, struct _header_raw *header, char *xevl } while (header) { - if (strcasecmp(header->name, "X-Evolution")) { + if (strcmp(header->name, "X-Evolution")) { + printf("writing header: '%s'\n", header->name); len = fprintf(out, "%s:%s\n", header->name, header->value); if (len == -1) { fclose(out); @@ -439,7 +464,7 @@ local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMess xev = camel_local_summary_encode_x_evolution(cls, mi); camel_medium_set_header((CamelMedium *)msg, "X-Evolution", xev); g_free(xev); - camel_folder_change_info_add_uid(ci, mi->uid); + camel_folder_change_info_add_uid(ci, camel_message_info_uid(mi)); } else { d(printf("Failed!\n")); camel_exception_set(ex, 1, "Unable to add message to summary: unknown reason"); @@ -455,18 +480,19 @@ local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo GString *val = g_string_new(""); CamelFlag *flag = mi->user_flags; CamelTag *tag = mi->user_tags; - char *ret, *p; + char *ret; + const char *p, *uidstr; guint32 uid; /* FIXME: work out what to do with uid's that aren't stored here? */ /* FIXME: perhaps make that a mbox folder only issue?? */ - p = mi->uid; + p = uidstr = camel_message_info_uid(mi); while (*p && isdigit(*p)) p++; - if (*p == 0 && sscanf(mi->uid, "%u", &uid) == 1) { + if (*p == 0 && sscanf(uidstr, "%u", &uid) == 1) { g_string_sprintf(out, "%08x-%04x", uid, mi->flags & 0xffff); } else { - g_string_sprintf(out, "%s-%04x", mi->uid, mi->flags & 0xffff); + g_string_sprintf(out, "%s-%04x", uidstr, mi->flags & 0xffff); } if (flag || tag) { @@ -517,8 +543,7 @@ local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelM char uidstr[20]; if (mi) { sprintf(uidstr, "%u", uid); - g_free(mi->uid); - mi->uid = g_strdup(uidstr); + camel_message_info_set_uid(mi, g_strdup(uidstr)); mi->flags = flags; } } else { @@ -579,7 +604,7 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) if (xev==NULL || camel_local_summary_decode_x_evolution(cls, xev, mi) == -1) { /* to indicate it has no xev header */ mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - mi->uid = camel_folder_summary_next_uid_string(s); + camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); /* shortcut, no need to look it up in the index library */ doindex = TRUE; @@ -588,11 +613,11 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) if (cls->index && (doindex || cls->index_force - || !ibex_contains_name(cls->index, mi->uid))) { - d(printf("Am indexing message %s\n", mi->uid)); + || !ibex_contains_name(cls->index, (char *)camel_message_info_uid(mi)))) { + d(printf("Am indexing message %s\n", camel_message_info_uid(mi))); camel_folder_summary_set_index(s, cls->index); } else { - d(printf("Not indexing message %s\n", mi->uid)); + d(printf("Not indexing message %s\n", camel_message_info_uid(mi))); camel_folder_summary_set_index(s, NULL); } } diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h index 5349194edf..e0dadde899 100644 --- a/camel/providers/local/camel-local-summary.h +++ b/camel/providers/local/camel-local-summary.h @@ -54,6 +54,7 @@ struct _CamelLocalSummary { struct _CamelLocalSummaryClass { CamelFolderSummaryClass parent_class; + int (*load)(CamelLocalSummary *cls, int forceindex, CamelException *ex); int (*check)(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); int (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c index 1cffbdabd2..d4771db5b8 100644 --- a/camel/providers/local/camel-maildir-folder.c +++ b/camel/providers/local/camel-maildir-folder.c @@ -138,12 +138,10 @@ static void maildir_append_message(CamelFolder * folder, CamelMimeMessage * mess mdi = (CamelMaildirMessageInfo *)mi; - g_assert(mdi->filename); - - d(printf("Appending message: uid is %s filename is %s\n", mi->uid, mdi->filename)); + d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename)); /* write it out to tmp, use the uid we got from the summary */ - name = g_strdup_printf("%s/tmp/%s", lf->folder_path, mi->uid); + name = g_strdup_printf("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi)); output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600); if (output_stream == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, @@ -163,7 +161,7 @@ static void maildir_append_message(CamelFolder * folder, CamelMimeMessage * mess } /* now move from tmp to cur (bypass new, does it matter?) */ - dest = g_strdup_printf("%s/cur/%s", lf->folder_path, mdi->filename); + dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename(mdi)); if (rename(name, dest) == 1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot append message to maildir folder: %s: %s"), name, g_strerror(errno)); @@ -201,7 +199,7 @@ static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * mdi = (CamelMaildirMessageInfo *)info; /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess */ - name = g_strdup_printf("%s/cur/%s", lf->folder_path, mdi->filename); + name = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename(mdi)); if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), name, g_strerror(errno)); diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c index 0fa9f1c0d9..8bf630efe5 100644 --- a/camel/providers/local/camel-maildir-summary.c +++ b/camel/providers/local/camel-maildir-summary.c @@ -33,13 +33,17 @@ #include <ctype.h> +#include "e-util/e-memory.h" + #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ #define CAMEL_MAILDIR_SUMMARY_VERSION (0x2000) +static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in); static CamelMessageInfo *message_info_new(CamelFolderSummary *, struct _header_raw *); static void message_info_free(CamelFolderSummary *, CamelMessageInfo *mi); +static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); static int maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); static int maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); /*static int maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex);*/ @@ -55,6 +59,8 @@ static void camel_maildir_summary_finalise (CamelObject *obj); struct _CamelMaildirSummaryPrivate { char *current_file; char *hostname; + + GHashTable *load_map; }; static CamelLocalSummaryClass *parent_class; @@ -86,10 +92,12 @@ camel_maildir_summary_class_init (CamelMaildirSummaryClass *class) parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); /* override methods */ + sklass->message_info_load = message_info_load; sklass->message_info_new = message_info_new; sklass->message_info_free = message_info_free; sklass->next_uid_string = maildir_summary_next_uid_string; + lklass->load = maildir_summary_load; lklass->check = maildir_summary_check; lklass->sync = maildir_summary_sync; /*lklass->add = maildir_summary_add;*/ @@ -108,6 +116,10 @@ camel_maildir_summary_init (CamelMaildirSummary *o) s->message_info_size = sizeof(CamelMaildirMessageInfo); s->content_info_size = sizeof(CamelMaildirMessageContentInfo); +#ifdef DOESTRV + s->message_info_strings = CAMEL_MAILDIR_INFO_LAST; +#endif + if (gethostname(hostname, 256) == 0) { o->priv->hostname = g_strdup(hostname); } else { @@ -155,9 +167,11 @@ char *camel_maildir_summary_info_to_name(const CamelMessageInfo *info) { char *p, *buf; int i; + const char *uid; - buf = alloca(strlen(info->uid) + strlen(":2,") + (sizeof(flagbits)/sizeof(flagbits[0])) + 1); - p = buf + sprintf(buf, "%s:2,", info->uid); + uid = camel_message_info_uid(info); + buf = alloca(strlen(uid) + strlen(":2,") + (sizeof(flagbits)/sizeof(flagbits[0])) + 1); + p = buf + sprintf(buf, "%s:2,", uid); for (i=0;i<sizeof(flagbits)/sizeof(flagbits[0]);i++) { if (info->flags & flagbits[i].flagbit) *p++ = flagbits[i].flag; @@ -209,18 +223,19 @@ static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _header CamelMessageInfo *mi; CamelMaildirSummary *mds = (CamelMaildirSummary *)s; CamelMaildirMessageInfo *mdi; + const char *uid; mi = ((CamelFolderSummaryClass *) parent_class)->message_info_new(s, h); /* assign the uid and new filename */ if (mi) { mdi = (CamelMaildirMessageInfo *)mi; - if (mi->uid == NULL) { - mi->uid = camel_folder_summary_next_uid_string(s); - } + uid = camel_message_info_uid(mi); + if (uid==NULL || uid[0] == 0) + camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); /* with maildir we know the real received date, from the filename */ - mi->date_received = strtoul(mi->uid, NULL, 10); + mi->date_received = strtoul(camel_message_info_uid(mi), NULL, 10); if (mds->priv->current_file) { #if 0 @@ -228,8 +243,8 @@ static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _header unsigned long uid; #endif /* if setting from a file, grab the flags from it */ - mdi->filename = g_strdup(mds->priv->current_file); - camel_maildir_summary_name_to_info(mi, mdi->filename); + camel_maildir_info_set_filename(mi, g_strdup(mds->priv->current_file)); + camel_maildir_summary_name_to_info(mi, mds->priv->current_file); #if 0 /* Actually, I dont think all this effort is worth it at all ... */ @@ -249,19 +264,22 @@ static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _header #endif } else { /* if creating a file, set its name from the flags we have */ - mdi->filename = camel_maildir_summary_info_to_name(mi); + camel_maildir_info_set_filename(mdi, camel_maildir_summary_info_to_name(mi)); + d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); } } return mi; } + static void message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) { +#ifndef DOESTRV CamelMaildirMessageInfo *mdi = (CamelMaildirMessageInfo *)mi; g_free(mdi->filename); - +#endif ((CamelFolderSummaryClass *) parent_class)->message_info_free(s, mi); } @@ -312,6 +330,80 @@ static char *maildir_summary_next_uid_string(CamelFolderSummary *s) } } +static CamelMessageInfo * +message_info_load(CamelFolderSummary *s, FILE *in) +{ + CamelMessageInfo *mi; + CamelMaildirSummary *mds = (CamelMaildirSummary *)s; + + mi = ((CamelFolderSummaryClass *) parent_class)->message_info_load(s, in); + if (mi) { + char *name; + + if (mds->priv->load_map + && (name = g_hash_table_lookup(mds->priv->load_map, camel_message_info_uid(mi)))) { + d(printf("Setting filename of %s to %s\n", camel_message_info_uid(mi), name)); + camel_maildir_info_set_filename(mi, g_strdup(name)); + camel_maildir_summary_name_to_info(mi, name); + } + } + + return mi; +} + +static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) +{ + char *cur; + DIR *dir; + struct dirent *d; + CamelMaildirSummary *mds = (CamelMaildirSummary *)cls; + char *uid; + EMemPool *pool; + int ret; + + cur = g_strdup_printf("%s/cur", cls->folder_path); + + d(printf("pre-loading uid <> filename map\n")); + + dir = opendir(cur); + if (dir == NULL) { + camel_exception_setv(ex, 1, "Cannot open maildir directory path: %s: %s", cls->folder_path, strerror(errno)); + g_free(cur); + return -1; + } + + mds->priv->load_map = g_hash_table_new(g_str_hash, g_str_equal); + pool = e_mempool_new(1024, 512, E_MEMPOOL_ALIGN_BYTE); + + while ( (d = readdir(dir)) ) { + if (d->d_name[0] == '.') + continue; + + /* map the filename -> uid */ + uid = strchr(d->d_name, ':'); + if (uid) { + int len = uid-d->d_name; + uid = e_mempool_alloc(pool, len+1); + memcpy(uid, d->d_name, len); + uid[len] = 0; + g_hash_table_insert(mds->priv->load_map, uid, e_mempool_strdup(pool, d->d_name)); + } else { + uid = e_mempool_strdup(pool, d->d_name); + g_hash_table_insert(mds->priv->load_map, uid, uid); + } + } + closedir(dir); + g_free(cur); + + ret = ((CamelLocalSummaryClass *) parent_class)->load(cls, forceindex, ex); + + g_hash_table_destroy(mds->priv->load_map); + mds->priv->load_map = NULL; + e_mempool_destroy(pool); + + return ret; +} + static int camel_maildir_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) { CamelMaildirSummary *maildirs = (CamelMaildirSummary *)cls; @@ -350,7 +442,7 @@ remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) { d(printf("removing message %s from summary\n", key)); if (cls->index) - ibex_unindex(cls->index, info->uid); + ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); } @@ -408,7 +500,7 @@ maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Ca for (i=0;i<count;i++) { info = camel_folder_summary_index((CamelFolderSummary *)cls, i); if (info) { - g_hash_table_insert(left, info->uid, info); + g_hash_table_insert(left, (char *)camel_message_info_uid(info), info); } } @@ -429,20 +521,33 @@ maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Ca if (info == NULL || (cls->index && (!ibex_contains_name(cls->index, uid)))) { /* need to add this file to the summary */ if (info != NULL) { - g_hash_table_remove(left, info->uid); + g_hash_table_remove(left, uid); camel_folder_summary_remove((CamelFolderSummary *)cls, info); } camel_maildir_summary_add(cls, d->d_name, forceindex); } else { - if (info) { - mdi = (CamelMaildirMessageInfo *)info; - /* TODO: only store the extension in the mdi->filename struct, not the whole lot */ - if (mdi->filename == NULL || strcmp(mdi->filename, d->d_name) != 0) { - g_free(mdi->filename); - mdi->filename = g_strdup(d->d_name); - } + const char *filename; + + g_hash_table_remove(left, camel_message_info_uid(info)); + + mdi = (CamelMaildirMessageInfo *)info; + filename = camel_maildir_info_filename(mdi); + /* TODO: only store the extension in the mdi->filename struct, not the whole lot */ + if (filename == NULL || strcmp(filename, d->d_name) != 0) { +#ifdef DOESTRV + d(printf("filename changed: %s to %s\n", filename, d->d_name)); + + /* need to update the summary hash string reference since it might (will) change */ + g_hash_table_remove(s->messages_uid, uid); + info->strings = e_strv_set_ref(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name); + /* we need to re-pack as well */ + info->strings = e_strv_pack(info->strings); + g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); +#else + g_free(mdi->filename); + mdi->filename = g_strdup(d->d_name); +#endif } - g_hash_table_remove(left, info->uid); } g_free(uid); } @@ -473,6 +578,9 @@ maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Ca src = g_strdup_printf("%s/%s", new, name); destfilename = g_strdup_printf("%s:2,", destname); dest = g_strdup_printf("%s/%s", cur, destfilename); + + /* FIXME: This should probably use link/unlink */ + if (rename(src, dest) == 0) { camel_maildir_summary_add(cls, destfilename, forceindex); if (changes) @@ -516,6 +624,9 @@ maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChange int count, i; CamelMessageInfo *info; CamelMaildirMessageInfo *mdi; +#ifdef DOESTRV + CamelFolderSummary *s = (CamelFolderSummary *)cls; +#endif char *name; struct stat st; @@ -530,15 +641,15 @@ maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChange info = camel_folder_summary_index((CamelFolderSummary *)cls, i); mdi = (CamelMaildirMessageInfo *)info; if (info && (info->flags & CAMEL_MESSAGE_DELETED) && expunge) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, mdi->filename); + name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); d(printf("deleting %s\n", name)); if (unlink(name) == 0 || errno==ENOENT) { /* FIXME: put this in folder_summary::remove()? */ if (cls->index) - ibex_unindex(cls->index, info->uid); + ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); - camel_folder_change_info_remove_uid(changes, info->uid); + camel_folder_change_info_remove_uid(changes, camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); } g_free(name); @@ -550,16 +661,24 @@ maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChange /* probably should all go in the filename? */ /* have our flags/ i.e. name changed? */ - if (strcmp(newname, mdi->filename)) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, mdi->filename); + if (strcmp(newname, camel_maildir_info_filename(mdi))) { + name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); dest = g_strdup_printf("%s/cur/%s", cls->folder_path, newname); rename(name, dest); if (stat(dest, &st) == -1) { /* we'll assume it didn't work, but dont change anything else */ g_free(newname); } else { +#ifdef DOESTRV + /* need to update the summary hash ref */ + g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); + info->strings = e_strv_set_ref_free(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname); + info->strings = e_strv_pack(info->strings); + g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); +#else g_free(mdi->filename); mdi->filename = newname; +#endif } g_free(name); g_free(dest); diff --git a/camel/providers/local/camel-maildir-summary.h b/camel/providers/local/camel-maildir-summary.h index 25ea845c21..24c2b5579b 100644 --- a/camel/providers/local/camel-maildir-summary.h +++ b/camel/providers/local/camel-maildir-summary.h @@ -37,10 +37,19 @@ typedef struct _CamelMaildirMessageContentInfo { CamelMessageContentInfo info; } CamelMaildirMessageContentInfo; +#ifdef DOESTRV +enum { + CAMEL_MAILDIR_INFO_FILENAME = CAMEL_MESSAGE_INFO_LAST, + CAMEL_MAILDIR_INFO_LAST, +}; +#endif + typedef struct _CamelMaildirMessageInfo { CamelMessageInfo info; +#ifndef DOESTRV char *filename; /* maildir has this annoying status shit on the end of the filename, use this to get the real message id */ +#endif } CamelMaildirMessageInfo; struct _CamelMaildirSummary { @@ -63,5 +72,13 @@ CamelMaildirSummary *camel_maildir_summary_new (const char *filename, const char char *camel_maildir_summary_info_to_name(const CamelMessageInfo *info); int camel_maildir_summary_name_to_info(CamelMessageInfo *info, const char *name); +#ifdef DOESTRV +#define camel_maildir_info_filename(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MAILDIR_INFO_FILENAME) +#define camel_maildir_info_set_filename(x, s) camel_message_info_set_string((CamelMessageInfo *)(x), CAMEL_MAILDIR_INFO_FILENAME, s) +#else +#define camel_maildir_info_filename(x) (((CamelMaildirMessageInfo *)x)->filename) +#define camel_maildir_info_set_filename(x, s) (g_free(((CamelMaildirMessageInfo *)x)->filename),((CamelMaildirMessageInfo *)x)->filename = s) +#endif + #endif /* ! _CAMEL_MAILDIR_SUMMARY_H */ diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c index d5e76f7cab..41fb5865b5 100644 --- a/camel/providers/local/camel-mbox-folder.c +++ b/camel/providers/local/camel-mbox-folder.c @@ -188,7 +188,7 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel if (camel_exception_is_set(ex)) goto fail; - d(printf("Appending message: uid is %s\n", mi->uid)); + d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); output_stream = camel_stream_fs_new_with_name(lf->folder_path, O_WRONLY|O_APPEND, 0600); if (output_stream == NULL) { @@ -248,7 +248,7 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel fail_write: camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mbox file: %s: %s"), lf->folder_path, g_strerror(errno)); + _("Cannot append message to mbox file: %s: %s"), lf->folder_path, strerror(errno)); if (filter_stream) camel_object_unref(CAMEL_OBJECT(filter_stream)); @@ -313,8 +313,7 @@ retry: return NULL; } - /* if this has no content, its an error in the library */ - g_assert(info->info.content); + /* no frompos, its an error in the library (and we can't do anything with it */ g_assert(info->frompos != -1); /* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c index b2a5e13e4a..2dde67b70c 100644 --- a/camel/providers/local/camel-mbox-summary.c +++ b/camel/providers/local/camel-mbox-summary.c @@ -305,7 +305,7 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan for (i = 0; i < camel_folder_summary_count(s); i++) { CamelMessageInfo *mi = camel_folder_summary_index(s, i); - camel_folder_change_info_add_source(changeinfo, mi->uid); + camel_folder_change_info_add_source(changeinfo, camel_message_info_uid(mi)); } } @@ -317,7 +317,7 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan count = camel_folder_summary_count(s); for (i = 0; i < count; i++) { CamelMessageInfo *mi = camel_folder_summary_index(s, i); - camel_folder_change_info_add_update(changeinfo, mi->uid); + camel_folder_change_info_add_update(changeinfo, camel_message_info_uid(mi)); } camel_folder_change_info_build_diff(changeinfo); } @@ -523,13 +523,15 @@ mbox_summary_sync_full(CamelLocalSummary *cls, gboolean expunge, CamelFolderChan lastdel = FALSE; if (expunge && info->info.flags & CAMEL_MESSAGE_DELETED) { - d(printf("Deleting %s\n", info->info.uid)); + const char *uid = camel_message_info_uid(info); + + d(printf("Deleting %s\n", uid)); if (cls->index) - ibex_unindex(cls->index, info->info.uid); + ibex_unindex(cls->index, (char *)uid); /* remove it from the change list */ - camel_folder_change_info_remove_uid(changeinfo, info->info.uid); + camel_folder_change_info_remove_uid(changeinfo, uid); camel_folder_summary_remove(s, (CamelMessageInfo *)info); count--; i--; diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c index 8f223a34c2..063e7e939e 100644 --- a/camel/providers/local/camel-mh-folder.c +++ b/camel/providers/local/camel-mh-folder.c @@ -137,10 +137,10 @@ static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, return; } - d(printf("Appending message: uid is %s\n", mi->uid)); + d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); /* write it out, use the uid we got from the summary */ - name = g_strdup_printf("%s/%s", lf->folder_path, mi->uid); + name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi)); output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600); if (output_stream == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c index e9fb9f116c..e5f37d879a 100644 --- a/camel/providers/local/camel-mh-summary.c +++ b/camel/providers/local/camel-mh-summary.c @@ -204,7 +204,7 @@ remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) { d(printf("removing message %s from summary\n", key)); if (cls->index) - ibex_unindex(cls->index, info->uid); + ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); } @@ -238,7 +238,7 @@ mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, Came for (i=0;i<count;i++) { info = camel_folder_summary_index((CamelFolderSummary *)cls, i); if (info) { - g_hash_table_insert(left, info->uid, info); + g_hash_table_insert(left, (char *)camel_message_info_uid(info), info); } } @@ -254,12 +254,12 @@ mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, Came if (info == NULL || (cls->index && (!ibex_contains_name(cls->index, d->d_name)))) { /* need to add this file to the summary */ if (info != NULL) { - g_hash_table_remove(left, info->uid); + g_hash_table_remove(left, camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); } camel_mh_summary_add(cls, d->d_name, forceindex); } else { - g_hash_table_remove(left, info->uid); + g_hash_table_remove(left, camel_message_info_uid(info)); } } } @@ -288,7 +288,7 @@ mh_summary_sync_message(CamelLocalSummary *cls, CamelMessageInfo *info, CamelExc int fd, outfd, len, outlen, ret=0; char *name, *tmpname, *xevnew; - name = g_strdup_printf("%s/%s", cls->folder_path, info->uid); + name = g_strdup_printf("%s/%s", cls->folder_path, camel_message_info_uid(info)); fd = open(name, O_RDWR); if (fd == -1) return -1; @@ -306,7 +306,7 @@ mh_summary_sync_message(CamelLocalSummary *cls, CamelMessageInfo *info, CamelExc d(printf("camel local summary_decode_xev = %d\n", camel_local_summary_decode_x_evolution(cls, xev, NULL))); /* need to write a new copy/unlink old */ - tmpname = g_strdup_printf("%s/.tmp.%d.%s", cls->folder_path, getpid(), info->uid); + tmpname = g_strdup_printf("%s/.tmp.%d.%s", cls->folder_path, getpid(), camel_message_info_uid(info)); d(printf("old xev was %d %s new xev is %d %s\n", strlen(xev), xev, strlen(xevnew), xevnew)); d(printf("creating new message %s\n", tmpname)); outfd = open(tmpname, O_CREAT|O_WRONLY|O_TRUNC, 0600); @@ -360,6 +360,7 @@ mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo int count, i; CamelMessageInfo *info; char *name; + const char *uid; d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); @@ -373,15 +374,16 @@ mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo info = camel_folder_summary_index((CamelFolderSummary *)cls, i); g_assert(info); if (expunge && (info->flags & CAMEL_MESSAGE_DELETED)) { - name = g_strdup_printf("%s/%s", cls->folder_path, info->uid); + uid = camel_message_info_uid(info); + name = g_strdup_printf("%s/%s", cls->folder_path, uid); d(printf("deleting %s\n", name)); if (unlink(name) == 0 || errno==ENOENT) { /* FIXME: put this in folder_summary::remove()? */ if (cls->index) - ibex_unindex(cls->index, info->uid); + ibex_unindex(cls->index, (char *)uid); - camel_folder_change_info_remove_uid(changes, info->uid); + camel_folder_change_info_remove_uid(changes, uid); camel_folder_summary_remove((CamelFolderSummary *)cls, info); } g_free(name); diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c index e4d53d779f..ba469583e3 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -216,7 +216,7 @@ nntp_folder_get_uids (CamelFolder *folder) for (i = 0; i < count; i++) { message_info = camel_folder_summary_index (nntp_folder->summary, i); - out->pdata[i] = g_strdup (message_info->uid); + out->pdata[i] = g_strdup (camel_message_info_uid(message_info)); } return out; diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c index 90c09a494e..439626d977 100644 --- a/camel/providers/nntp/camel-nntp-utils.c +++ b/camel/providers/nntp/camel-nntp-utils.c @@ -67,6 +67,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, CamelMessageInfo *new_info = camel_folder_summary_info_new(nntp_folder->summary); char **split_line = g_strsplit (line, "\t", 7); char *subject, *from, *date, *message_id, *bytes; + char *uid; subject = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_SUBJECT].index]; from = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_FROM].index]; @@ -88,16 +89,18 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, if (nntp_store->overview_field [ CAMEL_NNTP_OVER_BYTES ].full) bytes += strlen ("Bytes:"); - new_info->subject = g_strdup(subject); - new_info->from = g_strdup(from); - new_info->to = g_strdup(folder->name); + uid = g_strdup_printf ("%s,%s", split_line[0], message_id); + camel_message_info_set_subject(new_info, g_strdup(subject)); + camel_message_info_set_from(new_info, g_strdup(from)); + camel_message_info_set_to(new_info, g_strdup(folder->name)); + camel_message_info_set_uid(new_info, uid); + new_info->date_sent = header_decode_date(date, NULL); #if 0 /* XXX do we need to fill in both dates? */ new_info->headers.date_received = g_strdup(date); #endif new_info->size = atoi(bytes); - new_info->uid = g_strdup_printf ("%s,%s", split_line[0], message_id); md5_get_digest(message_id, strlen(message_id), digest); memcpy(new_info->message_id.id.hash, digest, sizeof(new_info->message_id.id.hash)); diff --git a/camel/providers/vee/camel-vee-folder.c b/camel/providers/vee/camel-vee-folder.c index 77c3017179..c8ac7f2059 100644 --- a/camel/providers/vee/camel-vee-folder.c +++ b/camel/providers/vee/camel-vee-folder.c @@ -28,6 +28,10 @@ #include "camel-folder-search.h" #endif +#ifdef DOESTRV +#include "e-util/e-memory.h" +#endif + #include <string.h> /* our message info includes the parent folder */ @@ -210,11 +214,13 @@ camel_vee_folder_new (CamelStore *parent_store, const char *name, CamelException static void vfolder_remove_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo) { - printf("removing match %s\n", vinfo->info.uid); + const char *uid = camel_message_info_uid(vinfo); + + printf("removing match %s\n", uid); - g_hash_table_remove(vf->messages_uid, vinfo->info.uid); + g_hash_table_remove(vf->messages_uid, uid); g_ptr_array_remove_fast(vf->messages, vinfo); - camel_folder_change_info_remove_uid(vf->changes, vinfo->info.uid); + camel_folder_change_info_remove_uid(vf->changes, uid); camel_message_info_free((CamelMessageInfo *)vinfo); } @@ -222,18 +228,26 @@ static CamelVeeMessageInfo * vfolder_add_match(CamelVeeFolder *vf, CamelFolder *f, const CamelMessageInfo *info) { CamelVeeMessageInfo *mi; + char *uid; mi = g_malloc0(sizeof(*mi)); camel_message_info_dup_to(info, (CamelMessageInfo*)mi); + uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); +#ifdef DOESTRV + mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); + mi->info.strings = e_strv_pack(mi->info.strings); +#else g_free (mi->info.uid); - mi->info.uid = g_strdup_printf("%p:%s", f, info->uid); + mi->info.uid = uid; +#endif mi->folder = f; g_ptr_array_add(vf->messages, mi); - g_hash_table_insert(vf->messages_uid, mi->info.uid, mi); + uid = (char *)camel_message_info_uid(mi); + g_hash_table_insert(vf->messages_uid, uid, mi); - printf("adding match %s\n", mi->info.uid); + printf("adding match %s\n", uid); - camel_folder_change_info_add_uid(vf->changes, mi->info.uid); + camel_folder_change_info_add_uid(vf->changes, uid); return mi; } #endif @@ -244,7 +258,7 @@ vfolder_change_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo, const Camel CamelFlag *flag; CamelTag *tag; - printf("changing match %s\n", vinfo->info.uid); + printf("changing match %s\n", camel_message_info_uid(vinfo)); vinfo->info.flags = info->flags; camel_flag_list_free(&vinfo->info.user_flags); @@ -259,7 +273,7 @@ vfolder_change_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo, const Camel camel_tag_set(&vinfo->info.user_tags, tag->name, tag->value); tag = tag->next; } - camel_folder_change_info_change_uid(vf->changes, vinfo->info.uid); + camel_folder_change_info_change_uid(vf->changes, camel_message_info_uid(vinfo)); } static void @@ -462,7 +476,7 @@ get_real_message(CamelFolder *folder, const char *uid, CamelFolder **out_folder, g_return_val_if_fail(mi != NULL, FALSE); *out_folder = mi->folder; - *out_uid = strchr(mi->info.uid, ':')+1; + *out_uid = strchr(camel_message_info_uid(mi), ':')+1; return TRUE; } @@ -505,7 +519,7 @@ static GPtrArray *vee_get_uids (CamelFolder *folder) g_ptr_array_set_size (result, vf->messages->len); for (i=0;i<vf->messages->len;i++) { CamelMessageInfo *mi = g_ptr_array_index(vf->messages, i); - result->pdata[i] = g_strdup(mi->uid); + result->pdata[i] = g_strdup(camel_message_info_uid(mi)); } return result; @@ -574,8 +588,7 @@ vee_get_message_user_flag(CamelFolder *folder, const char *uid, const char *name } static void -vee_set_message_user_flag(CamelFolder *folder, const char *uid, - const char *name, gboolean value) +vee_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) { const char *real_uid; CamelFolder *real_folder; @@ -627,13 +640,21 @@ vee_folder_build(CamelVeeFolder *vf, CamelException *ex) for (i = 0; i < matches->len; i++) { info = camel_folder_get_message_info(f, matches->pdata[i]); if (info) { + char *uid; + mi = g_malloc0(sizeof(*mi)); camel_message_info_dup_to(info, (CamelMessageInfo *)mi); - g_free (mi->info.uid); - mi->info.uid = g_strdup_printf("%p:%s", f, info->uid); + uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); +#ifdef DOESTRV + mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); + mi->info.strings = e_strv_pack(mi->info.strings); +#else + g_free(mi->info.uid); + mi->info.uid = uid; +#endif mi->folder = f; g_ptr_array_add(messages, mi); - g_hash_table_insert(messages_uid, mi->info.uid, mi); + g_hash_table_insert(messages_uid, (char *)camel_message_info_uid(mi), mi); } } camel_folder_search_free(f, matches); @@ -658,8 +679,9 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException for (i=0;i<vf->messages->len;i++) { CamelVeeMessageInfo *mi = g_ptr_array_index(vf->messages, i); if (mi->folder == source) { - camel_folder_change_info_add_source(vf->changes, mi->info.uid); - g_hash_table_remove(vf->messages_uid, mi->info.uid); + const char *uid = camel_message_info_uid(mi); + camel_folder_change_info_add_source(vf->changes, uid); + g_hash_table_remove(vf->messages_uid, uid); g_ptr_array_remove_index_fast(vf->messages, i); camel_message_info_free((CamelMessageInfo *)mi); @@ -674,15 +696,23 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException for (i = 0; i < matches->len; i++) { info = camel_folder_get_message_info(f, matches->pdata[i]); if (info) { + char *uid; + mi = g_malloc0(sizeof(*mi)); camel_message_info_dup_to(info, (CamelMessageInfo*)mi); + uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); +#ifdef DOESTRV + mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); + mi->info.strings = e_strv_pack(mi->info.strings); +#else g_free (mi->info.uid); - mi->info.uid = g_strdup_printf("%p:%s", f, info->uid); + mi->info.uid = uid; +#endif mi->folder = f; g_ptr_array_add(messages, mi); - g_hash_table_insert(messages_uid, mi->info.uid, mi); - - camel_folder_change_info_add_update(vf->changes, mi->info.uid); + uid = (char *)camel_message_info_uid(mi); + g_hash_table_insert(messages_uid, uid, mi); + camel_folder_change_info_add_update(vf->changes, uid); } } camel_folder_search_free(f, matches); diff --git a/camel/tests/folder/test2.c b/camel/tests/folder/test2.c index 06053f76c0..a3a8f014b8 100644 --- a/camel/tests/folder/test2.c +++ b/camel/tests/folder/test2.c @@ -112,7 +112,8 @@ int main(int argc, char **argv) push("checking it is the right message (subject): %s", subject); info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject); + check_msg(strcmp(camel_message_info_subject(info), subject)==0, + "info->subject %s", camel_message_info_subject(info)); camel_folder_free_uids(folder, uids); pull(); @@ -150,7 +151,8 @@ int main(int argc, char **argv) test_folder_message(folder, uids->pdata[j]); info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject); + check_msg(strcmp(camel_message_info_subject(info), subject)==0, + "info->subject %s", camel_message_info_subject(info)); test_free(subject); pull(); } @@ -175,7 +177,8 @@ int main(int argc, char **argv) test_folder_message(folder, uids->pdata[j]); info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject); + check_msg(strcmp(camel_message_info_subject(info), subject)==0, + "info->subject %s", camel_message_info_subject(info)); test_free(subject); pull(); } @@ -202,7 +205,8 @@ int main(int argc, char **argv) test_folder_message(folder, uids->pdata[j]); info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject); + check_msg(strcmp(camel_message_info_subject(info), subject)==0, + "info->subject %s", camel_message_info_subject(info)); test_free(subject); pull(); } diff --git a/camel/tests/lib/folders.c b/camel/tests/lib/folders.c index 738f8d2913..7be1b0c4cf 100644 --- a/camel/tests/lib/folders.c +++ b/camel/tests/lib/folders.c @@ -62,8 +62,8 @@ safe_strcmp(const char *a, const char *b) void test_message_info(CamelMimeMessage *msg, const CamelMessageInfo *info) { - check_msg(safe_strcmp(info->subject, camel_mime_message_get_subject(msg)) == 0, - "info->subject = '%s', get_subject() = '%s'", info->subject, camel_mime_message_get_subject(msg)); + check_msg(safe_strcmp(camel_message_info_subject(info), camel_mime_message_get_subject(msg)) == 0, + "info->subject = '%s', get_subject() = '%s'", camel_message_info_subject(info), camel_mime_message_get_subject(msg)); /* FIXME: testing from/cc/to, etc is more tricky */ @@ -91,7 +91,7 @@ test_folder_message(CamelFolder *folder, const char *uid) /* first try getting info */ info = camel_folder_get_message_info(folder, uid); check(info != NULL); - check(strcmp(info->uid, uid) == 0); + check(strcmp(camel_message_info_uid(info), uid) == 0); /* then, getting message */ msg = camel_folder_get_message(folder, uid, ex); @@ -109,7 +109,7 @@ test_folder_message(CamelFolder *folder, const char *uid) found = 0; for (i=0;i<s->len;i++) { info = s->pdata[i]; - if (strcmp(info->uid, uid) == 0) + if (strcmp(camel_message_info_uid(info), uid) == 0) found++; } check(found == 1); @@ -160,7 +160,7 @@ test_folder_not_message(CamelFolder *folder, const char *uid) found = 0; for (i=0;i<s->len;i++) { info = s->pdata[i]; - if (strcmp(info->uid, uid) == 0) + if (strcmp(camel_message_info_uid(info), uid) == 0) found++; } check(found == 0); |