aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-folder-summary.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-folder-summary.c')
-rw-r--r--camel/camel-folder-summary.c288
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