Fix bug #2398, "Race when closing compose during drafting"
[claws.git] / src / compose.c
index a3a6cf8acca69ee4ec69ca39d836d867dc263a8a..6f4c8b9cbcf8a7b5508f02977619d32c4c50f9c5 100644 (file)
@@ -3282,16 +3282,18 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                        gchar *tmp1 = NULL;
                        if (!msginfo->from)
                                return;
-                       Xstrdup_a(tmp1, msginfo->from, return);
-                       extract_address(tmp1);
-                       if (to_all || to_sender ||
-                           !account_find_from_address(tmp1, FALSE))
+                       if (to_sender)
+                               compose_entry_append(compose, msginfo->from,
+                                                    COMPOSE_TO, PREF_NONE);
+                       else if (to_all) {
+                               Xstrdup_a(tmp1, msginfo->from, return);
+                               extract_address(tmp1);
                                compose_entry_append(compose,
-                                (compose->replyto && !to_sender)
-                                         ? compose->replyto :
-                                         msginfo->from ? msginfo->from : "",
+                                (!account_find_from_address(tmp1, FALSE))
+                                         ? msginfo->from :
+                                         msginfo->to,
                                          COMPOSE_TO, PREF_NONE);
-                       else if (!to_all && !to_sender) {
+                       } else {
                                if (!folder_has_parent_of_type(msginfo->folder, F_QUEUE) &&
                                    !folder_has_parent_of_type(msginfo->folder, F_OUTBOX) &&
                                    !folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
@@ -3671,9 +3673,18 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
                alertpanel_error("Can't get file size of %s\n", filename);
                return FALSE;
        }
-       if (size == 0) {
-               alertpanel_error(_("File %s is empty."), filename);
-               return FALSE;
+
+       /* In batch mode, we allow 0-length files to be attached no questions asked */
+       if (size == 0 && !compose->batch) {
+               gchar * msg = g_strdup_printf(_("File %s is empty."), filename);
+               AlertValue aval = alertpanel_full(_("Empty file"), msg, 
+                               GTK_STOCK_CANCEL, _("+_Attach anyway"), NULL, FALSE,
+                               NULL, ALERT_WARNING, G_ALERTDEFAULT);
+               g_free(msg);
+
+               if (aval != G_ALERTALTERNATE) {
+                       return FALSE;
+               }
        }
        if ((fp = g_fopen(file, "rb")) == NULL) {
                alertpanel_error(_("Can't read %s."), filename);
@@ -5337,6 +5348,8 @@ static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
                }
                generate_msgid(buf, sizeof(buf), addr);
                err |= (fprintf(fp, "Resent-Message-ID: <%s>\n", buf) < 0);
+               if (compose->msgid)
+                       g_free(compose->msgid);
                compose->msgid = g_strdup(buf);
        } else {
                compose->msgid = NULL;
@@ -6413,6 +6426,8 @@ static gchar *compose_get_header(Compose *compose)
                }
                generate_msgid(buf, sizeof(buf), addr);
                g_string_append_printf(header, "Message-ID: <%s>\n", buf);
+               if (compose->msgid)
+                       g_free(compose->msgid);
                compose->msgid = g_strdup(buf);
        } else {
                compose->msgid = NULL;
@@ -6453,7 +6468,7 @@ static gchar *compose_get_header(Compose *compose)
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
                        TARGET_ALIAS);
        }
-       if (compose->account->gen_xnewsreader &&
+       if (compose->account->gen_xmailer &&
            g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
                g_string_append_printf(header, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
@@ -9777,9 +9792,11 @@ gboolean compose_draft (gpointer data, guint action)
                goto warn_err;
        }
        
+       flag.perm_flags = MSG_NEW|MSG_UNREAD;
        if (compose->targetinfo) {
                target_locked = MSG_IS_LOCKED(compose->targetinfo->flags);
-               flag.perm_flags = target_locked?MSG_LOCKED:0;
+               if (target_locked) 
+                       flag.perm_flags |= MSG_LOCKED;
        }
        flag.tmp_flags = MSG_DRAFT;
 
@@ -9840,9 +9857,9 @@ warn_err:
        if (newmsginfo) {
                procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
                if (target_locked)
-                       procmsg_msginfo_set_flags(newmsginfo, MSG_LOCKED, MSG_DRAFT);
+                       procmsg_msginfo_set_flags(newmsginfo, MSG_NEW|MSG_UNREAD|MSG_LOCKED, MSG_DRAFT);
                else
-                       procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
+                       procmsg_msginfo_set_flags(newmsginfo, MSG_NEW|MSG_UNREAD, MSG_DRAFT);
                if (compose_use_attach(compose) && action != COMPOSE_AUTO_SAVE)
                        procmsg_msginfo_set_flags(newmsginfo, 0,
                                                  MSG_HAS_ATTACHMENT);
@@ -11176,7 +11193,8 @@ static gboolean scroll_postpone(gpointer data)
 {
        Compose *compose = (Compose *)data;
 
-       cm_return_val_if_fail(!compose->batch, FALSE);
+       if (compose->batch)
+               return FALSE;
 
        GTK_EVENTS_FLUSH();
        compose_show_first_last_header(compose, FALSE);
@@ -11209,7 +11227,10 @@ static void compose_show_first_last_header(Compose *compose, gboolean show_first
        GtkAdjustment *vadj;
 
        cm_return_if_fail(compose);
-       cm_return_if_fail(!compose->batch);
+
+       if(compose->batch)
+               return;
+
        cm_return_if_fail(GTK_IS_WIDGET(compose->header_table));
        cm_return_if_fail(GTK_IS_VIEWPORT(gtk_widget_get_parent(compose->header_table)));
        vadj = gtk_viewport_get_vadjustment(GTK_VIEWPORT(
@@ -11432,16 +11453,28 @@ gboolean compose_close(Compose *compose)
 {
        gint x, y;
 
+       cm_return_val_if_fail(compose, FALSE);
+
        if (!g_mutex_trylock(compose->mutex)) {
                /* we have to wait for the (possibly deferred by auto-save)
                 * drafting to be done, before destroying the compose under
                 * it. */
                debug_print("waiting for drafting to finish...\n");
                compose_allow_user_actions(compose, FALSE);
-               g_timeout_add (500, (GSourceFunc) compose_close, compose);
+               if (compose->close_timeout_tag == 0) {
+                       compose->close_timeout_tag = 
+                               g_timeout_add (500, (GSourceFunc) compose_close,
+                               compose);
+               }
                return FALSE;
        }
-       cm_return_val_if_fail(compose, FALSE);
+       
+       if (compose->close_timeout_tag) {
+               /* let the close be done by the deferred callback */
+               g_mutex_unlock(compose->mutex);
+               return FALSE;
+       }
+
        gtkut_widget_get_uposition(compose->window, &x, &y);
        if (!compose->batch) {
                prefs_common.compose_x = x;