1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-groupwise-folder.c: class for an groupwise folder */
6 * Sivaiah Nallagatla <snallagatla@novell.com>
7 * parthasarathi susarla <sparthasarathi@novell.com>
8 * Sankar P <psankar@novell.com>
11 * Copyright (C) 2004, Novell Inc.
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.
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.
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
38 #include <sys/types.h>
41 #include <glib/gi18n-lib.h>
43 #include <libsoup/soup-misc.h>
45 #include <libedataserver/e-msgport.h>
47 #include <e-gw-connection.h>
48 #include <e-gw-item.h>
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"
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"
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
73 static CamelOfflineFolderClass *parent_class = NULL;
75 struct _CamelGroupwiseFolderPrivate {
78 GStaticMutex search_lock; /* for locking the search object */
79 GStaticRecMutex cache_lock; /* for locking the cache object */
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 );
100 static CamelMimeMessage *
101 groupwise_folder_get_message( CamelFolder *folder, const char *uid, CamelException *ex )
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;
109 EGwConnectionStatus status;
112 CamelStream *stream, *cache_stream;
115 /* see if it is there in cache */
117 mi = (CamelGroupwiseMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
119 camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
120 _("Cannot get message: %s\n %s"), uid, _("No such message"));
123 cache_stream = camel_data_cache_get (gw_folder->cache, "cache", uid, ex);
124 stream = camel_stream_mem_new ();
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);
139 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"),
140 uid, g_strerror (errno));
141 camel_object_unref (msg);
145 camel_object_unref (cache_stream);
147 camel_object_unref (stream);
150 camel_message_info_free (&mi->info);
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);
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);
169 container_id = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name)) ;
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);
180 msg = groupwise_folder_item_to_msg (folder, item, ex);
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);
190 camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", groupwise_base_url_lookup (priv));
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);
201 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
203 camel_message_info_free (&mi->info);
204 g_free (container_id);
209 groupwise_populate_details_from_item (CamelMimeMessage *msg, EGwItem *item)
211 char *dtstring = NULL;
212 char *temp_str = NULL;
214 temp_str = (char *)e_gw_item_get_subject(item);
216 camel_mime_message_set_subject (msg, temp_str);
217 dtstring = e_gw_item_get_delivered_date (item);
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);
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);
235 groupwise_populate_msg_body_from_item (EGwConnection *cnc, CamelMultipart *multipart, EGwItem *item, char *body)
239 const char *temp_body = NULL;
241 part = camel_mime_part_new ();
242 camel_mime_part_set_encoding(part, CAMEL_TRANSFER_ENCODING_8BIT);
245 temp_body = e_gw_item_get_message (item);
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");
258 type = e_gw_item_get_item_type (item);
261 case E_GW_ITEM_TYPE_APPOINTMENT:
262 case E_GW_ITEM_TYPE_TASK:
263 case E_GW_ITEM_TYPE_NOTE:
265 char *cal_buffer = NULL;
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);
272 convert_to_note (item, &cal_buffer, &len);
274 camel_mime_part_set_content(part, cal_buffer, len, "text/calendar");
278 case E_GW_ITEM_TYPE_NOTIFICATION:
279 case E_GW_ITEM_TYPE_MAIL:
281 camel_mime_part_set_content(part, body, strlen(body), "text/html");
283 camel_mime_part_set_content(part, temp_body, strlen(temp_body), e_gw_item_get_msg_content_type (item));
285 camel_mime_part_set_content(part, " ", strlen(" "), "text/html");
293 camel_multipart_set_boundary (multipart, NULL);
294 camel_multipart_add_part (multipart, part);
295 camel_object_unref (part);
299 groupwise_msg_set_recipient_list (CamelMimeMessage *msg, EGwItem *item)
301 GSList *recipient_list;
302 EGwItemOrganizer *org;
303 struct _camel_header_address *ha;
305 struct _camel_header_address *to_list = NULL, *cc_list = NULL, *bcc_list=NULL;
307 org = e_gw_item_get_organizer (item);
308 recipient_list = e_gw_item_get_recipient_list (item);
310 if (recipient_list) {
312 char *status_opt = NULL;
315 for (rl = recipient_list ; rl != NULL ; rl = rl->next) {
316 EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
317 enabled = recp->status_enabled;
320 ha=camel_header_address_new_group(recp->display_name);
322 ha=camel_header_address_new_name(recp->display_name,recp->email);
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);
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);
339 camel_header_address_unref(ha);
341 if (recp->status_enabled) {
342 status_opt = g_strconcat (status_opt,
343 recp->display_name,";",
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 : "", ";",
357 /* README: This entire status-opt code should go away once the new status-tracking code is tested */
359 camel_medium_add_header ( CAMEL_MEDIUM (msg), "X-gw-status-opt", (const char *)status_opt);
365 subs_email=camel_header_address_list_encode(to_list);
366 camel_medium_set_header( CAMEL_MEDIUM(msg), "To", subs_email);
368 camel_header_address_list_clear(&to_list);
372 subs_email=camel_header_address_list_encode(cc_list);
373 camel_medium_set_header( CAMEL_MEDIUM(msg), "Cc", subs_email);
375 camel_header_address_list_clear(&cc_list);
379 subs_email=camel_header_address_list_encode(bcc_list);
380 camel_medium_set_header( CAMEL_MEDIUM(msg), "Bcc", subs_email);
382 camel_header_address_list_clear(&bcc_list);
386 if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
388 for (i = 0; org->display_name[i] != '<' &&
389 org->display_name[i] != '\0';
392 org->display_name[i] = '\0';
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);
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);
407 groupwise_folder_rename (CamelFolder *folder, const char *new)
409 CamelGroupwiseFolder *gw_folder = (CamelGroupwiseFolder *)folder;
410 CamelGroupwiseStore *gw_store = (CamelGroupwiseStore *) folder->parent_store;
411 CamelGroupwiseStorePrivate *priv = gw_store->priv;
413 char *folder_dir, *summary_path, *state_file, *storage_path = storage_path_lookup (priv);
416 folders = g_strconcat (storage_path, "/folders", NULL);
417 folder_dir = e_path_to_physical (folders, new);
420 summary_path = g_strdup_printf ("%s/summary", folder_dir);
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);
427 ((CamelFolderClass *)parent_class)->rename(folder, new);
428 camel_folder_summary_set_filename (folder->summary, summary_path);
430 state_file = g_strdup_printf ("%s/cmeta", folder_dir);
431 camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state_file, NULL);
434 g_free (summary_path);
439 groupwise_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
441 CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
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);
453 groupwise_folder_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
455 CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
459 return g_ptr_array_new();
461 CAMEL_GROUPWISE_FOLDER_LOCK(gw_folder, search_lock);
463 camel_folder_search_set_folder(gw_folder->search, folder);
464 matches = camel_folder_search_search(gw_folder->search, expression, uids, ex);
466 CAMEL_GROUPWISE_FOLDER_UNLOCK(gw_folder, search_lock);
472 groupwise_folder_search_free (CamelFolder *folder, GPtrArray *uids)
474 CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
476 g_return_if_fail (gw_folder->search);
478 CAMEL_GROUPWISE_FOLDER_LOCK(gw_folder, search_lock);
480 camel_folder_search_free_result (gw_folder->search, uids);
482 CAMEL_GROUPWISE_FOLDER_UNLOCK(gw_folder, search_lock);
486 /******************* functions specific to Junk Mail Handling**************/
488 free_node (EGwJunkEntry *entry)
492 g_free (entry->match);
493 g_free (entry->matchType);
494 g_free (entry->lastUsed);
495 g_free (entry->modified);
501 update_junk_list (CamelStore *store, CamelMessageInfo *info, int flag)
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);
508 if (!(from = g_strdup (camel_message_info_from (info))))
511 email = g_strsplit_set (from, "<>", -1);
513 if (!email || !email[1])
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) {
521 if (e_gw_connection_get_junk_entries (cnc, &list)== E_GW_CONNECTION_STATUS_OK){
524 if (!g_ascii_strcasecmp (entry->match, email[1])) {
525 e_gw_connection_remove_junk_entry (cnc, entry->id);
529 g_list_foreach (list, (GFunc) free_node, NULL);
539 move_to_mailbox (CamelFolder *folder, CamelMessageInfo *info, CamelException *ex)
543 const char *uid = camel_message_info_uid (info);
545 uids = g_ptr_array_new ();
546 g_ptr_array_add (uids, (gpointer) uid);
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);
551 groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
553 g_warning ("No Mailbox folder found");
555 update_junk_list (folder->parent_store, info, REMOVE_JUNK_ENTRY);
559 move_to_junk (CamelFolder *folder, CamelMessageInfo *info, CamelException *ex)
564 const char *uid = camel_message_info_uid (info);
566 uids = g_ptr_array_new ();
567 g_ptr_array_add (uids, (gpointer) uid);
569 dest = camel_store_get_folder (folder->parent_store, JUNK_FOLDER, 0, ex);
572 groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
574 fi = create_junk_folder (folder->parent_store);
575 dest = camel_store_get_folder (folder->parent_store, JUNK_FOLDER, 0, ex);
577 g_warning ("Could not get JunkFolder:Message not moved");
579 groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
581 update_junk_list (folder->parent_store, info, ADD_JUNK_ENTRY);
584 /********************* back to folder functions*************************/
587 groupwise_sync_summary (CamelFolder *folder, CamelException *ex)
589 camel_folder_summary_save (folder->summary);
590 camel_store_summary_save ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
594 groupwise_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
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;
608 GList *deleted_items, *deleted_head;
610 deleted_items = deleted_head = NULL;
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);
617 cnc = cnc_lookup (priv);
619 container_id = camel_groupwise_store_container_id_lookup (gw_store, folder->full_name) ;
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);
627 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
629 count = camel_folder_summary_count (folder->summary);
630 CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
631 for (i=0 ; i < count ; i++) {
633 info = camel_folder_summary_index (folder->summary, i);
634 gw_info = (CamelGroupwiseMessageInfo *) info;
636 /**Junk Mail handling**/
639 flags = camel_message_info_flags (info);
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);
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);
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);
661 diff.changed &= folder->permanent_flags;
663 /* weed out flag changes that we can't sync to the server */
665 camel_message_info_free(info);
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) {
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);
680 deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
682 g_list_free (deleted_head);
684 deleted_head = deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
687 if (g_list_length (deleted_items) == GROUPWISE_BULK_DELETE_LIMIT ) {
688 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
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.
696 if (deleted_read_items) {
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 */
702 status = e_gw_connection_mark_read (cnc, deleted_read_items);
703 g_list_free (deleted_read_items);
704 deleted_read_items = NULL;
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) {
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;
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);
731 camel_message_info_free (info);
734 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
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);
741 status = e_gw_connection_remove_items (cnc, container_id, deleted_items);
743 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
744 if (status == E_GW_CONNECTION_STATUS_OK) {
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;
757 g_list_free (deleted_head);
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);
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);
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);
780 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
783 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
784 groupwise_sync_summary (folder, ex);
785 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
789 camel_gw_folder_new(CamelStore *store, const char *folder_name, const char *folder_dir, CamelException *ex)
792 CamelGroupwiseFolder *gw_folder;
793 char *summary_file, *state_file, *journal_file;
797 folder = CAMEL_FOLDER (camel_object_new(camel_groupwise_folder_get_type ()) );
799 gw_folder = CAMEL_GROUPWISE_FOLDER(folder);
800 short_name = strrchr (folder_name, '/');
804 short_name = (char *) folder_name;
805 camel_folder_construct (folder, store, folder_name, short_name);
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"),
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);
822 camel_object_state_read(folder);
824 gw_folder->cache = camel_data_cache_new (folder_dir,0 ,ex);
825 if (!gw_folder->cache) {
826 camel_object_unref (folder);
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);
838 if (!strcmp (folder_name, "Mailbox")) {
839 if (camel_url_get_param (((CamelService *) store)->url, "filter"))
840 folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
843 gw_folder->search = camel_folder_search_new ();
844 if (!gw_folder->search) {
845 camel_object_unref (folder);
852 struct _folder_update_msg {
853 CamelSessionThreadMsg msg;
863 update_update (CamelSession *session, CamelSessionThreadMsg *msg)
865 struct _folder_update_msg *m = (struct _folder_update_msg *)msg;
866 EGwConnectionStatus status;
867 CamelException *ex = NULL;
869 GList *item_list, *items_full_list = NULL, *last_element=NULL;
871 const char *position = E_GW_CURSOR_POSITION_END;
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");
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);
892 if (!item_list || g_list_length (item_list) == 0)
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 */
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;
906 items_full_list = item_list;
908 position = E_GW_CURSOR_POSITION_CURRENT;
910 e_gw_connection_destroy_cursor (m->cnc, m->container_id, cursor);
912 /* Take out only the first part in the list until the @ since it is guaranteed
913 to be unique only until that symbol */
915 /*if (items_full_list) {
917 item_list = items_full_list;
919 while (item_list->next) {
921 while (((const char *)item_list->data)[i++]!='@');
922 ((char *)item_list->data)[i-1] = '\0';
923 item_list = item_list->next;
927 while (((const char *)item_list->data)[i++]!='@');
928 ((char *)item_list->data)[i-1] = '\0';
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);
936 update_free (CamelSession *session, CamelSessionThreadMsg *msg)
938 struct _folder_update_msg *m = (struct _folder_update_msg *)msg;
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);
949 static CamelSessionThreadOps update_ops = {
955 groupwise_refresh_info(CamelFolder *folder, CamelException *ex)
957 CamelGroupwiseSummary *summary = (CamelGroupwiseSummary *) folder->summary;
959 CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
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
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);
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) {
974 camel_store_summary_touch ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
976 camel_store_summary_info_free ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary, si);
978 camel_folder_summary_save (folder->summary);
979 camel_store_summary_save ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
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
984 g_print("Reloading folder...something wrong with the summary....\n");
985 gw_store_reload_folder (gw_store, folder, 0, ex);
990 groupwise_refresh_folder(CamelFolder *folder, CamelException *ex)
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;
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;
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);
1012 if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
1013 g_warning ("In offline mode. Cannot refresh!!!\n");
1017 container_id = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, folder->full_name)) ;
1019 if (!container_id) {
1020 g_warning ("\nERROR - Container id not present. Cannot refresh info for %s\n", folder->full_name);
1027 if (camel_folder_is_frozen (folder) ) {
1028 gw_folder->need_refresh = TRUE;
1031 CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
1033 if (!camel_groupwise_store_connected (gw_store, ex))
1036 if (!strcmp (folder->full_name, "Trash")) {
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."));
1044 /*groupwise_expunge (folder, ex);*/
1046 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
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);
1061 time_string = g_strdup (((CamelGroupwiseSummary *) folder->summary)->time_string);
1062 t_str = g_strdup (time_string);
1064 /*Get the New Items*/
1068 if ( !strcmp (folder->full_name, RECEIVED) || !strcmp(folder->full_name, SENT) ) {
1071 source = "sent received";
1074 status = e_gw_connection_get_quick_messages (cnc, container_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"));
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.
1086 if (summary->time_string)
1087 g_free (summary->time_string);
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);
1098 for ( sl = slist ; sl != NULL; sl = sl->next)
1099 list = g_list_append (list, sl->data);*/
1101 if (slist && g_slist_length(slist) != 0)
1104 g_slist_free (slist);
1107 t_str = g_strdup (time_string);
1109 /*Get those items which have been modifed*/
1111 status = e_gw_connection_get_quick_messages (cnc, container_id,
1113 &t_str, "Modified", NULL, source, -1, &slist);
1115 if (status != E_GW_CONNECTION_STATUS_OK) {
1116 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
1120 /* The storing of time-stamp to summary code below should be commented if the
1121 above commented code is uncommented */
1123 /* if (summary->time_string)
1124 g_free (summary->time_string);
1126 summary->time_string = g_strdup (t_str);
1128 g_free (t_str), t_str = NULL;*/
1130 for ( sl = slist ; sl != NULL; sl = sl->next)
1131 list = g_list_prepend (list, sl->data);
1133 if (!check_all && slist && g_slist_length(slist) != 0)
1136 g_slist_free (slist);
1139 if (gw_store->current_folder != folder) {
1140 gw_store->current_folder = folder;
1144 gw_update_cache (folder, list, ex, FALSE);
1149 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
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.
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));
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*/
1172 g_list_foreach (list, (GFunc) g_object_unref, NULL);
1177 g_free (time_string);
1178 g_free (container_id);
1181 CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
1186 gw_update_cache (CamelFolder *folder, GList *list, CamelException *ex, gboolean uid_flag)
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;
1205 gboolean is_proxy = folder->parent_store->flags & CAMEL_STORE_WRITE;
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);
1215 if (!strcmp (folder->full_name, JUNK_FOLDER)) {
1219 camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
1221 for ( ; item_list != NULL ; item_list = g_list_next (item_list) ) {
1222 EGwItem *temp_item ;
1224 EGwItemType type = E_GW_ITEM_TYPE_UNKNOWN;
1225 EGwItemOrganizer *org;
1226 char *temp_date = NULL;
1228 GSList *recp_list = NULL;
1229 CamelStream *cache_stream, *t_cache_stream;
1230 CamelMimeMessage *mail_msg = NULL;
1231 const char *recurrence_key = NULL;
1237 if (uid_flag == FALSE) {
1238 temp_item = (EGwItem *)item_list->data;
1239 id = e_gw_item_get_id (temp_item);
1241 id = (char *) item_list->data;
1243 camel_operation_progress (NULL, (100*i)/total_items);
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) {
1251 /************************ First populate summary *************************/
1254 pmi = camel_folder_summary_uid (folder->summary, id);
1257 camel_message_info_ref (pmi);
1258 mi = (CamelGroupwiseMessageInfo *)pmi;
1262 type = e_gw_item_get_item_type (item);
1263 if ((type == E_GW_ITEM_TYPE_CONTACT) || (type == E_GW_ITEM_TYPE_UNKNOWN)) {
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");
1275 rk = e_gw_item_get_recurrence_key (item);
1277 recurrence_key = g_strdup_printf("%d", rk);
1278 camel_message_info_set_user_tag ((CamelMessageInfo*)mi, "recurrence-key", recurrence_key);
1281 /*all items in the Junk Mail folder should have this flag set*/
1283 mi->info.flags |= CAMEL_GW_MESSAGE_JUNK;
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;
1289 mi->info.flags &= ~CAMEL_MESSAGE_SEEN;
1291 if (item_status & E_GW_ITEM_STAT_REPLIED)
1292 status_flags |= CAMEL_MESSAGE_ANSWERED;
1294 mi->info.flags |= status_flags;
1296 mi->info.flags = status_flags;
1298 priority = e_gw_item_get_priority (item);
1299 if (priority && !(g_ascii_strcasecmp (priority,"High"))) {
1300 mi->info.flags |= CAMEL_MESSAGE_FLAGGED;
1303 if (e_gw_item_has_attachment (item))
1304 mi->info.flags |= CAMEL_MESSAGE_ATTACHMENTS;
1306 mi->info.flags |= CAMEL_MESSAGE_USER_NOT_DELETABLE;
1308 mi->server_flags = mi->info.flags;
1310 org = e_gw_item_get_organizer (item);
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';
1320 org->display_name[i] = '\0';
1321 str = g_string_append (str, org->display_name);
1322 str = g_string_append (str, " ");
1325 if (org->display_name[0] == '\0') {
1327 str = g_string_append (str, org->email);
1328 str = g_string_append (str, " ");
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, ">");
1335 mi->info.from = camel_pstring_strdup (str->str);
1336 g_string_free (str, TRUE);
1338 g_string_truncate (str, 0);
1339 recp_list = e_gw_item_get_recipient_list (item);
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) {
1347 str = g_string_append (str, ", ");
1348 g_string_append_printf (str,"%s <%s>", recp->display_name, recp->email);
1353 camel_pstring_free(mi->info.to);
1354 mi->info.to = camel_pstring_strdup (str->str);
1355 g_string_truncate (str, 0);
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);
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;
1368 temp_date = e_gw_item_get_delivered_date(item);
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;
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;
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));
1390 camel_folder_change_info_change_uid (changes, mi->info.uid);
1391 camel_message_info_free (pmi);
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);
1398 /********************* Summary ends *************************/
1399 if (!strcmp (folder->full_name, "Junk Mail"))
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);
1408 mail_msg = groupwise_folder_item_to_msg (folder, item, ex);
1410 camel_medium_set_header (CAMEL_MEDIUM (mail_msg), "X-Evolution-Source", groupwise_base_url_lookup (priv));
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);
1419 camel_object_unref (mail_msg);
1420 CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
1422 /******************** Caching stuff ends *************************/
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);
1430 camel_folder_change_info_free (changes);
1434 gw_update_summary ( CamelFolder *folder, GList *list,CamelException *ex)
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;
1447 gboolean is_proxy = folder->parent_store->flags & CAMEL_STORE_WRITE;
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);
1458 if (!strcmp (folder->full_name, JUNK_FOLDER)) {
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;
1468 GSList *recp_list = NULL;
1469 const char *recurrence_key = NULL;
1473 id = e_gw_item_get_id (item);
1475 mi = (CamelGroupwiseMessageInfo *)camel_folder_summary_uid (folder->summary, id);
1480 type = e_gw_item_get_item_type (item);
1481 if ((type == E_GW_ITEM_TYPE_CONTACT) || (type == E_GW_ITEM_TYPE_UNKNOWN)) {
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");
1493 rk = e_gw_item_get_recurrence_key (item);
1495 recurrence_key = g_strdup_printf("%d", rk);
1496 camel_message_info_set_user_tag ((CamelMessageInfo*)mi, "recurrence-key", recurrence_key);
1499 /*all items in the Junk Mail folder should have this flag set*/
1501 mi->info.flags |= CAMEL_GW_MESSAGE_JUNK;
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;
1509 if (!strcmp (folder->full_name, "Trash"))
1510 status_flags |= CAMEL_MESSAGE_SEEN;
1512 mi->info.flags |= status_flags;
1515 priority = e_gw_item_get_priority (item);
1516 if (priority && !(g_ascii_strcasecmp (priority,"High"))) {
1517 mi->info.flags |= CAMEL_MESSAGE_FLAGGED;
1520 if (e_gw_item_has_attachment (item))
1521 mi->info.flags |= CAMEL_MESSAGE_ATTACHMENTS;
1524 mi->info.flags |= CAMEL_MESSAGE_USER_NOT_DELETABLE;
1526 mi->server_flags = mi->info.flags;
1528 org = e_gw_item_get_organizer (item);
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';
1538 org->display_name[i] = '\0';
1539 str = g_string_append (str, org->display_name);
1540 str = g_string_append (str, " ");
1543 if (org->display_name[0] == '\0') {
1545 str = g_string_append (str, org->email);
1546 str = g_string_append (str, " ");
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, ">");
1554 mi->info.from = camel_pstring_strdup (str->str);
1555 g_string_free (str, TRUE);
1557 g_string_truncate (str, 0);
1558 recp_list = e_gw_item_get_recipient_list (item);
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) {
1566 str = g_string_append (str, ", ");
1567 g_string_append_printf (str,"%s <%s>", recp->display_name, recp->email);
1571 mi->info.to = camel_pstring_strdup (str->str);
1572 g_string_truncate (str, 0);
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);
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;
1585 temp_date = e_gw_item_get_delivered_date(item);
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;
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;
1600 mi->info.uid = g_strdup(e_gw_item_get_id(item));
1602 mi->info.size = e_gw_item_get_mail_size (item);
1603 mi->info.subject = camel_pstring_strdup(e_gw_item_get_subject(item));
1606 camel_folder_change_info_change_uid (changes, e_gw_item_get_id (item));
1607 camel_message_info_free (&mi->info);
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);
1616 g_free (container_id);
1617 g_string_free (str, TRUE);
1618 camel_object_trigger_event (folder, "folder_changed", changes);
1620 camel_folder_change_info_free (changes);
1623 static CamelMimeMessage *
1624 groupwise_folder_item_to_msg( CamelFolder *folder,
1626 CamelException *ex )
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;
1634 EGwConnectionStatus status;
1636 CamelMultipart *multipart = NULL;
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;
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);
1651 attach_list = e_gw_item_get_attach_id_list (item);
1653 //int attach_count = g_slist_length (attach_list);
1654 GSList *al = attach_list;
1655 EGwItemAttachment *attach = (EGwItemAttachment *)al->data;
1656 char *attachment = NULL;
1659 if (!g_ascii_strcasecmp (attach->name, "Text.htm") ||
1660 !g_ascii_strcasecmp (attach->name, "Header")) {
1662 status = e_gw_connection_get_attachment (cnc,
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"));
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;
1676 }//if attachment and len
1677 } // if Mime.822 or TEXT.htm
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);
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) {
1695 temp = soup_base64_decode(t_attach, &len_iter);
1696 gstr = g_string_append_len (gstr, temp, len_iter);
1706 g_string_free (gstr, FALSE);
1708 status = e_gw_connection_get_attachment (cnc,
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"));
1716 body = g_strdup (attachment);
1718 g_free (attachment);
1720 has_mime_822 = TRUE;
1727 msg = camel_mime_message_new ();
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);
1737 multipart = camel_multipart_new ();
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");
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)) {
1749 const char *mess = e_gw_item_get_message (item);
1752 reply_within = e_gw_item_get_reply_within (item);
1757 t = e_gw_connection_get_date_from_string (reply_within);
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);
1765 value = g_strconcat (N_("Reply Requested: When convenient"), "\n\n", mess ? mess : "", NULL);
1766 e_gw_item_set_message (item, (const char *) value);
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*/
1780 gboolean has_boundary = FALSE;
1783 for (al = attach_list ; al != NULL ; al = al->next) {
1784 EGwItemAttachment *attach = (EGwItemAttachment *)al->data;
1785 char *attachment = NULL;
1787 CamelMimePart *part;
1789 is_base64_encoded = FALSE;
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"))
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");
1805 temp_msg = groupwise_folder_item_to_msg(folder, temp_item, ex);
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));
1813 camel_multipart_add_part (multipart,part);
1814 camel_object_unref (temp_msg);
1815 camel_object_unref (part);
1817 g_object_unref (temp_item);
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);
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) {
1833 temp = soup_base64_decode(t_attach, &len_iter);
1834 gstr = g_string_append_len (gstr, temp, len_iter);
1843 attachment = gstr->str;
1844 g_string_free (gstr, FALSE);
1845 is_base64_encoded = FALSE;
1847 status = e_gw_connection_get_attachment (cnc,
1849 (const char **)&attachment, &len);
1851 if (status != E_GW_CONNECTION_STATUS_OK) {
1852 g_warning ("Could not get attachment\n");
1855 if (attachment && (len !=0) ) {
1856 part = camel_mime_part_new ();
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) {
1865 t= g_strsplit_set (attach->contentid, "<>", -1);
1867 camel_mime_part_set_content_id (part, attach->contentid);
1869 camel_mime_part_set_content_id (part, t[1]);
1871 camel_mime_part_set_content_location (part, attach->name);
1874 camel_mime_part_set_filename(part, g_strdup(attach->name));
1875 camel_mime_part_set_content_id (part, attach->contentid);
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);
1885 camel_mime_part_set_content(part, attachment, len, "text/plain");
1888 camel_data_wrapper_set_mime_type(CAMEL_DATA_WRAPPER (multipart),"multipart/digest");
1890 camel_multipart_set_boundary(multipart, NULL);
1891 camel_multipart_add_part (multipart, part);
1893 camel_object_unref (part);
1894 g_free (attachment);
1895 } /* if attachment */
1899 }/* if attach_list */
1900 /********************/
1902 camel_medium_set_content_object(CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart));
1903 camel_object_unref (multipart);
1913 gw_update_all_items (CamelFolder *folder, GList *item_list, CamelException *ex)
1915 CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
1916 GPtrArray *summary = NULL;
1919 CamelFolderChangeInfo *changes = NULL;
1920 CamelMessageInfo *info;
1921 changes = camel_folder_change_info_new ();
1923 item_list = g_list_reverse (item_list);
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);
1932 temp = g_list_find_custom (item_list, (const char *)info->uid, (GCompareFunc) strcmp);
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);
1942 item_list = g_list_delete_link (item_list, temp);
1947 camel_object_trigger_event (folder, "folder_changed", changes);
1950 CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
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);
1956 g_list_foreach (item_list, (GFunc)g_free, NULL);
1957 g_list_free (item_list);
1960 camel_folder_free_summary (folder, summary);
1964 groupwise_append_message (CamelFolder *folder, CamelMimeMessage *message,
1965 const CamelMessageInfo *info, char **appended_uid,
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, };
1976 gboolean is_ok = FALSE;
1978 if (!strcmp (folder->name, RECEIVED))
1980 if(!strcmp (folder->name, SENT))
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));
1989 if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
1990 camel_groupwise_journal_append ((CamelGroupwiseJournal *) ((CamelGroupwiseFolder *)folder)->journal, message, info, appended_uid, ex);
1993 cnc = cnc_lookup (priv);
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) ;
1999 item = camel_groupwise_util_item_from_message (cnc, message, CAMEL_ADDRESS (message->from));
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);
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));
2018 *appended_uid = NULL;
2019 CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
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));
2030 *appended_uid = NULL;
2032 CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
2037 *appended_uid = g_strdup (id);
2039 CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
2043 uid_compar (const void *va, const void *vb)
2045 const char **sa = (const char **)va, **sb = (const char **)vb;
2048 a = strtoul (*sa, NULL, 10);
2049 b = strtoul (*sb, NULL, 10);
2059 groupwise_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
2060 CamelFolder *destination, GPtrArray **transferred_uids,
2061 gboolean delete_originals, CamelException *ex)
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;
2071 CamelFolderChangeInfo *changes = NULL;
2073 count = camel_folder_summary_count (destination->summary);
2074 qsort (uids->pdata, uids->len, sizeof (void *), uid_compar);
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));
2082 if (transferred_uids)
2083 *transferred_uids = NULL;
2085 if (delete_originals)
2086 source_container_id = camel_groupwise_store_container_id_lookup (gw_store, source->full_name) ;
2088 source_container_id = NULL;
2089 dest_container_id = camel_groupwise_store_container_id_lookup (gw_store, destination->full_name) ;
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;
2099 for (l = item_ids, i = 0; l; l = l->next, i++) {
2100 CamelMessageInfo *info;
2102 if (!(info = camel_folder_summary_uid (source->summary, uids->pdata[i])))
2105 if (!(message = groupwise_folder_get_message (source, camel_message_info_uid (info), ex)))
2108 camel_groupwise_journal_transfer (journal, (CamelGroupwiseFolder *)source, message, info, uids->pdata[i], NULL, ex);
2109 camel_object_unref (message);
2111 if (camel_exception_is_set (ex))
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."));
2120 camel_folder_summary_remove_uid (source->summary, uids->pdata[index]);
2121 camel_folder_change_info_remove_uid (changes, uids->pdata[index]);
2126 CAMEL_SERVICE_REC_UNLOCK (source->parent_store, connect_lock);
2131 cnc = cnc_lookup (priv);
2133 while (index < uids->len) {
2134 CamelMessageInfo *info = NULL;
2135 CamelGroupwiseMessageInfo *gw_info = NULL;
2136 flags_diff_t diff, unset_flags;
2138 count = camel_folder_summary_count (destination->summary);
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;
2147 /* sync the read changes */
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;
2154 if (diff.bits & CAMEL_MESSAGE_SEEN) {
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
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);
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.
2174 However, Remember that When a mail is deleted after being marked as unread,
2175 I am not syncing the read-status.
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);
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);
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);
2202 status = e_gw_connection_move_item (cnc, (const char *)uids->pdata[index],
2203 dest_container_id, NULL);
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]);
2210 camel_folder_summary_remove_uid (source->summary, uids->pdata[index]);
2211 camel_folder_change_info_remove_uid (changes, uids->pdata[index]);
2215 g_warning ("Warning!! Could not move item : %s\n", (char *)uids->pdata[index]);
2220 camel_object_trigger_event (source, "folder_changed", changes);
2221 camel_folder_change_info_free (changes);
2223 /* Refresh the destination folder, if its not refreshed already */
2224 if (gw_store->current_folder != destination )
2225 camel_folder_refresh_info (destination, ex);
2227 camel_folder_summary_touch (source->summary);
2228 camel_folder_summary_touch (destination->summary);
2230 gw_store->current_folder = source;
2232 CAMEL_SERVICE_REC_UNLOCK (source->parent_store, connect_lock);
2236 groupwise_expunge (CamelFolder *folder, CamelException *ex)
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;
2245 EGwConnectionStatus status;
2246 CamelFolderChangeInfo *changes;
2248 gboolean delete = FALSE;
2249 GList *deleted_items, *deleted_head;
2252 deleted_items = deleted_head = NULL;
2253 cnc = cnc_lookup (priv);
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);
2265 g_warning ("Could not Empty Trash\n");
2266 CAMEL_SERVICE_REC_UNLOCK (groupwise_store, connect_lock);
2270 changes = camel_folder_change_info_new ();
2272 container_id = g_strdup (camel_groupwise_store_container_id_lookup (groupwise_store, folder->full_name)) ;
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)) {
2281 deleted_items = g_list_prepend (deleted_items, (char *)camel_message_info_uid (info));
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));
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) {
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;
2309 camel_message_info_free (info);
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) {
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);
2330 g_list_free (deleted_head);
2334 camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes);
2336 g_free (container_id);
2337 camel_folder_change_info_free (changes);
2341 camel_groupwise_folder_class_init (CamelGroupwiseFolderClass *camel_groupwise_folder_class)
2343 CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_groupwise_folder_class);
2345 parent_class = CAMEL_OFFLINE_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_offline_folder_get_type ()));
2347 ((CamelObjectClass *) camel_groupwise_folder_class)->getv = gw_getv;
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;
2362 camel_groupwise_folder_init (gpointer object, gpointer klass)
2364 CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (object);
2365 CamelFolder *folder = CAMEL_FOLDER (object);
2368 folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED |
2369 CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN;
2371 folder->folder_flags = CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
2373 gw_folder->priv = g_malloc0 (sizeof(*gw_folder->priv));
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);
2380 gw_folder->need_rescan = TRUE;
2384 camel_groupwise_folder_finalize (CamelObject *object)
2386 CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (object);
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);
2398 camel_groupwise_folder_get_type (void)
2400 static CamelType camel_groupwise_folder_type = CAMEL_INVALID_TYPE;
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,
2411 (CamelObjectInitFunc) camel_groupwise_folder_init,
2412 (CamelObjectFinalizeFunc) camel_groupwise_folder_finalize);
2415 return camel_groupwise_folder_type;
2419 gw_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
2421 CamelFolder *folder = (CamelFolder *)object;
2425 for (i=0 ; i<args->argc ; i++) {
2426 CamelArgGet *arg = &args->argv[i];
2430 switch (tag & CAMEL_ARG_TAG) {
2432 case CAMEL_OBJECT_ARG_DESCRIPTION:
2433 if (folder->description == NULL) {
2434 CamelURL *uri = ((CamelService *)folder->parent_store)->url;
2436 folder->description = g_strdup_printf("%s@%s:%s", uri->user, uri->host, folder->full_name);
2438 *arg->ca_str = folder->description;
2445 arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
2449 return ((CamelObjectClass *)parent_class)->getv(object, ex, args);
2456 convert_to_calendar (EGwItem *item, char **str, int *len)
2458 EGwItemOrganizer *org = NULL;
2459 GSList *recp_list = NULL;
2460 GSList *attach_list = NULL;
2461 GString *gstr = g_string_new (NULL);
2464 const char *temp = NULL;
2466 tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
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");
2472 if ((recur_key = e_gw_item_get_recurrence_key (item)) != 0) {
2473 char *recur_k = g_strdup_printf ("%d", recur_key);
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);
2480 g_string_append_printf (gstr, "UID:%s\n",e_gw_item_get_icalid (item));
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));
2486 temp = e_gw_item_get_message (item);
2488 g_string_append(gstr, "DESCRIPTION:");
2491 g_string_append(gstr, "\\n");
2493 g_string_append_c(gstr, *temp);
2496 g_string_append(gstr, "\n");
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]);
2504 org = e_gw_item_get_organizer (item);
2506 g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
2507 org->display_name, org->email);
2509 recp_list = e_gw_item_get_recipient_list (item);
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);
2521 g_string_append_printf (gstr, "DTEND:%s\n", e_gw_item_get_end_date (item));
2524 temp = e_gw_item_get_place (item);
2526 g_string_append_printf (gstr, "LOCATION:%s\n", temp);
2529 temp = e_gw_item_get_task_priority (item);
2531 g_string_append_printf (gstr, "PRIORITY:%s\n", temp);
2534 attach_list = e_gw_item_get_attach_id_list (item);
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);
2543 gstr = g_string_append (gstr, "END:VEVENT\n");
2544 gstr = g_string_append (gstr, "END:VCALENDAR\n");
2549 g_string_free (gstr, FALSE);
2554 convert_to_task (EGwItem *item, char **str, int *len)
2556 EGwItemOrganizer *org = NULL;
2557 GSList *recp_list = NULL;
2558 GString *gstr = g_string_new (NULL);
2560 const char *temp = NULL;
2562 tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
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]);
2576 org = e_gw_item_get_organizer (item);
2578 g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
2579 org->display_name, org->email);
2581 recp_list = e_gw_item_get_recipient_list (item);
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);
2593 g_string_append_printf (gstr, "DTEND:%s\n", e_gw_item_get_end_date (item));
2595 temp = e_gw_item_get_place (item);
2597 g_string_append_printf (gstr, "LOCATION:%s\n", temp);
2600 temp = e_gw_item_get_task_priority (item);
2602 g_string_append_printf (gstr, "PRIORITY:%s\n", temp);
2605 temp = e_gw_item_get_due_date (item);
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");
2612 *str = g_strdup (gstr->str);
2615 g_string_free (gstr, TRUE);
2620 convert_to_note (EGwItem *item, char **str, int *len)
2622 EGwItemOrganizer *org = NULL;
2623 GString *gstr = g_string_new (NULL);
2626 tmp = g_strsplit (e_gw_item_get_id (item), "@", -1);
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]);
2639 org = e_gw_item_get_organizer (item);
2641 g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
2642 org->display_name, org->email);
2644 gstr = g_string_append (gstr, "END:VJOURNAL\n");
2645 gstr = g_string_append (gstr, "END:VCALENDAR\n");
2647 *str = g_strdup (gstr->str);
2650 g_string_free (gstr, TRUE);