+2003-10-09 [christoph] 0.9.6claws10
+
+ * src/action.c
+ * src/compose.c
+ * src/messageview.c
+ * src/mimeview.c
+ * src/procmime.[ch]
+ * src/procmsg.c
+ * src/rfc2015.c
+ * src/textview.c
+ * src/common/utils.[ch]
+ * src/plugins/clamav/clamav_plugin.c
+ * src/plugins/dillo_viewer/dillo_viewer.c
+ * src/plugins/image_viewer/viewer.c
+ * src/plugins/mathml_viewer/mathml_viewer.c
+ new mime parser (several things need fixing)
+
2003-10-09 [paul] 0.9.6claws9
* src/imap.c
MICRO_VERSION=6
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=9
+EXTRA_VERSION=10
if test $EXTRA_VERSION -eq 0; then
VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws
else
filename = procmsg_get_message_file_path(msginfo);
part_filename = procmime_get_tmp_file_name(partinfo);
- ret = procmime_get_part(part_filename, filename, partinfo);
+ ret = procmime_get_part(part_filename, partinfo);
if (single_part)
procmime_mimeinfo_free_all(partinfo);
return tmpfile();
}
+FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
+{
+ int fd;
+
+ *filename = g_strdup_printf("%s%csylpheed.XXXXXX", dir, G_DIR_SEPARATOR);
+ fd = mkstemp(*filename);
+
+ return fdopen(fd, "w+");
+}
+
FILE *str_open_as_stream(const gchar *str)
{
FILE *fp;
return 0;
}
-FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
-{
- int fd;
-
- *filename = g_strdup_printf("%s%csylpheed.XXXXXX", dir, G_DIR_SEPARATOR);
- fd = mkstemp(*filename);
-
- return fdopen(fd, "w+");
-}
-
/* allow Mutt-like patterns in quick search */
gchar *expand_search_string(const gchar *search_string)
{
gint change_file_mode_rw (FILE *fp,
const gchar *file);
FILE *my_tmpfile (void);
+FILE *get_tmpfile_in_dir (const gchar *dir,
+ gchar **filename);
FILE *str_open_as_stream (const gchar *str);
gint str_write_to_file (const gchar *str,
const gchar *file);
}
#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->type == MIMETYPE_TEXT) || \
+ (info->type == MIMETYPE_MULTIPART && info->subtype && \
+ !strcasecmp(info->subtype, "alternative") && \
(info->children && \
- (info->children->mime_type == MIME_TEXT || \
- info->children->mime_type == MIME_TEXT_HTML || \
- info->children->mime_type == MIME_TEXT_ENRICHED))))
+ (info->children->type == MIMETYPE_TEXT))))
static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
{
infile = procmsg_get_message_file_path(msginfo);
while (child != NULL) {
- if (child->children || child->mime_type == MIME_MULTIPART) {
+ if (child->children || child->type == MIMETYPE_MULTIPART) {
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) {
+ && (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 */
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"))
+ else if (compose->mode != COMPOSE_REEDIT ||
+ !((child->type == MIMETYPE_APPLICATION) && !strcmp(child->subtype, "pgp-signature"))) {
+ 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,
- child->content_type);
+ content_type);
+ g_free(content_type);
+ }
child = child->next;
}
GSList *cur;
gchar buf[BUFFSIZE];
gint num;
- MsgFlags flag = {0, 0};
static gboolean lock = FALSE;
PrefsAccount *mailac = NULL, *newsac = NULL;
textview_set_all_headers(messageview->textview, all_headers);
textview_set_all_headers(messageview->mimeview->textview, all_headers);
- if (mimeinfo->mime_type != MIME_TEXT) {
+ if (mimeinfo->type != MIMETYPE_TEXT) {
messageview_change_view_type(messageview, MVIEW_MIME);
mimeview_show_message(messageview->mimeview, mimeinfo, file);
} else {
partinfo = gtk_ctree_node_get_row_data(ctree, node);
if (partinfo &&
- (partinfo->mime_type == MIME_TEXT ||
- partinfo->mime_type == MIME_TEXT_HTML))
+ (partinfo->type == MIMETYPE_TEXT))
break;
}
textview_show_message(mimeview->messageview->textview, mimeinfo, file);
g_return_if_fail(mimeinfo != NULL);
- if (mimeinfo->children)
- mimeinfo = mimeinfo->children;
-
while (mimeinfo != NULL) {
node = mimeview_append_part(mimeview, mimeinfo, parent);
if (mimeinfo->children)
- mimeview_set_multipart_tree(mimeview, mimeinfo, node);
- else if (mimeinfo->sub &&
- mimeinfo->sub->mime_type != MIME_TEXT &&
- mimeinfo->sub->mime_type != MIME_TEXT_HTML)
- mimeview_set_multipart_tree(mimeview, mimeinfo->sub,
- node);
+ mimeview_set_multipart_tree(mimeview, mimeinfo->children, node);
mimeinfo = mimeinfo->next;
}
}
static gchar *get_part_name(MimeInfo *partinfo)
{
-#if USE_GPGME
- if (partinfo->sigstatus)
- return partinfo->sigstatus;
- else
-#endif
- if (partinfo->name)
- return partinfo->name;
- else if (partinfo->filename)
- return partinfo->filename;
- else if (partinfo->description)
- return partinfo->description;
- else
- return "";
+ gchar *name;
+
+ name = g_hash_table_lookup(partinfo->parameters, "name");
+ if(name == NULL)
+ name = "";
+
+ return name;
}
static gchar *get_part_description(MimeInfo *partinfo)
{
if (partinfo->description)
return partinfo->description;
- else if (partinfo->name)
- return partinfo->name;
- else if (partinfo->filename)
- return partinfo->filename;
+ else if (g_hash_table_lookup(partinfo->parameters, "name") != NULL)
+ return g_hash_table_lookup(partinfo->parameters, "name");
else
return "";
}
{
GtkCTree *ctree = GTK_CTREE(mimeview->ctree);
GtkCTreeNode *node;
+ static gchar content_type[64];
gchar *str[N_MIMEVIEW_COLS];
- str[COL_MIMETYPE] =
- partinfo->content_type ? partinfo->content_type : "";
- str[COL_SIZE] = to_human_readable(partinfo->size);
+ if (partinfo->type != MIMETYPE_UNKNOWN && partinfo->subtype) {
+ snprintf(content_type, 64, "%s/%s", procmime_get_type_str(partinfo->type), partinfo->subtype);
+ } else {
+ snprintf(content_type, 64, "UNKNOWN");
+ }
+
+ str[COL_MIMETYPE] = content_type;
+ str[COL_SIZE] = to_human_readable(partinfo->length);
if (prefs_common.attach_desc)
str[COL_NAME] = get_part_description(partinfo);
else
{
FILE *fp;
const gchar *fname;
-#if USE_GPGME
- MimeInfo *pi;
-#endif
if (!partinfo) return;
-#if USE_GPGME
- for (pi = partinfo; pi && !pi->plaintextfile ; pi = pi->parent)
- ;
- fname = pi ? pi->plaintextfile : mimeview->file;
-#else
fname = mimeview->file;
-#endif /* USE_GPGME */
if (!fname) return;
if ((fp = fopen(fname, "rb")) == NULL) {
return;
}
- if (fseek(fp, partinfo->fpos, SEEK_SET) < 0) {
+ if (fseek(fp, partinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeview->file, "fseek");
fclose(fp);
return;
gchar *content_type = NULL;
MimeViewer *viewer = NULL;
- if ((partinfo->mime_type == MIME_APPLICATION_OCTET_STREAM) &&
+ if ((partinfo->type == MIMETYPE_APPLICATION) &&
+ (g_strcasecmp(partinfo->subtype, "octet-stream")) &&
(partinfo->name != NULL)) {
content_type = procmime_get_mime_type(partinfo->name);
} else {
- content_type = g_strdup(partinfo->content_type);
+ content_type = g_strdup_printf("%s/%s", procmime_get_type_str(partinfo->type), partinfo->subtype);
}
if (content_type != NULL) {
mimeview->textview->default_text = FALSE;
if (!mimeview_show_part(mimeview, partinfo)) {
- switch (partinfo->mime_type) {
- case MIME_TEXT:
- case MIME_TEXT_HTML:
- case MIME_TEXT_ENRICHED:
- case MIME_MESSAGE_RFC822:
- case MIME_MULTIPART:
+ switch (partinfo->type) {
+ case MIMETYPE_TEXT:
+ case MIMETYPE_MESSAGE:
+ case MIMETYPE_MULTIPART:
mimeview_show_message_part(mimeview, partinfo);
break;
mimeview->textview->default_text = TRUE;
mimeview_change_view_type(mimeview, MIMEVIEW_TEXT);
#if USE_GPGME
- if (g_strcasecmp(partinfo->content_type,
- "application/pgp-signature") == 0)
+ if ((partinfo->type == MIMETYPE_APPLICATION) &&
+ !g_strcasecmp(partinfo->subtype, "pgp-signature"))
textview_show_signature_part(mimeview->textview,
partinfo);
else
/* call external program for image, audio or html */
mimeview_launch(mimeview);
} else if (event->button == 3) {
- if (partinfo && (partinfo->mime_type == MIME_TEXT ||
- partinfo->mime_type == MIME_TEXT_HTML ||
- partinfo->mime_type == MIME_TEXT_ENRICHED ||
- partinfo->mime_type == MIME_MESSAGE_RFC822 ||
- partinfo->mime_type == MIME_IMAGE ||
- partinfo->mime_type == MIME_MULTIPART))
+ if (partinfo && (partinfo->type == MIMETYPE_TEXT ||
+ partinfo->type == MIMETYPE_MESSAGE ||
+ partinfo->type == MIMETYPE_IMAGE ||
+ partinfo->type == MIMETYPE_MULTIPART))
menu_set_sensitive(mimeview->popupfactory,
"/Display as text", FALSE);
else
menu_set_sensitive(mimeview->popupfactory,
"/Display as text", TRUE);
if (partinfo &&
- partinfo->mime_type == MIME_APPLICATION_OCTET_STREAM)
+ partinfo->type == MIMETYPE_APPLICATION)
menu_set_sensitive(mimeview->popupfactory,
"/Open", FALSE);
else
NULL, NULL, NULL, NULL,
event->button, event->time);
}
-
}
filename = g_strconcat(get_mime_tmp_dir(), G_DIR_SEPARATOR_S,
filename, NULL);
- if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
+ if (procmime_get_part(filename, partinfo) < 0)
alertpanel_error
(_("Can't save the part of multipart message."));
}
g_free(attachname);
- if ((G_ALERTDEFAULT != aval) || (procmime_get_part(buf, mimeview->file, attachment) < 0))
+ if ((G_ALERTDEFAULT != aval) || (procmime_get_part(buf, attachment) < 0))
alertpanel_error(_("Can't save the part of multipart message."));
attachment = attachment->next;
}
if (G_ALERTDEFAULT != aval) return;
}
- if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
+ if (procmime_get_part(filename, partinfo) < 0)
alertpanel_error
(_("Can't save the part of multipart message."));
}
filename = procmime_get_tmp_file_name(partinfo);
- if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
+ if (procmime_get_part(filename, partinfo) < 0)
alertpanel_error
(_("Can't save the part of multipart message."));
else
filename = procmime_get_tmp_file_name(partinfo);
- if (procmime_get_part(filename, mimeview->file, partinfo) < 0) {
+ if (procmime_get_part(filename, partinfo) < 0) {
alertpanel_error
(_("Can't save the part of multipart message."));
g_free(filename);
if (cmdline) {
cmd = cmdline;
def_cmd = NULL;
- } else if (MIME_APPLICATION_OCTET_STREAM == partinfo->mime_type) {
+ } else if (MIMETYPE_APPLICATION == partinfo->type) {
return;
- } else if (MIME_IMAGE == partinfo->mime_type) {
+ } else if (MIMETYPE_IMAGE == partinfo->type) {
cmd = prefs_common.mime_image_viewer;
def_cmd = default_image_cmdline;
- } else if (MIME_AUDIO == partinfo->mime_type) {
+ } else if (MIMETYPE_AUDIO == partinfo->type) {
cmd = prefs_common.mime_audio_player;
def_cmd = default_audio_cmdline;
- } else if (MIME_TEXT_HTML == partinfo->mime_type) {
+ } else if (MIMETYPE_TEXT == partinfo->type && !strcmp(partinfo->subtype, "html")) {
cmd = prefs_common.uri_cmd;
def_cmd = default_html_cmdline;
} else {
+ gchar *content_type;
+
+ content_type = g_strdup_printf("%s/%s", procmime_get_type_str(partinfo->type), partinfo->subtype);
g_snprintf(m_buf, sizeof(m_buf), mime_cmdline,
- partinfo->content_type, "%s");
+ content_type, "%s");
+ g_free(content_type);
cmd = m_buf;
def_cmd = NULL;
}
partinfo = mimeview_get_selected_part(mimeview);
if (!partinfo) return;
- if (g_strcasecmp(partinfo->content_type,
- "application/pgp-signature") == 0) {
+ if ((partinfo->type == MIMETYPE_APPLICATION) &&
+ !g_strcasecmp(partinfo->subtype, "application/pgp-signature")) {
mimeview_change_view_type(mimeview, MIMEVIEW_TEXT);
textview_show_signature_part(mimeview->textview, partinfo);
}
static void icon_selected (MimeView *mimeview, gint num, MimeInfo *partinfo)
{
- if (num == 1 && (partinfo->mime_type == MIME_TEXT ||
- partinfo->mime_type == MIME_TEXT_HTML)) {
+ if (num == 1 && (partinfo->type == MIMETYPE_TEXT)) {
gtk_notebook_set_page(GTK_NOTEBOOK(mimeview->notebook), 0);
/* don't set the ctree, as it will unload the plugin, and
* we want to be able to switch quickly between the text
gtk_object_set_data(GTK_OBJECT(button), "partinfo",
mimeinfo);
- switch (mimeinfo->mime_type) {
+ switch (mimeinfo->type) {
- case MIME_TEXT:
- case MIME_MESSAGE_RFC822:
- stockp = STOCK_PIXMAP_MIME_TEXT_PLAIN;
+ case MIMETYPE_TEXT:
+ if (mimeinfo->subtype && !g_strcasecmp(mimeinfo->subtype, "html"))
+ stockp = STOCK_PIXMAP_MIME_TEXT_HTML;
+ else if (mimeinfo->subtype && !g_strcasecmp(mimeinfo->subtype, "enriched"))
+ stockp = STOCK_PIXMAP_MIME_TEXT_ENRICHED;
+ else
+ stockp = STOCK_PIXMAP_MIME_TEXT_PLAIN;
break;
- case MIME_TEXT_HTML:
- stockp = STOCK_PIXMAP_MIME_TEXT_HTML;
+ case MIMETYPE_MESSAGE:
+ stockp = STOCK_PIXMAP_MIME_TEXT_PLAIN;
break;
- case MIME_APPLICATION:
+ case MIMETYPE_APPLICATION:
#ifdef USE_GPGME
- if (mimeinfo->content_type
- && g_strcasecmp(mimeinfo->content_type,
- "application/pgp-signature") == 0) {
+ if (mimeinfo->subtype && !g_strcasecmp(mimeinfo->subtype, "pgp-signature")) {
if (mimeinfo->sigstatus_full) {
desc = mimeinfo->sigstatus;
if (mimeinfo->sig_ok)
} else
stockp = STOCK_PIXMAP_MIME_GPG_SIGNED;
} else
+
#endif
+ if (mimeinfo->subtype && !g_strcasecmp(mimeinfo->subtype, "octet-stream"))
+ stockp = STOCK_PIXMAP_MIME_APPLICATION_OCTET_STREAM;
+ else
stockp = STOCK_PIXMAP_MIME_APPLICATION;
break;
- case MIME_APPLICATION_OCTET_STREAM:
- stockp = STOCK_PIXMAP_MIME_APPLICATION_OCTET_STREAM;
- break;
- case MIME_IMAGE:
+ case MIMETYPE_IMAGE:
stockp = STOCK_PIXMAP_MIME_IMAGE;
break;
- case MIME_AUDIO:
+ case MIMETYPE_AUDIO:
stockp = STOCK_PIXMAP_MIME_AUDIO;
break;
- case MIME_TEXT_ENRICHED:
- stockp = STOCK_PIXMAP_MIME_TEXT_ENRICHED;
- break;
default:
stockp = STOCK_PIXMAP_MIME_UNKNOWN;
break;
else
desc = get_part_name(mimeinfo);
}
+
if (desc && *desc)
- tip = g_strdup_printf("%s\n%s\n%s", desc, mimeinfo->content_type,
- to_human_readable(mimeinfo->size));
+ tip = g_strdup_printf("%s\n%s/%s\n%s", desc,
+ procmime_get_type_str(mimeinfo->type),
+ mimeinfo->subtype,
+ to_human_readable(mimeinfo->length));
else
- tip = g_strdup_printf("%s\n%s", mimeinfo->content_type,
- to_human_readable(mimeinfo->size));
+ tip = g_strdup_printf("%s/%s\n%s",
+ procmime_get_type_str(mimeinfo->type),
+ mimeinfo->subtype,
+ to_human_readable(mimeinfo->length));
gtk_tooltips_set_tip(mimeview->tooltips, button, tip, NULL);
g_free(tip);
while (mimeinfo != NULL) {
if (mimeinfo->children)
icon_list_create(mimeview, mimeinfo);
- else if (mimeinfo->sub &&
- mimeinfo->sub->mime_type != MIME_TEXT &&
- mimeinfo->sub->mime_type != MIME_TEXT_HTML)
- icon_list_create(mimeview, mimeinfo->sub);
else
icon_list_append_icon(mimeview, mimeinfo);
mimeinfo = mimeinfo->next;
infile = procmsg_get_message_file_path(msginfo);
-
if((ret = cl_loaddbdir(cl_retdbdir(), &root, &no))) {
debug_print("cl_loaddbdir: %s\n", cl_perror(ret));
exit(2);
while (child != NULL) {
if(child->parent && child->parent->parent
- && !strcasecmp(child->parent->parent->content_type, "multipart/signed")
- && child->mime_type == MIME_TEXT) {
+ && (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 */
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 {
debug_print("Scanning %s\n", outfile);
viewer->filename = procmime_get_tmp_file_name(partinfo);
- if (!(procmime_get_part(viewer->filename, infile, partinfo) < 0)) {
+ if (!(procmime_get_part(viewer->filename, partinfo) < 0)) {
gchar *cmd;
if (viewer->socket)
gchar *imgfile;
imgfile = procmime_get_tmp_file_name(imageviewer->mimeinfo);
- if (procmime_get_part(imgfile, imageviewer->file, imageviewer->mimeinfo) < 0) {
+ if (procmime_get_part(imgfile, imageviewer->mimeinfo) < 0) {
g_warning("Can't get mimepart file");
g_free(imgfile);
return;
image_viewer_load_image(imageviewer);
else {
gtk_label_set_text(GTK_LABEL(imageviewer->filename), mimeinfo->filename);
- gtk_label_set_text(GTK_LABEL(imageviewer->filesize), to_human_readable(mimeinfo->size));
- gtk_label_set_text(GTK_LABEL(imageviewer->content_type), mimeinfo->content_type);
+ gtk_label_set_text(GTK_LABEL(imageviewer->filesize), to_human_readable(mimeinfo->length));
+ gtk_label_set_text(GTK_LABEL(imageviewer->content_type), mimeinfo->subtype);
}
}
viewer->filename = procmime_get_tmp_file_name(partinfo);
- if (!(procmime_get_part(viewer->filename, infile, partinfo) < 0)) {
+ if (!(procmime_get_part(viewer->filename, partinfo) < 0)) {
gchar *uri;
uri = g_strconcat("file://", viewer->filename, NULL);
#include <string.h>
#include <locale.h>
#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include "intl.h"
#include "procmime.h"
MimeInfo *mimeinfo;
mimeinfo = g_new0(MimeInfo, 1);
- mimeinfo->mime_type = MIME_UNKNOWN;
+ mimeinfo->type = MIMETYPE_UNKNOWN;
mimeinfo->encoding_type = ENC_UNKNOWN;
+ mimeinfo->parameters = g_hash_table_new(g_str_hash, g_str_equal);
+
return mimeinfo;
}
+static gboolean procmime_mimeinfo_parameters_destroy(gpointer key, gpointer value, gpointer user_data)
+{
+ g_free(key);
+ g_free(value);
+
+ return TRUE;
+}
+
void procmime_mimeinfo_free_all(MimeInfo *mimeinfo)
{
while (mimeinfo != NULL) {
MimeInfo *next;
g_free(mimeinfo->encoding);
- g_free(mimeinfo->content_type);
g_free(mimeinfo->charset);
g_free(mimeinfo->name);
- g_free(mimeinfo->boundary);
g_free(mimeinfo->content_disposition);
+ if(mimeinfo->tmpfile)
+ unlink(mimeinfo->filename);
g_free(mimeinfo->filename);
+
+ procmime_mimeinfo_free_all(mimeinfo->children);
+ g_free(mimeinfo->subtype);
g_free(mimeinfo->description);
-#if USE_GPGME
- g_free(mimeinfo->plaintextfile);
+ g_free(mimeinfo->id);
+
g_free(mimeinfo->sigstatus);
g_free(mimeinfo->sigstatus_full);
-#endif
- procmime_mimeinfo_free_all(mimeinfo->sub);
- procmime_mimeinfo_free_all(mimeinfo->children);
-#if USE_GPGME
- procmime_mimeinfo_free_all(mimeinfo->plaintext);
-#endif
+ g_hash_table_foreach_remove(mimeinfo->parameters, procmime_mimeinfo_parameters_destroy, NULL);
+ g_hash_table_destroy(mimeinfo->parameters);
next = mimeinfo->next;
g_free(mimeinfo);
if (mimeinfo->children)
return mimeinfo->children;
- if (mimeinfo->sub)
- return mimeinfo->sub;
if (mimeinfo->next)
return mimeinfo->next;
return NULL;
}
-#if 0
-void procmime_dump_mimeinfo(MimeInfo *mimeinfo)
-{
- gint i;
-
- g_print("\n");
-
- for (; mimeinfo != NULL; mimeinfo = procmime_mimeinfo_next(mimeinfo)) {
- for (i = 0; i < mimeinfo->level; i++)
- g_print(" ");
- g_print("%s%s\n", mimeinfo->main ? "sub: " : "",
- mimeinfo->content_type);
- }
-}
-#endif
-
MimeInfo *procmime_scan_message(MsgInfo *msginfo)
{
- FILE *fp;
+ gchar *filename;
MimeInfo *mimeinfo;
- g_return_val_if_fail(msginfo != NULL, NULL);
-
-#if USE_GPGME
- if ((fp = procmsg_open_message_decrypted(msginfo, &mimeinfo)) == NULL)
+ filename = procmsg_get_message_file(msginfo);
+ if(!filename)
return NULL;
-#else
- if ((fp = procmsg_open_message(msginfo)) == NULL) return NULL;
- mimeinfo = procmime_scan_mime_header(fp);
-#endif
-
- if (mimeinfo) {
- mimeinfo->size = get_left_file_size(fp);
- if (mimeinfo->mime_type == MIME_MULTIPART ||
- mimeinfo->mime_type == MIME_MESSAGE_RFC822)
- procmime_scan_multipart_message(mimeinfo, fp);
- }
-
- fclose(fp);
-
- return mimeinfo;
-}
-
-void procmime_scan_multipart_message(MimeInfo *mimeinfo, FILE *fp)
-{
- gchar *p;
- gchar *boundary;
- gint boundary_len = 0;
- gchar buf[BUFFSIZE];
- glong fpos, prev_fpos;
-
- g_return_if_fail(mimeinfo != NULL);
- g_return_if_fail(mimeinfo->mime_type == MIME_MULTIPART ||
- mimeinfo->mime_type == MIME_MESSAGE_RFC822);
-
- if (mimeinfo->mime_type == MIME_MULTIPART) {
- g_return_if_fail(mimeinfo->boundary != NULL);
- g_return_if_fail(mimeinfo->sub == NULL);
- }
- g_return_if_fail(fp != NULL);
-
- boundary = mimeinfo->boundary;
-
- if (boundary) {
- boundary_len = strlen(boundary);
-
- /* look for first boundary */
- while ((p = fgets(buf, sizeof(buf), fp)) != NULL)
- if (IS_BOUNDARY(buf, boundary, boundary_len)) break;
- if (!p) return;
- } else if (mimeinfo->parent && mimeinfo->parent->boundary) {
- boundary = mimeinfo->parent->boundary;
- boundary_len = strlen(boundary);
- }
-
- if ((fpos = ftell(fp)) < 0) {
- perror("ftell");
- return;
- }
-
- for (;;) {
- MimeInfo *partinfo;
- gboolean eom = FALSE;
- gint len;
-
- prev_fpos = fpos;
- debug_print("prev_fpos: %ld\n", fpos);
-
- if (mimeinfo->mime_type == MIME_MESSAGE_RFC822) {
- MimeInfo *sub;
-
- mimeinfo->sub = sub = procmime_scan_mime_header(fp);
- if (!sub) break;
-
- sub->level = mimeinfo->level + 1;
- sub->parent = mimeinfo->parent;
- sub->main = mimeinfo;
-
- partinfo = sub;
- } else {
- partinfo = procmime_scan_mime_header(fp);
- if (!partinfo) break;
- procmime_mimeinfo_insert(mimeinfo, partinfo);
- debug_print("content-type: %s\n",
- partinfo->content_type);
- }
-
- if (partinfo->mime_type == MIME_MULTIPART ||
- partinfo->mime_type == MIME_MESSAGE_RFC822) {
- if (partinfo->level < 8)
- procmime_scan_multipart_message(partinfo, fp);
- }
-
- /* look for next boundary */
- buf[0] = '\0';
- while ((p = fgets(buf, sizeof(buf), fp)) != NULL) {
- if (IS_BOUNDARY(buf, boundary, boundary_len)) {
- if (buf[2 + boundary_len] == '-' &&
- buf[2 + boundary_len + 1] == '-')
- eom = TRUE;
- break;
- }
- }
- if (p == NULL) {
- /* broken MIME, or single part MIME message */
- buf[0] = '\0';
- eom = TRUE;
- }
- debug_print("boundary: %s\n", buf);
-
- fpos = ftell(fp);
- debug_print("fpos: %ld\n", fpos);
-
- len = strlen(buf);
- partinfo->size = fpos - prev_fpos - len;
- debug_print("partinfo->size: %d\n", partinfo->size);
- if (partinfo->sub && !partinfo->sub->sub &&
- !partinfo->sub->children) {
- partinfo->sub->size =
- fpos - partinfo->sub->fpos - strlen(buf);
- debug_print("partinfo->sub->size: %d\n",
- partinfo->sub->size);
- }
-
- if (mimeinfo->mime_type == MIME_MESSAGE_RFC822) {
- if (len > 0 && fseek(fp, fpos - len, SEEK_SET) < 0)
- perror("fseek");
- break;
- }
-
- if (eom) break;
- }
-}
-
-void procmime_scan_encoding(MimeInfo *mimeinfo, const gchar *encoding)
-{
- gchar *buf;
-
- Xstrdup_a(buf, encoding, return);
-
- g_free(mimeinfo->encoding);
-
- mimeinfo->encoding = g_strdup(g_strstrip(buf));
- if (!strcasecmp(buf, "7bit"))
- mimeinfo->encoding_type = ENC_7BIT;
- else if (!strcasecmp(buf, "8bit"))
- mimeinfo->encoding_type = ENC_8BIT;
- else if (!strcasecmp(buf, "quoted-printable"))
- mimeinfo->encoding_type = ENC_QUOTED_PRINTABLE;
- else if (!strcasecmp(buf, "base64"))
- mimeinfo->encoding_type = ENC_BASE64;
- else if (!strcasecmp(buf, "x-uuencode"))
- mimeinfo->encoding_type = ENC_X_UUENCODE;
+ if (msginfo->folder->stype != F_QUEUE)
+ mimeinfo = procmime_scan_file(filename);
else
- mimeinfo->encoding_type = ENC_UNKNOWN;
-
-}
-
-void procmime_scan_content_type(MimeInfo *mimeinfo, const gchar *content_type)
-{
- gchar *delim, *p, *cnttype;
- gchar *buf;
-
- if (conv_get_current_charset() == C_EUC_JP &&
- strchr(content_type, '\033')) {
- gint len;
- len = strlen(content_type) * 2 + 1;
- Xalloca(buf, len, return);
- conv_jistoeuc(buf, len, content_type);
- } else
- Xstrdup_a(buf, content_type, return);
-
- g_free(mimeinfo->content_type);
- g_free(mimeinfo->charset);
- /* g_free(mimeinfo->name); */
- mimeinfo->content_type = NULL;
- mimeinfo->charset = NULL;
- /* mimeinfo->name = NULL; */
-
- if ((delim = strchr(buf, ';'))) *delim = '\0';
- mimeinfo->content_type = cnttype = g_strdup(g_strstrip(buf));
-
- mimeinfo->mime_type = procmime_scan_mime_type(cnttype);
-
- if (!delim) return;
- p = delim + 1;
-
- for (;;) {
- gchar *eq;
- gchar *attr, *value;
-
- if ((delim = strchr(p, ';'))) *delim = '\0';
-
- if (!(eq = strchr(p, '='))) break;
-
- *eq = '\0';
- attr = p;
- g_strstrip(attr);
- value = eq + 1;
- g_strstrip(value);
-
- if (*value == '"')
- extract_quote(value, '"');
- else {
- eliminate_parenthesis(value, '(', ')');
- g_strstrip(value);
- }
-
- if (*value) {
- if (!strcasecmp(attr, "charset"))
- mimeinfo->charset = g_strdup(value);
- else if (!strcasecmp(attr, "name")) {
- gchar *tmp;
- size_t len;
-
- len = strlen(value) + 1;
- Xalloca(tmp, len, return);
- conv_unmime_header(tmp, len, value, NULL);
- g_free(mimeinfo->name);
- /*pgp signatures should NOT have a name */
- if (mimeinfo->content_type
- && strcasecmp(mimeinfo->content_type, "application/pgp-signature"))
- mimeinfo->name = g_strdup(tmp);
- } else if (!strcasecmp(attr, "boundary"))
- mimeinfo->boundary = g_strdup(value);
- }
-
- if (!delim) break;
- p = delim + 1;
- }
-
- if (mimeinfo->mime_type == MIME_MULTIPART && !mimeinfo->boundary)
- mimeinfo->mime_type = MIME_TEXT;
-}
-
-void procmime_scan_content_disposition(MimeInfo *mimeinfo,
- const gchar *content_disposition)
-{
- gchar *delim, *p, *dispos;
- gchar *buf;
-
- if (conv_get_current_charset() == C_EUC_JP &&
- strchr(content_disposition, '\033')) {
- gint len;
- len = strlen(content_disposition) * 2 + 1;
- Xalloca(buf, len, return);
- conv_jistoeuc(buf, len, content_disposition);
- } else
- Xstrdup_a(buf, content_disposition, return);
-
- if ((delim = strchr(buf, ';'))) *delim = '\0';
- mimeinfo->content_disposition = dispos = g_strdup(g_strstrip(buf));
-
- if (!delim) return;
- p = delim + 1;
-
- for (;;) {
- gchar *eq;
- gchar *attr, *value;
-
- if ((delim = strchr(p, ';'))) *delim = '\0';
-
- if (!(eq = strchr(p, '='))) break;
-
- *eq = '\0';
- attr = p;
- g_strstrip(attr);
- value = eq + 1;
- g_strstrip(value);
-
- if (*value == '"')
- extract_quote(value, '"');
- else {
- eliminate_parenthesis(value, '(', ')');
- g_strstrip(value);
- }
-
- if (*value) {
- if (!strcasecmp(attr, "filename")) {
- gchar *tmp;
- size_t len;
-
- len = strlen(value) + 1;
- Xalloca(tmp, len, return);
- conv_unmime_header(tmp, len, value, NULL);
- g_free(mimeinfo->filename);
- /*pgp signatures should NOT have a name */
- if (mimeinfo->content_type
- && strcasecmp(mimeinfo->content_type, "application/pgp-signature"))
- mimeinfo->filename = g_strdup(tmp);
- break;
- }
- }
-
- if (!delim) break;
- p = delim + 1;
- }
-}
-
-void procmime_scan_content_description(MimeInfo *mimeinfo,
- const gchar *content_description)
-{
- gchar *buf;
-
- gchar *tmp;
- size_t blen;
-
- if (conv_get_current_charset() == C_EUC_JP &&
- strchr(content_description, '\033')) {
- gint len;
- len = strlen(content_description) * 2 + 1;
- Xalloca(buf, len, return);
- conv_jistoeuc(buf, len, content_description);
- } else
- Xstrdup_a(buf, content_description, return);
-
- blen = strlen(buf) + 1;
- Xalloca(tmp, blen, return);
- conv_unmime_header(tmp, blen, buf, NULL);
- /*pgp signatures should NOT have a name */
- if (mimeinfo->content_type
- && strcasecmp(mimeinfo->content_type, "application/pgp-signature"))
- mimeinfo->description = g_strdup(tmp);
-}
-
-void procmime_scan_subject(MimeInfo *mimeinfo,
- const gchar *subject)
-{
- gchar *buf;
-
- gchar *tmp;
- size_t blen;
+ mimeinfo = procmime_scan_queue_file(filename);
+ g_free(filename);
- if (conv_get_current_charset() == C_EUC_JP &&
- strchr(subject, '\033')) {
- gint len;
- len = strlen(subject) * 2 + 1;
- Xalloca(buf, len, return);
- conv_jistoeuc(buf, len, subject);
- } else
- Xstrdup_a(buf, subject, return);
-
- blen = strlen(buf) + 1;
- Xalloca(tmp, blen, return);
- conv_unmime_header(tmp, blen, buf, NULL);
- g_free(mimeinfo->name);
- mimeinfo->name = g_strdup(tmp);
+ return mimeinfo;
}
enum
H_SUBJECT = 4
};
-MimeInfo *procmime_scan_mime_header(FILE *fp)
+gboolean procmime_decode_content(MimeInfo *mimeinfo)
{
- static HeaderEntry hentry[] = {{"Content-Transfer-Encoding:",
- NULL, FALSE},
- {"Content-Type:", NULL, TRUE},
- {"Content-Disposition:",
- NULL, TRUE},
- {"Content-description:",
- NULL, TRUE},
- {"Subject:",
- NULL, TRUE},
- {NULL, NULL, FALSE}};
gchar buf[BUFFSIZE];
- gint hnum;
- HeaderEntry *hp;
- MimeInfo *mimeinfo;
+ gint readend;
+ gchar *tmpfilename;
+ gchar *mimetmpdir;
+ FILE *outfp, *infp;
+ struct stat statbuf;
- g_return_val_if_fail(fp != NULL, NULL);
-
- mimeinfo = procmime_mimeinfo_new();
- mimeinfo->mime_type = MIME_TEXT;
- mimeinfo->encoding_type = ENC_7BIT;
- mimeinfo->fpos = ftell(fp);
-
- while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, hentry))
- != -1) {
- hp = hentry + hnum;
-
- if (H_CONTENT_TRANSFER_ENCODING == hnum) {
- procmime_scan_encoding
- (mimeinfo, buf + strlen(hp->name));
- } else if (H_CONTENT_TYPE == hnum) {
- procmime_scan_content_type
- (mimeinfo, buf + strlen(hp->name));
- } else if (H_CONTENT_DISPOSITION == hnum) {
- procmime_scan_content_disposition
- (mimeinfo, buf + strlen(hp->name));
- } else if (H_CONTENT_DESCRIPTION == hnum) {
- procmime_scan_content_description
- (mimeinfo, buf + strlen(hp->name));
- } else if (H_SUBJECT == hnum) {
- procmime_scan_subject
- (mimeinfo, buf + strlen(hp->name));
- }
- }
-
- if (!mimeinfo->content_type)
- mimeinfo->content_type = g_strdup("text/plain");
-
- return mimeinfo;
-}
+ g_return_val_if_fail(mimeinfo != NULL, FALSE);
-FILE *procmime_decode_content(FILE *outfp, FILE *infp, MimeInfo *mimeinfo)
-{
- gchar buf[BUFFSIZE];
- gchar *boundary = NULL;
- gint boundary_len = 0;
- gboolean tmp_file = FALSE;
+ if(mimeinfo->encoding_type == ENC_BINARY)
+ return TRUE;
- g_return_val_if_fail(infp != NULL, NULL);
- g_return_val_if_fail(mimeinfo != NULL, NULL);
+ infp = fopen(mimeinfo->filename, "rb");
+ if(!infp) {
+ perror("fopen");
+ return FALSE;
+ }
+ fseek(infp, mimeinfo->offset, SEEK_SET);
+ mimetmpdir = get_mime_tmp_dir();
+ outfp = get_tmpfile_in_dir(mimetmpdir, &tmpfilename);
if (!outfp) {
- outfp = my_tmpfile();
- if (!outfp) {
- perror("tmpfile");
- return NULL;
- }
- tmp_file = TRUE;
+ perror("tmpfile");
+ return FALSE;
}
- if (mimeinfo->parent && mimeinfo->parent->boundary) {
- boundary = mimeinfo->parent->boundary;
- boundary_len = strlen(boundary);
- }
+ readend = mimeinfo->offset + mimeinfo->length;
if (mimeinfo->encoding_type == ENC_QUOTED_PRINTABLE) {
- while (fgets(buf, sizeof(buf), infp) != NULL &&
- (!boundary ||
- !IS_BOUNDARY(buf, boundary, boundary_len))) {
+ while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
gint len;
len = qp_decode_line(buf);
fwrite(buf, len, 1, outfp);
Base64Decoder *decoder;
decoder = base64_decoder_new();
- while (fgets(buf, sizeof(buf), infp) != NULL &&
- (!boundary ||
- !IS_BOUNDARY(buf, boundary, boundary_len))) {
+ while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
len = base64_decoder_decode(decoder, buf, outbuf);
if (len < 0) {
g_warning("Bad BASE64 content\n");
gint len;
gboolean flag = FALSE;
- while (fgets(buf, sizeof(buf), infp) != NULL &&
- (!boundary ||
- !IS_BOUNDARY(buf, boundary, boundary_len))) {
+ while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
if(!flag && strncmp(buf,"begin ", 6)) continue;
if (flag) {
flag = TRUE;
}
} else {
- while (fgets(buf, sizeof(buf), infp) != NULL &&
- (!boundary ||
- !IS_BOUNDARY(buf, boundary, boundary_len))) {
+ while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
fputs(buf, outfp);
}
}
- if (tmp_file) rewind(outfp);
- return outfp;
+ fclose(outfp);
+ fclose(infp);
+
+ stat(tmpfilename, &statbuf);
+ if(mimeinfo->tmpfile)
+ unlink(mimeinfo->filename);
+ g_free(mimeinfo->filename);
+ mimeinfo->filename = tmpfilename;
+ mimeinfo->tmpfile = TRUE;
+ mimeinfo->offset = 0;
+ mimeinfo->length = statbuf.st_size;
+ mimeinfo->encoding_type = ENC_BINARY;
+
+ return TRUE;
}
-gint procmime_get_part(const gchar *outfile, const gchar *infile,
- MimeInfo *mimeinfo)
+gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
{
FILE *infp, *outfp;
gchar buf[BUFFSIZE];
+ gint restlength, readlength;
g_return_val_if_fail(outfile != NULL, -1);
- g_return_val_if_fail(infile != NULL, -1);
g_return_val_if_fail(mimeinfo != NULL, -1);
- if ((infp = fopen(infile, "rb")) == NULL) {
- FILE_OP_ERROR(infile, "fopen");
+ if(mimeinfo->encoding_type != ENC_BINARY && !procmime_decode_content(mimeinfo))
+ return -1;
+
+ if ((infp = fopen(mimeinfo->filename, "rb")) == NULL) {
+ FILE_OP_ERROR(mimeinfo->filename, "fopen");
return -1;
}
- if (fseek(infp, mimeinfo->fpos, SEEK_SET) < 0) {
- FILE_OP_ERROR(infile, "fseek");
+ if (fseek(infp, mimeinfo->offset, SEEK_SET) < 0) {
+ FILE_OP_ERROR(mimeinfo->filename, "fseek");
fclose(infp);
return -1;
}
return -1;
}
- while (fgets(buf, sizeof(buf), infp) != NULL)
- if (buf[0] == '\r' || buf[0] == '\n') break;
+ restlength = mimeinfo->length;
- procmime_decode_content(outfp, infp, mimeinfo);
+ while ((restlength > 0) && ((readlength = fread(buf, 1, restlength > BUFFSIZE ? BUFFSIZE : restlength, infp)) > 0)) {
+ fwrite(buf, 1, readlength, outfp);
+ restlength -= readlength;
+ }
fclose(infp);
if (fclose(outfp) == EOF) {
FILE *procmime_get_text_content(MimeInfo *mimeinfo, FILE *infp)
{
+ return NULL;
+
+#if 0 /* FIXME */
FILE *tmpfp, *outfp;
gchar *src_codeset;
gboolean conv_fail = FALSE;
rewind(outfp);
return outfp;
+#endif
}
/* search the first text part of (multipart) MIME message,
decode, convert it and output to outfp. */
FILE *procmime_get_first_text_content(MsgInfo *msginfo)
{
+ return NULL;
+
+#if 0 /* FIXME */
FILE *infp, *outfp = NULL;
MimeInfo *mimeinfo, *partinfo;
procmime_mimeinfo_free_all(mimeinfo);
return outfp;
+#endif
}
gboolean procmime_find_string_part(MimeInfo *mimeinfo, const gchar *filename,
const gchar *str, gboolean case_sens)
{
+ return FALSE;
+#if 0 /* FIXME */
FILE *infp, *outfp;
gchar buf[BUFFSIZE];
gchar *(* StrFindFunc) (const gchar *haystack, const gchar *needle);
fclose(outfp);
return FALSE;
+#endif
}
gboolean procmime_find_string(MsgInfo *msginfo, const gchar *str,
gboolean case_sens)
{
+ return FALSE;
+
+#if 0 /* FIXME */
MimeInfo *mimeinfo;
MimeInfo *partinfo;
gchar *filename;
g_free(filename);
return found;
+#endif
}
gchar *procmime_get_tmp_file_name(MimeInfo *mimeinfo)
g_snprintf(f_prefix, sizeof(f_prefix), "%08x.", id++);
- if (MIME_TEXT_HTML == mimeinfo->mime_type)
+ if ((mimeinfo->type == MIMETYPE_TEXT) && !g_strcasecmp(mimeinfo->subtype, "html"))
base = "mimetmp.html";
else {
base = mimeinfo->filename ? mimeinfo->filename
return filename;
}
-ContentType procmime_scan_mime_type(const gchar *mime_type)
-{
- ContentType type;
-
- if (!strncasecmp(mime_type, "text/html", 9))
- type = MIME_TEXT_HTML;
- else if (!strncasecmp(mime_type, "text/enriched", 13))
- type = MIME_TEXT_ENRICHED;
- else if (!strncasecmp(mime_type, "text/", 5))
- type = MIME_TEXT;
- else if (!strncasecmp(mime_type, "message/rfc822", 14))
- type = MIME_MESSAGE_RFC822;
- else if (!strncasecmp(mime_type, "message/", 8))
- type = MIME_TEXT;
- else if (!strncasecmp(mime_type, "application/octet-stream", 24))
- type = MIME_APPLICATION_OCTET_STREAM;
- else if (!strncasecmp(mime_type, "application/", 12))
- type = MIME_APPLICATION;
- else if (!strncasecmp(mime_type, "multipart/", 10))
- type = MIME_MULTIPART;
- else if (!strncasecmp(mime_type, "image/", 6))
- type = MIME_IMAGE;
- else if (!strncasecmp(mime_type, "audio/", 6))
- type = MIME_AUDIO;
- else if (!strcasecmp(mime_type, "text"))
- type = MIME_TEXT;
- else
- type = MIME_UNKNOWN;
-
- return type;
-}
-
static GList *mime_type_list = NULL;
gchar *procmime_get_mime_type(const gchar *filename)
}
return NULL;
}
+
+/* --- NEW MIME STUFF --- */
+struct TypeTable
+{
+ gchar *str;
+ MimeMediaType type;
+};
+
+static struct TypeTable mime_type_table[] = {
+ {"text", MIMETYPE_TEXT},
+ {"image", MIMETYPE_IMAGE},
+ {"audio", MIMETYPE_AUDIO},
+ {"video", MIMETYPE_VIDEO},
+ {"application", MIMETYPE_APPLICATION},
+ {"message", MIMETYPE_MESSAGE},
+ {"multipart", MIMETYPE_MULTIPART},
+ {NULL, 0},
+};
+
+const gchar *procmime_get_type_str(MimeMediaType type)
+{
+ struct TypeTable *type_table;
+
+ for (type_table = mime_type_table; type_table->str != NULL; type_table++) {
+ if (type_table->type == type)
+ return type_table->str;
+ }
+ return NULL;
+}
+
+MimeInfo *procmime_parse_mimepart(MimeInfo *parent,
+ gchar *content_type,
+ gchar *content_encoding,
+ gchar *content_description,
+ gchar *content_id,
+ FILE *fp,
+ const gchar *filename,
+ guint offset,
+ guint length);
+
+void procmime_parse_message_rfc822(MimeInfo *mimeinfo, FILE *fp)
+{
+ HeaderEntry hentry[] = {{"Content-Type:", NULL, TRUE},
+ {"Content-Transfer-Encoding:",
+ NULL, FALSE},
+ {"Content-Description:",
+ NULL, TRUE},
+ {"Content-ID:",
+ NULL, TRUE},
+ {NULL, NULL, FALSE}};
+ guint content_start, i;
+
+ fseek(fp, mimeinfo->offset, SEEK_SET);
+ procheader_get_header_fields(fp, hentry);
+ content_start = ftell(fp);
+
+ mimeinfo->children = procmime_parse_mimepart(mimeinfo,
+ hentry[0].body, hentry[1].body,
+ hentry[2].body, hentry[3].body,
+ fp, mimeinfo->filename, content_start,
+ mimeinfo->length - (content_start - mimeinfo->offset));
+ for (i = 0; i < 4; i++) {
+ g_free(hentry[i].body);
+ hentry[i].body = NULL;
+ }
+}
+
+void procmime_parse_multipart(MimeInfo *mimeinfo, FILE *fp)
+{
+ HeaderEntry hentry[] = {{"Content-Type:", NULL, TRUE},
+ {"Content-Transfer-Encoding:",
+ NULL, FALSE},
+ {"Content-Description:",
+ NULL, TRUE},
+ {"Content-ID:",
+ NULL, TRUE},
+ {NULL, NULL, FALSE}};
+ gchar *p;
+ gchar *boundary;
+ gint boundary_len = 0, lastoffset = -1, i;
+ gchar buf[BUFFSIZE];
+ MimeInfo *lastmimeinfo = NULL;
+
+ boundary = g_hash_table_lookup(mimeinfo->parameters, "boundary");
+ if(!boundary)
+ return;
+ boundary_len = strlen(boundary);
+
+ fseek(fp, mimeinfo->offset, SEEK_SET);
+ while ((p = fgets(buf, sizeof(buf), fp)) != NULL) {
+ if (ftell(fp) > (mimeinfo->offset + mimeinfo->length))
+ break;
+
+ if (IS_BOUNDARY(buf, boundary, boundary_len)) {
+ if(lastoffset != -1) {
+ MimeInfo *newmimeinfo = NULL;
+
+ newmimeinfo = procmime_parse_mimepart(mimeinfo,
+ hentry[0].body, hentry[1].body,
+ hentry[2].body, hentry[3].body,
+ fp, mimeinfo->filename, lastoffset,
+ (ftell(fp) - strlen(buf)) - lastoffset);
+
+ if (lastmimeinfo == NULL)
+ mimeinfo->children = newmimeinfo;
+ else
+ lastmimeinfo->next = newmimeinfo;
+ lastmimeinfo = newmimeinfo;
+ }
+
+ if (buf[2 + boundary_len] == '-' &&
+ buf[2 + boundary_len + 1] == '-')
+ break;
+
+ for (i = 0; i < 4; i++) {
+ g_free(hentry[i].body);
+ hentry[i].body = NULL;
+ }
+ procheader_get_header_fields(fp, hentry);
+ lastoffset = ftell(fp);
+ }
+ }
+}
+
+static void procmime_parse_content_type(const gchar *content_type, MimeInfo *mimeinfo)
+{
+ gchar **content_type_parts;
+ gchar **strarray;
+ gchar *str;
+ struct TypeTable *typetablearray;
+
+ /* Split content type into parts and remove trailing
+ and leading whitespaces from all strings */
+ content_type_parts = g_strsplit(content_type, ";", 0);
+ for (strarray = content_type_parts; *strarray != NULL; strarray++) {
+ g_strstrip(*strarray);
+ }
+
+ /* Get mimeinfo->type and mimeinfo->subtype */
+ mimeinfo->type = MIMETYPE_UNKNOWN;
+ str = content_type_parts[0];
+ for (typetablearray = mime_type_table; typetablearray->str != NULL; typetablearray++) {
+ if (g_strncasecmp(str, typetablearray->str, strlen(typetablearray->str)) == 0 &&
+ str[strlen(typetablearray->str)] == '/') {
+ mimeinfo->type = typetablearray->type;
+ mimeinfo->subtype = g_strdup(str + strlen(typetablearray->str) + 1);
+ break;
+ }
+ }
+
+ /* Get mimeinfo->parmeters */
+ for (strarray = &content_type_parts[1]; *strarray != NULL; strarray++) {
+ gchar **parameters_parts;
+
+ parameters_parts = g_strsplit(*strarray, "=", 1);
+ g_strdown(parameters_parts[0]);
+ if(parameters_parts[1][0] == '"')
+ extract_quote(parameters_parts[1], '"');
+
+ g_hash_table_insert(mimeinfo->parameters,
+ g_strdup(parameters_parts[0]),
+ g_strdup(parameters_parts[1]));
+
+ g_strfreev(parameters_parts);
+ }
+
+ g_strfreev(content_type_parts);
+}
+
+static void procmime_parse_content_encoding(const gchar *content_encoding, MimeInfo *mimeinfo)
+{
+ struct EncodingTable *enc_table;
+
+ for (enc_table = encoding_table; enc_table->str != NULL; enc_table++) {
+ if (g_strcasecmp(enc_table->str, content_encoding) == 0) {
+ mimeinfo->encoding_type = enc_table->enc_type;
+ return;
+ }
+ }
+ mimeinfo->encoding_type = ENC_UNKNOWN;
+ return;
+}
+
+MimeInfo *procmime_parse_mimepart(MimeInfo *parent,
+ gchar *content_type,
+ gchar *content_encoding,
+ gchar *content_description,
+ gchar *content_id,
+ FILE *fp,
+ const gchar *filename,
+ guint offset,
+ guint length)
+{
+ MimeInfo *mimeinfo;
+ guint oldpos;
+
+ g_return_val_if_fail(fp != NULL, NULL);
+
+ /* Create MimeInfo */
+ mimeinfo = procmime_mimeinfo_new();
+ mimeinfo->parent = parent;
+ mimeinfo->filename = g_strdup(filename);
+ mimeinfo->offset = offset;
+ mimeinfo->length = length;
+
+ if (content_type != NULL) {
+ procmime_parse_content_type(content_type, mimeinfo);
+ } else {
+ mimeinfo->type = MIMETYPE_TEXT;
+ mimeinfo->subtype = g_strdup("plain");
+ g_hash_table_insert(mimeinfo->parameters, g_strdup("charset"), g_strdup("us-ascii"));
+ }
+
+ if (content_encoding != NULL) {
+ procmime_parse_content_encoding(content_encoding, mimeinfo);
+ } else {
+ mimeinfo->encoding_type = ENC_7BIT;
+ }
+
+ if (content_description != NULL)
+ mimeinfo->description = g_strdup(content_description);
+ else
+ mimeinfo->description = NULL;
+
+ if (content_id != NULL)
+ mimeinfo->id = g_strdup(content_id);
+ else
+ mimeinfo->id = NULL;
+
+ oldpos = ftell(fp);
+ /* Call parser for mime type */
+ switch (mimeinfo->type) {
+ case MIMETYPE_MESSAGE:
+ if (g_strcasecmp(mimeinfo->subtype, "rfc822") == 0) {
+ procmime_parse_message_rfc822(mimeinfo, fp);
+ }
+ break;
+
+ case MIMETYPE_MULTIPART:
+ procmime_parse_multipart(mimeinfo, fp);
+ break;
+
+ default:
+ break;
+ }
+ fseek(fp, oldpos, SEEK_SET);
+
+ return mimeinfo;
+}
+
+static gchar *typenames[] = {
+ "text",
+ "image",
+ "audio",
+ "video",
+ "application",
+ "message",
+ "multipart",
+ "unknown",
+};
+
+static void output_mime_structure(MimeInfo *mimeinfo, int indent)
+{
+ int i;
+
+ for(i = 0; i < indent; i++)
+ printf(" ");
+ printf("%s/%s (offset:%d length:%d encoding: %d)\n", typenames[mimeinfo->type], mimeinfo->subtype, mimeinfo->offset, mimeinfo->length, mimeinfo->encoding_type);
+
+ if(mimeinfo->children)
+ output_mime_structure(mimeinfo->children, indent + 4);
+ if(mimeinfo->next)
+ output_mime_structure(mimeinfo->next, indent);
+}
+
+MimeInfo *procmime_scan_fp(FILE *fp, const gchar *filename)
+{
+ MimeInfo *mimeinfo;
+ gint offset;
+ struct stat stat;
+
+ fstat(fileno(fp), &stat);
+ offset = ftell(fp);
+
+ mimeinfo = procmime_parse_mimepart(NULL, "message/rfc822", "binary", NULL, NULL, fp, filename, offset, stat.st_size - offset);
+ output_mime_structure(mimeinfo, 0);
+
+ return mimeinfo;
+}
+
+MimeInfo *procmime_scan_file(gchar *filename)
+{
+ FILE *fp;
+ MimeInfo *mimeinfo;
+
+ g_return_val_if_fail(filename != NULL, NULL);
+
+ /* Open file */
+ if((fp = fopen(filename, "rb")) == NULL)
+ return NULL;
+
+ mimeinfo = procmime_scan_fp(fp, filename);
+
+ fclose(fp);
+
+ return mimeinfo;
+}
+
+MimeInfo *procmime_scan_queue_file(gchar *filename)
+{
+ FILE *fp;
+ MimeInfo *mimeinfo;
+ gchar buf[BUFFSIZE];
+
+ g_return_val_if_fail(filename != NULL, NULL);
+
+ /* Open file */
+ if((fp = fopen(filename, "rb")) == NULL)
+ return NULL;
+
+ /* Skip queue header */
+ while (fgets(buf, sizeof(buf), fp) != NULL)
+ if (buf[0] == '\r' || buf[0] == '\n') break;
+
+ mimeinfo = procmime_scan_fp(fp, filename);
+
+ fclose(fp);
+
+ return mimeinfo;
+}
ENC_UNKNOWN
} EncodingType;
-typedef enum
-{
- MIME_TEXT,
- MIME_TEXT_HTML,
- MIME_MESSAGE_RFC822,
- MIME_APPLICATION,
- MIME_APPLICATION_OCTET_STREAM,
- MIME_MULTIPART,
- MIME_IMAGE,
- MIME_AUDIO,
- MIME_TEXT_ENRICHED,
- MIME_UNKNOWN
-} ContentType;
-
#include "procmsg.h"
struct _MimeType
gchar *extension;
};
+typedef enum
+{
+ MIMETYPE_TEXT,
+ MIMETYPE_IMAGE,
+ MIMETYPE_AUDIO,
+ MIMETYPE_VIDEO,
+ MIMETYPE_APPLICATION,
+ MIMETYPE_MESSAGE,
+ MIMETYPE_MULTIPART,
+ MIMETYPE_UNKNOWN,
+} MimeMediaType;
+
/*
* An example of MimeInfo structure:
*
{
gchar *encoding;
- EncodingType encoding_type;
- ContentType mime_type;
-
- gchar *content_type;
gchar *charset;
gchar *name;
- gchar *boundary;
gchar *content_disposition;
- gchar *filename;
- gchar *description;
-
- glong fpos;
- guint size;
MimeInfo *main;
- MimeInfo *sub;
+
+ gint level;
+
+ /* Internal data */
+ gchar *filename;
+ gboolean tmpfile;
MimeInfo *next;
MimeInfo *parent;
MimeInfo *children;
-#if USE_GPGME
- MimeInfo *plaintext;
- gchar *plaintextfile;
+ /* --- NEW MIME STUFF --- */
+ /* Content-Type */
+ MimeMediaType type;
+ gchar *subtype;
+
+ GHashTable *parameters;
+
+ /* Content-Transfer-Encoding */
+ EncodingType encoding_type;
+
+ /* Content-Description */
+ gchar *description;
+
+ /* Content-ID */
+ gchar *id;
+
+ guint offset;
+ guint length;
+
+ /* Privacy */
gchar *sigstatus;
gchar *sigstatus_full;
gboolean sig_ok;
gboolean sig_unknown;
gboolean sig_expired;
gboolean key_expired;
-#endif
-
- gint level;
};
#define IS_BOUNDARY(s, bnd, len) \
const gchar *subject);
MimeInfo *procmime_scan_mime_header (FILE *fp);
-FILE *procmime_decode_content (FILE *outfp,
- FILE *infp,
- MimeInfo *mimeinfo);
+gboolean procmime_decode_content (MimeInfo *mimeinfo);
gint procmime_get_part (const gchar *outfile,
- const gchar *infile,
MimeInfo *mimeinfo);
FILE *procmime_get_text_content (MimeInfo *mimeinfo,
FILE *infp);
gchar *procmime_get_tmp_file_name (MimeInfo *mimeinfo);
-ContentType procmime_scan_mime_type (const gchar *mime_type);
gchar *procmime_get_mime_type (const gchar *filename);
GList *procmime_get_mime_type_list (void);
EncodingType procmime_get_encoding_for_charset (const gchar *charset);
EncodingType procmime_get_encoding_for_file (const gchar *file);
const gchar *procmime_get_encoding_str (EncodingType encoding);
+MimeInfo *procmime_scan_file (gchar *filename);
+MimeInfo *procmime_scan_queue_file (gchar *filename);
+const gchar *procmime_get_type_str (MimeMediaType type);
void renderer_read_config(void);
void renderer_write_config(void);
return fp;
}
-#if USE_GPGME
-FILE *procmsg_open_message_decrypted(MsgInfo *msginfo, MimeInfo **mimeinfo)
-{
- FILE *fp;
- MimeInfo *mimeinfo_;
- glong fpos;
-
- g_return_val_if_fail(msginfo != NULL, NULL);
-
- if (mimeinfo) *mimeinfo = NULL;
-
- if ((fp = procmsg_open_message(msginfo)) == NULL) return NULL;
-
- mimeinfo_ = procmime_scan_mime_header(fp);
- if (!mimeinfo_) {
- fclose(fp);
- return NULL;
- }
-
- if (!MSG_IS_ENCRYPTED(msginfo->flags) &&
- rfc2015_is_encrypted(mimeinfo_)) {
- MSG_SET_TMP_FLAGS(msginfo->flags, MSG_ENCRYPTED);
- }
-
- if (MSG_IS_ENCRYPTED(msginfo->flags) &&
- !msginfo->plaintext_file &&
- !msginfo->decryption_failed) {
- fpos = ftell(fp);
- rfc2015_decrypt_message(msginfo, mimeinfo_, fp);
- if (msginfo->plaintext_file &&
- !msginfo->decryption_failed) {
- fclose(fp);
- procmime_mimeinfo_free_all(mimeinfo_);
- if ((fp = procmsg_open_message(msginfo)) == NULL)
- return NULL;
- mimeinfo_ = procmime_scan_mime_header(fp);
- if (!mimeinfo_) {
- fclose(fp);
- return NULL;
- }
- } else {
- if (fseek(fp, fpos, SEEK_SET) < 0)
- perror("fseek");
- }
- }
-
- if (mimeinfo) *mimeinfo = mimeinfo_;
- return fp;
-}
-#endif
-
gboolean procmsg_msg_exist(MsgInfo *msginfo)
{
gchar *path;
/* don't include the last empty line.
It does not belong to the signed text */
- if (mimeinfo->children->size > 0) {
- if (fseek(fp, mimeinfo->children->fpos + mimeinfo->children->size - 1,
+ if (mimeinfo->children->length > 0) {
+ if (fseek(fp, mimeinfo->children->offset + mimeinfo->children->length - 1,
SEEK_SET) < 0) {
perror("fseek");
goto leave;
}
if (fgetc(fp) == '\n') {
n_exclude_chars++;
- if (mimeinfo->children->size > 1) {
- if (fseek(fp, mimeinfo->children->fpos + mimeinfo->children->size - 2,
+ if (mimeinfo->children->length > 1) {
+ if (fseek(fp, mimeinfo->children->offset + mimeinfo->children->length - 2,
SEEK_SET) < 0) {
perror("fseek");
goto leave;
/* canonicalize the file part. */
tmp_file = get_tmp_file();
- if (copy_file_part(fp, mimeinfo->children->fpos,
- mimeinfo->children->size - n_exclude_chars,
+ if (copy_file_part(fp, mimeinfo->children->offset,
+ mimeinfo->children->length - n_exclude_chars,
tmp_file) < 0) {
g_free(tmp_file);
goto leave;
if (!err)
err = gpgme_data_new_from_filepart (&sig, NULL, fp,
- partinfo->fpos, partinfo->size);
+ partinfo->offset, partinfo->length);
if (err) {
debug_print ("gpgme_data_new_from_filepart failed: %s\n",
gpgme_strerror (err));
}
err = gpgme_data_new_from_filepart (&cipher, NULL, fp,
- partinfo->fpos, partinfo->size);
+ partinfo->offset, partinfo->length);
if (err) {
debug_print ("gpgme_data_new_from_filepart failed: %s\n",
gpgme_strerror (err));
if (!mimeinfo)
return NULL;
- if (g_strcasecmp (mimeinfo->content_type, "multipart/signed"))
+ if (!((mimeinfo->type == MIMETYPE_MULTIPART) && !g_strcasecmp(mimeinfo->subtype, "signed")))
return NULL;
debug_print ("** multipart/signed encountered\n");
/* check that we have at least 2 parts of the correct type */
for (partinfo = mimeinfo->children;
partinfo != NULL; partinfo = partinfo->next) {
- if (++n > 1 && !g_strcasecmp (partinfo->content_type,
- "application/pgp-signature"))
+ if (++n > 1 && (partinfo->type == MIMETYPE_APPLICATION &&
+ !g_strcasecmp (partinfo->subtype, "pgp-signature")))
break;
}
int rfc2015_is_encrypted (MimeInfo *mimeinfo)
{
- if (!mimeinfo || mimeinfo->mime_type != MIME_MULTIPART)
+ if (!mimeinfo || mimeinfo->type != MIMETYPE_MULTIPART)
return 0;
- if (g_strcasecmp (mimeinfo->content_type, "multipart/encrypted"))
+ if (g_strcasecmp (mimeinfo->subtype, "encrypted"))
return 0;
/* fixme: we should check the protocol parameter */
return 1;
{
FILE *fp;
MimeInfo *mimeinfo;
- int ret;
+ int ret = 0;
+#if 0 /* FIXME */
if ((fp = fopen(file, "rb")) == NULL)
return FALSE;
ret = rfc2015_is_encrypted(mimeinfo);
procmime_mimeinfo_free_all(mimeinfo);
+#endif
return ret != 0 ? TRUE : FALSE;
}
g_return_if_fail (msginfo != NULL);
g_return_if_fail (mimeinfo != NULL);
g_return_if_fail (fp != NULL);
- g_return_if_fail (mimeinfo->mime_type == MIME_MULTIPART);
+ g_return_if_fail (mimeinfo->type == MIMETYPE_MULTIPART);
debug_print ("** decrypting multipart/encrypted message\n");
+#if 0 /* FIXME */
+
/* skip headers */
- if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
+ if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0)
perror("fseek");
tmpinfo = procmime_scan_mime_header(fp);
- if (!tmpinfo || tmpinfo->mime_type != MIME_MULTIPART) {
+ if (!tmpinfo || tmpinfo->type != MIMETYPE_MULTIPART) {
DECRYPTION_ABORT();
}
- procmime_scan_multipart_message(tmpinfo, fp);
+ procmime_scan_message(tmpinfo);
/* check that we have the 2 parts */
partinfo = tmpinfo->children;
if (!partinfo || !partinfo->next) {
DECRYPTION_ABORT();
}
- if (!g_strcasecmp (partinfo->content_type, "application/pgp-encrypted")) {
+ if ((partinfo->type == MIMETYPE_APPLICATION) && !g_strcasecmp(partinfo->subtype, "pgp-encrypted")) {
/* Fixme: check that the version is 1 */
ver_ok = 1;
}
partinfo = partinfo->next;
- if (ver_ok &&
- !g_strcasecmp (partinfo->content_type, "application/octet-stream")) {
+ if (ver_ok && (partinfo->type == MIMETYPE_APPLICATION) &&
+ !g_strcasecmp (partinfo->subtype, "octet-stream")) {
if (partinfo->next)
g_warning ("oops: pgp_encrypted with more than 2 parts");
}
}
/* write the orginal header to the new file */
- if (fseek(fp, tmpinfo->fpos, SEEK_SET) < 0)
+ if (fseek(fp, tmpinfo->offset, SEEK_SET) < 0)
perror("fseek");
in_cline = 0;
msginfo->plaintext_file = fname;
msginfo->decryption_failed = 0;
+
+#endif
}
#undef DECRYPTION_ABORT
GtkSText *text;
FILE *fp;
const gchar *charset = NULL;
- GPtrArray *headers = NULL;
if ((fp = fopen(file, "rb")) == NULL) {
FILE_OP_ERROR(file, "fopen");
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);
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);
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)
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)
+*/
+ if (mimeinfo->type == MIMETYPE_MULTIPART)
textview_add_parts(textview, mimeinfo, fp);
else
textview_write_body(textview, mimeinfo, fp, charset);
{
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) {
+ if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) {
perror("fseek");
return;
}
- if (mimeinfo->parent && mimeinfo->parent->boundary) {
- boundary = mimeinfo->parent->boundary;
- boundary_len = strlen(boundary);
- }
-
- while (fgets(buf, sizeof(buf), fp) != NULL)
- if (buf[0] == '\r' || buf[0] == '\n') break;
-
- if (mimeinfo->mime_type == MIME_MESSAGE_RFC822) {
+ if ((mimeinfo->type == MIMETYPE_MESSAGE) && !g_strcasecmp(mimeinfo->subtype, "rfc822")) {
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);
#if USE_GPGME
if (mimeinfo->sigstatus)
- g_snprintf(buf, sizeof(buf), "\n[%s (%s)]\n",
- mimeinfo->content_type, mimeinfo->sigstatus);
+ g_snprintf(buf, sizeof(buf), "\n[%s/%s (%s)]\n",
+ procmime_get_type_str(mimeinfo->type),
+ mimeinfo->subtype, 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);
+ g_snprintf(buf, sizeof(buf), "\n[%s/%s (%d bytes)]\n",
+ procmime_get_type_str(mimeinfo->type),
+ mimeinfo->subtype, mimeinfo->length);
#if USE_GPGME
if (mimeinfo->sigstatus && !mimeinfo->sigstatus_full) {
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) {
+ 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)
+ else 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;
gtk_stext_thaw(text);
}
-static void textview_add_parts(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
+static void textview_add_parts_func(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
{
- gint level;
-
g_return_if_fail(mimeinfo != NULL);
g_return_if_fail(fp != NULL);
- level = mimeinfo->level;
-
- for (;;) {
+ while (mimeinfo) {
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;
+ if(mimeinfo->children)
+ textview_add_parts_func(textview, mimeinfo->children, fp);
+ mimeinfo = mimeinfo->next;
}
}
+static void textview_add_parts(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
+{
+ g_return_if_fail(mimeinfo != NULL);
+ g_return_if_fail(fp != NULL);
+
+ textview_add_part(textview, mimeinfo, fp);
+ if(mimeinfo->children)
+ textview_add_parts_func(textview, mimeinfo->children, fp);
+}
+
#define TEXT_INSERT(str) \
gtk_stext_insert(text, textview->msgfont, NULL, NULL, str, -1)
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);
}