talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit bc958116c87c67dc7e5e27d649c7dc1bfce2c926
parent a45deacf14b838a5bb50cf502eecc42f8e58ce3b
Author: Colin Leroy <colin@colino.net>
Date:   Tue, 12 Feb 2008 17:24:48 +0000

2008-02-12 [colin]	3.3.0cvs11

	* src/imap.c
	* src/etpan/imap-thread.c
	* src/etpan/imap-thread.h
		Fix handling of $Forwarded flag on Exchange:
		check for the existence or creatability of a
		flag before using it.

Diffstat:
MChangeLog | 9+++++++++
MPATCHSETS | 1+
Mconfigure.ac | 2+-
Msrc/etpan/imap-thread.c | 39++++++++++++++++++++++++++++++++++++---
Msrc/etpan/imap-thread.h | 13++++++++++++-
Msrc/imap.c | 112+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
6 files changed, 126 insertions(+), 50 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,12 @@ +2008-02-12 [colin] 3.3.0cvs11 + + * src/imap.c + * src/etpan/imap-thread.c + * src/etpan/imap-thread.h + Fix handling of $Forwarded flag on Exchange: + check for the existence or creatability of a + flag before using it. + 2008-02-12 [colin] 3.3.0cvs10 * src/matcher.c diff --git a/PATCHSETS b/PATCHSETS @@ -3224,3 +3224,4 @@ ( cvs diff -u -r 1.87.2.54 -r 1.87.2.55 src/folder.h; ) > 3.3.0cvs8.patchset ( cvs diff -u -r 1.207.2.195 -r 1.207.2.196 src/folderview.c; ) > 3.3.0cvs9.patchset ( cvs diff -u -r 1.75.2.54 -r 1.75.2.55 src/matcher.c; ) > 3.3.0cvs10.patchset +( cvs diff -u -r 1.179.2.209 -r 1.179.2.210 src/imap.c; cvs diff -u -r 1.1.4.96 -r 1.1.4.97 src/etpan/imap-thread.c; cvs diff -u -r 1.1.4.23 -r 1.1.4.24 src/etpan/imap-thread.h; ) > 3.3.0cvs11.patchset diff --git a/configure.ac b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=3 MICRO_VERSION=0 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=10 +EXTRA_VERSION=11 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/etpan/imap-thread.c b/src/etpan/imap-thread.c @@ -1326,7 +1326,8 @@ static void select_run(struct etpan_thread_op * op) int imap_threaded_select(Folder * folder, const char * mb, gint * exists, gint * recent, gint * unseen, - guint32 * uid_validity,gint *can_create_flags) + guint32 * uid_validity,gint *can_create_flags, + GSList **ok_flags) { struct select_param param; struct select_result result; @@ -1353,9 +1354,10 @@ int imap_threaded_select(Folder * folder, const char * mb, * can_create_flags = FALSE; if (imap->imap_selection_info->sel_perm_flags) { + GSList *t_flags = NULL; clistiter *cur = clist_begin(imap->imap_selection_info->sel_perm_flags); - for (; cur && !(*can_create_flags); cur = clist_next(cur)) { + for (; cur; cur = clist_next(cur)) { struct mailimap_flag_perm *flag = (struct mailimap_flag_perm *)clist_content(cur); if (flag->fl_type == MAILIMAP_FLAG_PERM_ALL) *can_create_flags = TRUE; @@ -1363,8 +1365,39 @@ int imap_threaded_select(Folder * folder, const char * mb, flag->fl_flag->fl_type == 6 && !strcmp(flag->fl_flag->fl_data.fl_extension, "*")) *can_create_flags = TRUE; - + if (ok_flags) { + MsgPermFlags c_flag = 0; + switch (flag->fl_flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + c_flag = IMAP_FLAG_ANSWERED; + break; + case MAILIMAP_FLAG_FLAGGED: + c_flag = IMAP_FLAG_FLAGGED; + break; + case MAILIMAP_FLAG_DELETED: + c_flag = IMAP_FLAG_DELETED; + break; + case MAILIMAP_FLAG_DRAFT: + c_flag = IMAP_FLAG_DRAFT; + break; + case MAILIMAP_FLAG_SEEN: + c_flag = IMAP_FLAG_SEEN; + break; + case MAILIMAP_FLAG_KEYWORD: + if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "$Forwarded")) + c_flag = IMAP_FLAG_FORWARDED; + break; + default: + break; + } + if (c_flag != 0) { + t_flags = g_slist_prepend(t_flags, + GUINT_TO_POINTER(c_flag)); + } + } } + if (ok_flags) + *ok_flags = t_flags; } debug_print("imap select - end\n"); diff --git a/src/etpan/imap-thread.h b/src/etpan/imap-thread.h @@ -26,6 +26,16 @@ #define IMAP_SET_MAX_COUNT 500 +typedef enum +{ + IMAP_FLAG_SEEN = 1 << 0, + IMAP_FLAG_ANSWERED = 1 << 1, + IMAP_FLAG_FLAGGED = 1 << 2, + IMAP_FLAG_DELETED = 1 << 3, + IMAP_FLAG_DRAFT = 1 << 4, + IMAP_FLAG_FORWARDED = 1 << 5 +} IMAPFlags; + void imap_main_set_timeout(int sec); void imap_main_init(gboolean skip_ssl_cert_check); void imap_main_done(void); @@ -70,7 +80,8 @@ int imap_threaded_rename(Folder * folder, int imap_threaded_delete(Folder * folder, const char * mb); int imap_threaded_select(Folder * folder, const char * mb, gint * exists, gint * recent, gint * unseen, - guint32 * uid_validity, gint * can_create_flags); + guint32 * uid_validity, gint * can_create_flags, + GSList **ok_flags); int imap_threaded_examine(Folder * folder, const char * mb, gint * exists, gint * recent, gint * unseen, guint32 * uid_validity); diff --git a/src/imap.c b/src/imap.c @@ -131,16 +131,6 @@ struct _IMAPNameSpace #define IMAPBUFSIZE 8192 -typedef enum -{ - IMAP_FLAG_SEEN = 1 << 0, - IMAP_FLAG_ANSWERED = 1 << 1, - IMAP_FLAG_FLAGGED = 1 << 2, - IMAP_FLAG_DELETED = 1 << 3, - IMAP_FLAG_DRAFT = 1 << 4, - IMAP_FLAG_FORWARDED = 1 << 5 -} IMAPFlags; - #define IMAP_IS_SEEN(flags) ((flags & IMAP_FLAG_SEEN) != 0) #define IMAP_IS_ANSWERED(flags) ((flags & IMAP_FLAG_ANSWERED) != 0) #define IMAP_IS_FLAGGED(flags) ((flags & IMAP_FLAG_FLAGGED) != 0) @@ -181,6 +171,7 @@ struct _IMAPFolderItem GHashTable *tags_set_table; GHashTable *tags_unset_table; + GSList *ok_flags; }; @@ -290,6 +281,7 @@ static void imap_set_batch (Folder *folder, FolderItem *item, gboolean batch); static gint imap_set_message_flags (IMAPSession *session, + IMAPFolderItem *item, MsgNumberList *numlist, IMAPFlags flags, GSList *tags, @@ -346,6 +338,7 @@ static gint imap_cmd_select (IMAPSession *session, gint *unseen, guint32 *uid_validity, gint *can_create_flags, + GSList **ok_flags, gboolean block); static gint imap_cmd_close (IMAPSession *session); static gint imap_cmd_examine (IMAPSession *session, @@ -368,6 +361,7 @@ static gint imap_cmd_fetch (IMAPSession *sock, gboolean headers, gboolean body); static gint imap_cmd_append (IMAPSession *session, + IMAPFolderItem *item, const gchar *destfolder, const gchar *file, IMAPFlags flags, @@ -379,6 +373,7 @@ static gint imap_cmd_copy (IMAPSession *session, struct mailimap_set ** source, struct mailimap_set ** dest); static gint imap_cmd_store (IMAPSession *session, + IMAPFolderItem *item, struct mailimap_set * set, IMAPFlags flags, GSList *tags, @@ -429,7 +424,7 @@ static void imap_flags_hash_from_lep_uid_flags_tab(carray * list, static MsgInfo *imap_envelope_from_lep(struct imap_fetch_env_info * info, FolderItem *item); static void imap_lep_set_free(GSList *seq_list); -static struct mailimap_flag_list * imap_flag_to_lep(IMAPFlags flags, GSList *tags); +static struct mailimap_flag_list * imap_flag_to_lep(IMAPFolderItem *item, IMAPFlags flags, GSList *tags); typedef struct _hashtable_data { GSList *msglist; @@ -1348,7 +1343,8 @@ static void imap_commit_tags(FolderItem *item, MsgInfo *msginfo, GSList *tags_se list_set = g_slist_prepend(list_set, g_strdup(str)); } if (list_set) { - ok = imap_set_message_flags(session, &numlist, 0, list_set, TRUE); + ok = imap_set_message_flags(session, + IMAP_FOLDER_ITEM(item), &numlist, 0, list_set, TRUE); slist_free_strings(list_set); g_slist_free(list_set); if (ok != MAILIMAP_NO_ERROR) { @@ -1362,7 +1358,8 @@ static void imap_commit_tags(FolderItem *item, MsgInfo *msginfo, GSList *tags_se list_unset = g_slist_prepend(list_unset, g_strdup(str)); } if (list_unset) { - ok = imap_set_message_flags(session, &numlist, 0, list_unset, FALSE); + ok = imap_set_message_flags(session, + IMAP_FOLDER_ITEM(item), &numlist, 0, list_unset, FALSE); slist_free_strings(list_unset); g_slist_free(list_unset); if (ok != MAILIMAP_NO_ERROR) { @@ -1614,7 +1611,7 @@ static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, folder_has_parent_of_type(dest, F_TRASH)) iflags |= IMAP_FLAG_SEEN; - ok = imap_cmd_append(session, destdir, real_file, iflags, + ok = imap_cmd_append(session, IMAP_FOLDER_ITEM(dest), destdir, real_file, iflags, &new_uid); if (ok != MAILIMAP_NO_ERROR) { @@ -1963,7 +1960,7 @@ static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest, if (numlist != NULL) { ok = imap_set_message_flags - (session, numlist, IMAP_FLAG_DELETED, NULL, TRUE); + (session, IMAP_FOLDER_ITEM(msginfo->folder), numlist, IMAP_FLAG_DELETED, NULL, TRUE); if (ok != MAILIMAP_NO_ERROR) { log_warning(LOG_PROTOCOL, _("can't set deleted flags\n")); return ok; @@ -3124,6 +3121,7 @@ static gchar *imap_get_real_path(IMAPSession *session, IMAPFolder *folder, const } static gint imap_set_message_flags(IMAPSession *session, + IMAPFolderItem *item, MsgNumberList *numlist, IMAPFlags flags, GSList *tags, @@ -3160,7 +3158,7 @@ static gint imap_set_message_flags(IMAPSession *session, statusbar_progress_all(set_item->set_first, total, 1); - ok = imap_cmd_store(session, imapset, + ok = imap_cmd_store(session, item, imapset, flags, tags, is_set); statusbar_progress_all(set_item->set_last, total, 1); if (ok != MAILIMAP_NO_ERROR && folder->max_set_size > 20) { @@ -3238,8 +3236,11 @@ static gint imap_select(IMAPSession *session, IMAPFolder *folder, real_path = imap_get_real_path(session, folder, path); + g_slist_free(IMAP_FOLDER_ITEM(item)->ok_flags); + IMAP_FOLDER_ITEM(item)->ok_flags = NULL; ok = imap_cmd_select(session, real_path, - exists, recent, unseen, uid_validity, can_create_flags, block); + exists, recent, unseen, uid_validity, can_create_flags, + &(IMAP_FOLDER_ITEM(item)->ok_flags), block); if (ok != MAILIMAP_NO_ERROR) { log_warning(LOG_PROTOCOL, _("can't select folder: %s\n"), real_path); } else { @@ -3490,12 +3491,12 @@ static gint imap_cmd_starttls(IMAPSession *session) static gint imap_cmd_select(IMAPSession *session, const gchar *folder, gint *exists, gint *recent, gint *unseen, guint32 *uid_validity, gint *can_create_flags, - gboolean block) + GSList **ok_flags, gboolean block) { int r; r = imap_threaded_select(session->folder, folder, - exists, recent, unseen, uid_validity, can_create_flags); + exists, recent, unseen, uid_validity, can_create_flags, ok_flags); if (r != MAILIMAP_NO_ERROR) { imap_handle_error(SESSION(session), r); debug_print("select err %d\n", r); @@ -3643,7 +3644,9 @@ static gint imap_cmd_fetch(IMAPSession *session, guint32 uid, } -static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder, +static gint imap_cmd_append(IMAPSession *session, + IMAPFolderItem *item, + const gchar *destfolder, const gchar *file, IMAPFlags flags, guint32 *new_uid) { @@ -3652,7 +3655,7 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder, g_return_val_if_fail(file != NULL, MAILIMAP_ERROR_BAD_STATE); - flag_list = imap_flag_to_lep(flags, NULL); + flag_list = imap_flag_to_lep(item, flags, NULL); lock_session(session); r = imap_threaded_append(session->folder, destfolder, file, flag_list, (int *)new_uid); @@ -3688,14 +3691,16 @@ static gint imap_cmd_copy(IMAPSession *session, struct mailimap_set * set, return MAILIMAP_NO_ERROR; } -static gint imap_cmd_store(IMAPSession *session, struct mailimap_set * set, +static gint imap_cmd_store(IMAPSession *session, + IMAPFolderItem *item, + struct mailimap_set * set, IMAPFlags flags, GSList *tags, int do_add) { int r; struct mailimap_flag_list * flag_list = NULL; struct mailimap_store_att_flags * store_att_flags; - flag_list = imap_flag_to_lep(flags, tags); + flag_list = imap_flag_to_lep(item, flags, tags); if (do_add) store_att_flags = @@ -4269,14 +4274,14 @@ void imap_change_flags(Folder *folder, FolderItem *item, MsgInfo *msginfo, MsgPe } else { debug_print("IMAP changing flags\n"); if (flags_set) { - ok = imap_set_message_flags(session, &numlist, flags_set, NULL, TRUE); + ok = imap_set_message_flags(session, IMAP_FOLDER_ITEM(item), &numlist, flags_set, NULL, TRUE); if (ok != MAILIMAP_NO_ERROR) { return; } } if (flags_unset) { - ok = imap_set_message_flags(session, &numlist, flags_unset, NULL, FALSE); + ok = imap_set_message_flags(session, IMAP_FOLDER_ITEM(item), &numlist, flags_unset, NULL, FALSE); if (ok != MAILIMAP_NO_ERROR) { return; } @@ -4310,7 +4315,7 @@ static gint imap_remove_msg(Folder *folder, FolderItem *item, gint uid) numlist.data = GINT_TO_POINTER(uid); ok = imap_set_message_flags - (session, &numlist, IMAP_FLAG_DELETED, NULL, TRUE); + (session, IMAP_FOLDER_ITEM(item), &numlist, IMAP_FLAG_DELETED, NULL, TRUE); if (ok != MAILIMAP_NO_ERROR) { log_warning(LOG_PROTOCOL, _("can't set deleted flags: %d\n"), uid); return ok; @@ -4357,6 +4362,19 @@ static guint gslist_find_next_num(MsgNumberList **list, guint num) return elem != NULL ? GPOINTER_TO_INT(elem->data) : (gint)-1; } +static gboolean flag_ok(IMAPFolderItem *item, guint flag) +{ + if (item->ok_flags && g_slist_find(item->ok_flags, GUINT_TO_POINTER(flag))) { + debug_print("flag %d is OK\n", flag); + return TRUE; + } + if (item->can_create_flags == ITEM_CAN_CREATE_FLAGS) { + debug_print("creating flags is OK\n"); + return TRUE; + } + return FALSE; +} + /* * NEW and DELETED flags are not syncronized * - The NEW/RECENT flags in IMAP folders can not really be directly @@ -4491,18 +4509,20 @@ static /*gint*/ void *imap_get_flags_thread(void *data) goto bail; } - r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_FORWARDED, - full_search ? NULL:imapset, &lep_uidlist); - if (r == MAILIMAP_NO_ERROR) { - GSList * uidlist; + if (flag_ok(IMAP_FOLDER_ITEM(fitem), IMAP_FLAG_FORWARDED)) { + r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_FORWARDED, + full_search ? NULL:imapset, &lep_uidlist); + if (r == MAILIMAP_NO_ERROR) { + GSList * uidlist; - uidlist = imap_uid_list_from_lep(lep_uidlist); - mailimap_search_result_free(lep_uidlist); + uidlist = imap_uid_list_from_lep(lep_uidlist); + mailimap_search_result_free(lep_uidlist); - forwarded = g_slist_concat(forwarded, uidlist); - } else { - imap_handle_error(SESSION(session), r); - goto bail; + forwarded = g_slist_concat(forwarded, uidlist); + } else { + imap_handle_error(SESSION(session), r); + goto bail; + } } r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_DELETED, @@ -4719,7 +4739,8 @@ static gboolean process_flags(gpointer key, gpointer value, gpointer user_data) NULL, NULL, NULL, NULL, NULL, FALSE); } if (ok == MAILIMAP_NO_ERROR) { - ok = imap_set_message_flags(session, data->msglist, flags_value, NULL, flags_set); + ok = imap_set_message_flags(session, IMAP_FOLDER_ITEM(item), + data->msglist, flags_value, NULL, flags_set); } else { g_warning("can't select mailbox %s\n", item->path); } @@ -4761,7 +4782,8 @@ static gboolean process_tags(gpointer key, gpointer value, gpointer user_data) GSList list; list.data = str; list.next = NULL; - ok = imap_set_message_flags(session, data->msglist, 0, &list, tags_set); + ok = imap_set_message_flags(session, IMAP_FOLDER_ITEM(item), + data->msglist, 0, &list, tags_set); } else { g_warning("can't select mailbox %s\n", item->path); } @@ -5152,29 +5174,29 @@ static void imap_lep_set_free(GSList *seq_list) g_slist_free(seq_list); } -static struct mailimap_flag_list * imap_flag_to_lep(IMAPFlags flags, GSList *tags) +static struct mailimap_flag_list * imap_flag_to_lep(IMAPFolderItem *item, IMAPFlags flags, GSList *tags) { struct mailimap_flag_list * flag_list; GSList *cur = tags; flag_list = mailimap_flag_list_new_empty(); - if (IMAP_IS_SEEN(flags)) + if (IMAP_IS_SEEN(flags) && flag_ok(item, IMAP_FLAG_SEEN)) mailimap_flag_list_add(flag_list, mailimap_flag_new_seen()); - if (IMAP_IS_ANSWERED(flags)) + if (IMAP_IS_ANSWERED(flags) && flag_ok(item, IMAP_FLAG_ANSWERED)) mailimap_flag_list_add(flag_list, mailimap_flag_new_answered()); - if (IMAP_IS_FLAGGED(flags)) + if (IMAP_IS_FLAGGED(flags) && flag_ok(item, IMAP_FLAG_FLAGGED)) mailimap_flag_list_add(flag_list, mailimap_flag_new_flagged()); - if (IMAP_IS_DELETED(flags)) + if (IMAP_IS_DELETED(flags) && flag_ok(item, IMAP_FLAG_DELETED)) mailimap_flag_list_add(flag_list, mailimap_flag_new_deleted()); - if (IMAP_IS_DRAFT(flags)) + if (IMAP_IS_DRAFT(flags) && flag_ok(item, IMAP_FLAG_DRAFT)) mailimap_flag_list_add(flag_list, mailimap_flag_new_draft()); - if (IMAP_IS_FORWARDED(flags)) + if (IMAP_IS_FORWARDED(flags) && flag_ok(item, IMAP_FLAG_FORWARDED)) mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$Forwarded")));