* src/procmsg.c
[claws.git] / src / procmsg.c
index 3f4cb2048fbbc940008be07a5e115034d8dd3d48..8aee6db65a7fa04d51c135394c0344d9f352012b 100644 (file)
 #include "hooks.h"
 #include "msgcache.h"
 
-typedef struct _FlagInfo       FlagInfo;
-
-struct _FlagInfo
-{
-       guint    msgnum;
-       MsgFlags flags;
-};
-
 GHashTable *procmsg_msg_hash_table_create(GSList *mlist)
 {
        GHashTable *msg_table;
@@ -148,7 +140,7 @@ static gboolean procmsg_ignore_node(GNode *node, gpointer data)
 /* return the reversed thread tree */
 GNode *procmsg_get_thread_tree(GSList *mlist)
 {
-       GNode *root, *parent, *node, *next;
+       GNode *root, *parent, *node, *next, *last;
        GHashTable *msgid_table;
        GHashTable *subject_table;
        MsgInfo *msginfo;
@@ -183,20 +175,21 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                        g_hash_table_insert(msgid_table, (gchar *)msgid, node);
 
                if (prefs_common.thread_by_subject) {
-                       subject = msginfo->subject;
-                       found_subject = subject_table_lookup(subject_table,
-                                                            (gchar *) subject);
+                       subject  = msginfo->subject;
+                       subject += subject_get_reply_prefix_length(subject);
+                       found_subject = subject_table_lookup_clean(subject_table,
+                                                                  (gchar *) subject);
                        if (found_subject == NULL)
-                               subject_table_insert(subject_table, (gchar *) subject,
-                                                    node);
+                               subject_table_insert_clean(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);
-                               }       
+                                if ( ((MsgInfo*)(found_subject->data))->date_t > 
+                                     ((MsgInfo*)(node->data))->date_t )  {
+                                       subject_table_remove_clean(subject_table, (gchar *) subject);
+                                       subject_table_insert_clean(subject_table, (gchar *) subject, node);
+                               } 
                        }
                }
        }
@@ -208,7 +201,10 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                parent = NULL;
                if (msginfo->inreplyto) 
                        parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
-               if (parent && parent != node) {
+               /* node should not be the parent, and node should not be an ancestor
+                * of parent (circular reference) */
+               if (parent && parent != node 
+               && !g_node_is_ancestor(node, parent)) {
                        g_node_unlink(node);
                        g_node_insert_before
                                (parent, parent->children, node);
@@ -217,6 +213,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                                g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, procmsg_ignore_node, NULL);
                        }
                }
+               last = node; /* CLAWS: need to have the last one for subject threading */
                node = next;
        }
 
@@ -225,31 +222,38 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
         * circular reference from a node that has already been threaded by IN-REPLY-TO
         * but is also in the subject line hash table */
        if (prefs_common.thread_by_subject) {
-               for (node = root->children; node != NULL; ) {
-                       next = node->next;
+               for (node = last; node && node != NULL;) {
+                       next = node->prev;
                        msginfo = (MsgInfo *) node->data;
-                       parent = NULL;
-                       if (subject_is_reply(msginfo->subject)) {
-                               parent = subject_table_lookup(subject_table,
-                                                             msginfo->subject);
-                               /* the node may already be threaded by IN-REPLY-TO,
-                                  so go up in the tree to find the parent node */
-                               if (parent != NULL) {
-                                       if (g_node_is_ancestor(node, parent))
-                                               parent = NULL;
-                                       if (parent == node)
-                                               parent = NULL;
+                       subject = msginfo->subject + subject_get_reply_prefix_length(msginfo->subject);
+                       parent = subject_table_lookup_clean(subject_table, (gchar *) subject);
+                       
+                       /* the node may already be threaded by IN-REPLY-TO,
+                          so go up in the tree to find the parent node */
+                       if (parent != NULL) {
+                               if (g_node_is_ancestor(node, parent))
+                                       parent = NULL;
+                               if (parent == node)
+                                       parent = NULL;
+                               /* Make new thread parent if too old compared to previous one; probably
+                                * breaks ignoring threads for subject threading. This still isn't
+                                * accurate because the tree isn't sorted by date. */   
+                               if (parent && abs(difftime(msginfo->date_t, ((MsgInfo *)parent->data)->date_t)) >
+                                               prefs_common.thread_by_subject_max_age * 3600 * 24) {
+                                       subject_table_remove_clean(subject_table, (gchar *) subject);
+                                       subject_table_insert_clean(subject_table, (gchar *) subject, node);
+                                       parent = NULL;
                                }
+                       }
 
-                               if (parent) {
-                                       g_node_unlink(node);
-                                       g_node_append(parent, node);
-                                       /* CLAWS: ignore thread */
-                                       if (MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
-                                               g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, procmsg_ignore_node, NULL);
-                                       }
+                       if (parent) {
+                               g_node_unlink(node);
+                               g_node_append(parent, node);
+                               /* CLAWS: ignore thread */
+                               if (MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+                                       g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, procmsg_ignore_node, NULL);
                                }
-                       }                                       
+                       }
                        node = next;
                }       
        }
@@ -400,6 +404,7 @@ FILE *procmsg_open_message_decrypted(MsgInfo *msginfo, MimeInfo **mimeinfo)
 {
        FILE *fp;
        MimeInfo *mimeinfo_;
+       glong fpos;
 
        g_return_val_if_fail(msginfo != NULL, NULL);
 
@@ -419,7 +424,9 @@ FILE *procmsg_open_message_decrypted(MsgInfo *msginfo, MimeInfo **mimeinfo)
        }
 
        if (MSG_IS_ENCRYPTED(msginfo->flags) &&
-           (!msginfo->plaintext_file || msginfo->decryption_failed)) {
+           !msginfo->plaintext_file &&
+           !msginfo->decryption_failed) {
+               fpos = ftell(fp);
                rfc2015_decrypt_message(msginfo, mimeinfo_, fp);
                if (msginfo->plaintext_file &&
                    !msginfo->decryption_failed) {
@@ -432,6 +439,9 @@ FILE *procmsg_open_message_decrypted(MsgInfo *msginfo, MimeInfo **mimeinfo)
                                fclose(fp);
                                return NULL;
                        }
+               } else {
+                       if (fseek(fp, fpos, SEEK_SET) < 0)
+                               perror("fseek");
                }
        }
 
@@ -766,7 +776,7 @@ MsgInfo *procmsg_msginfo_new_ref(MsgInfo *msginfo)
        return msginfo;
 }
 
-MsgInfo *procmsg_msginfo_new()
+MsgInfo *procmsg_msginfo_new(void)
 {
        MsgInfo *newmsginfo;
 
@@ -1057,18 +1067,6 @@ gint procmsg_send_message_queue(const gchar *file)
                                mailval = send_message_smtp(&tmp_ac, to_list, fp);
                        }
                }
-               if (mailval < 0) {
-                       if (!local)
-                               alertpanel_error_log(
-                                       _("Error occurred while sending the message to `%s'."),
-                                       mailac ? mailac->smtp_server : smtpserver);
-                       else
-                               alertpanel_error_log(
-                                       _("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);
-               }
        }
 
        fseek(fp, filepos, SEEK_SET);
@@ -1149,7 +1147,12 @@ gint procmsg_send_message_queue(const gchar *file)
                        MsgInfo *msginfo;
                        
                        msginfo = folder_item_get_msginfo(item, atoi(tokens[1]));
-                       if ((msginfo != NULL) && (strcmp(msginfo->msgid, tokens[2]) != 0)) {
+                       
+                       /*!< note that if the message has no msgid (maybe it was invalid), 
+                       * we also refuse to do something with the reply to flag */
+                       if ((msginfo != NULL) && 
+                           (msginfo->msgid != NULL) &&
+                           (strcmp(msginfo->msgid, tokens[2]) != 0)) {
                                procmsg_msginfo_free(msginfo);
                                msginfo = NULL;
                        }