* src/summaryview.c
[claws.git] / src / compose.c
index a9c28b4e049e019e08857103bc7459531aa566aa..4cd00fc27c54e5ab54beaa779caba4871ec5434c 100644 (file)
@@ -62,6 +62,7 @@
 #include <sys/wait.h>
 #include <signal.h>
 #include <errno.h>
+#include <libgen.h>
 
 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
 #  include <wchar.h>
@@ -149,6 +150,14 @@ typedef enum
        PRIORITY_LOWEST
 } PriorityLevel;
 
+typedef enum
+{
+       COMPOSE_INSERT_SUCCESS,
+       COMPOSE_INSERT_READ_ERROR,
+       COMPOSE_INSERT_INVALID_CHARACTER,
+       COMPOSE_INSERT_NO_FILE
+} ComposeInsertResult;
+
 #define B64_LINE_SIZE          57
 #define B64_BUFFSIZE           77
 
@@ -199,7 +208,7 @@ static void compose_reedit_set_entry                (Compose        *compose,
 static void compose_insert_sig                 (Compose        *compose,
                                                 gboolean        replace);
 static gchar *compose_get_signature_str                (Compose        *compose);
-static void compose_insert_file                        (Compose        *compose,
+static ComposeInsertResult compose_insert_file (Compose        *compose,
                                                 const gchar    *file);
 static void compose_attach_append              (Compose        *compose,
                                                 const gchar    *file,
@@ -873,7 +882,7 @@ void compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar *body)
        case COMPOSE_FORWARD_INLINE:
                /* check if we reply to more than one Message */
                if (list_len == 1) {
-                       compose_forward(NULL, msginfo, FALSE, body);
+                       compose_forward(NULL, msginfo, FALSE, body, FALSE);
                        break;
                } 
                /* more messages FALL THROUGH */
@@ -1012,7 +1021,8 @@ if (msginfo->var && *msginfo->var) { \
 }
 
 Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
-                        gboolean as_attach, const gchar *body)
+                        gboolean as_attach, const gchar *body,
+                        gboolean no_extedit)
 {
        Compose *compose;
        GtkSText *text;
@@ -1033,7 +1043,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 
        if (!account && prefs_common.forward_account_autosel) {
                gchar cc[BUFFSIZE];
-               if (!get_header_from_msginfo(msginfo,cc,sizeof(cc),"CC:")){ /* Found a CC header */
+               if (!procheader_get_header_from_msginfo(msginfo,cc,sizeof(cc),"CC:")){ /* Found a CC header */
                        extract_address(cc);
                        account = account_find_from_address(cc);
                 }
@@ -1122,7 +1132,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 #endif
        gtk_widget_grab_focus(compose->header_last->entry);
 
-       if (prefs_common.auto_exteditor)
+       if (!no_extedit && prefs_common.auto_exteditor)
                compose_exec_ext_editor(compose);
        
        /*save folder*/
@@ -1221,22 +1231,22 @@ void compose_reedit(MsgInfo *msginfo)
                gint id;
 
                /* Select Account from queue headers */
-               if (!get_header_from_msginfo(msginfo, queueheader_buf, 
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "X-Sylpheed-Account-Id:")) {
                        id = atoi(&queueheader_buf[22]);
                        account = account_find_from_id(id);
                }
-               if (!account && !get_header_from_msginfo(msginfo, queueheader_buf, 
+               if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "NAID:")) {
                        id = atoi(&queueheader_buf[5]);
                        account = account_find_from_id(id);
                }
-               if (!account && !get_header_from_msginfo(msginfo, queueheader_buf, 
+               if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                                    sizeof(queueheader_buf), "MAID:")) {
                        id = atoi(&queueheader_buf[5]);
                        account = account_find_from_id(id);
                }
-               if (!account && !get_header_from_msginfo(msginfo, queueheader_buf, 
+               if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                                                sizeof(queueheader_buf), "S:")) {
                        account = account_find_from_address(queueheader_buf);
                }
@@ -1245,7 +1255,7 @@ void compose_reedit(MsgInfo *msginfo)
 
        if (!account && prefs_common.reedit_account_autosel) {
                        gchar from[BUFFSIZE];
-               if (!get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")){
+               if (!procheader_get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")){
                        extract_address(from);
                        account = account_find_from_address(from);
                 }
@@ -1261,7 +1271,7 @@ void compose_reedit(MsgInfo *msginfo)
                gchar queueheader_buf[BUFFSIZE];
 
                /* Set message save folder */
-               if (!get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) {
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) {
                        gint startpos = 0;
 
                        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE);
@@ -1299,6 +1309,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
        Compose *compose;
        gchar *filename;
        GtkItemFactory *ifactory;
+       FolderItem *item;
 
        g_return_val_if_fail(msginfo != NULL, NULL);
 
@@ -1323,6 +1334,17 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
 
        compose->redirect_filename = filename;
        
+       /* Set save folder */
+       item = msginfo->folder;
+       if (item && item->prefs && item->prefs->save_copy_to_folder) {
+               gchar *folderidentifier;
+
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), prefs_common.savemsg);
+               folderidentifier = folder_item_get_identifier(item);
+               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               g_free(folderidentifier);
+       }
+
        compose_attach_parts(compose, msginfo);
 
        if (msginfo->subject)
@@ -1842,6 +1864,10 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
 
        if (replyto && from)
                cc_list = address_list_append_with_comments(cc_list, from);
+       if (to_all && msginfo->folder && 
+           msginfo->folder->prefs->enable_default_reply_to)
+               cc_list = address_list_append_with_comments(cc_list,
+                               msginfo->folder->prefs->default_reply_to);
        cc_list = address_list_append_with_comments(cc_list, msginfo->to);
        cc_list = address_list_append_with_comments(cc_list, compose->cc);
 
@@ -1927,8 +1953,10 @@ static void compose_insert_sig(Compose *compose, gboolean replace)
 
        gtk_stext_freeze(text);
 
-       len = gtk_stext_get_length(text);
-       gtk_stext_set_point(text, len);
+       if (replace) {
+               len = gtk_stext_get_length(text);
+               gtk_stext_set_point(text, len);
+       }
 
        if (replace && compose->sig_str) {
                gint pos;
@@ -2004,18 +2032,19 @@ static gchar *compose_get_signature_str(Compose *compose)
        return sig_str;
 }
 
-static void compose_insert_file(Compose *compose, const gchar *file)
+static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *file)
 {
        GtkSText *text = GTK_STEXT(compose->text);
        gchar buf[BUFFSIZE];
        gint len;
        FILE *fp;
+       gboolean badtxt = FALSE;
 
-       g_return_if_fail(file != NULL);
+       g_return_val_if_fail(file != NULL, COMPOSE_INSERT_NO_FILE);
 
        if ((fp = fopen(file, "rb")) == NULL) {
                FILE_OP_ERROR(file, "fopen");
-               return;
+               return COMPOSE_INSERT_READ_ERROR;
        }
 
        gtk_stext_freeze(text);
@@ -2029,12 +2058,19 @@ static void compose_insert_file(Compose *compose, const gchar *file)
                        while (--len >= 0)
                                if (buf[len] == '\r') buf[len] = '\n';
                }
+               if (mbstowcs(NULL, buf, 0) == -1)
+                       badtxt = TRUE;
                gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
        }
 
        gtk_stext_thaw(text);
 
        fclose(fp);
+
+       if (badtxt)
+               return COMPOSE_INSERT_INVALID_CHARACTER;
+       else 
+               return COMPOSE_INSERT_SUCCESS;
 }
 
 static void compose_attach_append(Compose *compose, const gchar *file,
@@ -2132,67 +2168,122 @@ static void compose_attach_append(Compose *compose, const gchar *file,
        gtk_clist_set_row_data(GTK_CLIST(compose->attach_clist), row, ainfo);
 }
 
-#define IS_FIRST_PART_TEXT(info) \
-       ((info->mime_type == MIME_TEXT || info->mime_type == MIME_TEXT_HTML || \
-         info->mime_type == MIME_TEXT_ENRICHED) || \
-        (info->mime_type == MIME_MULTIPART && info->content_type && \
-         !strcasecmp(info->content_type, "multipart/alternative") && \
-         (info->children && \
-          (info->children->mime_type == MIME_TEXT || \
-           info->children->mime_type == MIME_TEXT_HTML || \
-           info->children->mime_type == MIME_TEXT_ENRICHED))))
+#ifdef USE_GPGME
+static void compose_use_signing(Compose *compose, gboolean use_signing)
+{
+       GtkItemFactory *ifactory;
+       GtkWidget *menuitem = NULL;
+
+       compose->use_signing = use_signing;
+       ifactory = gtk_item_factory_from_widget(compose->menubar);
+       menuitem = gtk_item_factory_get_item
+               (ifactory, "/Message/Sign");
+       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), 
+                                      use_signing);
+       compose_update_gnupg_mode_menu_item(compose);
+}
+#endif /* USE_GPGME */
+
+#define NEXT_PART_NOT_CHILD(info)  \
+{  \
+       node = info->node;  \
+       while (node->children)  \
+               node = g_node_last_child(node);  \
+       info = procmime_mimeinfo_next((MimeInfo *)node->data);  \
+}
 
 static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
 {
        MimeInfo *mimeinfo;
        MimeInfo *child;
-       gchar *infile;
+       MimeInfo *firsttext = NULL;
+       MimeInfo *encrypted = NULL;
+       GNode    *node;
        gchar *outfile;
+       const gchar *partname = NULL;
 
        mimeinfo = procmime_scan_message(msginfo);
        if (!mimeinfo) return;
 
-       /* skip first text (presumably message body) */
-       child = mimeinfo->children;
-       if (!child || IS_FIRST_PART_TEXT(mimeinfo)) {
+       if (mimeinfo->node->children == NULL) {
                procmime_mimeinfo_free_all(mimeinfo);
                return;
        }
 
-       if (IS_FIRST_PART_TEXT(child))
-               child = child->next;
-
-       infile = procmsg_get_message_file_path(msginfo);
+       /* find first content part */
+       child = (MimeInfo *) mimeinfo->node->children->data;
+       while (child && child->node->children && (child->type == MIMETYPE_MULTIPART))
+               child = (MimeInfo *)child->node->children->data;
 
+       if (child->type == MIMETYPE_TEXT) {
+               firsttext = child;
+               debug_print("First text part found\n");
+       } else if (compose->mode == COMPOSE_REEDIT &&
+                child->type == MIMETYPE_APPLICATION &&
+                !strcasecmp(child->subtype, "pgp-encrypted")) {
+               AlertValue val;
+               val = alertpanel(_("Encrypted message"),
+                                _("Cannot re-edit an encrypted message. \n"
+                                  "Discard encrypted part?"),
+                                _("Yes"), _("No"), NULL);
+               if (val == G_ALERTDEFAULT) 
+                       encrypted = (MimeInfo *)child->node->parent->data;
+       }
+     
+       child = (MimeInfo *) mimeinfo->node->children->data;
        while (child != NULL) {
-               if (child->children || child->mime_type == MIME_MULTIPART) {
+               if (child == encrypted) {
+                       /* skip this part of tree */
+                       NEXT_PART_NOT_CHILD(child);
+                       continue;
+               }
+
+               if (child->type == MIMETYPE_MULTIPART) {
+                       /* get the actual content */
                        child = procmime_mimeinfo_next(child);
                        continue;
                }
-               if (child->parent && child->parent->parent
-               && !strcasecmp(child->parent->parent->content_type, "multipart/signed")
-               && child->mime_type == MIME_TEXT) {
-                       /* this is the main text part of a signed message */
+                   
+               if (child == firsttext) {
+                       child = procmime_mimeinfo_next(child);
+                       continue;
+               }
+
+               if ((compose->mode == COMPOSE_REEDIT || 
+                    compose->mode == COMPOSE_FORWARD_INLINE ||
+                    compose->mode == COMPOSE_FORWARD )  &&
+                   (child->type == MIMETYPE_APPLICATION) && 
+                   !strcmp(child->subtype, "pgp-signature")) {
+#ifdef USE_GPGME
+                       if (compose->mode == COMPOSE_REEDIT) {
+                               compose->gnupg_mode  = GNUPG_MODE_DETACH;
+                               compose_use_signing(compose, TRUE);
+                       }
+#endif
                        child = procmime_mimeinfo_next(child);
                        continue;
                }
                outfile = procmime_get_tmp_file_name(child);
-               if (procmime_get_part(outfile, infile, child) < 0)
+               if (procmime_get_part(outfile, child) < 0)
                        g_warning("Can't get the part of multipart message.");
-               else if (compose->mode != COMPOSE_REEDIT || strcmp(child->content_type, "application/pgp-signature"))
-                       compose_attach_append
-                               (compose, outfile,
-                                child->filename ? child->filename : child->name,
-                                child->content_type);
-
-               child = child->next;
+               else {
+                       gchar *content_type;
+
+                       content_type = g_strdup_printf("%s/%s", procmime_get_type_str(child->type), child->subtype);
+                       partname = procmime_mimeinfo_get_parameter(child, "name");
+                       if (partname == NULL)
+                               partname = "";
+                       compose_attach_append(compose, outfile, 
+                                             partname, content_type);
+                       g_free(content_type);
+               }
+               g_free(outfile);
+               NEXT_PART_NOT_CHILD(child);
        }
-
-       g_free(infile);
        procmime_mimeinfo_free_all(mimeinfo);
 }
 
-#undef IS_FIRST_PART_TEXT
+#undef NEXT_PART_NOT_CHILD
 
 #define GET_CHAR(pos, buf, len)                                                     \
 {                                                                           \
@@ -3262,7 +3353,7 @@ static gint compose_redirect_write_to_file(Compose *compose, const gchar *file)
                g_warning("can't change file mode\n");
        }
 
-       while (procheader_get_unfolded_line(buf, sizeof(buf), fp)) {
+       while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
                /* should filter returnpath, delivered-to */
                if (g_strncasecmp(buf, "Return-Path:",
                                   strlen("Return-Path:")) == 0 ||
@@ -3698,7 +3789,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        GSList *cur;
        gchar buf[BUFFSIZE];
        gint num;
-       MsgFlags flag = {0, 0};
         static gboolean lock = FALSE;
        PrefsAccount *mailac = NULL, *newsac = NULL;
        
@@ -4018,14 +4108,15 @@ static void compose_write_attach(Compose *compose, FILE *fp)
 
 static gint compose_write_headers_from_headerlist(Compose *compose, 
                                                  FILE *fp, 
-                                                 gchar *header)
+                                                 const gchar *header,
+                                                 const gchar *seperator)
 {
-       gchar buf[BUFFSIZE];
        gchar *str, *header_w_colon, *trans_hdr;
-       gboolean first_address;
+       gboolean write_header = FALSE;
        GSList *list;
        ComposeHeaderEntry *headerentry;
        gchar * headerentryname;
+       GString *headerstr;
 
        if (IS_IN_CUSTOM_HEADER(header)) {
                return 0;
@@ -4033,10 +4124,11 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
 
        debug_print("Writing %s-header\n", header);
 
+       headerstr = g_string_sized_new(64);
+
        header_w_colon = g_strconcat(header, ":", NULL);
        trans_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
 
-       first_address = TRUE;
        for (list = compose->header_list; list; list = list->next) {
                headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
@@ -4046,24 +4138,26 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
                        Xstrdup_a(str, str, return -1);
                        g_strstrip(str);
                        if (str[0] != '\0') {
-                               compose_convert_header
-                                       (buf, sizeof(buf), str,
-                                       strlen(header) + 2, TRUE);
-                               if (first_address) {
-                                       fprintf(fp, "%s: ", header);
-                                       first_address = FALSE;
-                               } else {
-                                       fprintf(fp, ",");
-                               }
-                               fprintf(fp, "%s", buf);
+                               if (write_header)
+                                       g_string_append(headerstr, seperator);
+                               g_string_append(headerstr, str);
+                               write_header = TRUE;
                        }
                }
        }
-       if (!first_address) {
-               fprintf(fp, "\n");
+       if (write_header) {
+               gchar *buf;
+
+               buf = g_new0(gchar, headerstr->len * 4 + 256);
+               compose_convert_header
+                       (buf, headerstr->len * 4  + 256, headerstr->str,
+                       strlen(header) + 2, TRUE);
+               fprintf(fp, "%s: %s\n", header, buf);
+               g_free(buf);
        }
 
        g_free(header_w_colon);
+       g_string_free(headerstr, TRUE);
 
        return(0);
 }
@@ -4119,7 +4213,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
        
        /* To */
-       compose_write_headers_from_headerlist(compose, fp, "To");
+       compose_write_headers_from_headerlist(compose, fp, "To", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_to) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->to_entry));
@@ -4128,7 +4222,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
 #endif
 
        /* Newsgroups */
-       compose_write_headers_from_headerlist(compose, fp, "Newsgroups");
+       compose_write_headers_from_headerlist(compose, fp, "Newsgroups", ",");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_newsgroups) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->newsgroups_entry));
@@ -4149,7 +4243,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 #endif
        /* Cc */
-       compose_write_headers_from_headerlist(compose, fp, "Cc");
+       compose_write_headers_from_headerlist(compose, fp, "Cc", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_cc) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->cc_entry));
@@ -4157,7 +4251,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 #endif
        /* Bcc */
-       compose_write_headers_from_headerlist(compose, fp, "Bcc");
+       compose_write_headers_from_headerlist(compose, fp, "Bcc", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_bcc) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->bcc_entry));
@@ -4195,7 +4289,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 
        /* Followup-To */
-       compose_write_headers_from_headerlist(compose, fp, "Followup-To");
+       compose_write_headers_from_headerlist(compose, fp, "Followup-To", ",");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_followupto && !IS_IN_CUSTOM_HEADER("Followup-To")) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->followup_entry));
@@ -4213,7 +4307,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 #endif
        /* Reply-To */
-       compose_write_headers_from_headerlist(compose, fp, "Reply-To");
+       compose_write_headers_from_headerlist(compose, fp, "Reply-To", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_replyto && !IS_IN_CUSTOM_HEADER("Reply-To")) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->reply_entry));
@@ -4287,7 +4381,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        /* MIME */
        fprintf(fp, "Mime-Version: 1.0\n");
        if (compose_use_attach(compose)) {
-               compose->boundary = generate_mime_boundary();
+               compose->boundary = generate_mime_boundary(NULL);
                fprintf(fp,
                        "Content-Type: multipart/mixed;\n"
                        " boundary=\"%s\"\n", compose->boundary);
@@ -4349,6 +4443,11 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                headerentry = ((ComposeHeaderEntry *)list->data);
                
                tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry)));
+               if (strchr(tmp, ' ') != NULL || strchr(tmp, '\r') != NULL || strchr(tmp, '\n') != NULL) {
+                       g_free(tmp);
+                       continue;
+               }
+
                if (!strstr(tmp, ":")) {
                        headername_wcolon = g_strconcat(tmp, ":", NULL);
                        headername = g_strdup(tmp);
@@ -4359,6 +4458,8 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                g_free(tmp);
                
                headervalue = gtk_entry_get_text(GTK_ENTRY(headerentry->entry));
+               subst_char(headervalue, '\r', ' ');
+               subst_char(headervalue, '\n', ' ');
                string = std_headers;
                while (*string != NULL) {
                        headername_trans = prefs_common.trans_hdr ? gettext(*string) : *string;
@@ -4370,8 +4471,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                        fprintf(fp, "%s %s\n", headername_wcolon, headervalue);
                                
                g_free(headername);
-               g_free(headername_wcolon);
-               
+               g_free(headername_wcolon);              
        }
 
        /* separator between header and body */
@@ -4390,6 +4490,8 @@ static void compose_convert_header(gchar *dest, gint len, gchar *src,
 
        if (len < 1) return;
 
+       subst_char(src, '\n', ' ');
+       subst_char(src, '\r', ' ');
        g_strchomp(src);
 
        conv_encode_header(dest, len, src, header_len, addr_field);
@@ -6389,7 +6491,19 @@ static void compose_insert_file_cb(gpointer data, guint action,
 
                for ( tmp = file_list; tmp; tmp = tmp->next) {
                        gchar *file = (gchar *) tmp->data;
-                       compose_insert_file(compose, file);
+                       gchar *filedup = g_strdup(file);
+                       gchar *shortfile;
+                       ComposeInsertResult res;
+
+                       res = compose_insert_file(compose, file);
+                       shortfile = g_basename(filedup);
+                       if (res == COMPOSE_INSERT_READ_ERROR) {
+                               alertpanel_error(_("File '%s' could not be read."), shortfile);
+                       } else if (res == COMPOSE_INSERT_INVALID_CHARACTER) {
+                               alertpanel_error(_("File '%s' contained invalid characters\n"
+                                                  "for the current encoding, insertion may be incorrect."), shortfile);
+                       }
+                       g_free(filedup);
                        g_free(file);
                }
                g_list_free(file_list);