static gint maildir_folder_cmp_uids (CamelFolder *folder, const gchar *uid1, const gchar *uid2) { CamelMessageInfo *a, *b; time_t tma, tmb; g_return_val_if_fail (folder != NULL, 0); g_return_val_if_fail (folder->summary != NULL, 0); a = camel_folder_summary_uid (folder->summary, uid1); b = camel_folder_summary_uid (folder->summary, uid2); g_return_val_if_fail (a != NULL, 0); g_return_val_if_fail (b != NULL, 0); tma = camel_message_info_date_received (a); tmb = camel_message_info_date_received (b); camel_message_info_free (a); camel_message_info_free (b); return tma < tmb ? -1 : tma == tmb ? 0 : 1; }
static int groupwise_entry_play_transfer (CamelOfflineJournal *journal, CamelGroupwiseJournalEntry *entry, CamelException *ex) { CamelGroupwiseFolder *gw_folder = (CamelGroupwiseFolder *) journal->folder; CamelFolder *folder = journal->folder; CamelGroupwiseMessageInfo *real; CamelMessageInfoBase *info; GPtrArray *xuids, *uids; CamelException lex; CamelFolder *src; const char *name; if (!(info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, entry->uid))) { /* Note: this should never happen, but rather than crash lets make a new info */ info = camel_message_info_new (NULL); } name = camel_groupwise_store_folder_lookup ((CamelGroupwiseStore *) folder->parent_store, entry->source_container); if (name && (src = camel_store_get_folder (folder->parent_store, name, 0, ex))) { uids = g_ptr_array_sized_new (1); g_ptr_array_add (uids, entry->original_uid); camel_exception_init (&lex); camel_folder_transfer_messages_to (src, uids, folder, &xuids, FALSE, &lex); if (!camel_exception_is_set (&lex)) { real = (CamelGroupwiseMessageInfo *) camel_folder_summary_uid (folder->summary, xuids->pdata[0]); /* transfer all the system flags, user flags/tags, etc */ gw_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info); camel_message_info_free (real); } else { camel_exception_xfer (ex, &lex); goto exception; } g_ptr_array_free (xuids, TRUE); g_ptr_array_free (uids, TRUE); camel_object_unref (src); } else if (!name) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get folder container %s"), entry->source_container); goto exception; } /* message was successfully transferred, remove the fake item from the cache/summary */ camel_folder_summary_remove_uid (folder->summary, entry->uid); camel_data_cache_remove (gw_folder->cache, "cache", entry->uid, NULL); camel_message_info_free (info); return 0; exception: camel_message_info_free (info); return -1; }
/** * camel_imap_message_cache_new: * @path: directory to use for storage * @summary: CamelFolderSummary for the folder we are caching * @ex: a CamelException * * Return value: a new CamelImapMessageCache object using @path for * storage. If cache files already exist in @path, then any that do not * correspond to messages in @summary will be deleted. **/ CamelImapMessageCache * camel_imap_message_cache_new (const char *path, CamelFolderSummary *summary, CamelException *ex) { CamelImapMessageCache *cache; GDir *dir; const char *dname; char *uid, *p; GPtrArray *deletes; CamelMessageInfo *info; GError *error = NULL; dir = g_dir_open (path, 0, &error); if (!dir) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not open cache directory: %s"), error->message); g_error_free (error); return NULL; } cache = (CamelImapMessageCache *)camel_object_new (CAMEL_IMAP_MESSAGE_CACHE_TYPE); cache->path = g_strdup (path); cache->parts = g_hash_table_new (g_str_hash, g_str_equal); cache->cached = g_hash_table_new (NULL, NULL); deletes = g_ptr_array_new (); while ((dname = g_dir_read_name (dir))) { if (!isdigit (dname[0])) continue; p = strchr (dname, '.'); if (p) uid = g_strndup (dname, p - dname); else uid = g_strdup (dname); info = camel_folder_summary_uid (summary, uid); if (info) { camel_message_info_free(info); cache_put (cache, uid, dname, NULL); } else g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, dname)); g_free (uid); } g_dir_close (dir); while (deletes->len) { g_unlink (deletes->pdata[0]); g_free (deletes->pdata[0]); g_ptr_array_remove_index_fast (deletes, 0); } g_ptr_array_free (deletes, TRUE); return cache; }
static const gchar * vee_info_user_tag (const CamelMessageInfo *mi, const gchar *id) { CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); const gchar *ret; HANDLE_NULL_INFO(""); ret = camel_message_info_user_tag (rmi, id); camel_message_info_free (rmi); return ret; }
static time_t vee_info_time (const CamelMessageInfo *mi, gint id) { CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); time_t ret; HANDLE_NULL_INFO (0); ret = camel_message_info_time (rmi, id); camel_message_info_free (rmi); return ret; }
static gconstpointer vee_info_ptr (const CamelMessageInfo *mi, gint id) { CamelVeeMessageInfo *vmi = (CamelVeeMessageInfo *) mi; CamelMessageInfo *rmi; gpointer p; rmi = camel_folder_summary_uid (vmi->summary, mi->uid+8); HANDLE_NULL_INFO (NULL); p = (gpointer) camel_message_info_ptr (rmi, id); camel_message_info_free (rmi); return p; }
static gboolean vee_info_set_user_tag (CamelMessageInfo *mi, const gchar *name, const gchar *value) { gint res = FALSE; if (mi->uid) { CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); HANDLE_NULL_INFO (FALSE); res = camel_message_info_set_user_tag (rmi, name, value); camel_message_info_free (rmi); } return res; }
static void imap4_fetch_all_add (struct imap4_fetch_all_t *fetch) { CamelFolderChangeInfo *changes = NULL; struct imap4_envelope_t *envelope; CamelMessageInfo *info; int i; changes = fetch->changes; for (i = 0; i < fetch->added->len; i++) { if (!(envelope = fetch->added->pdata[i])) { courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first); break; } if (envelope->changed != IMAP4_FETCH_ALL) { d(fprintf (stderr, "Hmmm, IMAP4 server didn't give us everything for message %d\n", i + 1)); camel_message_info_free (envelope->info); g_free (envelope); continue; } if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) { camel_message_info_free (envelope->info); camel_message_info_free (info); g_free (envelope); continue; } camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info)); if ((((CamelMessageInfoBase *) envelope->info)->flags & CAMEL_IMAP4_MESSAGE_RECENT)) camel_folder_change_info_recent_uid (changes, camel_message_info_uid (envelope->info)); camel_folder_summary_add (fetch->summary, envelope->info); g_free (envelope); } g_ptr_array_free (fetch->added, TRUE); g_hash_table_destroy (fetch->uid_hash); if (camel_folder_change_info_changed (changes)) camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes); camel_folder_change_info_free (changes); g_free (fetch); }
static int groupwise_entry_play_append (CamelOfflineJournal *journal, CamelGroupwiseJournalEntry *entry, CamelException *ex) { CamelGroupwiseFolder *gw_folder = (CamelGroupwiseFolder *) journal->folder; CamelFolder *folder = journal->folder; CamelMimeMessage *message; CamelMessageInfo *info; CamelStream *stream; CamelException lex; /* if the message isn't in the cache, the user went behind our backs so "not our problem" */ if (!gw_folder->cache || !(stream = camel_data_cache_get (gw_folder->cache, "cache", entry->uid, ex))) goto done; message = camel_mime_message_new (); if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) { camel_object_unref (message); camel_object_unref (stream); goto done; } camel_object_unref (stream); if (!(info = camel_folder_summary_uid (folder->summary, entry->uid))) { /* Note: this should never happen, but rather than crash lets make a new info */ info = camel_message_info_new (NULL); } camel_exception_init (&lex); camel_folder_append_message (folder, message, info, NULL, &lex); camel_message_info_free (info); camel_object_unref (message); if (camel_exception_is_set (&lex)) { camel_exception_xfer (ex, &lex); return -1; } done: camel_folder_summary_remove_uid (folder->summary, entry->uid); camel_data_cache_remove (gw_folder->cache, "cache", entry->uid, NULL); return 0; }
static gboolean vee_info_set_user_flag (CamelMessageInfo *mi, const gchar *name, gboolean value) { gint res = FALSE; gboolean hacked_unread_folder = FALSE; CamelVeeFolder *vf = (CamelVeeFolder *)mi->summary->folder; if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", camel_folder_get_full_name (mi->summary->folder), g_strescape (vf->expression, "")); if (camel_vee_folder_get_unread_vfolder (vf) == -1) camel_vee_summary_load_check_unread_vfolder (CAMEL_VEE_SUMMARY (mi->summary)); if (camel_vee_folder_get_unread_vfolder (vf) == 1) hacked_unread_folder = TRUE; if (mi->uid) { CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); HANDLE_NULL_INFO (FALSE); if (hacked_unread_folder) camel_vee_folder_mask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); res = camel_message_info_set_user_flag (rmi, name, value); if (hacked_unread_folder) camel_vee_folder_unmask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); camel_message_info_free (rmi); } return res; }
static gchar * maildir_folder_get_filename (CamelFolder *folder, const gchar *uid, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *)folder; CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; gchar *res; /* get the message summary info */ if ((info = camel_folder_summary_uid (folder->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); return NULL; } mdi = (CamelMaildirMessageInfo *)info; /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess If filename is NULL, it means folder_summary_check is not yet executed. */ if (!camel_maildir_info_filename (mdi)) { gchar *temp; temp = camel_maildir_summary_info_to_name (mdi); res = g_strdup_printf("%s/cur/%s", lf->folder_path, temp); g_free (temp); } else res = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); camel_message_info_free (info); return res; }
static guint32 imap4_fetch_all_update (struct imap4_fetch_all_t *fetch) { CamelIMAP4MessageInfo *iinfo, *new_iinfo; CamelFolderChangeInfo *changes = NULL; struct imap4_envelope_t *envelope; CamelMessageInfo *info; guint32 first = 0; guint32 flags; int total, i; changes = fetch->changes; total = camel_folder_summary_count (fetch->summary); for (i = 0; i < total; i++) { info = camel_folder_summary_index (fetch->summary, i); if (!(envelope = g_hash_table_lookup (fetch->uid_hash, camel_message_info_uid (info)))) { /* remove it */ camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); camel_folder_summary_remove (fetch->summary, info); total--; i--; } else if (envelope->changed & IMAP4_FETCH_FLAGS) { /* update it with the new flags */ new_iinfo = (CamelIMAP4MessageInfo *) envelope->info; iinfo = (CamelIMAP4MessageInfo *) info; flags = iinfo->info.flags; iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, new_iinfo->server_flags); iinfo->server_flags = new_iinfo->server_flags; if (iinfo->info.flags != flags) camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); } camel_message_info_free (info); } for (i = 0; i < fetch->added->len; i++) { if (!(envelope = fetch->added->pdata[i])) { courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first); break; } info = envelope->info; if (!first && camel_message_info_uid (info)) { if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (info)))) { camel_message_info_free(info); } else { first = i + fetch->first; } } camel_message_info_free(envelope->info); g_free (envelope); } g_ptr_array_free (fetch->added, TRUE); g_hash_table_destroy (fetch->uid_hash); if (camel_folder_change_info_changed (changes)) camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes); camel_folder_change_info_free (changes); g_free (fetch); return first; }
static gboolean vee_info_set_flags (CamelMessageInfo *mi, guint32 flags, guint32 set) { gint res = FALSE; CamelVeeFolder *vf = (CamelVeeFolder *)mi->summary->folder; gboolean hacked_unread_folder = FALSE; if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", camel_folder_get_full_name (mi->summary->folder), g_strescape (vf->expression, "")); if (camel_vee_folder_get_unread_vfolder (vf) == -1) camel_vee_summary_load_check_unread_vfolder (CAMEL_VEE_SUMMARY (mi->summary)); if (camel_vee_folder_get_unread_vfolder (vf) == 1) hacked_unread_folder = TRUE; if (mi->uid) { guint32 old_visible, visible, old_unread; CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); CamelVeeSummary *vsummary = (CamelVeeSummary *)mi->summary; HANDLE_NULL_INFO (FALSE); old_visible = rmi->summary->visible_count; old_unread = mi->summary->unread_count; camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), TRUE); if (hacked_unread_folder) camel_vee_folder_mask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); camel_folder_freeze (rmi->summary->folder); res = camel_message_info_set_flags (rmi, flags, set); ((CamelVeeMessageInfo *) mi)->old_flags = camel_message_info_flags (rmi); camel_folder_thaw (rmi->summary->folder); if (hacked_unread_folder) camel_vee_folder_unmask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); visible = rmi->summary->visible_count; /* Keep the summary in sync */ camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), FALSE); if (hacked_unread_folder && !vsummary->fake_visible_count) vsummary->fake_visible_count = mi->summary->visible_count; if (vsummary->fake_visible_count || hacked_unread_folder) vsummary->fake_visible_count += visible - old_visible; d(printf("VF %d %d %d %d %d\n", mi->summary->unread_count, mi->summary->deleted_count, mi->summary->junk_count, mi->summary->junk_not_deleted_count, mi->summary->visible_count)); /* This is where the ugly-created-hack is used */ if (hacked_unread_folder && mi->summary->unread_count - old_unread != 0) { CamelFolderChangeInfo *changes = camel_folder_change_info_new (); GPtrArray *match, *array; camel_folder_change_info_change_uid (changes, mi->uid); array = g_ptr_array_new (); g_ptr_array_add (array, (gpointer)rmi->uid); match = camel_folder_search_by_uids (rmi->summary->folder, vf->expression, array, NULL); if ((match && !match->len) || !match) { vsummary->fake_visible_count--; } else { vsummary->fake_visible_count++; } g_ptr_array_free (array, TRUE); if (match) camel_folder_search_free (rmi->summary->folder, match); camel_folder_changed (mi->summary->folder, changes); camel_folder_change_info_free (changes); } camel_message_info_free (rmi); } return res; }
static gboolean maildir_folder_transfer_messages_to_sync (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, gboolean delete_originals, GPtrArray **transferred_uids, GCancellable *cancellable, GError **error) { gboolean fallback = FALSE; if (delete_originals && CAMEL_IS_MAILDIR_FOLDER (source) && CAMEL_IS_MAILDIR_FOLDER (dest)) { gint i; CamelLocalFolder *lf = (CamelLocalFolder *) source; CamelLocalFolder *df = (CamelLocalFolder *) dest; camel_operation_push_message ( cancellable, _("Moving messages")); camel_folder_freeze (dest); camel_folder_freeze (source); for (i = 0; i < uids->len; i++) { gchar *uid = (gchar *) uids->pdata[i]; gchar *s_filename, *d_filename, *tmp; CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; if ((info = camel_folder_summary_uid (source->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); return FALSE; } mdi = (CamelMaildirMessageInfo *) info; tmp = camel_maildir_summary_info_to_name (mdi); d_filename = g_strdup_printf ("%s/cur/%s", df->folder_path, tmp); g_free (tmp); s_filename = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); if (g_rename (s_filename, d_filename) != 0) { if (errno == EXDEV) { i = uids->len + 1; fallback = TRUE; } else { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Cannot transfer message to destination folder: %s"), g_strerror (errno)); camel_message_info_free (info); break; } } else { camel_folder_set_message_flags ( source, uid, CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN, ~0); camel_folder_summary_remove (source->summary, info); } camel_message_info_free (info); g_free (s_filename); g_free (d_filename); } camel_folder_thaw (source); camel_folder_thaw (dest); camel_operation_pop_message (cancellable); } else fallback = TRUE; if (fallback) { CamelFolderClass *folder_class; /* Chain up to parent's transfer_messages_to() method. */ folder_class = CAMEL_FOLDER_CLASS (camel_maildir_folder_parent_class); return folder_class->transfer_messages_to_sync ( source, uids, dest, delete_originals, transferred_uids, cancellable, error); } return TRUE; }