#include "displayheader.h"
#include "account.h"
#include "mimeview.h"
+#include "alertpanel.h"
typedef struct _RemoteURI RemoteURI;
};
#endif
-#if USE_GPGME
static GdkColor good_sig_color = {
(gulong)0,
(gushort)0,
(gushort)0,
(gushort)0
};
-#endif
static GdkFont *text_sb_font;
static GdkFont *text_mb_font;
FILE *fp,
CodeConverter *conv);
static void textview_add_part (TextView *textview,
- MimeInfo *mimeinfo,
- FILE *fp);
+ MimeInfo *mimeinfo);
static void textview_add_parts (TextView *textview,
- MimeInfo *mimeinfo,
- FILE *fp);
+ MimeInfo *mimeinfo);
static void textview_write_body (TextView *textview,
MimeInfo *mimeinfo,
- FILE *fp,
const gchar *charset);
static void textview_show_html (TextView *textview,
FILE *fp,
GtkSText *text;
FILE *fp;
const gchar *charset = NULL;
- GPtrArray *headers = NULL;
if ((fp = fopen(file, "rb")) == NULL) {
FILE_OP_ERROR(file, "fopen");
charset = textview->messageview->forced_charset;
else if (prefs_common.force_charset)
charset = prefs_common.force_charset;
- else if (mimeinfo->charset)
- charset = mimeinfo->charset;
+ else
+ charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
textview_set_font(textview, charset);
textview_clear(textview);
gtk_stext_freeze(text);
- if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0) perror("fseek");
+/*
+ if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) perror("fseek");
headers = textview_scan_header(textview, fp);
if (headers) {
textview_show_header(textview, headers);
procheader_header_array_destroy(headers);
textview->body_pos = gtk_stext_get_length(text);
}
-
- textview_add_parts(textview, mimeinfo, fp);
+*/
+ textview_add_parts(textview, mimeinfo);
gtk_stext_thaw(text);
void textview_show_part(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
{
GtkSText *text;
- gchar buf[BUFFSIZE];
- const gchar *boundary = NULL;
- gint boundary_len = 0;
const gchar *charset = NULL;
- GPtrArray *headers = NULL;
- gboolean is_rfc822_part = FALSE;
g_return_if_fail(mimeinfo != NULL);
g_return_if_fail(fp != NULL);
- if (mimeinfo->mime_type == MIME_MULTIPART) {
+ if ((mimeinfo->type == MIMETYPE_MULTIPART) ||
+ ((mimeinfo->type == MIMETYPE_MESSAGE) && !g_strcasecmp(mimeinfo->subtype, "rfc822"))) {
textview_clear(textview);
- textview_add_parts(textview, mimeinfo, fp);
+ textview_add_parts(textview, mimeinfo);
return;
}
- if (mimeinfo->parent && mimeinfo->parent->boundary) {
- boundary = mimeinfo->parent->boundary;
- boundary_len = strlen(boundary);
- }
-
- if (!boundary && (mimeinfo->mime_type == MIME_TEXT ||
- mimeinfo->mime_type == MIME_TEXT_HTML ||
- mimeinfo->mime_type == MIME_TEXT_ENRICHED)) {
-
- if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
- perror("fseek");
- headers = textview_scan_header(textview, fp);
- } else {
- if (mimeinfo->mime_type == MIME_TEXT && mimeinfo->parent) {
- glong fpos;
- MimeInfo *parent = mimeinfo->parent;
-
- while (parent->parent) {
- if (parent->main &&
- parent->main->mime_type ==
- MIME_MESSAGE_RFC822)
- break;
- parent = parent->parent;
- }
-
- if ((fpos = ftell(fp)) < 0)
- perror("ftell");
- else if (fseek(fp, parent->fpos, SEEK_SET) < 0)
- perror("fseek");
- else {
- headers = textview_scan_header(textview, fp);
- if (fseek(fp, fpos, SEEK_SET) < 0)
- perror("fseek");
- }
- }
- /* skip MIME part headers */
- while (fgets(buf, sizeof(buf), fp) != NULL)
- if (buf[0] == '\r' || buf[0] == '\n') break;
- }
-
- /* display attached RFC822 single text message */
- if (mimeinfo->mime_type == MIME_MESSAGE_RFC822) {
- if (headers) procheader_header_array_destroy(headers);
- if (!mimeinfo->sub) {
- textview_clear(textview);
- return;
- }
- headers = textview_scan_header(textview, fp);
- mimeinfo = mimeinfo->sub;
- is_rfc822_part = TRUE;
- }
-
+ if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0)
+ perror("fseek");
+/*
+ headers = textview_scan_header(textview, fp);
+*/
if (textview->messageview->forced_charset)
charset = textview->messageview->forced_charset;
else if (prefs_common.force_charset)
charset = prefs_common.force_charset;
- else if (mimeinfo->charset)
- charset = mimeinfo->charset;
+ else
+ charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
textview_set_font(textview, charset);
gtk_stext_freeze(text);
textview_clear(textview);
+/*
if (headers) {
textview_show_header(textview, headers);
procheader_header_array_destroy(headers);
if (!mimeinfo->main)
gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
}
-
- if (mimeinfo->mime_type == MIME_MULTIPART || is_rfc822_part)
- textview_add_parts(textview, mimeinfo, fp);
+*/
+ if (mimeinfo->type == MIMETYPE_MULTIPART)
+ textview_add_parts(textview, mimeinfo);
else
- textview_write_body(textview, mimeinfo, fp, charset);
+ textview_write_body(textview, mimeinfo, charset);
gtk_stext_thaw(text);
}
-static void textview_add_part(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
+static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
{
GtkSText *text = GTK_STEXT(textview->text);
gchar buf[BUFFSIZE];
- const gchar *boundary = NULL;
- gint boundary_len = 0;
const gchar *charset = NULL;
GPtrArray *headers = NULL;
g_return_if_fail(mimeinfo != NULL);
- g_return_if_fail(fp != NULL);
- if (mimeinfo->mime_type == MIME_MULTIPART) return;
+ if (mimeinfo->type == MIMETYPE_MULTIPART) return;
- if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0) {
- perror("fseek");
- return;
- }
-
- if (mimeinfo->parent && mimeinfo->parent->boundary) {
- boundary = mimeinfo->parent->boundary;
- boundary_len = strlen(boundary);
- }
+ if ((mimeinfo->type == MIMETYPE_MESSAGE) && !g_strcasecmp(mimeinfo->subtype, "rfc822")) {
+ FILE *fp;
- while (fgets(buf, sizeof(buf), fp) != NULL)
- if (buf[0] == '\r' || buf[0] == '\n') break;
-
- if (mimeinfo->mime_type == MIME_MESSAGE_RFC822) {
+ fp = fopen(mimeinfo->filename, "rb");
+ fseek(fp, mimeinfo->offset, SEEK_SET);
headers = textview_scan_header(textview, fp);
if (headers) {
gtk_stext_freeze(text);
- gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
+ if (gtk_stext_get_length(text) > 0)
+ gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
textview_show_header(textview, headers);
procheader_header_array_destroy(headers);
gtk_stext_thaw(text);
}
+ fclose(fp);
return;
}
gtk_stext_freeze(text);
-#if USE_GPGME
- if (mimeinfo->sigstatus)
- g_snprintf(buf, sizeof(buf), "\n[%s (%s)]\n",
- mimeinfo->content_type, mimeinfo->sigstatus);
- else
-#endif
- if (mimeinfo->filename || mimeinfo->name)
- g_snprintf(buf, sizeof(buf), "\n[%s %s (%d bytes)]\n",
- mimeinfo->filename ? mimeinfo->filename :
- mimeinfo->name,
- mimeinfo->content_type, mimeinfo->size);
+ if (g_hash_table_lookup(mimeinfo->parameters, "name") != NULL)
+ g_snprintf(buf, sizeof(buf), "\n[%s %s/%s (%d bytes)]\n",
+ (gchar *) g_hash_table_lookup(mimeinfo->parameters, "name"),
+ procmime_get_type_str(mimeinfo->type),
+ mimeinfo->subtype, mimeinfo->length);
else
- g_snprintf(buf, sizeof(buf), "\n[%s (%d bytes)]\n",
- mimeinfo->content_type, mimeinfo->size);
-
-#if USE_GPGME
- if (mimeinfo->sigstatus && !mimeinfo->sigstatus_full) {
- gchar *tmp;
- /* use standard font */
- gpointer oldfont = textview->msgfont;
- textview->msgfont = NULL;
-
- tmp = g_strconcat("pgp: ", _("Check signature"), NULL);
- textview_write_link(textview, buf, tmp, NULL);
-
- /* put things back */
- textview->msgfont = (GdkFont *)oldfont;
- oldfont = NULL;
- g_free(tmp);
- } else if (mimeinfo->sigstatus) {
- GdkColor *color;
- if (!strcmp(mimeinfo->sigstatus, _("Good signature")))
- color = &good_sig_color;
- else if (!strcmp(mimeinfo->sigstatus, _("BAD signature")))
- color = &bad_sig_color;
- else
- color = &nocheck_sig_color;
- gtk_stext_insert(text, NULL, color, NULL, buf, -1);
- } else
-#endif
- if (mimeinfo->mime_type != MIME_TEXT &&
- mimeinfo->mime_type != MIME_TEXT_HTML &&
- mimeinfo->mime_type != MIME_TEXT_ENRICHED) {
+ g_snprintf(buf, sizeof(buf), "\n[%s/%s (%d bytes)]\n",
+ procmime_get_type_str(mimeinfo->type),
+ mimeinfo->subtype, mimeinfo->length);
+
+ if (mimeinfo->type != MIMETYPE_TEXT) {
gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
} else {
- if (!mimeinfo->main &&
- mimeinfo->parent &&
- mimeinfo->parent->children != mimeinfo)
- gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
- else if (prefs_common.display_header)
+ if (prefs_common.display_header && (gtk_stext_get_length(text) > 0))
gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
if (textview->messageview->forced_charset)
charset = textview->messageview->forced_charset;
else if (prefs_common.force_charset)
charset = prefs_common.force_charset;
- else if (mimeinfo->charset)
- charset = mimeinfo->charset;
- textview_write_body(textview, mimeinfo, fp, charset);
+ else
+ charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
+
+ textview_write_body(textview, mimeinfo, charset);
}
gtk_stext_thaw(text);
}
-static void textview_add_parts(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
+#if 0
+static gboolean add_parts_func(GNode *node, gpointer data)
{
- gint level;
+ MimeInfo *mimeinfo = (MimeInfo *) node->data;
+ TextView *textview = (TextView *) data;
- g_return_if_fail(mimeinfo != NULL);
- g_return_if_fail(fp != NULL);
+ g_return_val_if_fail(mimeinfo != NULL, FALSE);
- level = mimeinfo->level;
+ textview_add_part(textview, mimeinfo);
- for (;;) {
- textview_add_part(textview, mimeinfo, fp);
- if (mimeinfo->parent && mimeinfo->parent->content_type &&
- !strcasecmp(mimeinfo->parent->content_type,
- "multipart/alternative"))
- mimeinfo = mimeinfo->parent->next;
- else
- mimeinfo = procmime_mimeinfo_next(mimeinfo);
- if (!mimeinfo || mimeinfo->level <= level)
- break;
- }
+ return FALSE;
}
-#define TEXT_INSERT(str) \
- gtk_stext_insert(text, textview->msgfont, NULL, NULL, str, -1)
-
-void textview_show_mime_part(TextView *textview, MimeInfo *partinfo)
+static void textview_add_parts(TextView *textview, MimeInfo *mimeinfo)
{
- GtkSText *text;
-
- if (!partinfo) return;
-
- textview_set_font(textview, NULL);
- text = GTK_STEXT(textview->text);
- textview_clear(textview);
-
- gtk_stext_freeze(text);
-
- TEXT_INSERT(_("To save this part, pop up the context menu with "));
- TEXT_INSERT(_("right click and select `Save as...', "));
- TEXT_INSERT(_("or press `y' key.\n\n"));
+ g_return_if_fail(mimeinfo != NULL);
- TEXT_INSERT(_("To display this part as a text message, select "));
- TEXT_INSERT(_("`Display as text', or press `t' key.\n\n"));
+ g_node_traverse(mimeinfo->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, add_parts_func, textview);
+}
+#endif
- TEXT_INSERT(_("To open this part with external program, select "));
- TEXT_INSERT(_("`Open' or `Open with...', "));
- TEXT_INSERT(_("or double-click, or click the center button, "));
- TEXT_INSERT(_("or press `l' key."));
+static void recursive_add_parts(TextView *textview, GNode *node)
+{
+ GNode * iter;
+ MimeInfo *mimeinfo;
+
+ mimeinfo = (MimeInfo *) node->data;
+
+ textview_add_part(textview, mimeinfo);
+
+ if ((mimeinfo->type != MIMETYPE_MULTIPART) &&
+ (mimeinfo->type != MIMETYPE_MESSAGE))
+ return;
+
+ if (strcasecmp(mimeinfo->subtype, "alternative") == 0) {
+ GNode * prefered_body;
+ int prefered_score;
+
+ /*
+ text/plain : score 3
+ text/ * : score 2
+ other : score 1
+ */
+ prefered_body = NULL;
+ prefered_score = 0;
+
+ for(iter = g_node_first_child(node) ; iter != NULL ;
+ iter = g_node_next_sibling(iter)) {
+ int score;
+ MimeInfo * submime;
+
+ score = 1;
+ submime = (MimeInfo *) iter->data;
+ if (submime->type == MIMETYPE_TEXT)
+ score = 2;
+
+ if (submime->subtype != NULL) {
+ if (strcasecmp(submime->subtype, "plain") == 0)
+ score = 3;
+ }
+
+ if (score > prefered_score) {
+ prefered_score = score;
+ prefered_body = iter;
+ }
+ }
+
+ if (prefered_body != NULL) {
+ recursive_add_parts(textview, prefered_body);
+ }
+ }
+ else {
+ for(iter = g_node_first_child(node) ; iter != NULL ;
+ iter = g_node_next_sibling(iter)) {
+ recursive_add_parts(textview, iter);
+ }
+ }
+}
- gtk_stext_thaw(text);
+static void textview_add_parts(TextView *textview, MimeInfo *mimeinfo)
+{
+ g_return_if_fail(mimeinfo != NULL);
+
+ recursive_add_parts(textview, mimeinfo->node);
}
-#if USE_GPGME
-void textview_show_signature_part(TextView *textview, MimeInfo *partinfo)
+#define TEXT_INSERT(str) \
+ gtk_stext_insert(text, textview->msgfont, NULL, NULL, str, -1)
+
+void textview_show_mime_part(TextView *textview, MimeInfo *partinfo)
{
GtkSText *text;
gtk_stext_freeze(text);
- if (partinfo->sigstatus_full == NULL) {
- TEXT_INSERT(_("This signature has not been checked yet.\n"));
- TEXT_INSERT(_("To check it, pop up the context menu with\n"));
- TEXT_INSERT(_("right click and select `Check signature'.\n"));
- } else {
- TEXT_INSERT(partinfo->sigstatus_full);
- }
+ TEXT_INSERT(_("The following can be performed on this part by "));
+ TEXT_INSERT(_("right-clicking the icon or list item:\n"));
+
+ TEXT_INSERT(_(" To save select 'Save as...' (Shortcut key: 'y')\n"));
+ TEXT_INSERT(_(" To display as text select 'Display as text' "));
+ TEXT_INSERT(_("(Shortcut key: 't')\n"));
+ TEXT_INSERT(_(" To open with an external program select 'Open' "));
+ TEXT_INSERT(_("(Shortcut key: 'l'),\n"));
+ TEXT_INSERT(_(" (alternately double-click, or click the middle "));
+ TEXT_INSERT(_("mouse button),\n"));
+ TEXT_INSERT(_(" or 'Open with...' (Shortcut key: 'o')\n"));
gtk_stext_thaw(text);
}
-#endif /* USE_GPGME */
#undef TEXT_INSERT
static void textview_write_body(TextView *textview, MimeInfo *mimeinfo,
- FILE *fp, const gchar *charset)
+ const gchar *charset)
{
FILE *tmpfp;
gchar buf[BUFFSIZE];
conv = conv_code_converter_new(charset);
- tmpfp = procmime_decode_content(NULL, fp, mimeinfo);
-
textview->is_in_signature = FALSE;
- if (tmpfp) {
- if (mimeinfo->mime_type == MIME_TEXT_HTML)
+ if(mimeinfo->encoding_type != ENC_BINARY &&
+ mimeinfo->encoding_type != ENC_7BIT &&
+ mimeinfo->encoding_type != ENC_8BIT)
+ procmime_decode_content(mimeinfo);
+
+ if (!g_strcasecmp(mimeinfo->subtype, "html")) {
+ gchar *filename;
+
+ filename = procmime_get_tmp_file_name(mimeinfo);
+ if (procmime_get_part(filename, mimeinfo) == 0) {
+ tmpfp = fopen(filename, "rb");
textview_show_html(textview, tmpfp, conv);
- else if (mimeinfo->mime_type == MIME_TEXT_ENRICHED)
+ fclose(tmpfp);
+ unlink(filename);
+ }
+ g_free(filename);
+ } else if (!g_strcasecmp(mimeinfo->subtype, "enriched")) {
+ gchar *filename;
+
+ filename = procmime_get_tmp_file_name(mimeinfo);
+ if (procmime_get_part(filename, mimeinfo) == 0) {
+ tmpfp = fopen(filename, "rb");
textview_show_ertf(textview, tmpfp, conv);
- else
- while (fgets(buf, sizeof(buf), tmpfp) != NULL)
- textview_write_line(textview, buf, conv);
+ fclose(tmpfp);
+ unlink(filename);
+ }
+ g_free(filename);
+ } else {
+ tmpfp = fopen(mimeinfo->filename, "rb");
+ fseek(tmpfp, mimeinfo->offset, SEEK_SET);
+ debug_print("Viewing text content of type: %s (length: %d)\n", mimeinfo->subtype, mimeinfo->length);
+ while ((fgets(buf, sizeof(buf), tmpfp) != NULL) &&
+ (ftell(tmpfp) <= mimeinfo->offset + mimeinfo->length))
+ textview_write_line(textview, buf, conv);
fclose(tmpfp);
}
spacingfont = gdk_font_load("-*-*-medium-r-normal--6-*");
}
+void textview_set_text(TextView *textview, const gchar *text)
+{
+ GtkSText *stext;
+
+ g_return_if_fail(textview != NULL);
+ g_return_if_fail(text != NULL);
+
+ textview_clear(textview);
+
+ stext = GTK_STEXT(textview->text);
+ gtk_stext_freeze(stext);
+ gtk_stext_insert(stext, textview->msgfont, NULL, NULL, text, strlen(text));
+ gtk_stext_thaw(stext);
+}
+
enum
{
H_DATE = 0,
if (summaryview)
summary_pass_key_press_event(summaryview, event);
break;
- case GDK_n:
- case GDK_N:
- case GDK_p:
- case GDK_P:
case GDK_y:
case GDK_t:
case GDK_l:
- if (messageview->type == MVIEW_MIME &&
- textview == messageview->mimeview->textview) {
+ if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) == 0) {
KEY_PRESS_EVENT_STOP();
mimeview_pass_key_press_event(messageview->mimeview,
event);
break;
}
- /* fall through */
+ /* possible fall through */
default:
if (summaryview &&
event->window != messageview->mainwin->window->window) {
return FALSE;
}
+/*!
+ *\brief Check to see if a web URL has been disguised as a different
+ * URL (possible with HTML email).
+ *
+ *\param uri The uri to check
+ *
+ *\param textview The TextView the URL is contained in
+ *
+ *\return gboolean TRUE if the URL is ok, or if the user chose to open
+ * it anyway, otherwise FALSE
+ */
+static gboolean uri_security_check(RemoteURI *uri, TextView *textview)
+{
+ gchar *clicked_str;
+ gboolean retval = TRUE;
+
+ if (g_strncasecmp(uri->uri, "http:", 5) &&
+ g_strncasecmp(uri->uri, "https:", 6) &&
+ g_strncasecmp(uri->uri, "www.", 4))
+ return retval;
+
+ clicked_str = gtk_editable_get_chars(GTK_EDITABLE(textview->text),
+ uri->start,
+ uri->end);
+ if (clicked_str == NULL)
+ return TRUE;
+
+ if (strcmp(clicked_str, uri->uri) &&
+ (!g_strncasecmp(clicked_str, "http:", 5) ||
+ !g_strncasecmp(clicked_str, "https:", 6) ||
+ !g_strncasecmp(clicked_str, "www.", 4))) {
+ gchar *str;
+ retval = FALSE;
+
+ /* allow uri->uri == http://somewhere.com
+ and clicked_str == somewhere.com */
+ str = g_strconcat("http://", clicked_str, NULL);
+
+ if (!g_strcasecmp(str, uri->uri))
+ retval = TRUE;
+ g_free(str);
+ }
+
+ if (retval == FALSE) {
+ gchar *msg = NULL;
+ AlertValue resp;
+
+ msg = g_strdup_printf(_("The real URL (%s) is different from\n"
+ "the apparent URL (%s). \n"
+ "Open it anyway?"),
+ uri->uri, clicked_str);
+ resp = alertpanel(_("Warning"),
+ msg,
+ _("Yes"),
+ _("No"),
+ NULL);
+ g_free(msg);
+ if (resp == G_ALERTDEFAULT)
+ retval = TRUE;
+ }
+ g_free(clicked_str);
+ return retval;
+}
+
static gint textview_button_pressed(GtkWidget *widget, GdkEventButton *event,
TextView *textview)
{
}
compose_new(account, uri->uri + 7, NULL);
}
- } else
-#if USE_GPGME
- if (!g_strncasecmp(uri->uri, "pgp:", 4)) {
- GtkAdjustment *pos = gtk_scrolled_window_get_vadjustment(
- GTK_SCROLLED_WINDOW(textview->scrolledwin));
- gfloat vpos = pos->value;
- mimeview_check_signature(textview->messageview->mimeview);
- /* scroll back where we were */
- gtk_adjustment_set_value(pos, vpos);
- } else
-#endif
- {
- open_uri(uri->uri,
- prefs_common.uri_cmd);
+ } else {
+ if (uri_security_check(uri, textview) == TRUE)
+ open_uri(uri->uri,
+ prefs_common.uri_cmd);
}
+ g_free(trimmed_uri);
}
}
}