#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
+#include <libgen.h>
#if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
# include <wchar.h>
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
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,
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 */
}
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;
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);
}
#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*/
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);
}
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);
}
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);
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);
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);
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,
gtk_clist_set_row_data(GTK_CLIST(compose->attach_clist), row, ainfo);
}
-#define IS_FIRST_PART_TEXT(info) \
- ((info->type == MIMETYPE_TEXT) || \
- (info->type == MIMETYPE_MULTIPART && info->subtype && \
- !strcasecmp(info->subtype, "alternative") && \
- (info->children && \
- (info->children->type == MIMETYPE_TEXT))))
+#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->type == MIMETYPE_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 == firsttext) {
child = procmime_mimeinfo_next(child);
continue;
}
- if (child->parent && child->parent->parent
- && (child->parent->parent->type == MIMETYPE_MULTIPART)
- && !strcasecmp(child->parent->parent->subtype, "signed")
- && child->type == MIMETYPE_TEXT) {
- /* this is the main text part of a signed message */
+
+ 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, child) < 0)
g_warning("Can't get the part of multipart message.");
- else if (compose->mode != COMPOSE_REEDIT ||
- !((child->type == MIMETYPE_APPLICATION) && !strcmp(child->subtype, "pgp-signature"))) {
+ else {
gchar *content_type;
content_type = g_strdup_printf("%s/%s", procmime_get_type_str(child->type), child->subtype);
- compose_attach_append
- (compose, outfile,
- child->filename ? child->filename : child->name,
- content_type);
+ partname = procmime_mimeinfo_get_parameter(child, "name");
+ if (partname == NULL)
+ partname = "";
+ compose_attach_append(compose, outfile,
+ partname, content_type);
g_free(content_type);
}
-
- child = child->next;
+ 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) \
{ \
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 ||
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);