diff options
Diffstat (limited to 'camel/camel-folder-summary.c')
-rw-r--r-- | camel/camel-folder-summary.c | 288 |
1 files changed, 263 insertions, 25 deletions
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index de66646483..bdca6e677c 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -24,6 +24,7 @@ #include <ctype.h> #include <string.h> #include <errno.h> +#include <stdlib.h> #include "camel-folder-summary.h" @@ -34,7 +35,11 @@ #include <camel/camel-mime-filter-basic.h> #include "hash-table-utils.h" +/* this should probably be conditional on it existing */ +#define USE_BSEARCH + #define d(x) +#define io(x) /* io debug */ #if 0 extern int strdup_count, malloc_count, free_count; @@ -216,8 +221,6 @@ void camel_folder_summary_set_index(CamelFolderSummary *s, ibex *index) { struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); - if (p->index) - ibex_write(p->index); p->index = index; } @@ -275,8 +278,8 @@ perform_content_info_load(CamelFolderSummary *s, FILE *in) for (i=0;i<count;i++) { part = perform_content_info_load(s, in); if (part) { - my_list_append((struct _node **)&ci->childs, (struct _node *)ci); - ci->parent = ci; + my_list_append((struct _node **)&ci->childs, (struct _node *)part); + part->parent = ci; } else { g_warning("Summary file format messed up?"); } @@ -293,27 +296,39 @@ camel_folder_summary_load(CamelFolderSummary *s) g_assert(s->summary_path); + printf("loading summary\n"); + in = fopen(s->summary_path, "r"); if ( in == NULL ) { return -1; } + printf("loading header\n"); + if ( ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->summary_header_load(s, in) == -1) { fclose(in); return -1; } + printf("loading content\n"); + /* now read in each message ... */ /* FIXME: check returns */ for (i=0;i<s->saved_count;i++) { mi = ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->message_info_load(s, in); if (s->build_content) { - mi->content = content_info_load(s, in); + mi->content = perform_content_info_load(s, in); } + + camel_folder_summary_add(s, mi); } + + if (fclose(in) == -1) + return -1; + + s->flags &= ~CAMEL_SUMMARY_DIRTY; - /* FIXME: check error return */ return 0; } @@ -344,6 +359,13 @@ camel_folder_summary_save(CamelFolderSummary *s) g_assert(s->summary_path); + printf("saving summary?\n"); + + if ((s->flags & CAMEL_SUMMARY_DIRTY) == 0) { + printf("nup\n"); + return 0; + } + fd = open(s->summary_path, O_RDWR|O_CREAT, 0600); if (fd == -1) return -1; @@ -353,6 +375,8 @@ camel_folder_summary_save(CamelFolderSummary *s) return -1; } + io(printf("saving header\n")); + if ( ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->summary_header_save(s, out) == -1) { fclose(out); return -1; @@ -369,7 +393,11 @@ camel_folder_summary_save(CamelFolderSummary *s) perform_content_info_save(s, out, mi->content); } } - return fclose(out); + if (fclose(out) == -1) + return -1; + + s->flags &= ~CAMEL_SUMMARY_DIRTY; + return 0; } void camel_folder_summary_add(CamelFolderSummary *s, CamelMessageInfo *info) @@ -392,17 +420,19 @@ retry: s->flags |= CAMEL_SUMMARY_DIRTY; } -void camel_folder_summary_add_from_header(CamelFolderSummary *s, struct _header_raw *h) +CamelMessageInfo *camel_folder_summary_add_from_header(CamelFolderSummary *s, struct _header_raw *h) { - CamelMessageInfo *info; + CamelMessageInfo *info = NULL; info = ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->message_info_new(s, h); camel_folder_summary_add(s, info); + + return info; } -void camel_folder_summary_add_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) +CamelMessageInfo *camel_folder_summary_add_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) { - CamelMessageInfo *info; + CamelMessageInfo *info = NULL; char *buffer; int len; struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); @@ -437,6 +467,68 @@ void camel_folder_summary_add_from_parser(CamelFolderSummary *s, CamelMimeParser camel_folder_summary_add(s, info); } + return info; +} + +static void +perform_content_info_free(CamelFolderSummary *s, CamelMessageContentInfo *ci) +{ + CamelMessageContentInfo *pw, *pn; + + pw = ci->childs; + ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->content_info_free(s, ci); + while (pw) { + pn = pw->next; + perform_content_info_free(s, pw); + pw = pn; + } +} + +void +camel_folder_summary_clear(CamelFolderSummary *s) +{ + int i; + + if (camel_folder_summary_count(s) == 0) + return; + + for (i=0;i<camel_folder_summary_count(s);i++) { + CamelMessageInfo *mi = camel_folder_summary_index(s, i); + CamelMessageContentInfo *ci = mi->content; + + ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->message_info_free(s, mi); + if (s->build_content && ci) { + perform_content_info_free(s, ci); + } + } + + 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; +} + +void camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info) +{ + CamelMessageContentInfo *ci = info->content; + + g_hash_table_remove(s->messages_uid, info->uid); + g_ptr_array_remove(s->messages, info); + ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->message_info_free(s, info); + if (s->build_content && ci) { + perform_content_info_free(s, ci); + } +} + +void camel_folder_summary_remove_uid(CamelFolderSummary *s, const char *uid) +{ + CamelMessageInfo *oldinfo; + char *olduid; + + if (g_hash_table_lookup_extended(s->messages_uid, uid, (void *)&olduid, (void *)&oldinfo)) { + camel_folder_summary_remove(s, oldinfo); + g_free(olduid); + } } int @@ -444,6 +536,8 @@ camel_folder_summary_encode_uint32(FILE *out, guint32 value) { int i; + io(printf("Encoding int %u\n", value)); + for (i=28;i>0;i-=7) { if (value >= (1<<i)) { unsigned int c = (value>>i) & 0x7f; @@ -469,6 +563,9 @@ camel_folder_summary_decode_uint32(FILE *in, guint32 *dest) return 01; } *dest = value | (v&0x7f); + + io(printf("Decoding int %u\n", *dest)); + return 0; } @@ -520,10 +617,12 @@ static char * tokens[] = { "octet-stream", "parallel", "plain", + "postscript", "quoted-printable", + "related", "rfc822", "text", - "us-ascii", /* 23 words */ + "us-ascii", /* 25 words */ }; #define tokens_len (sizeof(tokens)/sizeof(tokens[0])) @@ -534,9 +633,20 @@ static char * tokens[] = { >=32 string, length = n-32 */ +#ifdef USE_BSEARCH +static int +token_search_cmp(char *key, char **index) +{ + d(printf("comparing '%s' to '%s'\n", key, *index)); + return strcmp(key, *index); +} +#endif + int camel_folder_summary_encode_token(FILE *out, char *str) { + io(printf("Encoding token: '%s'\n", str)); + if (str == NULL) { return camel_folder_summary_encode_uint32(out, 0); } else { @@ -545,16 +655,23 @@ camel_folder_summary_encode_token(FILE *out, char *str) if (len <= 16) { char lower[32]; + char **match; for (i=0;i<len;i++) lower[i] = tolower(str[i]); lower[i] = 0; +#ifdef USE_BSEARCH + match = bsearch(lower, tokens, tokens_len, sizeof(char *), (int (*)(void *, void *))token_search_cmp); + if (match) + token = match-tokens; +#else for (i=0;i<tokens_len;i++) { if (!strcmp(tokens[i], lower)) { token = i; break; } } +#endif } if (token != -1) { return camel_folder_summary_encode_uint32(out, token+1); @@ -573,8 +690,11 @@ camel_folder_summary_decode_token(FILE *in, char **str) { char *ret; int len; + + io(printf("Decode token ...\n")); if (camel_folder_summary_decode_uint32(in, &len) == -1) { + g_warning("Could not decode token from file"); *str = NULL; return -1; } @@ -604,6 +724,8 @@ camel_folder_summary_decode_token(FILE *in, char **str) ret[len]=0; } + io(printf("Token = '%s'\n", ret)); + *str = ret; return 0; } @@ -613,6 +735,8 @@ camel_folder_summary_encode_string(FILE *out, char *str) { register int len; + io(printf("Encoding string: '%s'\n", str)); + if (str == NULL) return camel_folder_summary_encode_uint32(out, 0); @@ -631,6 +755,8 @@ camel_folder_summary_decode_string(FILE *in, char **str) int len; register char *ret; + io(printf("Decode string ...\n", str)); + if (camel_folder_summary_decode_uint32(in, &len) == -1) { *str = NULL; return -1; @@ -639,6 +765,7 @@ camel_folder_summary_decode_string(FILE *in, char **str) len--; if (len < 0) { *str = NULL; + io(printf("String = '%s'\n", *str)); return -1; } @@ -649,6 +776,8 @@ camel_folder_summary_decode_string(FILE *in, char **str) return -1; } + io(printf("String = '%s'\n", ret)); + ret[len] = 0; *str = ret; return 0; @@ -698,6 +827,8 @@ summary_header_load(CamelFolderSummary *s, FILE *in) fseek(in, 0, SEEK_SET); + io(printf("Loading header\n")); + if (camel_folder_summary_decode_fixed_int32(in, &version) == -1 || camel_folder_summary_decode_fixed_int32(in, &flags) == -1 || camel_folder_summary_decode_fixed_int32(in, &nextuid) == -1 @@ -722,6 +853,8 @@ summary_header_save(CamelFolderSummary *s, FILE *out) { fseek(out, 0, SEEK_SET); + io(printf("Savining header\n")); + camel_folder_summary_encode_fixed_int32(out, s->version); camel_folder_summary_encode_fixed_int32(out, s->flags); camel_folder_summary_encode_fixed_int32(out, s->nextuid); @@ -788,6 +921,21 @@ summary_format_address(struct _header_raw *h, const char *name) return ret; } +static char * +summary_format_string(struct _header_raw *h, const char *name) +{ + const char *text; + + text = header_raw_find(&h, name, NULL); + if (text) { + while (isspace(*text)) + text++; + return header_decode_string(text); + } else { + return NULL; + } +} + static CamelMessageInfo * message_info_new(CamelFolderSummary *s, struct _header_raw *h) { @@ -795,7 +943,7 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) mi = g_malloc0(s->message_info_size); - mi->subject = header_decode_string(header_raw_find(&h, "subject", NULL)); + mi->subject = summary_format_string(h, "subject"); mi->from = summary_format_address(h, "from"); mi->to = summary_format_address(h, "to"); mi->date_sent = header_decode_date(header_raw_find(&h, "date", NULL), NULL); @@ -808,13 +956,13 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) static CamelMessageInfo * message_info_load(CamelFolderSummary *s, FILE *in) { - guint32 tmp; CamelMessageInfo *mi; mi = g_malloc0(s->message_info_size); - camel_folder_summary_decode_uint32(in, &tmp); - mi->uid = g_strdup_printf("%u", tmp); + io(printf("Loading message info\n")); + + camel_folder_summary_decode_string(in, &mi->uid); camel_folder_summary_decode_uint32(in, &mi->flags); camel_folder_summary_decode_uint32(in, &mi->date_sent); /* warnings, leave them here */ camel_folder_summary_decode_uint32(in, &mi->date_received); @@ -830,7 +978,9 @@ message_info_load(CamelFolderSummary *s, FILE *in) static int message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) { - camel_folder_summary_encode_uint32(out, strtoul(mi->uid, NULL, 10)); + io(printf("Saving message info\n")); + + camel_folder_summary_encode_string(out, mi->uid); camel_folder_summary_encode_uint32(out, mi->flags); camel_folder_summary_encode_uint32(out, mi->date_sent); camel_folder_summary_encode_uint32(out, mi->date_received); @@ -875,8 +1025,14 @@ content_info_load(CamelFolderSummary *s, FILE *in) guint32 count, i; struct _header_content_type *ct; + io(printf("Loading content info\n")); + ci = g_malloc0(s->content_info_size); + camel_folder_summary_decode_uint32(in, &ci->pos); + camel_folder_summary_decode_uint32(in, &ci->bodypos); + camel_folder_summary_decode_uint32(in, &ci->endpos); + camel_folder_summary_decode_token(in, &type); camel_folder_summary_decode_token(in, &subtype); ct = header_content_type_new(type, subtype); @@ -908,6 +1064,12 @@ content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci) struct _header_content_type *ct; struct _header_param *hp; + io(printf("Saving content info\n")); + + camel_folder_summary_encode_uint32(out, ci->pos); + camel_folder_summary_encode_uint32(out, ci->bodypos); + camel_folder_summary_encode_uint32(out, ci->endpos); + ct = ci->type; if (ct) { camel_folder_summary_encode_token(out, ct->type); @@ -952,20 +1114,21 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) char *buffer; CamelMessageContentInfo *info = NULL; struct _header_content_type *ct; - int start, body; + int body; int enc_id = -1, chr_id = -1, idx_id = -1; struct _CamelFolderSummaryPrivate *p = _PRIVATE(s); CamelMimeFilterCharset *mfc; CamelMessageContentInfo *part; + d(printf("building content info\n")); + /* start of this part */ - start = camel_mime_parser_tell(mp); state = camel_mime_parser_step(mp, &buffer, &len); body = camel_mime_parser_tell(mp); info = ((CamelFolderSummaryClass *)((GtkObject *)s)->klass)->content_info_new_from_parser(s, mp); - info->pos = start; + info->pos = camel_mime_parser_tell_start_headers(mp); info->bodypos = body; switch(state) { @@ -975,17 +1138,23 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) if (p->index && header_content_type_is(ct, "text", "*")) { char *encoding; const char *charset; - + + d(printf("generating index:\n")); + encoding = header_content_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL)); if (encoding) { if (!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); enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_64); } else if (!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); enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_qp); + } else { + d(printf(" ignoring encoding %s\n", encoding)); } g_free(encoding); } @@ -994,7 +1163,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) if (charset!=NULL && !(strcasecmp(charset, "us-ascii")==0 || strcasecmp(charset, "utf-8")==0)) { - d(printf("Adding conversion filter from %s to utf-8\n", charset)); + 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"); @@ -1020,6 +1189,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) camel_mime_parser_filter_remove(mp, idx_id); break; case HSCAN_MULTIPART: + d(printf("Summarising multipart\n")); while (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_MULTIPART_END) { camel_mime_parser_unstep(mp); part = summary_build_content_info(s, mp); @@ -1032,6 +1202,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) } break; case HSCAN_MESSAGE: + d(printf("Summarising message\n")); part = summary_build_content_info(s, mp); if (part) { part->parent = info; @@ -1049,10 +1220,54 @@ summary_build_content_info(CamelFolderSummary *s, CamelMimeParser *mp) info->endpos = camel_mime_parser_tell(mp); + d(printf("finished building content info\n")); + return info; } -#if 1 +static void +content_info_dump(CamelMessageContentInfo *ci, int depth) +{ + char *p; + + p = alloca(depth*4+1); + memset(p, ' ', depth*4); + p[depth*4] = 0; + + if (ci == NULL) { + printf("%s<empty>\n", p); + return; + } + + printf("%sconent-type: %s/%s\n", p, ci->type->type, ci->type->subtype); + printf("%sontent-transfer-encoding: %s\n", p, ci->encoding); + printf("%scontent-description: %s\n", p, ci->description); + printf("%sbytes: %d %d %d\n", p, (int)ci->pos, (int)ci->bodypos, (int)ci->endpos); + ci = ci->childs; + while (ci) { + content_info_dump(ci, depth+1); + ci = ci->next; + } +} + +static void +message_info_dump(CamelMessageInfo *mi) +{ + if (mi == NULL) { + printf("No message?\n"); + return; + } + + printf("Subject: %s\n", mi->subject); + printf("To: %s\n", mi->to); + printf("From: %s\n", mi->from); + printf("UID: %s\n", mi->uid); + printf("Flags: %04x\n", mi->flags & 0xffff); + content_info_dump(mi->content, 0); +} + + +#if 0 int main(int argc, char **argv) { CamelMimeParser *mp; @@ -1060,6 +1275,7 @@ int main(int argc, char **argv) CamelFolderSummary *s; char *buffer; int len; + int i; ibex *index; gtk_init(&argc, &argv); @@ -1109,12 +1325,34 @@ int main(int argc, char **argv) } } + printf("Printing summary\n"); + for (i=0;i<camel_folder_summary_count(s);i++) { + message_info_dump(camel_folder_summary_index(s, i)); + } + printf("Saivng summary\n"); camel_folder_summary_set_filename(s, "index.summary"); camel_folder_summary_save(s); - gtk_object_unref(GTK_OBJECT(mp)); - gtk_object_unref(GTK_OBJECT(s)); + { + CamelFolderSummary *n; + + printf("\nLoading summary\n"); + n = camel_folder_summary_new(); + camel_folder_summary_set_build_content(n, TRUE); + camel_folder_summary_set_filename(n, "index.summary"); + camel_folder_summary_load(n); + + printf("Printing summary\n"); + for (i=0;i<camel_folder_summary_count(n);i++) { + message_info_dump(camel_folder_summary_index(n, i)); + } + gtk_object_unref(n); + } + + + gtk_object_unref(mp); + gtk_object_unref(s); printf("summarised %d messages\n", camel_folder_summary_count(s)); #if 0 |