X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Fprocmsg.c;h=461c0c9d89aa7d7b40c602bb381eab62d8e26100;hp=c141f09264fcefa10b9d96463e6a7cf31d2ecdf2;hb=8bd1d905d643bdb7b71dd9db298bae35399c05fc;hpb=0d249e3c4087f8fc608f47922d7c3888b56b3b76 diff --git a/src/procmsg.c b/src/procmsg.c index c141f0926..461c0c9d8 100644 --- a/src/procmsg.c +++ b/src/procmsg.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * Copyright (C) 1999-2002 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,6 +34,12 @@ #include "folder.h" #include "prefs_common.h" #include "account.h" +#if USE_GPGME +# include "rfc2015.h" +#endif +#include "alertpanel.h" +#include "news.h" +#include "imap.h" typedef struct _FlagInfo FlagInfo; @@ -43,15 +49,8 @@ struct _FlagInfo MsgFlags flags; }; -static void mark_sum_func (gpointer key, - gpointer value, - gpointer data); - static GHashTable *procmsg_read_mark_file (const gchar *folder); -static gint procmsg_cmp_msgnum (gconstpointer a, - gconstpointer b); -static gint procmsg_cmp_flag_msgnum (gconstpointer a, - gconstpointer b); +void procmsg_msginfo_write_flags (MsgInfo *msginfo); GHashTable *procmsg_msg_hash_table_create(GSList *mlist) @@ -178,13 +177,14 @@ GSList *procmsg_read_cache(FolderItem *item, gboolean scan_file) default_flags.perm_flags = MSG_NEW|MSG_UNREAD; default_flags.tmp_flags = MSG_CACHED; - if (type == F_MH) { + if (type == F_MH || type == F_IMAP) { if (item->stype == F_QUEUE) { MSG_SET_TMP_FLAGS(default_flags, MSG_QUEUED); } else if (item->stype == F_DRAFT) { MSG_SET_TMP_FLAGS(default_flags, MSG_DRAFT); } - } else if (type == F_IMAP) { + } + if (type == F_IMAP) { MSG_SET_TMP_FLAGS(default_flags, MSG_IMAP); } else if (type == F_NEWS) { MSG_SET_TMP_FLAGS(default_flags, MSG_NEWS); @@ -201,7 +201,7 @@ GSList *procmsg_read_cache(FolderItem *item, gboolean scan_file) g_free(path); } cache_file = folder_item_get_cache_file(item); - if ((fp = fopen(cache_file, "r")) == NULL) { + if ((fp = fopen(cache_file, "rb")) == NULL) { debug_print(_("\tNo cache file\n")); g_free(cache_file); return NULL; @@ -220,7 +220,7 @@ GSList *procmsg_read_cache(FolderItem *item, gboolean scan_file) } while (fread(&num, sizeof(num), 1, fp) == 1) { - msginfo = g_new0(MsgInfo, 1); + msginfo = procmsg_msginfo_new(); msginfo->msgnum = num; READ_CACHE_DATA_INT(msginfo->size, fp); READ_CACHE_DATA_INT(msginfo->mtime, fp); @@ -238,6 +238,8 @@ GSList *procmsg_read_cache(FolderItem *item, gboolean scan_file) READ_CACHE_DATA(msginfo->msgid, fp); READ_CACHE_DATA(msginfo->inreplyto, fp); READ_CACHE_DATA(msginfo->references, fp); + READ_CACHE_DATA(msginfo->xref, fp); + MSG_SET_PERM_FLAGS(msginfo->flags, default_flags.perm_flags); MSG_SET_TMP_FLAGS(msginfo->flags, default_flags.tmp_flags); @@ -332,14 +334,12 @@ void procmsg_set_flags(GSList *mlist, FolderItem *item) g_hash_table_destroy(mark_table); } -gint procmsg_get_last_num_in_cache(GSList *mlist) +gint procmsg_get_last_num_in_msg_list(GSList *mlist) { GSList *cur; MsgInfo *msginfo; gint last = 0; - if (mlist == NULL) return 0; - for (cur = mlist; cur != NULL; cur = cur->next) { msginfo = (MsgInfo *)cur->data; if (msginfo && msginfo->msgnum > last) @@ -382,6 +382,8 @@ void procmsg_write_cache(MsgInfo *msginfo, FILE *fp) WRITE_CACHE_DATA(msginfo->msgid, fp); WRITE_CACHE_DATA(msginfo->inreplyto, fp); WRITE_CACHE_DATA(msginfo->references, fp); + WRITE_CACHE_DATA(msginfo->xref, fp); + } void procmsg_write_flags(MsgInfo *msginfo, FILE *fp) @@ -392,45 +394,66 @@ void procmsg_write_flags(MsgInfo *msginfo, FILE *fp) WRITE_CACHE_DATA_INT(flags, fp); } -struct MarkSum { - gint *new; - gint *unread; - gint *total; -}; - -static void mark_sum_func(gpointer key, gpointer value, gpointer data) +void procmsg_flush_mark_queue(FolderItem *item, FILE *fp) { - MsgFlags *flags = value; - struct MarkSum *marksum = data; + MsgInfo *flaginfo; - if (MSG_IS_NEW(*flags) && !MSG_IS_IGNORE_THREAD(*flags)) (*marksum->new)++; - if (MSG_IS_UNREAD(*flags) && !MSG_IS_IGNORE_THREAD(*flags)) (*marksum->unread)++; - (*marksum->total)++; + g_return_if_fail(item != NULL); + g_return_if_fail(fp != NULL); - g_free(flags); + while (item->mark_queue != NULL) { + flaginfo = (MsgInfo *)item->mark_queue->data; + procmsg_write_flags(flaginfo, fp); + procmsg_msginfo_free(flaginfo); + item->mark_queue = g_slist_remove(item->mark_queue, flaginfo); + } } -void procmsg_get_mark_sum(const gchar *folder, - gint *new, gint *unread, gint *total) +void procmsg_add_flags(FolderItem *item, gint num, MsgFlags flags) { - GHashTable *mark_table; - struct MarkSum marksum; + FILE *fp; + gchar *path; + MsgInfo msginfo; - *new = *unread = *total = 0; - marksum.new = new; - marksum.unread = unread; - marksum.total = total; + g_return_if_fail(item != NULL); + + if (item->opened) { + MsgInfo *queue_msginfo; + + queue_msginfo = g_new0(MsgInfo, 1); + queue_msginfo->msgnum = num; + queue_msginfo->flags = flags; + item->mark_queue = g_slist_append + (item->mark_queue, queue_msginfo); + return; + } - mark_table = procmsg_read_mark_file(folder); + path = folder_item_get_path(item); + g_return_if_fail(path != NULL); - if (mark_table) { - g_hash_table_foreach(mark_table, mark_sum_func, &marksum); - g_hash_table_destroy(mark_table); + if ((fp = procmsg_open_mark_file(path, TRUE)) == NULL) { + g_warning(_("can't open mark file\n")); + g_free(path); + return; } - debug_print("mark->new = %d, mark->unread = %d, mark->total = %d\n", - *(marksum.new), *(marksum.unread), *(marksum.total)); + g_free(path); + + msginfo.msgnum = num; + msginfo.flags = flags; + + procmsg_write_flags(&msginfo, fp); + fclose(fp); } +struct MarkSum { + gint *new; + gint *unread; + gint *total; + gint *min; + gint *max; + gint first; +}; + static GHashTable *procmsg_read_mark_file(const gchar *folder) { FILE *fp; @@ -445,12 +468,20 @@ static GHashTable *procmsg_read_mark_file(const gchar *folder) mark_table = g_hash_table_new(NULL, g_direct_equal); while (fread(&num, sizeof(num), 1, fp) == 1) { - if (fread(&perm_flags, sizeof(flags), 1, fp) != 1) break; + if (fread(&perm_flags, sizeof(perm_flags), 1, fp) != 1) break; + + flags = g_hash_table_lookup(mark_table, GUINT_TO_POINTER(num)); + if (flags != NULL) + g_free(flags); flags = g_new0(MsgFlags, 1); flags->perm_flags = perm_flags; - - g_hash_table_insert(mark_table, GUINT_TO_POINTER(num), flags); + + if(!MSG_IS_REALLY_DELETED(*flags)) { + g_hash_table_insert(mark_table, GUINT_TO_POINTER(num), flags); + } else { + g_hash_table_remove(mark_table, GUINT_TO_POINTER(num)); + } } fclose(fp); @@ -465,7 +496,7 @@ FILE *procmsg_open_mark_file(const gchar *folder, gboolean append) markfile = g_strconcat(folder, G_DIR_SEPARATOR_S, MARK_FILE, NULL); - if ((fp = fopen(markfile, "r")) == NULL) + if ((fp = fopen(markfile, "rb")) == NULL) debug_print(_("Mark file not found.\n")); else if (fread(&ver, sizeof(ver), 1, fp) != 1 || MARK_VERSION != ver) { debug_print(_("Mark version is different (%d != %d). " @@ -483,12 +514,12 @@ FILE *procmsg_open_mark_file(const gchar *folder, gboolean append) if (fp) { /* reopen with append mode */ fclose(fp); - if ((fp = fopen(markfile, "a")) == NULL) + if ((fp = fopen(markfile, "ab")) == NULL) g_warning(_("Can't open mark file with append mode.\n")); } else { /* open with overwrite mode if mark file doesn't exist or version is different */ - if ((fp = fopen(markfile, "w")) == NULL) + if ((fp = fopen(markfile, "wb")) == NULL) g_warning(_("Can't open mark file with write mode.\n")); else { ver = MARK_VERSION; @@ -509,6 +540,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist) MsgInfo *msginfo; const gchar *msgid; const gchar *subject; + GNode *found_subject; root = g_node_new(NULL); msgid_table = g_hash_table_new(g_str_hash, g_str_equal); @@ -523,8 +555,8 @@ GNode *procmsg_get_thread_tree(GSList *mlist) if (parent == NULL) { parent = root; } else { - if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) { - MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD); + if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0); } } } @@ -536,10 +568,20 @@ GNode *procmsg_get_thread_tree(GSList *mlist) g_hash_table_insert(msgid_table, (gchar *)msgid, node); subject = msginfo->subject; - if (subject_table_lookup(subject_table, - (gchar *) subject) == NULL) - subject_table_insert(subject_table, (gchar *)subject, + found_subject = subject_table_lookup(subject_table, + (gchar *) subject); + if (found_subject == NULL) + subject_table_insert(subject_table, (gchar *) subject, node); + else { + /* replace if msg in table is older than current one + * can add here more stuff. */ + if ( ((MsgInfo*)(found_subject->data))->date_t > + ((MsgInfo*)(node->data))->date_t ) { + subject_table_remove(subject_table, (gchar *) subject); + subject_table_insert(subject_table, (gchar *) subject, node); + } + } } /* complete the unfinished threads */ @@ -554,8 +596,8 @@ GNode *procmsg_get_thread_tree(GSList *mlist) g_node_insert_before (parent, parent->children, node); /* CLAWS: ignore thread */ - if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) { - MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD); + if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0); } } node = next; @@ -585,8 +627,8 @@ GNode *procmsg_get_thread_tree(GSList *mlist) g_node_unlink(node); g_node_append(parent, node); /* CLAWS: ignore thread */ - if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) { - MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD); + if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0); } } } @@ -604,14 +646,9 @@ void procmsg_move_messages(GSList *mlist) GSList *cur, *movelist = NULL; MsgInfo *msginfo; FolderItem *dest = NULL; - GHashTable *hash; if (!mlist) return; - hash = procmsg_to_folder_hash_table_create(mlist); - folder_item_scan_foreach(hash); - g_hash_table_destroy(hash); - for (cur = mlist; cur != NULL; cur = cur->next) { msginfo = (MsgInfo *)cur->data; if (!dest) { @@ -639,13 +676,17 @@ void procmsg_copy_messages(GSList *mlist) GSList *cur, *copylist = NULL; MsgInfo *msginfo; FolderItem *dest = NULL; - GHashTable *hash; if (!mlist) return; + /* + + Horrible: Scanning 2 times for every copy! + hash = procmsg_to_folder_hash_table_create(mlist); folder_item_scan_foreach(hash); g_hash_table_destroy(hash); + */ for (cur = mlist; cur != NULL; cur = cur->next) { msginfo = (MsgInfo *)cur->data; @@ -710,7 +751,13 @@ FILE *procmsg_open_message(MsgInfo *msginfo) file = procmsg_get_message_file_path(msginfo); g_return_val_if_fail(file != NULL, NULL); - if ((fp = fopen(file, "r")) == NULL) { + if (!is_file_exist(file)) { + g_free(file); + file = procmsg_get_message_file(msginfo); + g_return_val_if_fail(file != NULL, NULL); + } + + if ((fp = fopen(file, "rb")) == NULL) { FILE_OP_ERROR(file, "fopen"); g_free(file); return NULL; @@ -728,6 +775,52 @@ FILE *procmsg_open_message(MsgInfo *msginfo) return fp; } +#if USE_GPGME +FILE *procmsg_open_message_decrypted(MsgInfo *msginfo, MimeInfo **mimeinfo) +{ + FILE *fp; + MimeInfo *mimeinfo_; + + g_return_val_if_fail(msginfo != NULL, NULL); + + if (mimeinfo) *mimeinfo = NULL; + + if ((fp = procmsg_open_message(msginfo)) == NULL) return NULL; + + mimeinfo_ = procmime_scan_mime_header(fp); + if (!mimeinfo_) { + fclose(fp); + return NULL; + } + + if (!MSG_IS_ENCRYPTED(msginfo->flags) && + rfc2015_is_encrypted(mimeinfo_)) { + MSG_SET_TMP_FLAGS(msginfo->flags, MSG_ENCRYPTED); + } + + if (MSG_IS_ENCRYPTED(msginfo->flags) && + !msginfo->plaintext_file && + !msginfo->decryption_failed) { + rfc2015_decrypt_message(msginfo, mimeinfo_, fp); + if (msginfo->plaintext_file && + !msginfo->decryption_failed) { + fclose(fp); + procmime_mimeinfo_free_all(mimeinfo_); + if ((fp = procmsg_open_message(msginfo)) == NULL) + return NULL; + mimeinfo_ = procmime_scan_mime_header(fp); + if (!mimeinfo_) { + fclose(fp); + return NULL; + } + } + } + + if (mimeinfo) *mimeinfo = mimeinfo_; + return fp; +} +#endif + gboolean procmsg_msg_exist(MsgInfo *msginfo) { gchar *path; @@ -750,39 +843,122 @@ void procmsg_empty_trash(void) for (cur = folder_get_list(); cur != NULL; cur = cur->next) { trash = FOLDER(cur->data)->trash; - if (trash) folder_item_remove_all_msg(trash); + if (trash && trash->total > 0) + folder_item_remove_all_msg(trash); } } -gint procmsg_send_queue(void) +gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs) { - FolderItem *queue; - gint i; gint ret = 0; + GSList *list, *elem; - queue = folder_get_default_queue(); + if (!queue) + queue = folder_get_default_queue(); g_return_val_if_fail(queue != NULL, -1); + folder_item_scan(queue); - if (queue->last_num < 0) return -1; - else if (queue->last_num == 0) return 0; + list = folder_item_get_msg_list(queue); - for (i = 1; i <= queue->last_num; i++) { + + for(elem = list; elem != NULL; elem = elem->next) { gchar *file; + MsgInfo *msginfo; + + msginfo = (MsgInfo *)(elem->data); - file = folder_item_fetch_msg(queue, i); + file = folder_item_fetch_msg(queue, msginfo->msgnum); if (file) { if (procmsg_send_message_queue(file) < 0) { - g_warning(_("Sending queued message %d failed.\n"), i); + g_warning(_("Sending queued message %d failed.\n"), msginfo->msgnum); ret = -1; - } else - folder_item_remove_msg(queue, i); + } else { + /* CLAWS: + * We save in procmsg_send_message_queue because + * we need the destination folder from the queue + * header + + if (save_msgs) + procmsg_save_to_outbox + (queue->folder->outbox, + file, TRUE); +*/ + folder_item_remove_msg(queue, msginfo->msgnum); + } g_free(file); } + procmsg_msginfo_free(msginfo); } + folderview_update_item(queue, FALSE); + return ret; } +gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file, + gboolean is_queued) +{ + gint num; + FILE *fp; + MsgInfo *msginfo; + + debug_print("saving sent message...\n"); + + if (!outbox) + outbox = folder_get_default_outbox(); + g_return_val_if_fail(outbox != NULL, -1); + + /* remove queueing headers */ + if (is_queued) { + gchar tmp[MAXPATHLEN + 1]; + gchar buf[BUFFSIZE]; + FILE *outfp; + + g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.out.%08x", + get_rc_dir(), G_DIR_SEPARATOR, (guint)random()); + if ((fp = fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + return -1; + } + if ((outfp = fopen(tmp, "wb")) == NULL) { + FILE_OP_ERROR(tmp, "fopen"); + fclose(fp); + return -1; + } + while (fgets(buf, sizeof(buf), fp) != NULL) + if (buf[0] == '\r' || buf[0] == '\n') break; + while (fgets(buf, sizeof(buf), fp) != NULL) + fputs(buf, outfp); + fclose(outfp); + fclose(fp); + + folder_item_scan(outbox); + if ((num = folder_item_add_msg(outbox, tmp, TRUE)) < 0) { + g_warning("can't save message\n"); + unlink(tmp); + return -1; + } + } else { + folder_item_scan(outbox); + if ((num = folder_item_add_msg(outbox, file, FALSE)) < 0) { + g_warning("can't save message\n"); + return -1; + } + return -1; + } + msginfo = folder_item_fetch_msginfo(outbox, num); + if(msginfo != NULL) { + procmsg_msginfo_unset_flags(msginfo, ~0, ~0); + procmsg_msginfo_free(msginfo); + } + + if(is_queued) { + unlink(file); + } + + return 0; +} + void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline) { static const gchar *def_cmd = "lpr %s"; @@ -802,7 +978,7 @@ void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline) prtmp = g_strdup_printf("%s%cprinttmp.%08x", get_mime_tmp_dir(), G_DIR_SEPARATOR, id++); - if ((prfp = fopen(prtmp, "w")) == NULL) { + if ((prfp = fopen(prtmp, "wb")) == NULL) { FILE_OP_ERROR(prtmp, "fopen"); g_free(prtmp); fclose(tmpfp); @@ -841,6 +1017,23 @@ void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline) system(buf); } +MsgInfo *procmsg_msginfo_new_ref(MsgInfo *msginfo) +{ + msginfo->refcnt++; + + return msginfo; +} + +MsgInfo *procmsg_msginfo_new() +{ + MsgInfo *newmsginfo; + + newmsginfo = g_new0(MsgInfo, 1); + newmsginfo->refcnt = 1; + + return newmsginfo; +} + MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo) { MsgInfo *newmsginfo; @@ -849,6 +1042,8 @@ MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo) newmsginfo = g_new0(MsgInfo, 1); + newmsginfo->refcnt = 1; + #define MEMBCOPY(mmb) newmsginfo->mmb = msginfo->mmb #define MEMBDUP(mmb) newmsginfo->mmb = msginfo->mmb ? \ g_strdup(msginfo->mmb) : NULL @@ -869,6 +1064,7 @@ MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo) MEMBDUP(subject); MEMBDUP(msgid); MEMBDUP(inreplyto); + MEMBDUP(xref); MEMBCOPY(folder); MEMBCOPY(to_folder); @@ -888,6 +1084,10 @@ void procmsg_msginfo_free(MsgInfo *msginfo) { if (msginfo == NULL) return; + msginfo->refcnt--; + if(msginfo->refcnt > 0) + return; + g_free(msginfo->fromspace); g_free(msginfo->references); g_free(msginfo->returnreceiptto); @@ -904,19 +1104,46 @@ void procmsg_msginfo_free(MsgInfo *msginfo) g_free(msginfo->subject); g_free(msginfo->msgid); g_free(msginfo->inreplyto); + g_free(msginfo->xref); g_free(msginfo); } -static gint procmsg_cmp_msgnum(gconstpointer a, gconstpointer b) +guint procmsg_msginfo_memusage(MsgInfo *msginfo) { - const MsgInfo *msginfo = a; - const guint msgnum = GPOINTER_TO_UINT(b); - - if (!msginfo) - return -1; - - return msginfo->msgnum - msgnum; + guint memusage = 0; + + memusage += sizeof(MsgInfo); + if(msginfo->fromname) + memusage += strlen(msginfo->fromname); + if(msginfo->date) + memusage += strlen(msginfo->date); + if(msginfo->from) + memusage += strlen(msginfo->from); + if(msginfo->to) + memusage += strlen(msginfo->to); + if(msginfo->cc) + memusage += strlen(msginfo->cc); + if(msginfo->newsgroups) + memusage += strlen(msginfo->newsgroups); + if(msginfo->subject) + memusage += strlen(msginfo->subject); + if(msginfo->msgid) + memusage += strlen(msginfo->msgid); + if(msginfo->inreplyto) + memusage += strlen(msginfo->inreplyto); + if(msginfo->xface) + memusage += strlen(msginfo->xface); + if(msginfo->dispositionnotificationto) + memusage += strlen(msginfo->dispositionnotificationto); + if(msginfo->returnreceiptto) + memusage += strlen(msginfo->returnreceiptto); + if(msginfo->references) + memusage += strlen(msginfo->references); + if(msginfo->fromspace) + memusage += strlen(msginfo->fromspace); + + return memusage; } gint procmsg_cmp_msgnum_for_sort(gconstpointer a, gconstpointer b) @@ -932,25 +1159,16 @@ gint procmsg_cmp_msgnum_for_sort(gconstpointer a, gconstpointer b) return msginfo1->msgnum - msginfo2->msgnum; } -static gint procmsg_cmp_flag_msgnum(gconstpointer a, gconstpointer b) -{ - const FlagInfo *finfo = a; - const guint msgnum = GPOINTER_TO_UINT(b); - - if (!finfo) - return -1; - - return finfo->msgnum - msgnum; -} - enum { - Q_SENDER = 0, - Q_SMTPSERVER = 1, - Q_RECIPIENTS = 2, - Q_NEWSGROUPS = 3, - Q_MAIL_ACCOUNT_ID = 4, - Q_NEWS_ACCOUNT_ID = 5 + Q_SENDER = 0, + Q_SMTPSERVER = 1, + Q_RECIPIENTS = 2, + Q_NEWSGROUPS = 3, + Q_MAIL_ACCOUNT_ID = 4, + Q_NEWS_ACCOUNT_ID = 5, + Q_SAVE_COPY_FOLDER = 6, + Q_REPLY_MESSAGE_ID = 7, }; gint procmsg_send_message_queue(const gchar *file) @@ -961,6 +1179,8 @@ gint procmsg_send_message_queue(const gchar *file) {"NG:", NULL, FALSE}, {"MAID:", NULL, FALSE}, {"NAID:", NULL, FALSE}, + {"SCF:", NULL, FALSE}, + {"RMID:", NULL, FALSE}, {NULL, NULL, FALSE}}; FILE *fp; gint filepos; @@ -969,14 +1189,16 @@ gint procmsg_send_message_queue(const gchar *file) gchar *smtpserver = NULL; GSList *to_list = NULL; GSList *newsgroup_list = NULL; + gchar *savecopyfolder = NULL; + gchar *replymessageid = NULL; gchar buf[BUFFSIZE]; gint hnum; PrefsAccount *mailac = NULL, *newsac = NULL; - gchar *tmp = NULL; + int local = 0; g_return_val_if_fail(file != NULL, -1); - if ((fp = fopen(file, "r")) == NULL) { + if ((fp = fopen(file, "rb")) == NULL) { FILE_OP_ERROR(file, "fopen"); return -1; } @@ -1004,43 +1226,29 @@ gint procmsg_send_message_queue(const gchar *file) case Q_NEWS_ACCOUNT_ID: newsac = account_find_from_id(atoi(p)); break; - default: + case Q_SAVE_COPY_FOLDER: + if (!savecopyfolder) savecopyfolder = g_strdup(p); + break; + case Q_REPLY_MESSAGE_ID: + if (!replymessageid) replymessageid = g_strdup(p); + break; } } filepos = ftell(fp); - if(newsgroup_list || prefs_common.savemsg) { - FILE *tmpfp; - - /* write to temporary file */ - tmp = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(), - G_DIR_SEPARATOR, (gint)file); - if ((tmpfp = fopen(tmp, "w")) == NULL) { - FILE_OP_ERROR(tmp, "fopen"); - newsval = -1; - } - if (change_file_mode_rw(tmpfp, tmp) < 0) { - FILE_OP_ERROR(tmp, "chmod"); - g_warning(_("can't change file mode\n")); - } - - while ((newsval == 0) && fgets(buf, sizeof(buf), fp) != NULL) { - if (fputs(buf, tmpfp) == EOF) { - FILE_OP_ERROR(tmp, "fputs"); - newsval = -1; - } - } - fclose(tmpfp); - } - fseek(fp, filepos, SEEK_SET); if (to_list) { debug_print(_("Sending message by mail\n")); if(!from) { g_warning(_("Queued message header is broken.\n")); mailval = -1; + } else if (mailac && mailac->use_mail_command && + mailac->mail_command && (* mailac->mail_command)) { + mailval = send_message_local(mailac->mail_command, fp); + local = 1; } else if (prefs_common.use_extsend && prefs_common.extsend_cmd) { mailval = send_message_local(prefs_common.extsend_cmd, fp); + local = 1; } else { if (!mailac) { mailac = account_find_from_smtp_server(from, smtpserver); @@ -1065,71 +1273,234 @@ gint procmsg_send_message_queue(const gchar *file) mailval = send_message_smtp(&tmp_ac, to_list, fp); } } + if (mailval < 0) { + if (!local) + alertpanel_error( + _("Error occurred while sending the message to `%s'."), + mailac ? mailac->smtp_server : smtpserver); + else + alertpanel_error( + _("Error occurred while sending the message with command `%s'."), + (mailac && mailac->use_mail_command && + mailac->mail_command && (*mailac->mail_command)) ? + mailac->mail_command : prefs_common.extsend_cmd); + } } - if(newsgroup_list) { + if(newsgroup_list && (newsval == 0)) { Folder *folder; + gchar *tmp = NULL; + FILE *tmpfp; + + /* write to temporary file */ + tmp = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(), + G_DIR_SEPARATOR, (gint)file); + if ((tmpfp = fopen(tmp, "wb")) == NULL) { + FILE_OP_ERROR(tmp, "fopen"); + newsval = -1; + alertpanel_error(_("Could not create temporary file for news sending.")); + } else { + if (change_file_mode_rw(tmpfp, tmp) < 0) { + FILE_OP_ERROR(tmp, "chmod"); + g_warning(_("can't change file mode\n")); + } + + while ((newsval == 0) && fgets(buf, sizeof(buf), fp) != NULL) { + if (fputs(buf, tmpfp) == EOF) { + FILE_OP_ERROR(tmp, "fputs"); + newsval = -1; + alertpanel_error(_("Error when writing temporary file for news sending.")); + } + } + fclose(tmpfp); - debug_print(_("Sending message by news\n")); + if(newsval == 0) { + debug_print(_("Sending message by news\n")); - folder = FOLDER(newsac->folder); + folder = FOLDER(newsac->folder); - if(newsval == 0) { - newsval = news_post(folder, tmp); - if (newsval < 0) { - alertpanel_error(_("Error occurred while posting the message to %s ."), - newsac->nntp_server); - } + newsval = news_post(folder, tmp); + if (newsval < 0) { + alertpanel_error(_("Error occurred while posting the message to %s ."), + newsac->nntp_server); + } + } + unlink(tmp); } - + g_free(tmp); } + slist_free_strings(to_list); + g_slist_free(to_list); + slist_free_strings(newsgroup_list); + g_slist_free(newsgroup_list); + g_free(from); + g_free(smtpserver); + fclose(fp); + /* save message to outbox */ - if (mailval == 0 && newsval == 0 && prefs_common.savemsg) { + if (mailval == 0 && newsval == 0 && savecopyfolder) { FolderItem *outbox; - gchar *path; - gint num; - FILE *fp; debug_print(_("saving sent message...\n")); - outbox = folder_get_default_outbox(); - path = folder_item_get_path(outbox); - if (!is_dir_exist(path)) - make_dir_hier(path); + outbox = folder_find_item_from_identifier(savecopyfolder); + if(!outbox) + outbox = folder_get_default_outbox(); - folder_item_scan(outbox); - if ((num = folder_item_add_msg(outbox, tmp, FALSE)) < 0) { - g_warning(_("can't save message\n")); - } + procmsg_save_to_outbox(outbox, file, TRUE); + } - if(num) { - if ((fp = procmsg_open_mark_file(path, TRUE)) == NULL) - g_warning(_("can't open mark file\n")); - else { - MsgInfo newmsginfo; + if(replymessageid != NULL) { + gchar **tokens; + FolderItem *item; + + tokens = g_strsplit(replymessageid, "\x7f", 0); + item = folder_find_item_from_identifier(tokens[0]); + if(item != NULL) { + MsgInfo *msginfo; + + msginfo = folder_item_fetch_msginfo(item, atoi(tokens[1])); + if((msginfo != NULL) && (strcmp(msginfo->msgid, tokens[2]) != 0)) { + procmsg_msginfo_free(msginfo); + msginfo = NULL; + } + + if(msginfo == NULL) { + msginfo = folder_item_fetch_msginfo_by_id(item, tokens[2]); + } + + if(msginfo != NULL) { + procmsg_msginfo_unset_flags(msginfo, MSG_FORWARDED, 0); + procmsg_msginfo_set_flags(msginfo, MSG_REPLIED, 0); - newmsginfo.msgnum = num; - newmsginfo.flags.perm_flags = 0; - newmsginfo.flags.tmp_flags = 0; - procmsg_write_flags(&newmsginfo, fp); - fclose(fp); + procmsg_msginfo_free(msginfo); } } - g_free(path); + g_strfreev(tokens); } - slist_free_strings(to_list); - g_slist_free(to_list); - slist_free_strings(newsgroup_list); - g_slist_free(newsgroup_list); - g_free(from); - g_free(smtpserver); - fclose(fp); - if(tmp) { - unlink(tmp); - g_free(tmp); + g_free(savecopyfolder); + g_free(replymessageid); + + return (newsval != 0 ? newsval : mailval); +} + +#define CHANGE_FLAGS(msginfo) \ +{ \ +if (msginfo->folder->folder->change_flags != NULL) \ +msginfo->folder->folder->change_flags(msginfo->folder->folder, \ + msginfo->folder, \ + msginfo); \ +} + +void procmsg_msginfo_set_flags(MsgInfo *msginfo, MsgPermFlags perm_flags, MsgTmpFlags tmp_flags) +{ + gboolean changed = FALSE; + FolderItem *item = msginfo->folder; + + debug_print(_("Setting flags for message %d in folder %s\n"), msginfo->msgnum, item->path); + + /* if new flag is set */ + if((perm_flags & MSG_NEW) && !MSG_IS_NEW(msginfo->flags) && + !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + item->new++; + changed = TRUE; } - return (newsval != 0 ? newsval : mailval); + /* if unread flag is set */ + if((perm_flags & MSG_UNREAD) && !MSG_IS_UNREAD(msginfo->flags) && + !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + item->unread++; + changed = TRUE; + } + + /* if ignore thread flag is set */ + if((perm_flags & MSG_IGNORE_THREAD) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + if(MSG_IS_NEW(msginfo->flags) || (perm_flags & MSG_NEW)) { + item->new--; + changed = TRUE; + } + if(MSG_IS_UNREAD(msginfo->flags) || (perm_flags & MSG_UNREAD)) { + item->unread--; + changed = TRUE; + } + } + + if (MSG_IS_IMAP(msginfo->flags)) + imap_msg_set_perm_flags(msginfo, perm_flags); + + msginfo->flags.perm_flags |= perm_flags; + msginfo->flags.tmp_flags |= tmp_flags; + + if(changed) { + folderview_update_item(item, FALSE); + } + CHANGE_FLAGS(msginfo); + procmsg_msginfo_write_flags(msginfo); +} + +void procmsg_msginfo_unset_flags(MsgInfo *msginfo, MsgPermFlags perm_flags, MsgTmpFlags tmp_flags) +{ + gboolean changed = FALSE; + FolderItem *item = msginfo->folder; + + debug_print(_("Unsetting flags for message %d in folder %s\n"), msginfo->msgnum, item->path); + + /* if new flag is unset */ + if((perm_flags & MSG_NEW) && MSG_IS_NEW(msginfo->flags) && + !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + item->new--; + changed = TRUE; + } + + /* if unread flag is unset */ + if((perm_flags & MSG_UNREAD) && MSG_IS_UNREAD(msginfo->flags) && + !MSG_IS_IGNORE_THREAD(msginfo->flags)) { + item->unread--; + changed = TRUE; + } + + /* if ignore thread flag is unset */ + if((perm_flags & MSG_IGNORE_THREAD) && MSG_IS_IGNORE_THREAD(msginfo->flags)) { + if(MSG_IS_NEW(msginfo->flags) && !(perm_flags & MSG_NEW)) { + item->new++; + changed = TRUE; + } + if(MSG_IS_UNREAD(msginfo->flags) && !(perm_flags & MSG_UNREAD)) { + item->unread++; + changed = TRUE; + } + } + + if (MSG_IS_IMAP(msginfo->flags)) + imap_msg_unset_perm_flags(msginfo, perm_flags); + + msginfo->flags.perm_flags &= ~perm_flags; + msginfo->flags.tmp_flags &= ~tmp_flags; + + if(changed) { + folderview_update_item(item, FALSE); + } + CHANGE_FLAGS(msginfo); + procmsg_msginfo_write_flags(msginfo); +} + +void procmsg_msginfo_write_flags(MsgInfo *msginfo) +{ + gchar *destdir; + FILE *fp; + + destdir = folder_item_get_path(msginfo->folder); + if (!is_dir_exist(destdir)) + make_dir_hier(destdir); + + if ((fp = procmsg_open_mark_file(destdir, TRUE))) { + procmsg_write_flags(msginfo, fp); + fclose(fp); + } else { + g_warning(_("Can't open mark file.\n")); + } + + g_free(destdir); }