X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Fprocmime.c;h=97585cc3c1128c678225241330a30a78f8be88bf;hp=075b710a15fbca320b199f5e137e3c19d45e15d1;hb=99a7382d8fc0b91c98475ec8c92c9a86975accc7;hpb=334a0c19774f5ca6b85c0bb11d4220f0b6544467 diff --git a/src/procmime.c b/src/procmime.c index 075b710a1..97585cc3c 100644 --- a/src/procmime.c +++ b/src/procmime.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * Copyright (C) 1999-2003 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ #include "procmime.h" #include "procheader.h" #include "base64.h" +#include "quoted-printable.h" #include "uuencode.h" #include "unmime.h" #include "html.h" @@ -45,7 +46,7 @@ # include "rfc2015.h" #endif -#include "prefs.h" +#include "prefs_gtk.h" static GHashTable *procmime_get_mime_type_table (void); @@ -60,28 +61,6 @@ MimeInfo *procmime_mimeinfo_new(void) return mimeinfo; } -void procmime_mimeinfo_free(MimeInfo *mimeinfo) -{ - if (!mimeinfo) return; - - 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); - g_free(mimeinfo->filename); -#if USE_GPGME - g_free(mimeinfo->plaintextfile); - g_free(mimeinfo->sigstatus); - g_free(mimeinfo->sigstatus_full); -#endif - - procmime_mimeinfo_free(mimeinfo->sub); - - g_free(mimeinfo); -} - void procmime_mimeinfo_free_all(MimeInfo *mimeinfo) { while (mimeinfo != NULL) { @@ -168,6 +147,12 @@ MimeInfo *procmime_mimeinfo_next(MimeInfo *mimeinfo) if (mimeinfo->next) return mimeinfo->next; + if (mimeinfo->main) { + mimeinfo = mimeinfo->main; + if (mimeinfo->next) + return mimeinfo->next; + } + for (mimeinfo = mimeinfo->parent; mimeinfo != NULL; mimeinfo = mimeinfo->parent) { if (mimeinfo->next) @@ -244,12 +229,12 @@ void procmime_scan_multipart_message(MimeInfo *mimeinfo, FILE *fp) return; } - for (npart = 0;; npart++) { MimeInfo *partinfo; gboolean eom = FALSE; prev_fpos = fpos; + debug_print("prev_fpos: %ld\n", fpos); partinfo = procmime_scan_mime_header(fp); if (!partinfo) break; @@ -263,14 +248,20 @@ void procmime_scan_multipart_message(MimeInfo *mimeinfo, FILE *fp) partinfo->sub = sub = procmime_scan_mime_header(fp); if (!sub) break; + sub->level = partinfo->level + 1; - sub->parent = partinfo->parent; + sub->parent = partinfo; sub->main = partinfo; - if (sub->mime_type == MIME_MULTIPART) { - if (sub->level < 8) + if (sub->level < 8) { + if (sub->mime_type == MIME_MULTIPART) { procmime_scan_multipart_message (sub, fp); + } else if (sub->mime_type == MIME_MESSAGE_RFC822) { + fseek(fp, sub->fpos, SEEK_SET); + procmime_scan_multipart_message + (sub, fp); + } } } @@ -284,11 +275,23 @@ void procmime_scan_multipart_message(MimeInfo *mimeinfo, FILE *fp) break; } } - if (p == NULL) - eom = TRUE; /* broken MIME message */ + if (p == NULL) { + /* broken MIME, or single part MIME message */ + buf[0] = '\0'; + eom = TRUE; + } fpos = ftell(fp); + debug_print("fpos: %ld\n", fpos); partinfo->size = fpos - prev_fpos - strlen(buf); + 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); + } + debug_print("boundary: %s\n", buf); if (eom) break; } @@ -379,7 +382,10 @@ void procmime_scan_content_type(MimeInfo *mimeinfo, const gchar *content_type) Xalloca(tmp, len, return); conv_unmime_header(tmp, len, value, NULL); g_free(mimeinfo->name); - mimeinfo->name = g_strdup(tmp); + /*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); } @@ -443,7 +449,10 @@ void procmime_scan_content_disposition(MimeInfo *mimeinfo, Xalloca(tmp, len, return); conv_unmime_header(tmp, len, value, NULL); g_free(mimeinfo->filename); - mimeinfo->filename = g_strdup(tmp); + /*pgp signatures should NOT have a name */ + if (mimeinfo->content_type + && strcasecmp(mimeinfo->content_type, "application/pgp-signature")) + mimeinfo->filename = g_strdup(tmp); break; } } @@ -456,7 +465,6 @@ void procmime_scan_content_disposition(MimeInfo *mimeinfo, void procmime_scan_content_description(MimeInfo *mimeinfo, const gchar *content_description) { - gchar *delim, *p, *dispos; gchar *buf; gchar *tmp; @@ -475,13 +483,16 @@ void procmime_scan_content_description(MimeInfo *mimeinfo, Xalloca(tmp, blen, return); conv_unmime_header(tmp, blen, buf, NULL); g_free(mimeinfo->name); - mimeinfo->name = g_strdup(tmp); + mimeinfo->name = NULL; + /*pgp signatures should NOT have a name */ + if (mimeinfo->content_type + && strcasecmp(mimeinfo->content_type, "application/pgp-signature")) + mimeinfo->name = g_strdup(tmp); } void procmime_scan_subject(MimeInfo *mimeinfo, const gchar *subject) { - gchar *delim, *p, *dispos; gchar *buf; gchar *tmp; @@ -597,15 +608,12 @@ FILE *procmime_decode_content(FILE *outfp, FILE *infp, MimeInfo *mimeinfo) } if (mimeinfo->encoding_type == ENC_QUOTED_PRINTABLE) { - gboolean softline = FALSE; - while (fgets(buf, sizeof(buf), infp) != NULL && (!boundary || !IS_BOUNDARY(buf, boundary, boundary_len))) { - guchar *p = buf; - - softline = DoOneQPLine(&p, FALSE, softline); - fwrite(buf, p - (guchar *)buf, 1, outfp); + gint len; + len = qp_decode_line(buf); + fwrite(buf, len, 1, outfp); } } else if (mimeinfo->encoding_type == ENC_BASE64) { gchar outbuf[BUFFSIZE]; @@ -667,7 +675,7 @@ gint procmime_get_part(const gchar *outfile, const gchar *infile, g_return_val_if_fail(infile != NULL, -1); g_return_val_if_fail(mimeinfo != NULL, -1); - if ((infp = fopen(infile, "r")) == NULL) { + if ((infp = fopen(infile, "rb")) == NULL) { FILE_OP_ERROR(infile, "fopen"); return -1; } @@ -676,7 +684,7 @@ gint procmime_get_part(const gchar *outfile, const gchar *infile, fclose(infp); return -1; } - if ((outfp = fopen(outfile, "w")) == NULL) { + if ((outfp = fopen(outfile, "wb")) == NULL) { FILE_OP_ERROR(outfile, "fopen"); fclose(infp); return -1; @@ -736,7 +744,7 @@ void renderer_read_config(void) renderer_list = NULL; rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, RENDERER_RC, NULL); - f = fopen(rcpath, "r"); + f = fopen(rcpath, "rb"); g_free(rcpath); if (f == NULL) @@ -756,8 +764,6 @@ void renderer_read_config(void) if (cr == NULL) continue; - printf("%s %s\n", cr->content_type, cr->renderer); - renderer_list = g_list_append(renderer_list, cr); } @@ -766,7 +772,6 @@ void renderer_read_config(void) void renderer_write_config(void) { - int i; gchar * rcpath; PrefFile *pfile; GList * cur; @@ -774,7 +779,7 @@ void renderer_write_config(void) rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, RENDERER_RC, NULL); if ((pfile = prefs_write_open(rcpath)) == NULL) { - g_warning(_("failed to write configuration to file\n")); + g_warning("failed to write configuration to file\n"); g_free(rcpath); return; } @@ -788,8 +793,8 @@ void renderer_write_config(void) renderer->renderer); } - if (prefs_write_close(pfile) < 0) { - g_warning(_("failed to write configuration to file\n")); + if (prefs_file_close(pfile) < 0) { + g_warning("failed to write configuration to file\n"); return; } } @@ -801,7 +806,6 @@ FILE *procmime_get_text_content(MimeInfo *mimeinfo, FILE *infp) gboolean conv_fail = FALSE; gchar buf[BUFFSIZE]; gchar *str; - int i; struct ContentRenderer * renderer; GList * cur; @@ -900,7 +904,7 @@ FILE *procmime_get_text_content(MimeInfo *mimeinfo, FILE *infp) } if (conv_fail) - g_warning(_("procmime_get_text_content(): Code conversion failed.\n")); + g_warning("procmime_get_text_content(): Code conversion failed.\n"); fclose(tmpfp); rewind(outfp); @@ -959,7 +963,7 @@ gboolean procmime_find_string_part(MimeInfo *mimeinfo, const gchar *filename, mimeinfo->mime_type == MIME_TEXT_ENRICHED, FALSE); g_return_val_if_fail(str != NULL, FALSE); - if ((infp = fopen(filename, "r")) == NULL) { + if ((infp = fopen(filename, "rb")) == NULL) { FILE_OP_ERROR(filename, "fopen"); return FALSE; } @@ -1039,6 +1043,8 @@ gchar *procmime_get_tmp_file_name(MimeInfo *mimeinfo) : mimeinfo->name ? mimeinfo->name : "mimetmp"; base = g_basename(base); if (*base == '\0') base = "mimetmp"; + Xstrdup_a(base, base, return NULL); + subst_for_filename(base); } filename = g_strconcat(get_mime_tmp_dir(), G_DIR_SEPARATOR_S, @@ -1182,8 +1188,8 @@ GList *procmime_get_mime_type_list(void) if (mime_type_list) return mime_type_list; - if ((fp = fopen("/etc/mime.types", "r")) == NULL) { - if ((fp = fopen(SYSCONFDIR "/mime.types", "r")) == NULL) { + if ((fp = fopen("/etc/mime.types", "rb")) == NULL) { + if ((fp = fopen(SYSCONFDIR "/mime.types", "rb")) == NULL) { FILE_OP_ERROR(SYSCONFDIR "/mime.types", "fopen"); return NULL; } @@ -1232,21 +1238,66 @@ EncodingType procmime_get_encoding_for_charset(const gchar *charset) else if (!strncasecmp(charset, "ISO-2022-", 9) || !strcasecmp(charset, "US-ASCII")) return ENC_7BIT; + else if (!strcasecmp(charset, "ISO-8859-5") || + !strncasecmp(charset, "KOI8-", 5) || + !strcasecmp(charset, "Windows-1251")) + return ENC_8BIT; + else if (!strncasecmp(charset, "ISO-8859-", 9)) + return ENC_QUOTED_PRINTABLE; else return ENC_8BIT; - /* return ENC_BASE64; */ - /* return ENC_QUOTED_PRINTABLE; */ } -const gchar *procmime_get_encoding_str(EncodingType encoding) +EncodingType procmime_get_encoding_for_file(const gchar *file) { - static const gchar *encoding_str[] = { - "7bit", "8bit", "quoted-printable", "base64", "x-uuencode", - NULL - }; + FILE *fp; + guchar buf[BUFSIZ]; + size_t len; - if (encoding >= ENC_7BIT && encoding <= ENC_UNKNOWN) - return encoding_str[encoding]; - else - return NULL; + if ((fp = fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + return ENC_UNKNOWN; + } + + while ((len = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) { + guchar *p; + gint i; + + for (p = buf, i = 0; i < len; p++, i++) { + if (*p & 0x80) { + fclose(fp); + return ENC_BASE64; + } + } + } + + fclose(fp); + return ENC_7BIT; +} + +struct EncodingTable +{ + gchar *str; + EncodingType enc_type; +}; + +struct EncodingTable encoding_table[] = { + {"7bit", ENC_7BIT}, + {"8bit", ENC_8BIT}, + {"binary", ENC_BINARY}, + {"quoted-printable", ENC_QUOTED_PRINTABLE}, + {"base64", ENC_BASE64}, + {"x-uuencode", ENC_UNKNOWN}, + {NULL, ENC_UNKNOWN}, +}; + +const gchar *procmime_get_encoding_str(EncodingType encoding) +{ + struct EncodingTable *enc_table; + + for (enc_table = encoding_table; enc_table->str != NULL; enc_table++) { + if (enc_table->enc_type == encoding) + return enc_table->str; + } + return NULL; }