Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / camel / providers / local / camel-local-summary.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
2 /*
3  *  Copyright (C) 2000 Ximian Inc.
4  *
5  *  Authors: Michael Zucchi <notzed@ximian.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2 of the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <ctype.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32
33 #include <glib.h>
34 #include <glib/gi18n-lib.h>
35 #include <glib/gstdio.h>
36
37 #include "camel-file-utils.h"
38 #include "camel-mime-message.h"
39 #include "camel-stream-null.h"
40
41 #include "camel-local-summary.h"
42
43 #define w(x)
44 #define io(x)
45 #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
46
47 #define CAMEL_LOCAL_SUMMARY_VERSION (1)
48
49 static int summary_header_load (CamelFolderSummary *, FILE *);
50 static int summary_header_save (CamelFolderSummary *, FILE *);
51
52 static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *);
53
54 static int local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *mi);
55 static char *local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *mi);
56
57 static int local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex);
58 static int local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex);
59 static int local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex);
60 static CamelMessageInfo *local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex);
61
62 static void camel_local_summary_class_init (CamelLocalSummaryClass *klass);
63 static void camel_local_summary_init       (CamelLocalSummary *obj);
64 static void camel_local_summary_finalise   (CamelObject *obj);
65 static CamelFolderSummaryClass *camel_local_summary_parent;
66
67 CamelType
68 camel_local_summary_get_type(void)
69 {
70         static CamelType type = CAMEL_INVALID_TYPE;
71         
72         if (type == CAMEL_INVALID_TYPE) {
73                 type = camel_type_register(camel_folder_summary_get_type(), "CamelLocalSummary",
74                                            sizeof (CamelLocalSummary),
75                                            sizeof (CamelLocalSummaryClass),
76                                            (CamelObjectClassInitFunc) camel_local_summary_class_init,
77                                            NULL,
78                                            (CamelObjectInitFunc) camel_local_summary_init,
79                                            (CamelObjectFinalizeFunc) camel_local_summary_finalise);
80         }
81         
82         return type;
83 }
84
85 static void
86 camel_local_summary_class_init(CamelLocalSummaryClass *klass)
87 {
88         CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass;
89         
90         camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
91
92         sklass->summary_header_load = summary_header_load;
93         sklass->summary_header_save = summary_header_save;
94
95         sklass->message_info_new_from_header  = message_info_new_from_header;
96
97         klass->load = local_summary_load;
98         klass->check = local_summary_check;
99         klass->sync = local_summary_sync;
100         klass->add = local_summary_add;
101
102         klass->encode_x_evolution = local_summary_encode_x_evolution;
103         klass->decode_x_evolution = local_summary_decode_x_evolution;
104 }
105
106 static void
107 camel_local_summary_init(CamelLocalSummary *obj)
108 {
109         struct _CamelFolderSummary *s = (CamelFolderSummary *)obj;
110
111         /* subclasses need to set the right instance data sizes */
112         s->message_info_size = sizeof(CamelLocalMessageInfo);
113         s->content_info_size = sizeof(CamelMessageContentInfo);
114
115         /* and a unique file version */
116         s->version += CAMEL_LOCAL_SUMMARY_VERSION;
117 }
118
119 static void
120 camel_local_summary_finalise(CamelObject *obj)
121 {
122         CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(obj);
123
124         if (mbs->index)
125                 camel_object_unref((CamelObject *)mbs->index);
126         g_free(mbs->folder_path);
127 }
128
129 void
130 camel_local_summary_construct(CamelLocalSummary *new, const char *filename, const char *local_name, CamelIndex *index)
131 {
132         camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), FALSE);
133         camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY(new), filename);
134         new->folder_path = g_strdup(local_name);
135         new->index = index;
136         if (index)
137                 camel_object_ref((CamelObject *)index);
138 }
139
140 static int
141 local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex)
142 {
143         return camel_folder_summary_load((CamelFolderSummary *)cls);
144 }
145
146 /* load/check the summary */
147 int
148 camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex)
149 {
150         struct stat st;
151         CamelFolderSummary *s = (CamelFolderSummary *)cls;
152
153         d(printf("Loading summary ...\n"));
154
155         if (forceindex
156             || g_stat(s->summary_path, &st) == -1
157             || ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) {
158                 w(g_warning("Could not load summary: flags may be reset"));
159                 camel_folder_summary_clear((CamelFolderSummary *)cls);
160                 return -1;
161         }
162
163         return 0;
164 }
165
166 void camel_local_summary_check_force(CamelLocalSummary *cls)
167 {
168         cls->check_force = 1;
169 }
170
171 char *
172 camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *info)
173 {
174         return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->encode_x_evolution(cls, info);
175 }
176
177 int
178 camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *info)
179 {
180         return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info);
181 }
182
183 /*#define DOSTATS*/
184 #ifdef DOSTATS
185 struct _stat_info {
186         int mitotal;
187         int micount;
188         int citotal;
189         int cicount;
190         int msgid;
191         int msgcount;
192 };
193
194 static void
195 do_stat_ci(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageContentInfo *ci)
196 {
197         info->cicount++;
198         info->citotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4 memchunks are 1/4 byte overhead per mi */;
199         if (ci->id)
200                 info->citotal += strlen(ci->id) + 4;
201         if (ci->description)
202                 info->citotal += strlen(ci->description) + 4;
203         if (ci->encoding)
204                 info->citotal += strlen(ci->encoding) + 4;
205         if (ci->type) {
206                 CamelContentType *ct = ci->type;
207                 struct _camel_header_param *param;
208
209                 info->citotal += sizeof(*ct) + 4;
210                 if (ct->type)
211                         info->citotal += strlen(ct->type) + 4;
212                 if (ct->subtype)
213                         info->citotal += strlen(ct->subtype) + 4;
214                 param = ct->params;
215                 while (param) {
216                         info->citotal += sizeof(*param) + 4;
217                         if (param->name)
218                                 info->citotal += strlen(param->name)+4;
219                         if (param->value)
220                                 info->citotal += strlen(param->value)+4;
221                         param = param->next;
222                 }
223         }
224         ci = ci->childs;
225         while (ci) {
226                 do_stat_ci(cls, info, ci);
227                 ci = ci->next;
228         }
229 }
230
231 static void
232 do_stat_mi(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageInfo *mi)
233 {
234         info->micount++;
235         info->mitotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4*/;
236
237         if (mi->subject)
238                 info->mitotal += strlen(mi->subject) + 4;
239         if (mi->to)
240                 info->mitotal += strlen(mi->to) + 4;
241         if (mi->from)
242                 info->mitotal += strlen(mi->from) + 4;
243         if (mi->cc)
244                 info->mitotal += strlen(mi->cc) + 4;
245         if (mi->uid)
246                 info->mitotal += strlen(mi->uid) + 4;
247
248         if (mi->references) {
249                 info->mitotal += (mi->references->size-1) * sizeof(CamelSummaryMessageID) + sizeof(CamelSummaryReferences) + 4;
250                 info->msgid += (mi->references->size) * sizeof(CamelSummaryMessageID);
251                 info->msgcount += mi->references->size;
252         }
253
254         /* dont have any user flags yet */
255
256         if (mi->content) {
257                 do_stat_ci(cls, info, mi->content);
258         }
259 }
260
261 #endif
262
263 int
264 camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex)
265 {
266         int ret;
267
268         ret = ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->check(cls, changeinfo, ex);
269
270 #ifdef DOSTATS
271         if (ret != -1) {
272                 int i;
273                 CamelFolderSummary *s = (CamelFolderSummary *)cls;
274                 struct _stat_info stats = { 0 };
275
276                 for (i=0;i<camel_folder_summary_count(s);i++) {
277                         CamelMessageInfo *info = camel_folder_summary_index(s, i);
278                         do_stat_mi(cls, &stats, info);
279                         camel_message_info_free(info);
280                 }
281
282                 printf("\nMemory used by summary:\n\n");
283                 printf("Total of %d messages\n", camel_folder_summary_count(s)); 
284                 printf("Total: %d bytes (ave %f)\n", stats.citotal + stats.mitotal,
285                        (double)(stats.citotal+stats.mitotal)/(double)camel_folder_summary_count(s));
286                 printf("Message Info: %d (ave %f)\n", stats.mitotal, (double)stats.mitotal/(double)stats.micount);
287                 printf("Content Info; %d (ave %f) count %d\n", stats.citotal, (double)stats.citotal/(double)stats.cicount, stats.cicount);
288                 printf("message id's: %d (ave %f) count %d\n", stats.msgid, (double)stats.msgid/(double)stats.msgcount, stats.msgcount);
289         }
290 #endif
291         return ret;
292 }
293
294 int
295 camel_local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex)
296 {
297         return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->sync(cls, expunge, changeinfo, ex);
298 }
299
300 CamelMessageInfo *
301 camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex)
302 {
303         return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->add(cls, msg, info, ci, ex);
304 }
305
306 /**
307  * camel_local_summary_write_headers:
308  * @fd: 
309  * @header: 
310  * @xevline: 
311  * @status:
312  * @xstatus:
313  * 
314  * Write a bunch of headers to the file @fd.  IF xevline is non NULL, then
315  * an X-Evolution header line is created at the end of all of the headers.
316  * If @status is non NULL, then a Status header line is also written.
317  * The headers written are termianted with a blank line.
318  * 
319  * Return value: -1 on error, otherwise the number of bytes written.
320  **/
321 int
322 camel_local_summary_write_headers(int fd, struct _camel_header_raw *header, const char *xevline, const char *status, const char *xstatus)
323 {
324         int outlen = 0, len;
325         int newfd;
326         FILE *out;
327
328         /* dum de dum, maybe the whole sync function should just use stdio for output */
329         newfd = dup(fd);
330         if (newfd == -1)
331                 return -1;
332
333         out = fdopen(newfd, "w");
334         if (out == NULL) {
335                 close(newfd);
336                 errno = EINVAL;
337                 return -1;
338         }
339
340         while (header) {
341                 if (strcmp(header->name, "X-Evolution") != 0
342                     && (status == NULL || strcmp(header->name, "Status") != 0)
343                     && (xstatus == NULL || strcmp(header->name, "X-Status") != 0)) {
344                         len = fprintf(out, "%s:%s\n", header->name, header->value);
345                         if (len == -1) {
346                                 fclose(out);
347                                 return -1;
348                         }
349                         outlen += len;
350                 }
351                 header = header->next;
352         }
353
354         if (status) {
355                 len = fprintf(out, "Status: %s\n", status);
356                 if (len == -1) {
357                         fclose(out);
358                         return -1;
359                 }
360                 outlen += len;
361         }
362
363         if (xstatus) {
364                 len = fprintf(out, "X-Status: %s\n", xstatus);
365                 if (len == -1) {
366                         fclose(out);
367                         return -1;
368                 }
369                 outlen += len;
370         }
371
372         if (xevline) {
373                 len = fprintf(out, "X-Evolution: %s\n", xevline);
374                 if (len == -1) {
375                         fclose(out);
376                         return -1;
377                 }
378                 outlen += len;
379         }
380
381         len = fprintf(out, "\n");
382         if (len == -1) {
383                 fclose(out);
384                 return -1;
385         }
386         outlen += len;
387
388         if (fclose(out) == -1)
389                 return -1;
390
391         return outlen;
392 }
393
394 static int
395 local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex)
396 {
397         /* FIXME: sync index here ? */
398         return 0;
399 }
400
401 static int
402 local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex)
403 {
404         int ret = 0;
405
406         ret = camel_folder_summary_save((CamelFolderSummary *)cls);
407         if (ret == -1) {
408                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
409                                       _("Could not save summary: %s: %s"),
410                                       cls->folder_path, g_strerror (errno));
411                 
412                 g_warning ("Could not save summary for %s: %s", cls->folder_path, strerror (errno));
413         }
414
415         if (cls->index && camel_index_sync(cls->index) == -1)
416                 g_warning ("Could not sync index for %s: %s", cls->folder_path, strerror (errno));
417
418         return ret;
419 }
420
421 static CamelMessageInfo *
422 local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex)
423 {
424         CamelLocalMessageInfo *mi;
425         char *xev;
426
427         d(printf("Adding message to summary\n"));
428         
429         mi = (CamelLocalMessageInfo *)camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg);
430         if (mi) {
431                 d(printf("Added, uid = %s\n", mi->uid));
432                 if (info) {
433                         const CamelTag *tag = camel_message_info_user_tags(info);
434                         const CamelFlag *flag = camel_message_info_user_flags(info);
435
436                         while (flag) {
437                                 camel_message_info_set_user_flag((CamelMessageInfo *)mi, flag->name, TRUE);
438                                 flag = flag->next;
439                         }
440                         
441                         while (tag) {
442                                 camel_message_info_set_user_tag((CamelMessageInfo *)mi, tag->name, tag->value);
443                                 tag = tag->next;
444                         }
445
446                         mi->info.flags |= (camel_message_info_flags(info) & 0xffff);
447                         mi->info.size = camel_message_info_size(info);
448                 }
449
450                 /* we need to calculate the size ourselves */
451                 if (mi->info.size == 0) {
452                         CamelStreamNull *sn = (CamelStreamNull *)camel_stream_null_new();
453
454                         camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)sn);
455                         mi->info.size = sn->written;
456                         camel_object_unref((CamelObject *)sn);
457                 }
458
459                 mi->info.flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED);
460                 xev = camel_local_summary_encode_x_evolution(cls, mi);
461                 camel_medium_set_header((CamelMedium *)msg, "X-Evolution", xev);
462                 g_free(xev);
463                 camel_folder_change_info_add_uid(ci, camel_message_info_uid(mi));
464         } else {
465                 d(printf("Failed!\n"));
466                 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
467                                      _("Unable to add message to summary: unknown reason"));
468         }
469         return (CamelMessageInfo *)mi;
470 }
471
472 static char *
473 local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *mi)
474 {
475         GString *out = g_string_new("");
476         struct _camel_header_param *params = NULL;
477         GString *val = g_string_new("");
478         CamelFlag *flag = mi->info.user_flags;
479         CamelTag *tag = mi->info.user_tags;
480         char *ret;
481         const char *p, *uidstr;
482         guint32 uid;
483
484         /* FIXME: work out what to do with uid's that aren't stored here? */
485         /* FIXME: perhaps make that a mbox folder only issue?? */
486         p = uidstr = camel_message_info_uid(mi);
487         while (*p && isdigit(*p))
488                 p++;
489         if (*p == 0 && sscanf (uidstr, "%u", &uid) == 1) {
490                 g_string_printf (out, "%08x-%04x", uid, mi->info.flags & 0xffff);
491         } else {
492                 g_string_printf (out, "%s-%04x", uidstr, mi->info.flags & 0xffff);
493         }
494
495         if (flag || tag) {
496                 val = g_string_new ("");
497                 
498                 if (flag) {
499                         while (flag) {
500                                 g_string_append (val, flag->name);
501                                 if (flag->next)
502                                         g_string_append_c (val, ',');
503                                 flag = flag->next;
504                         }
505                         camel_header_set_param (&params, "flags", val->str);
506                         g_string_truncate (val, 0);
507                 }
508                 if (tag) {
509                         while (tag) {
510                                 g_string_append (val, tag->name);
511                                 g_string_append_c (val, '=');
512                                 g_string_append (val, tag->value);
513                                 if (tag->next)
514                                         g_string_append_c (val, ',');
515                                 tag = tag->next;
516                         }
517                         camel_header_set_param (&params, "tags", val->str);
518                 }
519                 g_string_free (val, TRUE);
520                 camel_header_param_list_format_append (out, params);
521                 camel_header_param_list_free (params);
522         }
523         ret = out->str;
524         g_string_free (out, FALSE);
525         
526         return ret;
527 }
528
529 static int
530 local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *mi)
531 {
532         struct _camel_header_param *params, *scan;
533         guint32 uid, flags;
534         char *header;
535         int i;
536         char uidstr[20];
537
538         uidstr[0] = 0;
539
540         /* check for uid/flags */
541         header = camel_header_token_decode(xev);
542         if (header && strlen(header) == strlen("00000000-0000")
543             && sscanf(header, "%08x-%04x", &uid, &flags) == 2) {
544                 if (mi)
545                         sprintf(uidstr, "%u", uid);
546         } else {
547                 g_free(header);
548                 return -1;
549         }
550         g_free(header);
551
552         if (mi == NULL)
553                 return 0;
554
555         /* check for additional data */ 
556         header = strchr(xev, ';');
557         if (header) {
558                 params = camel_header_param_list_decode(header+1);
559                 scan = params;
560                 while (scan) {
561                         if (!g_ascii_strcasecmp(scan->name, "flags")) {
562                                 char **flagv = g_strsplit(scan->value, ",", 1000);
563
564                                 for (i=0;flagv[i];i++)
565                                         camel_message_info_set_user_flag((CamelMessageInfo *)mi, flagv[i], TRUE);
566                                 g_strfreev(flagv);
567                         } else if (!g_ascii_strcasecmp(scan->name, "tags")) {
568                                 char **tagv = g_strsplit(scan->value, ",", 10000);
569                                 char *val;
570
571                                 for (i=0;tagv[i];i++) {
572                                         val = strchr(tagv[i], '=');
573                                         if (val) {
574                                                 *val++ = 0;
575                                                 camel_message_info_set_user_tag((CamelMessageInfo *)mi, tagv[i], val);
576                                                 val[-1]='=';
577                                         }
578                                 }
579                                 g_strfreev(tagv);
580                         }
581                         scan = scan->next;
582                 }
583                 camel_header_param_list_free(params);
584         }
585
586         mi->info.uid = g_strdup(uidstr);
587         mi->info.flags = flags;
588
589         return 0;
590 }
591
592 static int
593 summary_header_load(CamelFolderSummary *s, FILE *in)
594 {
595         CamelLocalSummary *cls = (CamelLocalSummary *)s;
596
597         /* We dont actually add our own headers, but version that we don't anyway */
598
599         if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_load(s, in) == -1)
600                 return -1;
601
602         /* Legacy version, version is in summary only */
603         if ((s->version & 0xfff) == 0x20c)
604                 return 0;
605
606         /* otherwise load the version number */
607         return camel_file_util_decode_fixed_int32(in, &cls->version);
608 }
609
610 static int
611 summary_header_save(CamelFolderSummary *s, FILE *out)
612 {
613         /*CamelLocalSummary *cls = (CamelLocalSummary *)s;*/
614
615         if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_save(s, out) == -1)
616                 return -1;
617
618         return camel_file_util_encode_fixed_int32(out, CAMEL_LOCAL_SUMMARY_VERSION);
619 }
620
621 static CamelMessageInfo *
622 message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h)
623 {
624         CamelLocalMessageInfo *mi;
625         CamelLocalSummary *cls = (CamelLocalSummary *)s;
626
627         mi = (CamelLocalMessageInfo *)((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_new_from_header(s, h);
628         if (mi) {
629                 const char *xev;
630                 int doindex = FALSE;
631
632                 xev = camel_header_raw_find(&h, "X-Evolution", NULL);
633                 if (xev==NULL || camel_local_summary_decode_x_evolution(cls, xev, mi) == -1) {
634                         /* to indicate it has no xev header */
635                         mi->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
636                         g_free (mi->info.uid);
637                         mi->info.uid = camel_folder_summary_next_uid_string(s);
638
639                         /* shortcut, no need to look it up in the index library */
640                         doindex = TRUE;
641                 }
642                 
643                 if (cls->index
644                     && (doindex
645                         || cls->index_force
646                         || !camel_index_has_name(cls->index, camel_message_info_uid(mi)))) {
647                         d(printf("Am indexing message %s\n", camel_message_info_uid(mi)));
648                         camel_folder_summary_set_index(s, cls->index);
649                 } else {
650                         d(printf("Not indexing message %s\n", camel_message_info_uid(mi)));
651                         camel_folder_summary_set_index(s, NULL);
652                 }
653         }
654         
655         return (CamelMessageInfo *)mi;
656 }