Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / camel / providers / groupwise / camel-groupwise-folder.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-groupwise-folder.c: class for an groupwise folder */
3
4 /* 
5  * Authors:
6  *  Sivaiah Nallagatla <snallagatla@novell.com>
7  *  parthasarathi susarla <sparthasarathi@novell.com>
8  *  Sankar P <psankar@novell.com>
9  *   
10  *
11  * Copyright (C) 2004, Novell Inc.
12  *
13  * This program is free software; you can redistribute it and/or 
14  * modify it under the terms of version 2 of the GNU Lesser General Public 
15  * License as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
25  * USA
26  */
27
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h> 
31 #endif
32
33 #include <errno.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39
40 #include <glib.h>
41 #include <glib/gi18n-lib.h>
42
43 #include <libsoup/soup-misc.h>
44
45 #include <libedataserver/e-msgport.h>
46
47 #include <e-gw-connection.h>
48 #include <e-gw-item.h>
49
50 #include "camel-folder-search.h"
51 #include "camel-folder.h"
52 #include "camel-private.h"
53 #include "camel-session.h"
54 #include "camel-stream-mem.h"
55 #include "camel-string-utils.h"
56
57 #include "camel-groupwise-folder.h"
58 #include "camel-groupwise-journal.h"
59 #include "camel-groupwise-private.h"
60 #include "camel-groupwise-store.h"
61 #include "camel-groupwise-store.h"
62 #include "camel-groupwise-summary.h"
63 #include "camel-groupwise-utils.h"
64 #include "camel-groupwise-utils.h"
65
66 #define ADD_JUNK_ENTRY 1
67 #define REMOVE_JUNK_ENTRY -1
68 #define JUNK_FOLDER "Junk Mail"
69 #define READ_CURSOR_MAX_IDS 500
70 #define MAX_ATTACHMENT_SIZE 1*1024*1024   /*In bytes*/
71 #define GROUPWISE_BULK_DELETE_LIMIT 100
72
73 static CamelOfflineFolderClass *parent_class = NULL;
74
75 struct _CamelGroupwiseFolderPrivate {
76
77 #ifdef ENABLE_THREADS
78         GStaticMutex search_lock;       /* for locking the search object */
79         GStaticRecMutex cache_lock;     /* for locking the cache object */
80 #endif
81
82 };
83
84 /*prototypes*/
85 static void groupwise_transfer_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *destination, GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex);
86 static int gw_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args);
87 void convert_to_calendar (EGwItem *item, char **str, int *len);
88 static void convert_to_task (EGwItem *item, char **str, int *len);
89 static void convert_to_note (EGwItem *item, char **str, int *len);
90 static void gw_update_all_items ( CamelFolder *folder, GList *item_list, CamelException *ex);
91 static void groupwise_populate_details_from_item (CamelMimeMessage *msg, EGwItem *item);
92 static void groupwise_populate_msg_body_from_item (EGwConnection *cnc, CamelMultipart *multipart, EGwItem *item, char *body);
93 static void groupwise_msg_set_recipient_list (CamelMimeMessage *msg, EGwItem *item);
94 static void gw_update_cache ( CamelFolder *folder, GList *item_list, CamelException *ex, gboolean uid_flag);
95 static CamelMimeMessage *groupwise_folder_item_to_msg ( CamelFolder *folder, EGwItem *item, CamelException *ex );
96
97
98 #define d(x) 
99
100 static CamelMimeMessage *
101 groupwise_folder_get_message( CamelFolder *folder, const char *uid, CamelException *ex )
102 {
103         CamelMimeMessage *msg = NULL;
104         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
105         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE(folder->parent_store);
106         CamelGroupwiseStorePrivate  *priv = gw_store->priv;
107         CamelGroupwiseMessageInfo *mi = NULL;
108         char *container_id;
109         EGwConnectionStatus status;
110         EGwConnection *cnc;
111         EGwItem *item;
112         CamelStream *stream, *cache_stream;
113         int errno;
114
115         /* see if it is there in cache */
116
117         mi = (CamelGroupwiseMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
118         if (mi == NULL) {
119                 camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
120                                 _("Cannot get message: %s\n  %s"), uid, _("No such message"));
121                 return NULL;
122         }
123         cache_stream  = camel_data_cache_get (gw_folder->cache, "cache", uid, ex);
124         stream = camel_stream_mem_new ();
125         if (cache_stream) {
126                 msg = camel_mime_message_new ();
127                 camel_stream_reset (stream);
128                 camel_stream_write_to_stream (cache_stream, stream);
129                 camel_stream_reset (stream);
130                 if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg, stream) == -1) {
131                         if (errno == EINTR) {
132                                 camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled"));
133                                 camel_object_unref (msg);
134                                 camel_object_unref (cache_stream);
135                                 camel_object_unref (stream);
136                                 camel_message_info_free (&mi->info);
137                                 return NULL;
138                         } else {
139                                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"),
140                                                 uid, g_strerror (errno));
141                                 camel_object_unref (msg);
142                                 msg = NULL;
143                         }
144                 }
145                 camel_object_unref (cache_stream);
146         }
147         camel_object_unref (stream);
148
149         if (msg != NULL) {
150                 camel_message_info_free (&mi->info);
151                 return msg;
152         }
153
154         if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
155                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
156                                 _("This message is not available in offline mode."));
157                 camel_message_info_free (&mi->info);
158                 return NULL;
159         }
160
161         /* Check if we are really offline */
162         if (!camel_groupwise_store_connected (gw_store, ex)) {
163                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
164                                 _("This message is not available in offline mode."));
165                 camel_message_info_free (&mi->info);
166                 return NULL;
167         }
168
169         container_id =  g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name)) ;
170
171         cnc = cnc_lookup (priv);
172         status = e_gw_connection_get_item (cnc, container_id, uid, "peek default distribution recipient message attachments subject notification created recipientStatus status", &item);
173         if (status != E_GW_CONNECTION_STATUS_OK) {
174                 g_free (container_id);
175                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Could not get message"));
176                 camel_message_info_free (&mi->info);
177                 return NULL;
178         }
179
180         msg = groupwise_folder_item_to_msg (folder, item, ex);
181         if (!msg) {
182                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Could not get message"));
183                 g_free (container_id);
184                 camel_message_info_free (&mi->info);
185
186                 return NULL;
187         }
188
189         if (msg)
190                 camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", groupwise_base_url_lookup (priv));
191
192         /* add to cache */
193         CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
194         if ((cache_stream = camel_data_cache_add (gw_folder->cache, "cache", uid, NULL))) {
195                 if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg, cache_stream) == -1
196                                 || camel_stream_flush (cache_stream) == -1)
197                         camel_data_cache_remove (gw_folder->cache, "cache", uid, NULL);
198                 camel_object_unref (cache_stream);
199         }
200
201         CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
202
203         camel_message_info_free (&mi->info);
204         g_free (container_id);
205         return msg;
206 }
207
208 static void
209 groupwise_populate_details_from_item (CamelMimeMessage *msg, EGwItem *item)
210 {
211         char *dtstring = NULL;
212         char *temp_str = NULL;
213
214         temp_str = (char *)e_gw_item_get_subject(item);
215         if(temp_str)
216                 camel_mime_message_set_subject (msg, temp_str);
217         dtstring = e_gw_item_get_delivered_date (item);
218         if(dtstring) {
219                 int offset = 0;
220                 time_t time = e_gw_connection_get_date_from_string (dtstring);
221                 time_t actual_time = camel_header_decode_date (ctime(&time), &offset);
222                 camel_mime_message_set_date (msg, actual_time, offset);
223         } else {
224                 time_t time;
225                 time_t actual_time;
226                 int offset = 0;
227                 dtstring = e_gw_item_get_creation_date (item);
228                 time = e_gw_connection_get_date_from_string (dtstring);
229                 actual_time = camel_header_decode_date (ctime(&time), NULL);
230                 camel_mime_message_set_date (msg, actual_time, offset);
231         }
232 }
233
234 static void
235 groupwise_populate_msg_body_from_item (EGwConnection *cnc, CamelMultipart *multipart, EGwItem *item, char *body)
236 {
237         CamelMimePart *part;
238         EGwItemType type;
239         const char *temp_body = NULL;
240
241         part = camel_mime_part_new ();
242         camel_mime_part_set_encoding(part, CAMEL_TRANSFER_ENCODING_8BIT);
243
244         if (!body) {
245                 temp_body = e_gw_item_get_message (item);
246                 if(!temp_body){
247                         int len = 0;
248                         EGwConnectionStatus status;
249                         status = e_gw_connection_get_attachment (cnc, 
250                                         e_gw_item_get_msg_body_id (item), 0, -1, 
251                                         (const char **)&temp_body, &len);
252                         if (status != E_GW_CONNECTION_STATUS_OK) {
253                                 g_warning ("Could not get Messagebody\n");
254                         }
255                 }
256         }
257
258         type = e_gw_item_get_item_type (item);
259         switch (type) {
260
261                 case E_GW_ITEM_TYPE_APPOINTMENT:
262                 case E_GW_ITEM_TYPE_TASK:
263                 case E_GW_ITEM_TYPE_NOTE:
264                         {
265                                 char *cal_buffer = NULL;
266                                 int len = 0;
267                                 if (type==E_GW_ITEM_TYPE_APPOINTMENT)
268                                         convert_to_calendar (item, &cal_buffer, &len);
269                                 else if (type == E_GW_ITEM_TYPE_TASK)
270                                         convert_to_task (item, &cal_buffer, &len);
271                                 else 
272                                         convert_to_note (item, &cal_buffer, &len);
273
274                                 camel_mime_part_set_content(part, cal_buffer, len, "text/calendar");
275                                 g_free (cal_buffer);
276                                 break;
277                         }
278                 case E_GW_ITEM_TYPE_NOTIFICATION:
279                 case E_GW_ITEM_TYPE_MAIL:
280                         if (body) 
281                                 camel_mime_part_set_content(part, body, strlen(body), "text/html");
282                         else if (temp_body)
283                                 camel_mime_part_set_content(part, temp_body, strlen(temp_body), e_gw_item_get_msg_content_type (item));
284                         else
285                                 camel_mime_part_set_content(part, " ", strlen(" "), "text/html");
286                         break;
287
288                 default:
289                         break;
290
291         }
292
293         camel_multipart_set_boundary (multipart, NULL);
294         camel_multipart_add_part (multipart, part);
295         camel_object_unref (part);
296 }
297
298 static void
299 groupwise_msg_set_recipient_list (CamelMimeMessage *msg, EGwItem *item)
300 {
301         GSList *recipient_list;
302         EGwItemOrganizer *org;
303         struct _camel_header_address *ha;
304         char *subs_email;
305         struct _camel_header_address *to_list = NULL, *cc_list = NULL, *bcc_list=NULL;
306
307         org = e_gw_item_get_organizer (item);
308         recipient_list = e_gw_item_get_recipient_list (item);
309
310         if (recipient_list) {
311                 GSList *rl;
312                 char *status_opt = NULL;
313                 gboolean enabled;
314
315                 for (rl = recipient_list ; rl != NULL ; rl = rl->next) {
316                         EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
317                         enabled = recp->status_enabled;
318
319                         if (!recp->email) {
320                                 ha=camel_header_address_new_group(recp->display_name);
321                         } else {
322                                 ha=camel_header_address_new_name(recp->display_name,recp->email);
323                         }
324
325                         if (recp->type == E_GW_ITEM_RECIPIENT_TO) {
326                                 if (recp->status_enabled) 
327                                         status_opt = g_strconcat (status_opt ? status_opt : "" , "TO", ";",NULL);
328                                 camel_header_address_list_append(&to_list, ha);
329                         } else if (recp->type == E_GW_ITEM_RECIPIENT_CC) {
330                                 if (recp->status_enabled) 
331                                         status_opt = g_strconcat (status_opt ? status_opt : "", "CC", ";",NULL);
332                                 camel_header_address_list_append(&cc_list,ha);
333
334                         } else if (recp->type == E_GW_ITEM_RECIPIENT_BC) {
335                                 if (recp->status_enabled) 
336                                         status_opt = g_strconcat (status_opt ? status_opt : "", "BCC", ";",NULL);
337                                 camel_header_address_list_append(&bcc_list,ha);
338                         } else {
339                                 camel_header_address_unref(ha);
340                         }
341                         if (recp->status_enabled) {
342                                 status_opt = g_strconcat (status_opt, 
343                                                 recp->display_name,";",
344                                                 recp->email,";",
345                                                 recp->delivered_date ? recp->delivered_date :  "", ";",
346                                                 recp->opened_date ? recp->opened_date : "", ";", 
347                                                 recp->accepted_date ? recp->accepted_date : "", ";",
348                                                 recp->deleted_date ? recp->deleted_date : "", ";", 
349                                                 recp->declined_date ? recp->declined_date : "", ";",
350                                                 recp->completed_date ? recp->completed_date : "", ";",
351                                                 recp->undelivered_date ? recp->undelivered_date : "", ";", 
352                                                 "::", NULL);
353
354                         }
355                 }
356
357                 /* README: This entire status-opt code should go away once the new status-tracking code is tested */
358                 if (enabled) {
359                         camel_medium_add_header ( CAMEL_MEDIUM (msg), "X-gw-status-opt", (const char *)status_opt);
360                         g_free (status_opt);
361                 }
362         }
363
364         if(to_list) { 
365                 subs_email=camel_header_address_list_encode(to_list);
366                 camel_medium_set_header( CAMEL_MEDIUM(msg), "To", subs_email);
367                 g_free(subs_email);
368                 camel_header_address_list_clear(&to_list);
369         }
370
371         if(cc_list) { 
372                 subs_email=camel_header_address_list_encode(cc_list);
373                 camel_medium_set_header( CAMEL_MEDIUM(msg), "Cc", subs_email);
374                 g_free(subs_email);
375                 camel_header_address_list_clear(&cc_list);
376         }
377
378         if(bcc_list) { 
379                 subs_email=camel_header_address_list_encode(bcc_list);
380                 camel_medium_set_header( CAMEL_MEDIUM(msg), "Bcc", subs_email);
381                 g_free(subs_email);
382                 camel_header_address_list_clear(&bcc_list);
383         }
384
385         if (org) {
386                 if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
387                                 int i;
388                                 for (i = 0; org->display_name[i] != '<' && 
389                                                 org->display_name[i] != '\0';
390                                                 i++);
391
392                                 org->display_name[i] = '\0';
393                 }
394                 if (org->display_name && org->email) 
395                         ha=camel_header_address_new_name(org->display_name, org->email);
396                 else if (org->display_name)
397                         ha=camel_header_address_new_group(org->display_name);
398
399                 subs_email=camel_header_address_list_encode(ha);        
400                 camel_medium_set_header( CAMEL_MEDIUM(msg), "From", subs_email);
401                 camel_header_address_unref(ha);
402                 g_free(subs_email);
403         }
404 }
405
406 static void
407 groupwise_folder_rename (CamelFolder *folder, const char *new)
408 {
409         CamelGroupwiseFolder *gw_folder = (CamelGroupwiseFolder *)folder;
410         CamelGroupwiseStore *gw_store = (CamelGroupwiseStore *) folder->parent_store;
411         CamelGroupwiseStorePrivate *priv = gw_store->priv;
412
413         char *folder_dir, *summary_path, *state_file, *storage_path = storage_path_lookup (priv);
414         char *folders;
415
416         folders = g_strconcat (storage_path, "/folders", NULL);
417         folder_dir = e_path_to_physical (folders, new);
418         g_free (folders);
419
420         summary_path = g_strdup_printf ("%s/summary", folder_dir);
421
422         CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
423         g_free (gw_folder->cache->path);
424         gw_folder->cache->path = g_strdup (folder_dir);
425         CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
426
427         ((CamelFolderClass *)parent_class)->rename(folder, new);
428         camel_folder_summary_set_filename (folder->summary, summary_path);
429
430         state_file = g_strdup_printf ("%s/cmeta", folder_dir);
431         camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state_file, NULL);
432         g_free (state_file);
433
434         g_free (summary_path);
435         g_free (folder_dir);
436 }
437
438 static GPtrArray *
439 groupwise_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
440 {
441         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
442         GPtrArray *matches;
443
444         CAMEL_GROUPWISE_FOLDER_LOCK(gw_folder, search_lock);
445         camel_folder_search_set_folder (gw_folder->search, folder);
446         matches = camel_folder_search_search(gw_folder->search, expression, NULL, ex);
447         CAMEL_GROUPWISE_FOLDER_UNLOCK(gw_folder, search_lock);
448
449         return matches;
450 }
451
452 static GPtrArray *
453 groupwise_folder_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
454 {
455         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
456         GPtrArray *matches;
457
458         if (uids->len == 0)
459                 return g_ptr_array_new();
460
461         CAMEL_GROUPWISE_FOLDER_LOCK(gw_folder, search_lock);
462
463         camel_folder_search_set_folder(gw_folder->search, folder);
464         matches = camel_folder_search_search(gw_folder->search, expression, uids, ex);
465
466         CAMEL_GROUPWISE_FOLDER_UNLOCK(gw_folder, search_lock);
467
468         return matches;
469 }
470
471 static void
472 groupwise_folder_search_free (CamelFolder *folder, GPtrArray *uids)
473 {
474         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
475
476         g_return_if_fail (gw_folder->search);
477
478         CAMEL_GROUPWISE_FOLDER_LOCK(gw_folder, search_lock);
479
480         camel_folder_search_free_result (gw_folder->search, uids);
481
482         CAMEL_GROUPWISE_FOLDER_UNLOCK(gw_folder, search_lock);
483
484 }
485
486 /******************* functions specific to Junk Mail Handling**************/
487 static void 
488 free_node (EGwJunkEntry *entry)
489 {
490         if (entry) {
491                 g_free (entry->id);
492                 g_free (entry->match);
493                 g_free (entry->matchType);
494                 g_free (entry->lastUsed);
495                 g_free (entry->modified);
496                 g_free (entry);
497         }
498 }
499
500 static void
501 update_junk_list (CamelStore *store, CamelMessageInfo *info, int flag)
502 {
503         gchar **email = NULL, *from = NULL;     
504         CamelGroupwiseStore *gw_store= CAMEL_GROUPWISE_STORE(store);
505         CamelGroupwiseStorePrivate  *priv = gw_store->priv;
506         EGwConnection *cnc = cnc_lookup (priv);
507
508         if (!(from = g_strdup (camel_message_info_from (info))))
509                 goto error;
510
511         email = g_strsplit_set (from, "<>", -1);
512
513         if (!email || !email[1])
514                 goto error;
515
516         if (flag == ADD_JUNK_ENTRY)
517                 e_gw_connection_create_junk_entry (cnc, email[1], "email", "junk");
518         else if (flag == REMOVE_JUNK_ENTRY) {
519                 GList *list = NULL;
520                 EGwJunkEntry *entry;
521                 if (e_gw_connection_get_junk_entries (cnc, &list)== E_GW_CONNECTION_STATUS_OK){
522                         while (list) {
523                                 entry = list->data;
524                                 if (!g_ascii_strcasecmp (entry->match, email[1])) { 
525                                         e_gw_connection_remove_junk_entry (cnc, entry->id);
526                                 }
527                                 list = list->next;
528                         }
529                         g_list_foreach (list, (GFunc) free_node, NULL);
530                 }
531         }
532
533 error:
534         g_free (from);
535         g_strfreev (email);
536 }
537
538 static void 
539 move_to_mailbox (CamelFolder *folder, CamelMessageInfo *info, CamelException *ex)
540 {
541         CamelFolder *dest;
542         GPtrArray *uids;
543         const char *uid = camel_message_info_uid (info);
544
545         uids = g_ptr_array_new ();
546         g_ptr_array_add (uids, (gpointer) uid);
547
548         dest = camel_store_get_folder (folder->parent_store, "Mailbox", 0, ex);
549         camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN|CAMEL_GW_MESSAGE_NOJUNK|CAMEL_GW_MESSAGE_JUNK, 0);
550         if (dest)
551                 groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
552         else
553                 g_warning ("No Mailbox folder found");
554
555         update_junk_list (folder->parent_store, info, REMOVE_JUNK_ENTRY);
556 }
557
558 static void 
559 move_to_junk (CamelFolder *folder, CamelMessageInfo *info, CamelException *ex)
560 {
561         CamelFolder *dest;
562         CamelFolderInfo *fi;
563         GPtrArray *uids;
564         const char *uid = camel_message_info_uid (info);
565
566         uids = g_ptr_array_new ();
567         g_ptr_array_add (uids, (gpointer) uid);
568
569         dest = camel_store_get_folder (folder->parent_store, JUNK_FOLDER, 0, ex);
570         
571         if (dest)
572                 groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
573         else {
574                 fi = create_junk_folder (folder->parent_store);
575                 dest = camel_store_get_folder (folder->parent_store, JUNK_FOLDER, 0, ex);
576                 if (!dest)
577                         g_warning ("Could not get JunkFolder:Message not moved");
578                 else
579                         groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
580         }
581         update_junk_list (folder->parent_store, info, ADD_JUNK_ENTRY);
582 }
583
584 /********************* back to folder functions*************************/
585
586 static void 
587 groupwise_sync_summary (CamelFolder *folder, CamelException *ex)
588 {
589         camel_folder_summary_save (folder->summary);
590         camel_store_summary_save ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
591 }
592
593 static void
594 groupwise_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
595 {
596         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
597         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
598         CamelGroupwiseStorePrivate *priv = gw_store->priv;
599         CamelMessageInfo *info = NULL;
600         CamelGroupwiseMessageInfo *gw_info;
601         GList *read_items = NULL, *deleted_read_items = NULL, *unread_items = NULL;
602         flags_diff_t diff, unset_flags;
603         const char *container_id;
604         EGwConnectionStatus status;
605         EGwConnection *cnc;
606         int count, i;
607
608         GList *deleted_items, *deleted_head;
609
610         deleted_items = deleted_head = NULL;
611
612         if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL || 
613                         ((CamelService *)gw_store)->status == CAMEL_SERVICE_DISCONNECTED) {
614                 groupwise_sync_summary (folder, ex);
615                 return;
616         }
617         cnc = cnc_lookup (priv);
618
619         container_id =  camel_groupwise_store_container_id_lookup (gw_store, folder->full_name) ;
620
621         CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
622         if (!camel_groupwise_store_connected (gw_store, ex)) {
623                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
624                 camel_exception_clear (ex);
625                 return;
626         }
627         CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
628
629         count = camel_folder_summary_count (folder->summary);
630         CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
631         for (i=0 ; i < count ; i++) {
632                 guint32 flags = 0;
633                 info = camel_folder_summary_index (folder->summary, i);
634                 gw_info = (CamelGroupwiseMessageInfo *) info;
635
636                 /**Junk Mail handling**/
637                 if(!info)
638                         continue;
639                 flags = camel_message_info_flags (info);        
640
641                 if ((flags & CAMEL_MESSAGE_JUNK) && strcmp(camel_folder_get_name(folder), JUNK_FOLDER)) { 
642                         /*marked a message junk*/
643                         move_to_junk (folder, info, ex);
644                         camel_folder_summary_remove_uid (folder->summary, camel_message_info_uid(info));
645                         camel_data_cache_remove (gw_folder->cache, "cache", camel_message_info_uid(info), NULL);
646                         continue;
647                 }
648
649                 if ((flags & CAMEL_GW_MESSAGE_NOJUNK) && !strcmp(camel_folder_get_name(folder), JUNK_FOLDER)) {
650                         /*message was marked as junk, now unjunk*/ 
651                         move_to_mailbox (folder, info, ex);
652                         camel_folder_summary_remove_uid (folder->summary, camel_message_info_uid(info));
653                         camel_data_cache_remove (gw_folder->cache, "cache", camel_message_info_uid(info), NULL);
654                         continue;
655                 }
656
657                 if (gw_info && (gw_info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
658                         do_flags_diff (&diff, gw_info->server_flags, gw_info->info.flags);
659                         do_flags_diff (&unset_flags, flags, gw_info->server_flags);
660                         
661                         diff.changed &= folder->permanent_flags;
662
663                         /* weed out flag changes that we can't sync to the server */
664                         if (!diff.changed) {
665                                 camel_message_info_free(info);
666                                 continue;
667                         } else {
668                                 const char *uid;
669
670                                 gw_info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
671                                 gw_info->server_flags = gw_info->info.flags;
672                                 uid = camel_message_info_uid (info);
673                                 if (diff.bits & CAMEL_MESSAGE_DELETED) {
674
675                                         /* In case a new message is READ and then deleted immediately */
676                                         if (diff.bits & CAMEL_MESSAGE_SEEN)
677                                                 deleted_read_items = g_list_prepend (deleted_read_items, (char *) uid);
678
679                                         if (deleted_items)
680                                                 deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
681                                         else {
682                                                 g_list_free (deleted_head);
683                                                 deleted_head = NULL;
684                                                 deleted_head = deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
685                                         }
686
687                                         if (g_list_length (deleted_items) == GROUPWISE_BULK_DELETE_LIMIT ) {
688                                                 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
689
690                                                 /* 
691                                                         Sync up the READ changes before deleting the message. 
692                                                         Note that if a message is marked as unread and then deleted,
693                                                         Evo doesnt not take care of it, as I find that scenario to be impractical.
694                                                 */
695
696                                                 if (deleted_read_items) {
697                                                         
698                                                         /* FIXME: As in many places, we need to handle the return value
699                                                         and do some error handling. But, we do not have all error codes also
700                                                         and errors are not returned always either */
701
702                                                         status = e_gw_connection_mark_read (cnc, deleted_read_items);
703                                                         g_list_free (deleted_read_items);
704                                                         deleted_read_items = NULL;
705                                                 }
706
707                                                 /* And now delete the messages */
708                                                 status = e_gw_connection_remove_items (cnc, container_id, deleted_items);
709                                                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
710                                                 if (status == E_GW_CONNECTION_STATUS_OK) {
711                                                         char *uid;
712                                                         while (deleted_items) {
713                                                                 uid = (char *)deleted_items->data;
714                                                                 CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
715                                                                 camel_folder_summary_remove_uid (folder->summary, uid);
716                                                                 camel_data_cache_remove(gw_folder->cache, "cache", uid, NULL);
717                                                                 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
718                                                                 deleted_items = g_list_next (deleted_items);
719                                                                 count -= GROUPWISE_BULK_DELETE_LIMIT;
720                                                                 i -= GROUPWISE_BULK_DELETE_LIMIT;
721                                                         }
722                                                 }
723                                         }
724                                 } else if (diff.bits & CAMEL_MESSAGE_SEEN) {
725                                         read_items = g_list_prepend (read_items, (char *)uid);
726                                 } else if (unset_flags.bits & CAMEL_MESSAGE_SEEN) {
727                                         unread_items = g_list_prepend (unread_items, (char *)uid);
728                                 }
729                         }
730                 }
731                 camel_message_info_free (info);
732         }
733         
734         CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
735
736         if (deleted_items) {
737                 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
738                 if (!strcmp (folder->full_name, "Trash")) {
739                         status = e_gw_connection_purge_selected_items (cnc, deleted_items);
740                 } else {
741                         status = e_gw_connection_remove_items (cnc, container_id, deleted_items);
742                 }
743                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
744                 if (status == E_GW_CONNECTION_STATUS_OK) {
745                         char *uid;
746                         while (deleted_items) {
747                                 uid = (char *)deleted_items->data;
748                                 CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
749                                 camel_folder_summary_remove_uid (folder->summary, uid);
750                                 camel_data_cache_remove(gw_folder->cache, "cache", uid, NULL);
751                                 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
752                                 deleted_items = g_list_next (deleted_items);
753                                 count -= GROUPWISE_BULK_DELETE_LIMIT;
754                                 i -= GROUPWISE_BULK_DELETE_LIMIT;
755                         }
756                 }
757                 g_list_free (deleted_head);
758         }
759
760         if (read_items) {
761                 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
762                 e_gw_connection_mark_read (cnc, read_items);
763                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
764                 g_list_free (read_items);
765         }
766
767         if (unread_items) {
768                 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
769                 e_gw_connection_mark_unread (cnc, unread_items);
770                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
771                 g_list_free (unread_items);
772         }
773
774         if (expunge) {
775                 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
776                 status = e_gw_connection_purge_deleted_items (cnc);
777                 if (status == E_GW_CONNECTION_STATUS_OK) {
778                         g_message ("Purged deleted items in %s", folder->name);
779                 }
780                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
781         }
782
783         CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
784         groupwise_sync_summary (folder, ex);
785         CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
786 }
787
788 CamelFolder *
789 camel_gw_folder_new(CamelStore *store, const char *folder_name, const char *folder_dir, CamelException *ex) 
790 {
791         CamelFolder *folder;
792         CamelGroupwiseFolder *gw_folder;
793         char *summary_file, *state_file, *journal_file;
794         char *short_name;
795
796
797         folder = CAMEL_FOLDER (camel_object_new(camel_groupwise_folder_get_type ()) );
798
799         gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
800         short_name = strrchr (folder_name, '/');
801         if (short_name)
802                 short_name++;
803         else
804                 short_name = (char *) folder_name;
805         camel_folder_construct (folder, store, folder_name, short_name);
806
807         summary_file = g_strdup_printf ("%s/summary",folder_dir);
808         folder->summary = camel_groupwise_summary_new(folder, summary_file);
809         g_free(summary_file);
810         if (!folder->summary) {
811                 camel_object_unref (CAMEL_OBJECT (folder));
812                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
813                                 _("Could not load summary for %s"),
814                                 folder_name);
815                 return NULL;
816         }
817
818         /* set/load persistent state */
819         state_file = g_strdup_printf ("%s/cmeta", folder_dir);
820         camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state_file, NULL);
821         g_free(state_file);
822         camel_object_state_read(folder);
823
824         gw_folder->cache = camel_data_cache_new (folder_dir,0 ,ex);
825         if (!gw_folder->cache) {
826                 camel_object_unref (folder);
827                 return NULL;
828         }
829
830         journal_file = g_strdup_printf ("%s/journal",folder_dir);
831         gw_folder->journal = camel_groupwise_journal_new (gw_folder, journal_file);
832         g_free (journal_file);
833         if (!gw_folder->journal) {
834                 camel_object_unref (folder);
835                 return NULL;
836         }
837
838         if (!strcmp (folder_name, "Mailbox")) {
839                 if (camel_url_get_param (((CamelService *) store)->url, "filter"))
840                         folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
841         }
842
843         gw_folder->search = camel_folder_search_new ();
844         if (!gw_folder->search) {
845                 camel_object_unref (folder);
846                 return NULL;
847         }
848
849         return folder;
850 }
851
852 struct _folder_update_msg {
853         CamelSessionThreadMsg msg;
854
855         EGwConnection *cnc;
856         CamelFolder *folder;
857         char *container_id;
858         char *t_str;
859         GSList *slist;
860 };
861
862 static void
863 update_update (CamelSession *session, CamelSessionThreadMsg *msg)
864 {
865         struct _folder_update_msg *m = (struct _folder_update_msg *)msg;
866         EGwConnectionStatus status;
867         CamelException *ex = NULL;
868
869         GList *item_list, *items_full_list = NULL, *last_element=NULL;
870         int cursor = 0;
871         const char *position = E_GW_CURSOR_POSITION_END;
872         gboolean done;
873
874         status = e_gw_connection_create_cursor (m->cnc, m->container_id, "id", NULL, &cursor);
875         if (status != E_GW_CONNECTION_STATUS_OK) {
876                 g_warning ("ERROR update update\n");
877                 return ;
878         }
879
880         done = FALSE;
881         m->slist = NULL;
882
883         while (!done) {
884                 item_list = NULL;
885                 status = e_gw_connection_get_all_mail_uids (m->cnc, m->container_id, cursor, FALSE, READ_CURSOR_MAX_IDS, position, &item_list);
886                 if (status != E_GW_CONNECTION_STATUS_OK) {
887                         g_warning ("ERROR update update\n");
888                         e_gw_connection_destroy_cursor (m->cnc, m->container_id, cursor);
889                         return;
890                 }
891
892                 if (!item_list  || g_list_length (item_list) == 0)
893                         done = TRUE;
894                 else {
895
896                         /* item_list is prepended to items_full_list and not the other way
897                            because when we have a large number of items say 50000, 
898                            for each iteration there will be more elements in items_full_list 
899                            and less elements in item_list */
900
901                         last_element = g_list_last (item_list);
902                         if (items_full_list) {
903                                 last_element->next = items_full_list;
904                                 items_full_list->prev = last_element;
905                         }
906                         items_full_list = item_list;
907                 }
908                 position = E_GW_CURSOR_POSITION_CURRENT;
909         }
910         e_gw_connection_destroy_cursor (m->cnc, m->container_id, cursor);
911
912         /* Take out only the first part in the list until the @ since it is guaranteed
913            to be unique only until that symbol */
914
915         /*if (items_full_list) {
916           int i;
917           item_list = items_full_list;
918
919           while (item_list->next) {
920           i = 0;
921           while (((const char *)item_list->data)[i++]!='@');
922           ((char *)item_list->data)[i-1] = '\0';
923           item_list = item_list->next;
924           }
925
926           i = 0;        
927           while (((const char *)item_list->data)[i++]!='@');
928           ((char *)item_list->data)[i-1] = '\0';
929           }*/
930
931         g_print ("\nNumber of items in the folder: %d \n", g_list_length(items_full_list));
932         gw_update_all_items (m->folder, items_full_list, ex);
933 }
934
935 static void
936 update_free (CamelSession *session, CamelSessionThreadMsg *msg)
937 {
938         struct _folder_update_msg *m = (struct _folder_update_msg *)msg;
939
940         g_free (m->t_str);
941         g_free (m->container_id);
942         camel_object_unref (m->folder);
943         camel_folder_thaw (m->folder);
944         g_slist_foreach (m->slist, (GFunc) g_free, NULL);
945         g_slist_free (m->slist);
946         m->slist = NULL;
947 }
948
949 static CamelSessionThreadOps update_ops = {
950         update_update,
951         update_free,
952 };
953
954 static void
955 groupwise_refresh_info(CamelFolder *folder, CamelException *ex)
956 {
957         CamelGroupwiseSummary *summary = (CamelGroupwiseSummary *) folder->summary;
958         CamelStoreInfo *si;
959         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
960         /*
961          * Checking for the summary->time_string here since the first the a
962          * user views a folder, the read cursor is in progress, and the getQM
963          * should not interfere with the process
964          */
965         if (summary->time_string && (strlen (summary->time_string) > 0))  {
966                 groupwise_refresh_folder(folder, ex);
967                 si = camel_store_summary_path ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary, folder->full_name);
968                 if (si) {
969                         guint32 unread, total;
970                         camel_object_get (folder, NULL, CAMEL_FOLDER_TOTAL, &total, CAMEL_FOLDER_UNREAD, &unread, NULL);
971                         if (si->total != total || si->unread != unread) {
972                                 si->total = total;
973                                 si->unread = unread;
974                                 camel_store_summary_touch ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
975                         }
976                         camel_store_summary_info_free ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary, si);
977                 }
978                 camel_folder_summary_save (folder->summary);
979                 camel_store_summary_save ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
980         } else {
981                 /* We probably could not get the messages the first time. (get_folder) failed???!
982                  * so do a get_folder again. And hope that it works
983                  */
984                 g_print("Reloading folder...something wrong with the summary....\n");
985                 gw_store_reload_folder (gw_store, folder, 0, ex);
986         }
987 }
988
989 void
990 groupwise_refresh_folder(CamelFolder *folder, CamelException *ex)
991 {
992         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
993         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
994         CamelGroupwiseStorePrivate *priv = gw_store->priv;
995         CamelGroupwiseSummary *summary = (CamelGroupwiseSummary *)folder->summary;
996         EGwConnection *cnc = cnc_lookup (priv);
997         CamelSession *session = ((CamelService *)folder->parent_store)->session;
998         gboolean is_proxy = folder->parent_store->flags & CAMEL_STORE_PROXY;
999         gboolean is_locked = TRUE;
1000         int status;
1001         GList *list = NULL;
1002         GSList *slist = NULL, *sl;
1003         char *container_id = NULL;
1004         char *time_string = NULL, *t_str = NULL;
1005         struct _folder_update_msg *msg;
1006         gboolean check_all = FALSE;
1007
1008         /* Sync-up the (un)read changes before getting updates,
1009         so that the getFolderList will reflect the most recent changes too */
1010         groupwise_sync (folder, FALSE, ex);
1011
1012         if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
1013                 g_warning ("In offline mode. Cannot refresh!!!\n");
1014                 return;
1015         }
1016
1017         container_id = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name)) ;
1018
1019         if (!container_id) {
1020                 g_warning ("\nERROR - Container id not present. Cannot refresh info for %s\n", folder->full_name);
1021                 return;
1022         }
1023
1024         if (!cnc) 
1025                 return;
1026
1027         if (camel_folder_is_frozen (folder) ) {
1028                 gw_folder->need_refresh = TRUE;
1029         }
1030
1031         CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
1032
1033         if (!camel_groupwise_store_connected (gw_store, ex)) 
1034                 goto end1;
1035
1036         if (!strcmp (folder->full_name, "Trash")) {
1037 #if 0
1038                 status = e_gw_connection_get_items (cnc, container_id, "peek recipient distribution created delivered attachments subject status size", NULL, &list);
1039                 if (status != E_GW_CONNECTION_STATUS_OK) {
1040                         if (status ==E_GW_CONNECTION_STATUS_OTHER) {
1041                                 g_warning ("Trash full....Empty Trash!!!!\n");
1042                                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Trash Folder Full. Please Empty."));
1043                                 goto end1;
1044                                 /*groupwise_expunge (folder, ex);*/
1045                         } else
1046                                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
1047                         goto end1;
1048                 }
1049                 if (list || g_list_length(list)) {
1050                         camel_folder_summary_clear (folder->summary);
1051                         gw_update_summary (folder, list, ex);
1052                         g_list_foreach (list, (GFunc) g_object_unref, NULL);
1053                         g_list_free (list);
1054                         list = NULL;
1055                 }
1056                 goto end1;
1057 #endif
1058                 is_proxy = TRUE;
1059         }
1060
1061         time_string =  g_strdup (((CamelGroupwiseSummary *) folder->summary)->time_string);
1062         t_str = g_strdup (time_string); 
1063
1064         /*Get the New Items*/
1065         if (!is_proxy) {
1066                 char *source;
1067
1068                 if ( !strcmp (folder->full_name, RECEIVED) || !strcmp(folder->full_name, SENT) ) {
1069                         source = NULL;
1070                 } else {
1071                         source = "sent received";
1072                 }
1073
1074                 status = e_gw_connection_get_quick_messages (cnc, container_id,
1075                                 "peek id",
1076                                 &t_str, "New", NULL, source, -1, &slist);
1077                 if (status != E_GW_CONNECTION_STATUS_OK) {
1078                         camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
1079                         goto end2;
1080                 }
1081
1082                 /*
1083                  * The value in t_str is the one that has to be used for the next set of calls. 
1084                  * so store this value in the summary.
1085                  */
1086                 if (summary->time_string)
1087                         g_free (summary->time_string);
1088
1089
1090                 //summary->time_string = g_strdup (t_str);
1091                 ((CamelGroupwiseSummary *) folder->summary)->time_string = g_strdup (t_str);
1092                 camel_folder_summary_touch (folder->summary);
1093                 groupwise_sync_summary (folder, ex);
1094                 g_free (t_str); 
1095                 t_str = NULL;
1096
1097                 /*
1098                    for ( sl = slist ; sl != NULL; sl = sl->next) 
1099                    list = g_list_append (list, sl->data);*/
1100
1101                 if (slist && g_slist_length(slist) != 0)
1102                         check_all = TRUE;
1103
1104                 g_slist_free (slist);
1105                 slist = NULL;
1106
1107                 t_str = g_strdup (time_string);
1108
1109                 /*Get those items which have been modifed*/
1110
1111                 status = e_gw_connection_get_quick_messages (cnc, container_id,
1112                                 "peek id",
1113                                 &t_str, "Modified", NULL, source, -1, &slist);
1114
1115                 if (status != E_GW_CONNECTION_STATUS_OK) {
1116                         camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
1117                         goto end3;
1118                 }
1119
1120                 /* The storing of time-stamp to summary code below should be commented if the 
1121                    above commented code is uncommented */
1122
1123                 /*      if (summary->time_string)
1124                         g_free (summary->time_string);
1125
1126                         summary->time_string = g_strdup (t_str);
1127
1128                         g_free (t_str), t_str = NULL;*/
1129
1130                 for ( sl = slist ; sl != NULL; sl = sl->next) 
1131                         list = g_list_prepend (list, sl->data);
1132
1133                 if (!check_all && slist && g_slist_length(slist) != 0)
1134                         check_all = TRUE;
1135
1136                 g_slist_free (slist);
1137                 slist = NULL;
1138
1139                 if (gw_store->current_folder != folder) {
1140                         gw_store->current_folder = folder;
1141                 }
1142
1143                 if (list) {
1144                         gw_update_cache (folder, list, ex, FALSE);
1145                 }
1146         }
1147
1148
1149         CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
1150         is_locked = FALSE;
1151
1152         /*
1153          * The New and Modified items in the server have been updated in the summary. 
1154          * Now we have to make sure that all the delted items in the server are deleted
1155          * from Evolution as well. So we get the id's of all the items on the sever in 
1156          * this folder, and update the summary.
1157          */
1158         /*create a new session thread for the update all operation*/
1159         if (check_all || is_proxy) {
1160                 msg = camel_session_thread_msg_new (session, &update_ops, sizeof(*msg));
1161                 msg->cnc = cnc;
1162                 msg->t_str = g_strdup (time_string);
1163                 msg->container_id = g_strdup (container_id);
1164                 msg->folder = folder;
1165                 camel_object_ref (folder);
1166                 camel_folder_freeze (folder);
1167                 camel_session_thread_queue (session, &msg->msg, 0);
1168                 /*thread creation and queueing done*/
1169         }
1170
1171 end3: 
1172         g_list_foreach (list, (GFunc) g_object_unref, NULL);
1173         g_list_free (list);
1174         list = NULL;
1175 end2:
1176         g_free (t_str);
1177         g_free (time_string);
1178         g_free (container_id);
1179 end1:
1180         if (is_locked)
1181                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
1182         return;
1183 }
1184
1185 static void
1186 gw_update_cache (CamelFolder *folder, GList *list, CamelException *ex, gboolean uid_flag) 
1187 {
1188         CamelGroupwiseMessageInfo *mi = NULL;
1189         CamelMessageInfo *pmi = NULL;
1190         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
1191         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
1192         CamelGroupwiseStorePrivate *priv = gw_store->priv;
1193         EGwConnection *cnc = cnc_lookup (priv);
1194         guint32 item_status, status_flags = 0;
1195         CamelFolderChangeInfo *changes = NULL;
1196         gboolean exists = FALSE;
1197         GString *str = g_string_new (NULL);
1198         const char *priority = NULL;
1199         char *container_id = NULL;
1200         gboolean is_junk = FALSE;
1201         EGwItemStatus status;
1202         GList *item_list = list;
1203         int total_items = g_list_length (item_list), i=0;
1204
1205         gboolean is_proxy = folder->parent_store->flags & CAMEL_STORE_WRITE;
1206
1207         changes = camel_folder_change_info_new ();
1208         container_id = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name));
1209         if (!container_id) {
1210                 g_warning ("\nERROR - Container id not present. Cannot refresh info\n");
1211                 camel_folder_change_info_free (changes);
1212                 return;
1213         }
1214
1215         if (!strcmp (folder->full_name, JUNK_FOLDER)) {
1216                 is_junk = TRUE;
1217         }
1218
1219         camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
1220
1221         for ( ; item_list != NULL ; item_list = g_list_next (item_list) ) {
1222                 EGwItem *temp_item ;
1223                 EGwItem *item;
1224                 EGwItemType type = E_GW_ITEM_TYPE_UNKNOWN;
1225                 EGwItemOrganizer *org;
1226                 char *temp_date = NULL;
1227                 const char *id;
1228                 GSList *recp_list = NULL;
1229                 CamelStream *cache_stream, *t_cache_stream;
1230                 CamelMimeMessage *mail_msg = NULL;
1231                 const char *recurrence_key = NULL;
1232                 int rk;
1233
1234                 exists = FALSE;
1235                 status_flags = 0;
1236
1237                 if (uid_flag == FALSE) {
1238                         temp_item = (EGwItem *)item_list->data;
1239                         id = e_gw_item_get_id (temp_item);
1240                 } else 
1241                         id = (char *) item_list->data;
1242
1243                 camel_operation_progress (NULL, (100*i)/total_items);
1244
1245                 status = e_gw_connection_get_item (cnc, container_id, id, "peek default distribution recipient message attachments subject notification created recipientStatus status hasAttachment size recurrenceKey", &item);
1246                 if (status != E_GW_CONNECTION_STATUS_OK) {
1247                         i++;
1248                         continue;
1249                 }
1250
1251                 /************************ First populate summary *************************/
1252                 mi = NULL;
1253                 pmi = NULL;
1254                 pmi = camel_folder_summary_uid (folder->summary, id);
1255                 if (pmi) {
1256                         exists = TRUE;
1257                         camel_message_info_ref (pmi);
1258                         mi = (CamelGroupwiseMessageInfo *)pmi;
1259                 }
1260
1261                 if (!exists) {
1262                         type = e_gw_item_get_item_type (item);
1263                         if ((type == E_GW_ITEM_TYPE_CONTACT) || (type == E_GW_ITEM_TYPE_UNKNOWN)) {
1264                                 exists = FALSE;
1265                                 continue;
1266                         }
1267
1268                         mi = (CamelGroupwiseMessageInfo *)camel_message_info_new (folder->summary); 
1269                         if (mi->info.content == NULL) {
1270                                 mi->info.content = camel_folder_summary_content_info_new (folder->summary);
1271                                 mi->info.content->type = camel_content_type_new ("multipart", "mixed"); 
1272                         }
1273                 }
1274                 
1275                 rk = e_gw_item_get_recurrence_key (item);
1276                 if (rk > 0) {
1277                         recurrence_key = g_strdup_printf("%d", rk); 
1278                         camel_message_info_set_user_tag ((CamelMessageInfo*)mi, "recurrence-key", recurrence_key);
1279                 } 
1280
1281                 /*all items in the Junk Mail folder should have this flag set*/
1282                 if (is_junk)
1283                         mi->info.flags |= CAMEL_GW_MESSAGE_JUNK;
1284
1285                 item_status = e_gw_item_get_item_status (item);
1286                 if (item_status & E_GW_ITEM_STAT_READ)
1287                         status_flags |= CAMEL_MESSAGE_SEEN;
1288                 else 
1289                         mi->info.flags &= ~CAMEL_MESSAGE_SEEN;
1290
1291                 if (item_status & E_GW_ITEM_STAT_REPLIED)
1292                         status_flags |= CAMEL_MESSAGE_ANSWERED;
1293                 if (exists) 
1294                         mi->info.flags |= status_flags;
1295                 else 
1296                         mi->info.flags = status_flags;
1297
1298                 priority = e_gw_item_get_priority (item);
1299                 if (priority && !(g_ascii_strcasecmp (priority,"High"))) {
1300                         mi->info.flags |= CAMEL_MESSAGE_FLAGGED;
1301                 }
1302
1303                 if (e_gw_item_has_attachment (item))
1304                         mi->info.flags |= CAMEL_MESSAGE_ATTACHMENTS;
1305                 if (is_proxy)
1306                         mi->info.flags |= CAMEL_MESSAGE_USER_NOT_DELETABLE;
1307                 
1308                 mi->server_flags = mi->info.flags;
1309
1310                 org = e_gw_item_get_organizer (item); 
1311                 if (org) {
1312                         GString *str;
1313                         int i;
1314                         str = g_string_new ("");
1315                         if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
1316                                 for (i = 0; org->display_name[i] != '<' && 
1317                                                 org->display_name[i] != '\0';
1318                                                 i++);
1319
1320                                 org->display_name[i] = '\0';
1321                                 str = g_string_append (str, org->display_name);
1322                                 str = g_string_append (str, " ");
1323                         }
1324
1325                         if (org->display_name[0] == '\0') { 
1326
1327                                 str = g_string_append (str, org->email);
1328                                 str = g_string_append (str, " ");
1329                         }
1330                         if (org->email && org->email[0]) { 
1331                                 g_string_append (str, "<");
1332                                 str = g_string_append (str, org->email);
1333                                 g_string_append (str, ">");
1334                         }
1335                         mi->info.from = camel_pstring_strdup (str->str);
1336                         g_string_free (str, TRUE);
1337                 }
1338                 g_string_truncate (str, 0);
1339                 recp_list = e_gw_item_get_recipient_list (item);
1340                 if (recp_list) {
1341                         GSList *rl;
1342                         int i = 0;
1343                         for (rl = recp_list; rl != NULL; rl = rl->next) {
1344                                 EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
1345                                 if (recp->type == E_GW_ITEM_RECIPIENT_TO) {
1346                                         if (i)
1347                                                 str = g_string_append (str, ", ");
1348                                         g_string_append_printf (str,"%s <%s>", recp->display_name, recp->email);
1349                                         i++;
1350                                 }
1351                         }
1352                         if (exists)
1353                                 camel_pstring_free(mi->info.to);
1354                         mi->info.to = camel_pstring_strdup (str->str);
1355                         g_string_truncate (str, 0);
1356                 }
1357
1358                 if (type == E_GW_ITEM_TYPE_APPOINTMENT
1359                                 || type ==  E_GW_ITEM_TYPE_NOTE 
1360                                 || type ==  E_GW_ITEM_TYPE_TASK ) {
1361                         temp_date = e_gw_item_get_start_date (item);
1362                         if (temp_date) {
1363                                 time_t time = e_gw_connection_get_date_from_string (temp_date);
1364                                 time_t actual_time = camel_header_decode_date (ctime(&time), NULL);
1365                                 mi->info.date_sent = mi->info.date_received = actual_time;
1366                         }
1367                 } else {
1368                         temp_date = e_gw_item_get_delivered_date(item);
1369                         if (temp_date) {
1370                                 time_t time = e_gw_connection_get_date_from_string (temp_date);
1371                                 time_t actual_time = camel_header_decode_date (ctime(&time), NULL);
1372                                 mi->info.date_sent = mi->info.date_received = actual_time;
1373                         } else {
1374                                 time_t time;
1375                                 time_t actual_time;
1376                                 temp_date = e_gw_item_get_creation_date (item);
1377                                 time = e_gw_connection_get_date_from_string (temp_date);
1378                                 actual_time = camel_header_decode_date (ctime(&time), NULL);
1379                                 mi->info.date_sent = mi->info.date_received = actual_time;
1380                         }
1381                 }
1382
1383                 if (!exists) {
1384                         mi->info.uid = g_strdup (e_gw_item_get_id(item));
1385                         mi->info.size = e_gw_item_get_mail_size (item); 
1386                         mi->info.subject = camel_pstring_strdup(e_gw_item_get_subject(item));
1387                 }
1388
1389                 if (exists) {
1390                         camel_folder_change_info_change_uid (changes, mi->info.uid);
1391                         camel_message_info_free (pmi);
1392                 } else {
1393                         camel_folder_summary_add (folder->summary,(CamelMessageInfo *)mi);
1394                         camel_folder_change_info_add_uid (changes, mi->info.uid);
1395                         camel_folder_change_info_recent_uid (changes, mi->info.uid);
1396                 }
1397
1398                 /********************* Summary ends *************************/
1399                 if (!strcmp (folder->full_name, "Junk Mail"))
1400                         continue;
1401
1402                 /******************** Begine Caching ************************/
1403                 /* add to cache if its a new message*/
1404                 t_cache_stream  = camel_data_cache_get (gw_folder->cache, "cache", id, ex);
1405                 if (t_cache_stream) {
1406                         camel_object_unref (t_cache_stream);
1407
1408                         mail_msg = groupwise_folder_item_to_msg (folder, item, ex);
1409                         if (mail_msg)
1410                                 camel_medium_set_header (CAMEL_MEDIUM (mail_msg), "X-Evolution-Source", groupwise_base_url_lookup (priv));
1411
1412                         CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
1413                         if ((cache_stream = camel_data_cache_add (gw_folder->cache, "cache", id, NULL))) {
1414                                 if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) mail_msg,  cache_stream) == -1 || camel_stream_flush (cache_stream) == -1)
1415                                         camel_data_cache_remove (gw_folder->cache, "cache", id, NULL);
1416                                 camel_object_unref (cache_stream);
1417                         }
1418
1419                         camel_object_unref (mail_msg);
1420                         CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
1421                 }
1422                 /******************** Caching stuff ends *************************/
1423                 i++;
1424         }
1425         camel_operation_end (NULL);
1426         g_free (container_id);
1427         g_string_free (str, TRUE);
1428         camel_object_trigger_event (folder, "folder_changed", changes);
1429
1430         camel_folder_change_info_free (changes);
1431 }
1432
1433 void
1434 gw_update_summary ( CamelFolder *folder, GList *list,CamelException *ex) 
1435 {
1436         CamelGroupwiseMessageInfo *mi = NULL;
1437         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
1438         guint32 item_status, status_flags = 0;
1439         CamelFolderChangeInfo *changes = NULL;
1440         gboolean exists = FALSE;
1441         GString *str = g_string_new (NULL);
1442         const char *priority = NULL;
1443         char *container_id = NULL;
1444         gboolean is_junk = FALSE;
1445         GList *item_list = list;
1446
1447         gboolean is_proxy = folder->parent_store->flags & CAMEL_STORE_WRITE;
1448
1449         /*Assert lock???*/
1450         changes = camel_folder_change_info_new ();
1451         container_id = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name));
1452         if (!container_id) {
1453                 g_warning ("\nERROR - Container id not present. Cannot refresh info\n");
1454                 camel_folder_change_info_free (changes);
1455                 return;
1456         }
1457
1458         if (!strcmp (folder->full_name, JUNK_FOLDER)) {
1459                 is_junk = TRUE;
1460         }
1461
1462         for (; item_list != NULL ; item_list = g_list_next (item_list) ) {
1463                 EGwItem *item = (EGwItem *)item_list->data;
1464                 EGwItemType type = E_GW_ITEM_TYPE_UNKNOWN;
1465                 EGwItemOrganizer *org;
1466                 char *temp_date = NULL;
1467                 const char *id;
1468                 GSList *recp_list = NULL;
1469                 const char *recurrence_key = NULL;
1470                 int rk;
1471
1472                 status_flags = 0;
1473                 id = e_gw_item_get_id (item);
1474
1475                 mi = (CamelGroupwiseMessageInfo *)camel_folder_summary_uid (folder->summary, id);
1476                 if (mi) 
1477                         exists = TRUE;
1478
1479                 if (!exists) {
1480                         type = e_gw_item_get_item_type (item);
1481                         if ((type == E_GW_ITEM_TYPE_CONTACT) || (type == E_GW_ITEM_TYPE_UNKNOWN)) {
1482                                 exists = FALSE;
1483                                 continue;
1484                         }
1485
1486                         mi = camel_message_info_new (folder->summary); 
1487                         if (mi->info.content == NULL) {
1488                                 mi->info.content = camel_folder_summary_content_info_new (folder->summary);
1489                                 mi->info.content->type = camel_content_type_new ("multipart", "mixed");
1490                         }
1491                 }
1492                 
1493                 rk = e_gw_item_get_recurrence_key (item);
1494                 if (rk > 0) {
1495                         recurrence_key = g_strdup_printf("%d", rk); 
1496                         camel_message_info_set_user_tag ((CamelMessageInfo*)mi, "recurrence-key", recurrence_key);
1497                 } 
1498
1499                 /*all items in the Junk Mail folder should have this flag set*/
1500                 if (is_junk)
1501                         mi->info.flags |= CAMEL_GW_MESSAGE_JUNK;
1502
1503                 item_status = e_gw_item_get_item_status (item);
1504                 if (item_status & E_GW_ITEM_STAT_READ)
1505                         status_flags |= CAMEL_MESSAGE_SEEN;
1506                 if (item_status & E_GW_ITEM_STAT_REPLIED)
1507                         status_flags |= CAMEL_MESSAGE_ANSWERED;
1508
1509                 if (!strcmp (folder->full_name, "Trash"))
1510                         status_flags |= CAMEL_MESSAGE_SEEN;
1511
1512                 mi->info.flags |= status_flags;
1513
1514
1515                 priority = e_gw_item_get_priority (item);
1516                 if (priority && !(g_ascii_strcasecmp (priority,"High"))) {
1517                         mi->info.flags |= CAMEL_MESSAGE_FLAGGED;
1518                 }
1519                 
1520                 if (e_gw_item_has_attachment (item))
1521                         mi->info.flags |= CAMEL_MESSAGE_ATTACHMENTS;
1522
1523                 if (is_proxy) 
1524                         mi->info.flags |= CAMEL_MESSAGE_USER_NOT_DELETABLE;
1525
1526                 mi->server_flags = mi->info.flags;
1527
1528                 org = e_gw_item_get_organizer (item); 
1529                 if (org) {
1530                         GString *str;
1531                         int i;
1532                         str = g_string_new ("");
1533                         if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
1534                                 for (i = 0; org->display_name[i] != '<' && 
1535                                                 org->display_name[i] != '\0'; 
1536                                                 i++);
1537
1538                                 org->display_name[i] = '\0';
1539                                 str = g_string_append (str, org->display_name);
1540                                 str = g_string_append (str, " ");
1541                         }
1542
1543                         if (org->display_name[0] == '\0') { 
1544                                 
1545                                 str = g_string_append (str, org->email);
1546                                 str = g_string_append (str, " ");
1547                         }
1548
1549                         if (org->email && org->email[0]) { 
1550                                 g_string_append (str, "<");
1551                                 str = g_string_append (str, org->email);
1552                                 g_string_append (str, ">");
1553                         }
1554                         mi->info.from = camel_pstring_strdup (str->str);
1555                         g_string_free (str, TRUE);
1556                 }
1557                 g_string_truncate (str, 0);
1558                 recp_list = e_gw_item_get_recipient_list (item);
1559                 if (recp_list) {
1560                         GSList *rl;
1561                         int i = 0;
1562                         for (rl = recp_list; rl != NULL; rl = rl->next) {
1563                                 EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
1564                                 if (recp->type == E_GW_ITEM_RECIPIENT_TO) {
1565                                         if (i)
1566                                                 str = g_string_append (str, ", ");
1567                                         g_string_append_printf (str,"%s <%s>", recp->display_name, recp->email);
1568                                         i++;
1569                                 }
1570                         }
1571                         mi->info.to = camel_pstring_strdup (str->str);
1572                         g_string_truncate (str, 0);
1573                 }
1574
1575                 if (type == E_GW_ITEM_TYPE_APPOINTMENT ||
1576                     type ==  E_GW_ITEM_TYPE_NOTE ||
1577                     type ==  E_GW_ITEM_TYPE_TASK ) {
1578                         temp_date = e_gw_item_get_start_date (item);
1579                         if (temp_date) {
1580                                 time_t time = e_gw_connection_get_date_from_string (temp_date);
1581                                 time_t actual_time = camel_header_decode_date (ctime(&time), NULL);
1582                                 mi->info.date_sent = mi->info.date_received = actual_time;
1583                         } 
1584                 } else {
1585                         temp_date = e_gw_item_get_delivered_date(item);
1586                         if (temp_date) {
1587                                 time_t time = e_gw_connection_get_date_from_string (temp_date);
1588                                 time_t actual_time = camel_header_decode_date (ctime(&time), NULL);
1589                                 mi->info.date_sent = mi->info.date_received = actual_time;
1590                         } else {
1591                                 time_t time;
1592                                 time_t actual_time;
1593                                 temp_date = e_gw_item_get_creation_date (item);
1594                                 time = e_gw_connection_get_date_from_string (temp_date);
1595                                 actual_time = camel_header_decode_date (ctime(&time), NULL);
1596                                 mi->info.date_sent = mi->info.date_received = actual_time;
1597                         }
1598                 }
1599
1600                 mi->info.uid = g_strdup(e_gw_item_get_id(item));
1601                 if (!exists)
1602                         mi->info.size = e_gw_item_get_mail_size (item); 
1603                 mi->info.subject = camel_pstring_strdup(e_gw_item_get_subject(item));
1604
1605                 if (exists) {
1606                         camel_folder_change_info_change_uid (changes, e_gw_item_get_id (item));
1607                         camel_message_info_free (&mi->info);
1608                 } else {
1609                         camel_folder_summary_add (folder->summary,(CamelMessageInfo *)mi);
1610                         camel_folder_change_info_add_uid (changes, mi->info.uid);
1611                         camel_folder_change_info_recent_uid (changes, mi->info.uid);
1612                 }
1613
1614                 exists = FALSE;
1615         }
1616         g_free (container_id);
1617         g_string_free (str, TRUE);
1618         camel_object_trigger_event (folder, "folder_changed", changes);
1619
1620         camel_folder_change_info_free (changes);
1621 }
1622
1623 static CamelMimeMessage *
1624 groupwise_folder_item_to_msg( CamelFolder *folder,
1625                 EGwItem *item,
1626                 CamelException *ex )
1627 {
1628         CamelMimeMessage *msg = NULL;
1629         CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE(folder->parent_store);
1630         CamelGroupwiseStorePrivate  *priv = gw_store->priv;
1631         const char *container_id = NULL;
1632         GSList *attach_list = NULL;
1633         EGwItemType type;
1634         EGwConnectionStatus status;
1635         EGwConnection *cnc;
1636         CamelMultipart *multipart = NULL;
1637         int errno;
1638         char *body = NULL;
1639         int body_len = 0;
1640         const char *uid = NULL;
1641         gboolean is_text_html = FALSE;
1642         gboolean has_mime_822 = FALSE;
1643         gboolean is_text_html_embed = FALSE;
1644         gboolean is_base64_encoded = FALSE;
1645         CamelStream *temp_stream;
1646
1647         uid = e_gw_item_get_id(item);
1648         cnc = cnc_lookup (priv);
1649         container_id = camel_groupwise_store_container_id_lookup (gw_store, folder->full_name);
1650
1651         attach_list = e_gw_item_get_attach_id_list (item);
1652         if (attach_list) {
1653                 //int attach_count = g_slist_length (attach_list);
1654                 GSList *al = attach_list;
1655                 EGwItemAttachment *attach = (EGwItemAttachment *)al->data;
1656                 char *attachment = NULL;
1657                 int len = 0;
1658
1659                 if (!g_ascii_strcasecmp (attach->name, "Text.htm") ||
1660                     !g_ascii_strcasecmp (attach->name, "Header")) {
1661
1662                         status = e_gw_connection_get_attachment (cnc,
1663                                         attach->id, 0, -1,
1664                                         (const char **)&attachment, &len);
1665                         if (status != E_GW_CONNECTION_STATUS_OK) {
1666                                 g_warning ("Could not get attachment\n");
1667                                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Could not get message"));
1668                                 return NULL;
1669                         }
1670                         if (attachment && attachment[0] && (len !=0) ) {
1671                                 if (!g_ascii_strcasecmp (attach->name, "TEXT.htm")) {
1672                                         body = g_strdup (attachment);
1673                                         g_free (attachment);
1674                                         is_text_html = TRUE;
1675                                 } 
1676                         }//if attachment and len
1677                 } // if Mime.822 or TEXT.htm
1678
1679                 for (al = attach_list ; al != NULL ; al = al->next) {
1680                         EGwItemAttachment *attach = (EGwItemAttachment *)al->data;
1681                         if (!g_ascii_strcasecmp (attach->name, "Mime.822")) {
1682                                 if (attach->size > MAX_ATTACHMENT_SIZE) {
1683                                         int len_iter = 0, t_len , offset = 0, t_offset = 0;
1684                                         char *t_attach = NULL;
1685                                         GString *gstr = g_string_new (NULL);
1686                                         
1687                                         len = 0;
1688                                         do {
1689                                                 status = e_gw_connection_get_attachment_base64 (cnc, 
1690                                                                 attach->id, t_offset, MAX_ATTACHMENT_SIZE, 
1691                                                                 (const char **)&t_attach, &t_len, &offset);
1692                                                 if (status == E_GW_CONNECTION_STATUS_OK) {
1693                                                         char *temp = NULL;
1694         
1695                                                         temp = soup_base64_decode(t_attach, &len_iter);
1696                                                         gstr = g_string_append_len (gstr, temp, len_iter);
1697                                                         g_free (temp);
1698                                                         len += len_iter;
1699                                                         t_offset = offset;
1700                                                         g_free (t_attach);
1701                                                         t_attach = NULL;
1702                                                 }
1703                                         } while (offset);
1704                                         body = gstr->str;
1705                                         body_len = len;
1706                                         g_string_free (gstr, FALSE);
1707                                 } else {
1708                                         status = e_gw_connection_get_attachment (cnc, 
1709                                                         attach->id, 0, -1, 
1710                                                         (const char **)&attachment, &len);
1711                                         if (status != E_GW_CONNECTION_STATUS_OK) {
1712                                                 g_warning ("Could not get attachment\n");
1713                                                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Could not get message"));
1714                                                 return NULL;
1715                                         }
1716                                         body = g_strdup (attachment);
1717                                         body_len = len;
1718                                         g_free (attachment);
1719                                 }
1720                                 has_mime_822 = TRUE;
1721                         } 
1722                 }
1723
1724         }//if attach_list
1725
1726
1727         msg = camel_mime_message_new ();
1728         if (has_mime_822) {
1729                 temp_stream = camel_stream_mem_new_with_buffer (body, body_len);
1730                 if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg, temp_stream) == -1) {
1731                         camel_object_unref (msg);
1732                         camel_object_unref (temp_stream);
1733                         msg = NULL;
1734                         goto end;
1735                 }
1736         } else {
1737                 multipart = camel_multipart_new ();
1738         }
1739
1740         camel_mime_message_set_message_id (msg, uid);
1741         type = e_gw_item_get_item_type (item);
1742         if (type == E_GW_ITEM_TYPE_NOTIFICATION)
1743                 camel_medium_add_header ( CAMEL_MEDIUM (msg), "X-Notification", "shared-folder");
1744
1745         /*If the reply-requested flag is set. Append the mail message with the
1746          *          * approprite detail*/
1747         if (e_gw_item_get_reply_request (item)) {
1748                 char *reply_within;
1749                 const char *mess = e_gw_item_get_message (item);
1750                 char *value;
1751
1752                 reply_within = e_gw_item_get_reply_within (item);
1753                 if (reply_within) {
1754                         time_t t;
1755                         char *temp;
1756
1757                         t = e_gw_connection_get_date_from_string (reply_within);
1758                         temp = ctime (&t);
1759                         temp [strlen (temp)-1] = '\0';
1760                         value = g_strconcat (N_("Reply Requested: by "), temp, "\n\n", mess ? mess : "", NULL);
1761                         e_gw_item_set_message (item, (const char *) value);
1762                         g_free (value);
1763
1764                 } else {
1765                         value = g_strconcat (N_("Reply Requested: When convenient"), "\n\n", mess ? mess : "", NULL);
1766                         e_gw_item_set_message (item, (const char *) value);
1767                         g_free (value);
1768                 }
1769         }
1770         
1771         if (has_mime_822)
1772                 goto end;
1773         else
1774                 groupwise_populate_msg_body_from_item (cnc, multipart, item, body);
1775         /*Set recipient details*/
1776         groupwise_msg_set_recipient_list (msg, item);
1777         groupwise_populate_details_from_item (msg, item);
1778         /*Now set attachments*/
1779         if (attach_list) {
1780                 gboolean has_boundary = FALSE;
1781                 GSList *al;
1782
1783                 for (al = attach_list ; al != NULL ; al = al->next) {
1784                         EGwItemAttachment *attach = (EGwItemAttachment *)al->data;
1785                         char *attachment = NULL;
1786                         int len = 0;
1787                         CamelMimePart *part;
1788                         EGwItem *temp_item;
1789                         is_base64_encoded = FALSE;
1790
1791                         if (attach->contentid && (is_text_html_embed != TRUE))
1792                                 is_text_html_embed = TRUE;
1793                         if ( !g_ascii_strcasecmp (attach->name, "TEXT.htm") ||
1794                              !g_ascii_strcasecmp (attach->name, "Mime.822") ||
1795                              !g_ascii_strcasecmp (attach->name, "Header"))
1796                                 continue;
1797
1798                         if ( (attach->item_reference) && (!g_ascii_strcasecmp (attach->item_reference, "1")) ) {
1799                                 CamelMimeMessage *temp_msg = NULL;
1800                                 status = e_gw_connection_get_item (cnc, container_id, attach->id, "default distribution recipient message attachments subject notification created recipientStatus status startDate", &temp_item);
1801                                 if (status != E_GW_CONNECTION_STATUS_OK) {
1802                                         g_warning ("Could not get attachment\n");
1803                                         continue;
1804                                 }
1805                                 temp_msg = groupwise_folder_item_to_msg(folder, temp_item, ex);
1806                                 if (temp_msg) {
1807                                         CamelContentType *ct = camel_content_type_new("message", "rfc822");
1808                                         part = camel_mime_part_new ();
1809                                         camel_data_wrapper_set_mime_type_field(CAMEL_DATA_WRAPPER (temp_msg), ct);
1810                                         camel_content_type_unref(ct);
1811                                         camel_medium_set_content_object ( CAMEL_MEDIUM (part),CAMEL_DATA_WRAPPER(temp_msg));
1812                                         
1813                                         camel_multipart_add_part (multipart,part);
1814                                         camel_object_unref (temp_msg);
1815                                         camel_object_unref (part);
1816                                 }
1817                                 g_object_unref (temp_item);
1818                         } else {
1819                                 if (attach->size > MAX_ATTACHMENT_SIZE) {
1820                                         int t_len=0, offset=0, t_offset=0;
1821                                         char *t_attach = NULL;
1822                                         GString *gstr = g_string_new (NULL);
1823
1824                                         len = 0;
1825                                         do {
1826                                                 status = e_gw_connection_get_attachment_base64 (cnc, 
1827                                                                 attach->id, t_offset, MAX_ATTACHMENT_SIZE, 
1828                                                                 (const char **)&t_attach, &t_len, &offset);
1829                                                 if (status == E_GW_CONNECTION_STATUS_OK) {
1830                                                         int len_iter = 0;
1831                                                         char *temp = NULL;
1832         
1833                                                         temp = soup_base64_decode(t_attach, &len_iter);
1834                                                         gstr = g_string_append_len (gstr, temp, len_iter);
1835                                                         g_free (temp);
1836                                                         len += len_iter;
1837                                                         t_offset = offset;
1838                                                         g_free (t_attach);
1839                                                         t_attach = NULL;
1840                                                         t_len = 0;
1841                                                 }
1842                                         } while (t_offset);
1843                                         attachment =  gstr->str;
1844                                         g_string_free (gstr, FALSE);
1845                                         is_base64_encoded = FALSE;
1846                                 } else {
1847                                         status = e_gw_connection_get_attachment (cnc, 
1848                                                         attach->id, 0, -1, 
1849                                                         (const char **)&attachment, &len);
1850                                 }
1851                                 if (status != E_GW_CONNECTION_STATUS_OK) {
1852                                         g_warning ("Could not get attachment\n");
1853                                         continue;
1854                                 }
1855                                 if (attachment && (len !=0) ) {
1856                                         part = camel_mime_part_new ();
1857                                         /*multiparts*/
1858                                         if (is_text_html_embed) {
1859                                                 camel_mime_part_set_filename(part, g_strdup(attach->name));
1860                                                 camel_data_wrapper_set_mime_type(CAMEL_DATA_WRAPPER (multipart), "multipart/related");
1861                                                 has_boundary = TRUE;
1862                                                 camel_content_type_set_param(CAMEL_DATA_WRAPPER (multipart)->mime_type, "type", "multipart/alternative");
1863                                                 if (attach->contentid) {
1864                                                         gchar **t;
1865                                                         t= g_strsplit_set (attach->contentid, "<>", -1);
1866                                                         if (!t[1]) 
1867                                                                 camel_mime_part_set_content_id (part, attach->contentid);
1868                                                         else 
1869                                                                 camel_mime_part_set_content_id (part, t[1]);
1870                                                         g_strfreev (t);
1871                                                         camel_mime_part_set_content_location (part, attach->name);
1872                                                 }
1873                                         } else {
1874                                                 camel_mime_part_set_filename(part, g_strdup(attach->name));
1875                                                 camel_mime_part_set_content_id (part, attach->contentid);
1876                                         }
1877
1878                                         //camel_mime_part_set_filename(part, g_strdup(attach->name));
1879                                         if (attach->contentType) {
1880                                                 if (is_base64_encoded)
1881                                                         camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
1882                                                 camel_mime_part_set_content(part, attachment, len, attach->contentType);
1883                                                 camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", attach->name);
1884                                         } else {
1885                                                         camel_mime_part_set_content(part, attachment, len, "text/plain");
1886                                         }
1887                                         if (!has_boundary)
1888                                                 camel_data_wrapper_set_mime_type(CAMEL_DATA_WRAPPER (multipart),"multipart/digest");
1889
1890                                         camel_multipart_set_boundary(multipart, NULL);
1891                                         camel_multipart_add_part (multipart, part);
1892
1893                                         camel_object_unref (part);
1894                                         g_free (attachment);
1895                                 } /* if attachment */
1896                         }
1897                 } /* end of for*/
1898
1899         }/* if attach_list */
1900         /********************/
1901
1902         camel_medium_set_content_object(CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart));
1903         camel_object_unref (multipart);
1904
1905 end:
1906         if (body)
1907                 g_free (body);
1908
1909         return msg;
1910 }
1911
1912 static void
1913 gw_update_all_items (CamelFolder *folder, GList *item_list, CamelException *ex) 
1914 {
1915         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
1916         GPtrArray *summary = NULL;
1917         int index = 0;
1918         GList *temp;
1919         CamelFolderChangeInfo *changes = NULL;
1920         CamelMessageInfo *info; 
1921         changes = camel_folder_change_info_new ();
1922
1923         item_list = g_list_reverse (item_list);
1924
1925         summary = camel_folder_get_summary (folder);
1926         /*item_ids : List of ids from the summary*/
1927         while (index < summary->len) {
1928                 info = g_ptr_array_index (summary, index);
1929                 temp = NULL; 
1930
1931                 if (item_list) {
1932                         temp = g_list_find_custom (item_list, (const char *)info->uid, (GCompareFunc) strcmp);
1933                 }
1934
1935                 if (!temp) {
1936                         CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
1937                         camel_folder_summary_remove_uid (folder->summary, info->uid);
1938                         camel_data_cache_remove (gw_folder->cache, "cache", info->uid, NULL);
1939                         camel_folder_change_info_remove_uid (changes, info->uid);
1940                         CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
1941                 } else { 
1942                         item_list = g_list_delete_link (item_list, temp);
1943                 }
1944                 index ++;
1945         }
1946
1947         camel_object_trigger_event (folder, "folder_changed", changes);
1948
1949         if (item_list) {
1950                 CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
1951
1952                 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
1953                 gw_update_cache (folder, item_list, ex, TRUE);  
1954                 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
1955
1956                 g_list_foreach (item_list, (GFunc)g_free, NULL);        
1957                 g_list_free (item_list);
1958         }
1959
1960         camel_folder_free_summary (folder, summary);
1961 }
1962
1963 static void
1964 groupwise_append_message (CamelFolder *folder, CamelMimeMessage *message,
1965                 const CamelMessageInfo *info, char **appended_uid,
1966                 CamelException *ex)
1967 {
1968         const char *container_id = NULL;
1969         CamelGroupwiseStore *gw_store= CAMEL_GROUPWISE_STORE(folder->parent_store);
1970         CamelGroupwiseStorePrivate  *priv = gw_store->priv;
1971         CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
1972         EGwConnectionStatus status = { 0, };
1973         EGwConnection *cnc;
1974         EGwItem *item;
1975         char *id;
1976         gboolean is_ok = FALSE;
1977
1978         if (!strcmp (folder->name, RECEIVED))
1979                 is_ok = TRUE;
1980         if(!strcmp (folder->name, SENT))
1981                 is_ok = TRUE;
1982
1983         if (!is_ok) {
1984                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot append message to folder `%s': %s"),
1985                                 folder->full_name, e_gw_connection_get_error_message (status));
1986                 return;
1987         }
1988
1989         if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
1990                 camel_groupwise_journal_append ((CamelGroupwiseJournal *) ((CamelGroupwiseFolder *)folder)->journal, message, info, appended_uid, ex);
1991                 return;
1992         }
1993         cnc = cnc_lookup (priv);
1994
1995         CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock);
1996         /*Get the container id*/
1997         container_id = camel_groupwise_store_container_id_lookup (gw_store, folder->full_name) ;
1998         
1999         item = camel_groupwise_util_item_from_message (cnc, message, CAMEL_ADDRESS (message->from));
2000         /*Set the source*/
2001         if (!strcmp (folder->name, RECEIVED))
2002                 e_gw_item_set_source (item, "received");
2003         if (!strcmp (folder->name, SENT))
2004                 e_gw_item_set_source (item, "sent");
2005         if (!strcmp (folder->name, DRAFT))
2006                 e_gw_item_set_source (item, "draft");
2007         if (!strcmp (folder->name, PERSONAL))
2008                 e_gw_item_set_source (item, "personal");
2009         /*set container id*/
2010         e_gw_item_set_container_id (item, container_id);
2011
2012         status = e_gw_connection_create_item (cnc, item, &id);
2013         if (status != E_GW_CONNECTION_STATUS_OK) {
2014                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create message: %s"),
2015                                 e_gw_connection_get_error_message (status));
2016
2017                 if (appended_uid)
2018                         *appended_uid = NULL;
2019                 CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
2020                 return;
2021         }
2022
2023         status = e_gw_connection_add_item (cnc, container_id, id);
2024         g_message ("Adding %s to %s", id, container_id);
2025         if (status != E_GW_CONNECTION_STATUS_OK) {
2026                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot append message to folder `%s': %s"),
2027                                 folder->full_name, e_gw_connection_get_error_message (status));
2028
2029                 if (appended_uid)
2030                         *appended_uid = NULL;
2031
2032                 CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
2033                 return;
2034         }
2035
2036         if (appended_uid)
2037                 *appended_uid = g_strdup (id);  
2038         g_free (id);
2039         CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
2040 }
2041
2042 static int
2043 uid_compar (const void *va, const void *vb)
2044 {
2045         const char **sa = (const char **)va, **sb = (const char **)vb;
2046         unsigned long a, b;
2047
2048         a = strtoul (*sa, NULL, 10);
2049         b = strtoul (*sb, NULL, 10);
2050         if (a < b)
2051                 return -1;
2052         else if (a == b)
2053                 return 0;
2054         else
2055                 return 1;
2056 }
2057
2058 static void
2059 groupwise_transfer_messages_to (CamelFolder *source, GPtrArray *uids, 
2060                 CamelFolder *destination, GPtrArray **transferred_uids, 
2061                 gboolean delete_originals, CamelException *ex)
2062 {
2063         int count, index = 0;
2064         GList *item_ids = NULL;
2065         const char *source_container_id = NULL, *dest_container_id = NULL;
2066         CamelGroupwiseStore *gw_store= CAMEL_GROUPWISE_STORE(source->parent_store);
2067         CamelOfflineStore *offline = (CamelOfflineStore *) destination->parent_store;
2068         CamelGroupwiseStorePrivate  *priv = gw_store->priv;
2069         EGwConnectionStatus status;
2070         EGwConnection *cnc;
2071         CamelFolderChangeInfo *changes = NULL;
2072
2073         count = camel_folder_summary_count (destination->summary);
2074         qsort (uids->pdata, uids->len, sizeof (void *), uid_compar);
2075
2076         changes = camel_folder_change_info_new ();
2077         while (index < uids->len) {
2078                 item_ids = g_list_append (item_ids, g_ptr_array_index (uids, index));
2079                 index ++;
2080         }
2081
2082         if (transferred_uids)
2083                 *transferred_uids = NULL;
2084
2085         if (delete_originals) 
2086                 source_container_id = camel_groupwise_store_container_id_lookup (gw_store, source->full_name) ;
2087         else
2088                 source_container_id = NULL;
2089         dest_container_id = camel_groupwise_store_container_id_lookup (gw_store, destination->full_name) ;
2090
2091         CAMEL_SERVICE_REC_LOCK (source->parent_store, connect_lock);
2092         /* check for offline operation */
2093         if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
2094                 CamelGroupwiseJournal *journal = (CamelGroupwiseJournal *) ((CamelGroupwiseFolder *) destination)->journal;
2095                 CamelMimeMessage *message;
2096                 GList *l;
2097                 int i;
2098
2099                 for (l = item_ids, i = 0; l; l = l->next, i++) {
2100                         CamelMessageInfo *info;
2101
2102                         if (!(info = camel_folder_summary_uid (source->summary, uids->pdata[i])))
2103                                 continue;
2104
2105                         if (!(message = groupwise_folder_get_message (source, camel_message_info_uid (info), ex)))
2106                                 break;
2107
2108                         camel_groupwise_journal_transfer (journal, (CamelGroupwiseFolder *)source, message, info, uids->pdata[i], NULL, ex);
2109                         camel_object_unref (message);
2110
2111                         if (camel_exception_is_set (ex))
2112                                 break;
2113
2114                         if (delete_originals) { 
2115                                 if ( !strcmp(source->full_name, SENT) ) {
2116                                         camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
2117                                                         _("This message is not available in offline mode."));
2118
2119                                 } else {
2120                                         camel_folder_summary_remove_uid (source->summary, uids->pdata[index]);
2121                                         camel_folder_change_info_remove_uid (changes, uids->pdata[index]);
2122                                 }
2123                         }
2124                 }
2125
2126                 CAMEL_SERVICE_REC_UNLOCK (source->parent_store, connect_lock);
2127                 return;
2128         }
2129
2130
2131         cnc = cnc_lookup (priv);
2132         index = 0;
2133         while (index < uids->len) {
2134                 CamelMessageInfo *info = NULL;
2135                 CamelGroupwiseMessageInfo *gw_info = NULL;
2136                 flags_diff_t diff, unset_flags;
2137                 int count;
2138                 count = camel_folder_summary_count (destination->summary);
2139
2140                 info = camel_folder_summary_uid (source->summary, uids->pdata[index]);
2141                 gw_info = (CamelGroupwiseMessageInfo *) info;
2142                 if (gw_info && (gw_info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
2143                         do_flags_diff (&diff, gw_info->server_flags, gw_info->info.flags);
2144                         do_flags_diff (&unset_flags, gw_info->info.flags, gw_info->server_flags);
2145                         diff.changed &= source->permanent_flags;
2146
2147                         /* sync the read changes */
2148                         if (diff.changed) {
2149                                 const char *uid = camel_message_info_uid (info);
2150                                 GList *wrapper = NULL;
2151                                 gw_info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
2152                                 gw_info->server_flags = gw_info->info.flags;
2153
2154                                 if (diff.bits & CAMEL_MESSAGE_SEEN) {
2155                                         
2156                                         /*
2157                                         wrapper is a list wrapper bcos e_gw_connection_mark_read 
2158                                         is designed for passing multiple uids. Also, there are is not much
2159                                         need/use for a e_gw_connection_mark_ITEM_[un]read       
2160                                         */
2161
2162                                         wrapper = g_list_prepend (wrapper, (char *)uid);
2163                                         CAMEL_SERVICE_REC_LOCK (source->parent_store, connect_lock);
2164                                         e_gw_connection_mark_read (cnc, wrapper);
2165                                         CAMEL_SERVICE_REC_UNLOCK (source->parent_store, connect_lock);
2166                                         g_list_free (wrapper);
2167                                         wrapper = NULL;
2168                                 }
2169
2170                                 
2171                                 /* A User may mark a message as Unread and then immediately move it to
2172                                 some other folder. The following piece of code take care of such scenario.
2173                                 
2174                                 However, Remember that When a mail is deleted after being marked as unread, 
2175                                 I am not syncing the read-status. 
2176                                 */
2177
2178                                 if (unset_flags.bits & CAMEL_MESSAGE_SEEN) {
2179                                         wrapper = g_list_prepend (wrapper, (char *)uid);
2180                                         CAMEL_SERVICE_REC_LOCK (source->parent_store, connect_lock);
2181                                         e_gw_connection_mark_unread (cnc, wrapper);
2182                                         CAMEL_SERVICE_REC_UNLOCK (source->parent_store, connect_lock);
2183                                         g_list_free (wrapper);
2184                                         wrapper = NULL;
2185                                 }
2186                         }
2187                 }
2188
2189                 if (delete_originals) {
2190                         if (strcmp(source->full_name, "Sent Items")) {
2191                                 status = e_gw_connection_move_item (cnc, (const char *)uids->pdata[index], 
2192                                                 dest_container_id, source_container_id);
2193                         } else {
2194                                 char *container_id = NULL;
2195                                 container_id = e_gw_connection_get_container_id (cnc, "Mailbox");
2196                                 status = e_gw_connection_move_item (cnc, (const char *)uids->pdata[index], 
2197                                                 dest_container_id, container_id);
2198                                 g_free (container_id);
2199                         }
2200
2201                 } else
2202                         status = e_gw_connection_move_item (cnc, (const char *)uids->pdata[index], 
2203                                         dest_container_id, NULL);
2204
2205                 if (status == E_GW_CONNECTION_STATUS_OK) {
2206                         if (delete_originals) { 
2207                                 if ( !strcmp(source->full_name, SENT) ) {
2208                                         camel_folder_delete_message(source, uids->pdata[index]);
2209                                 } else {
2210                                         camel_folder_summary_remove_uid (source->summary, uids->pdata[index]);
2211                                         camel_folder_change_info_remove_uid (changes, uids->pdata[index]);
2212                                 }
2213                         }
2214                 } else {
2215                         g_warning ("Warning!! Could not move item : %s\n", (char *)uids->pdata[index]);
2216                 }
2217                 index ++;
2218         }
2219
2220         camel_object_trigger_event (source, "folder_changed", changes);
2221         camel_folder_change_info_free (changes);
2222
2223         /* Refresh the destination folder, if its not refreshed already */
2224         if (gw_store->current_folder != destination )
2225                 camel_folder_refresh_info (destination, ex);
2226
2227         camel_folder_summary_touch (source->summary);
2228         camel_folder_summary_touch (destination->summary);
2229
2230         gw_store->current_folder = source;
2231
2232         CAMEL_SERVICE_REC_UNLOCK (source->parent_store, connect_lock);
2233 }
2234
2235 static void
2236 groupwise_expunge (CamelFolder *folder, CamelException *ex)
2237 {
2238         CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE(folder->parent_store);
2239         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
2240         CamelGroupwiseStorePrivate  *priv = groupwise_store->priv;
2241         CamelGroupwiseMessageInfo *ginfo;
2242         CamelMessageInfo *info;
2243         char *container_id;
2244         EGwConnection *cnc;
2245         EGwConnectionStatus status;
2246         CamelFolderChangeInfo *changes;
2247         int i, max;
2248         gboolean delete = FALSE;
2249         GList *deleted_items, *deleted_head;
2250         
2251
2252         deleted_items = deleted_head = NULL;
2253         cnc = cnc_lookup (priv);
2254         if (!cnc)
2255                 return;
2256
2257         if (!strcmp (folder->full_name, "Trash")) {
2258                 CAMEL_SERVICE_REC_LOCK (groupwise_store, connect_lock);
2259                 status = e_gw_connection_purge_deleted_items (cnc);
2260                 if (status == E_GW_CONNECTION_STATUS_OK) {
2261                         camel_folder_freeze (folder);
2262                         groupwise_summary_clear (folder->summary, TRUE);
2263                         camel_folder_thaw (folder);
2264                 } else
2265                         g_warning ("Could not Empty Trash\n");
2266                 CAMEL_SERVICE_REC_UNLOCK (groupwise_store, connect_lock);
2267                 return;
2268         }
2269
2270         changes = camel_folder_change_info_new ();
2271
2272         container_id =  g_strdup (camel_groupwise_store_container_id_lookup (groupwise_store, folder->full_name)) ;
2273
2274         max = camel_folder_summary_count (folder->summary);
2275         for (i = 0; i < max; i++) {
2276                 info = camel_folder_summary_index (folder->summary, i);
2277                 ginfo = (CamelGroupwiseMessageInfo *) info;
2278                 if (ginfo && (ginfo->info.flags & CAMEL_MESSAGE_DELETED)) {
2279
2280                         if (deleted_items)
2281                                 deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
2282                         else {
2283                                 g_list_free (deleted_head);
2284                                 deleted_head = NULL;
2285                                 deleted_head = deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
2286                         }
2287                         if (g_list_length (deleted_items) == GROUPWISE_BULK_DELETE_LIMIT ) {
2288                                 /* Read the FIXME below */
2289                                 CAMEL_SERVICE_REC_LOCK (groupwise_store, connect_lock);
2290                                 status = e_gw_connection_remove_items (cnc, container_id, deleted_items);
2291                                 CAMEL_SERVICE_REC_UNLOCK (groupwise_store, connect_lock);
2292                                 if (status == E_GW_CONNECTION_STATUS_OK) {
2293                                         char *uid;
2294                                         while (deleted_items) {
2295                                                 uid = (char *)deleted_items->data;
2296                                                 CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
2297                                                 camel_folder_change_info_remove_uid (changes, uid);
2298                                                 camel_folder_summary_remove_uid (folder->summary, uid);
2299                                                 camel_data_cache_remove(gw_folder->cache, "cache", uid, NULL);
2300                                                 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
2301                                                 deleted_items = g_list_next (deleted_items);
2302                                                 max -= GROUPWISE_BULK_DELETE_LIMIT;
2303                                                 i -= GROUPWISE_BULK_DELETE_LIMIT;
2304                                         }
2305                                 }
2306                                 delete = TRUE;
2307                         }
2308                 }
2309                 camel_message_info_free (info);
2310         }
2311
2312         if (deleted_items) {
2313                 /* FIXME: Put these in a function and reuse it inside the above loop, here and in groupwise_sync*/
2314                 CAMEL_SERVICE_REC_LOCK (groupwise_store, connect_lock);
2315                 status = e_gw_connection_remove_items (cnc, container_id, deleted_items);
2316                 CAMEL_SERVICE_REC_UNLOCK (groupwise_store, connect_lock);
2317                 if (status == E_GW_CONNECTION_STATUS_OK) {
2318                         char *uid;
2319                         while (deleted_items) {
2320                                 uid = (char *)deleted_items->data;
2321                                 CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
2322                                 camel_folder_change_info_remove_uid (changes, uid);
2323                                 camel_folder_summary_remove_uid (folder->summary, uid);
2324                                 camel_data_cache_remove(gw_folder->cache, "cache", uid, NULL);
2325                                 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
2326                                 deleted_items = g_list_next (deleted_items);
2327                         }
2328                 }
2329                 delete = TRUE;
2330                 g_list_free (deleted_head);
2331         }
2332
2333         if (delete)
2334                 camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes);
2335
2336         g_free (container_id);
2337         camel_folder_change_info_free (changes);
2338 }
2339
2340 static void
2341 camel_groupwise_folder_class_init (CamelGroupwiseFolderClass *camel_groupwise_folder_class)
2342 {
2343         CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_groupwise_folder_class);
2344
2345         parent_class = CAMEL_OFFLINE_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_offline_folder_get_type ()));
2346
2347         ((CamelObjectClass *) camel_groupwise_folder_class)->getv = gw_getv;
2348
2349         camel_folder_class->get_message = groupwise_folder_get_message;
2350         camel_folder_class->rename = groupwise_folder_rename;
2351         camel_folder_class->search_by_expression = groupwise_folder_search_by_expression;
2352         camel_folder_class->search_by_uids = groupwise_folder_search_by_uids; 
2353         camel_folder_class->search_free = groupwise_folder_search_free;
2354         camel_folder_class->append_message = groupwise_append_message;
2355         camel_folder_class->refresh_info = groupwise_refresh_info;
2356         camel_folder_class->sync = groupwise_sync;
2357         camel_folder_class->expunge = groupwise_expunge;
2358         camel_folder_class->transfer_messages_to = groupwise_transfer_messages_to;
2359 }
2360
2361 static void
2362 camel_groupwise_folder_init (gpointer object, gpointer klass)
2363 {
2364         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (object);
2365         CamelFolder *folder = CAMEL_FOLDER (object);
2366
2367
2368         folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED |
2369                 CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN;
2370
2371         folder->folder_flags = CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
2372
2373         gw_folder->priv = g_malloc0 (sizeof(*gw_folder->priv));
2374
2375 #ifdef ENABLE_THREADS
2376         g_static_mutex_init(&gw_folder->priv->search_lock);
2377         g_static_rec_mutex_init(&gw_folder->priv->cache_lock);
2378 #endif 
2379
2380         gw_folder->need_rescan = TRUE;
2381 }
2382
2383 static void
2384 camel_groupwise_folder_finalize (CamelObject *object)
2385 {
2386         CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (object);
2387
2388         if (gw_folder->priv)
2389                 g_free(gw_folder->priv);
2390         if (gw_folder->cache)
2391                 camel_object_unref (gw_folder->cache);
2392         if (gw_folder->search)
2393                 camel_object_unref (gw_folder->search);
2394
2395 }
2396
2397 CamelType
2398 camel_groupwise_folder_get_type (void)
2399 {
2400         static CamelType camel_groupwise_folder_type = CAMEL_INVALID_TYPE;
2401
2402
2403         if (camel_groupwise_folder_type == CAMEL_INVALID_TYPE) {
2404                 camel_groupwise_folder_type =
2405                         camel_type_register (camel_offline_folder_get_type (),
2406                                         "CamelGroupwiseFolder",
2407                                         sizeof (CamelGroupwiseFolder),
2408                                         sizeof (CamelGroupwiseFolderClass),
2409                                         (CamelObjectClassInitFunc) camel_groupwise_folder_class_init,
2410                                         NULL,
2411                                         (CamelObjectInitFunc) camel_groupwise_folder_init,
2412                                         (CamelObjectFinalizeFunc) camel_groupwise_folder_finalize);
2413         }
2414
2415         return camel_groupwise_folder_type;
2416 }
2417
2418 static int
2419 gw_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
2420 {
2421         CamelFolder *folder = (CamelFolder *)object;
2422         int i, count = 0;
2423         guint32 tag;
2424
2425         for (i=0 ; i<args->argc ; i++) {
2426                 CamelArgGet *arg = &args->argv[i];
2427
2428                 tag = arg->tag;
2429
2430                 switch (tag & CAMEL_ARG_TAG) {
2431
2432                         case CAMEL_OBJECT_ARG_DESCRIPTION:
2433                                 if (folder->description == NULL) {
2434                                         CamelURL *uri = ((CamelService *)folder->parent_store)->url;
2435
2436                                         folder->description = g_strdup_printf("%s@%s:%s", uri->user, uri->host, folder->full_name);
2437                                 }
2438                                 *arg->ca_str = folder->description;
2439                                 break;
2440                         default:
2441                                 count++;
2442                                 continue;
2443                 }
2444
2445                 arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
2446         }
2447
2448         if (count)
2449                 return ((CamelObjectClass *)parent_class)->getv(object, ex, args);
2450
2451         return 0;
2452
2453 }
2454
2455 void 
2456 convert_to_calendar (EGwItem *item, char **str, int *len)
2457 {
2458         EGwItemOrganizer *org = NULL;
2459         GSList *recp_list = NULL;
2460         GSList *attach_list = NULL;
2461         GString *gstr = g_string_new (NULL);
2462         int recur_key = 0;
2463         char **tmp = NULL;
2464         const char *temp = NULL;
2465
2466         tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
2467
2468         gstr = g_string_append (gstr, "BEGIN:VCALENDAR\n");
2469         gstr = g_string_append (gstr, "METHOD:REQUEST\n");
2470         gstr = g_string_append (gstr, "BEGIN:VEVENT\n");
2471
2472         if ((recur_key = e_gw_item_get_recurrence_key (item)) != 0) {
2473                 char *recur_k = g_strdup_printf ("%d", recur_key); 
2474
2475                 g_string_append_printf (gstr, "UID:%s\n", recur_k);
2476                 g_string_append_printf (gstr, "X-GW-RECURRENCE-KEY:%s\n", recur_k);
2477
2478                 g_free (recur_k);
2479         } else
2480                 g_string_append_printf (gstr, "UID:%s\n",e_gw_item_get_icalid (item));
2481
2482         g_string_append_printf (gstr, "X-GWITEM-TYPE:APPOINTMENT\n");
2483         g_string_append_printf (gstr, "DTSTART:%s\n",e_gw_item_get_start_date (item));
2484         g_string_append_printf (gstr, "SUMMARY:%s\n", e_gw_item_get_subject (item));
2485
2486         temp = e_gw_item_get_message (item);
2487         if (temp) {
2488                 g_string_append(gstr, "DESCRIPTION:");
2489                 while (*temp) {
2490                         if (*temp == '\n')
2491                                 g_string_append(gstr, "\\n");
2492                         else
2493                                 g_string_append_c(gstr, *temp);
2494                         temp++;
2495                 }
2496                 g_string_append(gstr, "\n");    
2497         }
2498
2499         g_string_append_printf (gstr, "DTSTAMP:%s\n", e_gw_item_get_creation_date (item));
2500         g_string_append_printf (gstr, "X-GWMESSAGEID:%s\n", e_gw_item_get_id (item));
2501         g_string_append_printf (gstr, "X-GWSHOW-AS:BUSY\n");
2502         g_string_append_printf (gstr, "X-GWRECORDID:%s\n", tmp[0]);
2503
2504         org = e_gw_item_get_organizer (item);
2505         if (org)
2506                 g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n", 
2507                                 org->display_name, org->email);
2508
2509         recp_list = e_gw_item_get_recipient_list (item);
2510         if (recp_list) {
2511                 GSList *rl ;
2512
2513                 for (rl = recp_list ; rl != NULL ; rl = rl->next) {
2514                         EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
2515                         g_string_append_printf (gstr, 
2516                                         "ATTENDEE;CN= %s;ROLE= REQ-PARTICIPANT:\nMAILTO:%s\n",
2517                                         recp->display_name, recp->email);
2518                 }
2519         }
2520
2521         g_string_append_printf (gstr, "DTEND:%s\n", e_gw_item_get_end_date (item));
2522
2523         temp = NULL;
2524         temp = e_gw_item_get_place (item);
2525         if (temp)
2526                 g_string_append_printf (gstr, "LOCATION:%s\n", temp);
2527
2528         temp = NULL;
2529         temp = e_gw_item_get_task_priority (item);
2530         if (temp)
2531                 g_string_append_printf (gstr, "PRIORITY:%s\n", temp);
2532
2533         temp = NULL;
2534         attach_list = e_gw_item_get_attach_id_list (item);
2535         if (attach_list) {
2536                 GSList *al;
2537
2538                 for (al = attach_list ; al != NULL ; al = al->next) {
2539                         EGwItemAttachment *attach = (EGwItemAttachment *)al->data;
2540                         g_string_append_printf (gstr, "ATTACH:%s\n", attach->id);
2541                 }
2542         }
2543         gstr = g_string_append (gstr, "END:VEVENT\n");
2544         gstr = g_string_append (gstr, "END:VCALENDAR\n");
2545
2546         *str = gstr->str;
2547         *len = gstr->len;
2548
2549         g_string_free (gstr, FALSE);
2550         g_strfreev (tmp);
2551 }
2552
2553 static void 
2554 convert_to_task (EGwItem *item, char **str, int *len)
2555 {
2556         EGwItemOrganizer *org = NULL;
2557         GSList *recp_list = NULL;
2558         GString *gstr = g_string_new (NULL);
2559         char **tmp = NULL;
2560         const char *temp = NULL;
2561
2562         tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
2563
2564         gstr = g_string_append (gstr, "BEGIN:VCALENDAR\n");
2565         gstr = g_string_append (gstr, "METHOD:REQUEST\n");
2566         gstr = g_string_append (gstr, "BEGIN:VTODO\n");
2567         g_string_append_printf (gstr, "UID:%s\n",e_gw_item_get_icalid (item));
2568         g_string_append_printf (gstr, "DTSTART:%s\n",e_gw_item_get_start_date (item));
2569         g_string_append_printf (gstr, "SUMMARY:%s\n", e_gw_item_get_subject (item));
2570         g_string_append_printf (gstr, "DESCRIPTION:%s\n", e_gw_item_get_message (item));
2571         g_string_append_printf (gstr, "DTSTAMP:%s\n", e_gw_item_get_creation_date (item));
2572         g_string_append_printf (gstr, "X-GWMESSAGEID:%s\n", e_gw_item_get_id (item));
2573         g_string_append_printf (gstr, "X-GWSHOW-AS:BUSY\n");
2574         g_string_append_printf (gstr, "X-GWRECORDID:%s\n", tmp[0]);
2575
2576         org = e_gw_item_get_organizer (item);
2577         if (org)
2578                 g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n", 
2579                                 org->display_name, org->email);
2580
2581         recp_list = e_gw_item_get_recipient_list (item);
2582         if (recp_list) {
2583                 GSList *rl;
2584
2585                 for (rl = recp_list ; rl != NULL ; rl = rl->next) {
2586                         EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
2587                         g_string_append_printf (gstr, 
2588                                         "ATTENDEE;CN= %s;ROLE= REQ-PARTICIPANT:\nMAILTO:%s\n",
2589                                         recp->display_name, recp->email);
2590                 }
2591         }
2592
2593         g_string_append_printf (gstr, "DTEND:%s\n", e_gw_item_get_end_date (item));
2594
2595         temp = e_gw_item_get_place (item);
2596         if (temp)
2597                 g_string_append_printf (gstr, "LOCATION:%s\n", temp);
2598
2599         temp = NULL;
2600         temp = e_gw_item_get_task_priority (item);
2601         if (temp)
2602                 g_string_append_printf (gstr, "PRIORITY:%s\n", temp);
2603
2604         temp = NULL;
2605         temp = e_gw_item_get_due_date (item);
2606         if (temp)
2607                 g_string_append_printf (gstr, "DUE:%s\n", temp);
2608         gstr = g_string_append (gstr, "END:VTODO\n");
2609         gstr = g_string_append (gstr, "END:VCALENDAR\n");
2610
2611
2612         *str = g_strdup (gstr->str);
2613         *len = gstr->len;
2614
2615         g_string_free (gstr, TRUE);
2616         g_strfreev (tmp);
2617 }
2618
2619 static void 
2620 convert_to_note (EGwItem *item, char **str, int *len)
2621 {
2622         EGwItemOrganizer *org = NULL;
2623         GString *gstr = g_string_new (NULL);
2624         char **tmp = NULL;
2625
2626         tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
2627
2628         gstr = g_string_append (gstr, "BEGIN:VCALENDAR\n");
2629         gstr = g_string_append (gstr, "METHOD:PUBLISH\n");
2630         gstr = g_string_append (gstr, "BEGIN:VJOURNAL\n");
2631         g_string_append_printf (gstr, "UID:%s\n",e_gw_item_get_icalid (item));
2632         g_string_append_printf (gstr, "DTSTART:%s\n",e_gw_item_get_start_date (item));
2633         g_string_append_printf (gstr, "SUMMARY:%s\n", e_gw_item_get_subject (item));
2634         g_string_append_printf (gstr, "DESCRIPTION:%s\n", e_gw_item_get_message (item));
2635         g_string_append_printf (gstr, "DTSTAMP:%s\n", e_gw_item_get_creation_date (item));
2636         g_string_append_printf (gstr, "X-GWMESSAGEID:%s\n", e_gw_item_get_id (item));
2637         g_string_append_printf (gstr, "X-GWRECORDID:%s\n", tmp[0]);
2638
2639         org = e_gw_item_get_organizer (item);
2640         if (org)
2641                 g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n", 
2642                                 org->display_name, org->email);
2643         
2644         gstr = g_string_append (gstr, "END:VJOURNAL\n");
2645         gstr = g_string_append (gstr, "END:VCALENDAR\n");
2646
2647         *str = g_strdup (gstr->str);
2648         *len = gstr->len;
2649
2650         g_string_free (gstr, TRUE);
2651         g_strfreev (tmp);
2652 }
2653
2654 /** End **/