Compare commits

..

6 commits

Author SHA1 Message Date
gfgit 9af4ccb9ad PGPMime: return full decrypted message instead of first child 2023-08-26 20:03:23 +02:00
gfgit f3f7e7ad45 TextView: move header extraction to textview_process_headers()
Allow to extract headers from MULTIPART messages too
2023-08-26 20:02:20 +02:00
gfgit 40734845db Substitute Subject header when decrypting
- New procmsg_extract_subject() to get better subject from
  MIME child parts recursively
- Use it for HeaderView and SummaryView
2023-08-26 19:58:10 +02:00
gfgit 6710e0ec6b PGP/MIME: fix leak of MimeInfo if parsing fails 2023-08-26 19:48:03 +02:00
gfgit 9d0d7ecc8d CMake: enable GPGME plugin sources 2023-08-26 19:45:35 +02:00
gfgit 21d139a922 Add initial CMake project file 2023-08-19 17:45:14 +02:00
18 changed files with 373 additions and 548 deletions

View file

@ -348,4 +348,3 @@ contributors (in addition to the above; based on Changelog)
Sakaguchi Takayuki
Charles Huber
nycex
Holger Smolinski

View file

@ -1152,10 +1152,9 @@ AC_ARG_ENABLE(libravatar-plugin,
[ --disable-libravatar-plugin Do not build libravatar plugin],
[enable_libravatar_plugin=$enableval], [enable_libravatar_plugin=auto])
dnl disabled by default
AC_ARG_ENABLE(litehtml_viewer-plugin,
[ --enable-litehtml_viewer-plugin Build litehtml_viewer plugin],
[enable_litehtml_viewer_plugin=$enableval], [enable_litehtml_viewer_plugin=no])
[ --disable-litehtml_viewer-plugin Do not build litehtml_viewer plugin],
[enable_litehtml_viewer_plugin=$enableval], [enable_litehtml_viewer_plugin=auto])
AC_ARG_ENABLE(mailmbox-plugin,
[ --disable-mailmbox-plugin Do not build mailmbox plugin],
@ -1726,7 +1725,7 @@ if test x"$enable_litehtml_viewer_plugin" != xno; then
if test x"$dependencies_missing" = x; then
PLUGINS="$PLUGINS litehtml_viewer"
AC_MSG_RESULT(yes)
elif test x"$enable_litehtml_viewer_plugin" = xyes; then
elif test x"$enable_litehtml_viewer_plugin" = xauto; then
AC_MSG_RESULT(no)
AC_MSG_WARN("Plugin litehtml_viewer will not be built; missing $dependencies_missing")
enable_litehtml_viewer_plugin=no

View file

@ -1431,6 +1431,25 @@ gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
messageview_set_menu_sensitive(messageview);
messageview->msginfo = msginfo;
}
// Extract a better subject from encrypted content
gchar *alt_subject = procmsg_extract_subject(mimeinfo);
if(alt_subject) {
g_free(messageview->msginfo->subject);
messageview->msginfo->subject = alt_subject;
GtkCMCTreeNode *summary_node = summary_find_msg_by_msgnum(
messageview->mainwin->summaryview,
messageview->msginfo->msgnum);
GtkCMCTree *ctree = GTK_CMCTREE(messageview->mainwin->summaryview->ctree);
gtk_cmctree_node_set_pixtext(ctree,
summary_node,
ctree->tree_column,
alt_subject,
0, NULL);
}
if (prefs_common.display_header_pane)
headerview_show(messageview->headerview, messageview->msginfo);

View file

@ -1690,7 +1690,7 @@ static void mimeview_drag_data_get(GtkWidget *widget,
subst_for_filename(name);
}
}
g_ptr_array_free(headers, TRUE);
procheader_header_array_destroy(headers);
}
}
if (fp != NULL)

View file

@ -1,6 +1,6 @@
/*
* Claws Mail -- a GTK based, lightweight, and fast e-mail client
* Copyright (C) 2016-2023 The Claws Mail Team
* Copyright (C) 2016-2021 The Claws Mail Team
*
* 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
@ -14,6 +14,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
@ -266,7 +267,6 @@ void primary_passphrase_change(const gchar *oldp, const gchar *newp)
}
#endif
#ifdef PASSWORD_CRYPTO_OLD
gchar *password_encrypt_old(const gchar *password)
{
if (!password || strlen(password) == 0) {
@ -285,10 +285,7 @@ gchar *password_encrypt_old(const gchar *password)
return result;
}
#endif
/* Decryption is still needed for supporting migration of old
* configurations to newer encryption mechanisms. */
gchar *password_decrypt_old(const gchar *password)
{
if (!password || strlen(password) == 0) {

View file

@ -1,6 +1,6 @@
/*
* Claws Mail -- a GTK based, lightweight, and fast e-mail client
* Copyright (C) 2016-2023 The Claws Mail team
* Copyright (C) 2016 Claws Mail team
*
* 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
@ -14,6 +14,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __PASSWORD_H
@ -49,11 +50,7 @@ void primary_passphrase_change(const gchar *oldp, const gchar *newp);
* returns a newly allocated string for the encrypt/decrypt result.
* This is for compatibility with with the rest of password-related
* functions.*/
#ifdef PASSWORD_CRYPTO_OLD
gchar *password_encrypt_old(const gchar *password);
#endif
/* Decryption is still needed for supporting migration of old
* configurations to newer encryption mechanisms. */
gchar *password_decrypt_old(const gchar *password);
#ifdef PASSWORD_CRYPTO_GNUTLS

View file

@ -33,7 +33,6 @@
#include "utils.h"
#include "privacy.h"
#include "procmime.h"
#include "procheader.h"
#include "plugin.h"
#include "pgpmime.h"
@ -317,17 +316,22 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
privacy_free_signature_data(sig_data);
return NULL;
}
/*
decinfo = g_node_first_child(parseinfo->node) != NULL ?
g_node_first_child(parseinfo->node)->data : NULL;
if (decinfo == NULL) {
privacy_set_error(_("Couldn't parse decrypted file parts."));
if (sig_data)
privacy_free_signature_data(sig_data);
procmime_mimeinfo_free_all(&parseinfo);
return NULL;
}
g_node_unlink(decinfo->node);
procmime_mimeinfo_free_all(&parseinfo);
*/
decinfo = parseinfo;
decinfo->tmp = TRUE;
@ -708,62 +712,13 @@ static PrivacySystem pgpmime_system = {
prefs_gpg_auto_check_signatures,
};
static MimeParser *protected_headers_parser = NULL;
static void pgpmime_add_header_no_content(void *header, void *data) {
Header *hdr = (Header *)header;
MimeInfo *mimeinfo = (MimeInfo *)data;
if (!procheader_headername_equal(hdr->name,"Content-Type")) {
procmime_mimeinfo_add_extra_header(mimeinfo, hdr);
}
}
static gboolean protected_headers_parse (MimeParser *parser, MimeInfo *mimeinfo) {
FILE *fp;
fp = claws_fopen(mimeinfo->data.filename, "rb");
if (!fp) {
FILE_OP_ERROR(mimeinfo->data.filename, "claws_fopen");
return FALSE;
}
if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeinfo->data.filename, "fseek");
claws_fclose(fp);
return FALSE;
}
GPtrArray *protected_headers = procheader_get_header_array(fp);
if (protected_headers != NULL) {
g_ptr_array_foreach(protected_headers,
pgpmime_add_header_no_content, mimeinfo);
g_ptr_array_free(protected_headers, TRUE);
}
claws_fclose(fp);
return TRUE;
}
void pgpmime_init()
{
protected_headers_parser = g_new0(MimeParser, 1);
protected_headers_parser->type = MIMETYPE_TEXT;
protected_headers_parser->sub_type = "rfc822-headers";
protected_headers_parser->parse = protected_headers_parse;
procmime_mimeparser_register(protected_headers_parser);
privacy_register_system(&pgpmime_system);
}
void pgpmime_done()
{
if (protected_headers_parser != NULL) {
procmime_mimeparser_unregister(protected_headers_parser);
g_free(protected_headers_parser);
protected_headers_parser = NULL;
} else
g_warning("%s:%d protected_headers_parser not initialized",__FUNCTION__,__LINE__);
privacy_unregister_system(&pgpmime_system);
}

View file

@ -326,10 +326,6 @@ static gint decrypt(MimeInfo *mimeinfo, PrivacySystem *system)
procmime_mimeinfo_free_all(&mimeinfo);
if (decryptedinfo->protected_headers) {
parentinfo->protected_headers = decryptedinfo->protected_headers;
decryptedinfo->protected_headers = NULL;
}
g_node_insert(parentinfo->node, childnumber, decryptedinfo->node);
return 0;

View file

@ -265,18 +265,6 @@ gint procheader_get_one_field_asis(gchar **buf, FILE *fp)
FALSE);
}
inline
void procheader_header_free(gpointer ptr)
{
Header *header = (Header*) ptr;
if (!header) return;
g_free(header->name);
g_free(header->body);
g_free(header);
}
GPtrArray *procheader_get_header_array(FILE *fp)
{
gchar *buf = NULL;
@ -285,7 +273,7 @@ GPtrArray *procheader_get_header_array(FILE *fp)
cm_return_val_if_fail(fp != NULL, NULL);
headers = g_ptr_array_new_with_free_func(procheader_header_free);
headers = g_ptr_array_new();
while (procheader_get_one_field(&buf, fp, NULL) != -1) {
if ((header = procheader_parse_header(buf)) != NULL)
@ -297,6 +285,30 @@ GPtrArray *procheader_get_header_array(FILE *fp)
return headers;
}
void procheader_header_array_destroy(GPtrArray *harray)
{
gint i;
Header *header;
cm_return_if_fail(harray != NULL);
for (i = 0; i < harray->len; i++) {
header = g_ptr_array_index(harray, i);
procheader_header_free(header);
}
g_ptr_array_free(harray, TRUE);
}
void procheader_header_free(Header *header)
{
if (!header) return;
g_free(header->name);
g_free(header->body);
g_free(header);
}
/*
tests whether two headers' names are equal
remove the trailing ':' or ' ' before comparing
@ -375,41 +387,6 @@ Header * procheader_parse_header(gchar * buf)
return NULL;
}
static inline void update_hentry(HeaderEntry *hep, gchar *p)
{
while (*p == ' ' || *p == '\t')
p++;
if (hep->body == NULL)
hep->body = g_strdup(p);
else if (procheader_headername_equal(hep->name, "To")
|| procheader_headername_equal(hep->name, "Cc")) {
gchar *tp = hep->body;
hep->body = g_strconcat(tp, ", ", p, NULL);
g_free(tp);
}
}
void procheader_get_all_header_fields(FILE *fp, HeaderEntry hentry[],
GPtrArray *headers) {
char *buf = NULL;
while (procheader_get_one_field_asis(&buf, fp) != -1) {
HeaderEntry *hep = &hentry[0];
while( hep->name != NULL
&& g_ascii_strncasecmp(hep->name, buf, strlen(hep->name)))
hep++;
if (hep->name != NULL) {
gchar *p = buf + strlen(hep->name);
update_hentry(hep, p);
} else {
Header *header = procheader_parse_header(buf);
g_ptr_array_add(headers, header);
}
g_free(buf);
buf = NULL;
}
}
void procheader_get_header_fields(FILE *fp, HeaderEntry hentry[])
{
gchar *buf = NULL;
@ -423,8 +400,16 @@ void procheader_get_header_fields(FILE *fp, HeaderEntry hentry[])
hp = hentry + hnum;
p = buf + strlen(hp->name);
while (*p == ' ' || *p == '\t') p++;
update_hentry(hp, p);
if (hp->body == NULL)
hp->body = g_strdup(p);
else if (procheader_headername_equal(hp->name, "To") ||
procheader_headername_equal(hp->name, "Cc")) {
gchar *tp = hp->body;
hp->body = g_strconcat(tp, ", ", p, NULL);
g_free(tp);
}
g_free(buf);
buf = NULL;
}

View file

@ -48,11 +48,11 @@ gint procheader_get_one_field_asis (gchar **buf,
FILE *fp);
GPtrArray *procheader_get_header_array (FILE *fp);
void procheader_header_free (gpointer header);
void procheader_header_array_destroy (GPtrArray *harray);
void procheader_header_free (Header *header);
gboolean procheader_skip_headers(FILE *fp);
void procheader_get_all_header_fields(FILE *fp, HeaderEntry hentry[], GPtrArray *_headers);
void procheader_get_header_fields (FILE *fp,
HeaderEntry hentry[]);
MsgInfo *procheader_parse_file (const gchar *file,
@ -83,6 +83,7 @@ void procheader_date_get_localtime (gchar *dest,
Header * procheader_parse_header (gchar * buf);
gboolean procheader_headername_equal (char * hdr1, char * hdr2);
void procheader_header_free (Header * header);
gint procheader_get_header_from_msginfo (MsgInfo *msginfo,
gchar **buf,

View file

@ -149,9 +149,6 @@ static gboolean free_func(GNode *node, gpointer data)
if (mimeinfo->sig_data)
privacy_free_signature_data(mimeinfo->sig_data);
if (mimeinfo->protected_headers) {
g_ptr_array_free(mimeinfo->protected_headers, TRUE);
}
g_free(mimeinfo);
return FALSE;
@ -292,20 +289,6 @@ const gchar *procmime_mimeinfo_get_parameter(MimeInfo *mimeinfo, const gchar *na
strcpy(lastline, buf); \
}
void procmime_mimeinfo_add_extra_header (MimeInfo *mimeinfo, Header *header)
{
if (mimeinfo->protected_headers == NULL)
mimeinfo->protected_headers = g_ptr_array_new();
if (mimeinfo->protected_headers != NULL) {
Header *hdr = g_malloc0(sizeof(*hdr));
hdr->name = g_strdup(header->name);
hdr->body = g_strdup(header->body);
g_ptr_array_add(mimeinfo->protected_headers, hdr);
} else
g_warning("%s:%d(%s) failed to add mimeinfo->protected_headers",__FILE__,__LINE__,__FUNCTION__);
}
gboolean procmime_decode_content(MimeInfo *mimeinfo)
{
gchar buf[BUFFSIZE];
@ -1466,22 +1449,7 @@ gchar *procmime_get_content_type_str(MimeMediaType type,
return g_strdup_printf("%s/%s", type_str, subtype);
}
static MimeInfo * procmime_parse_mimehdrs(MimeInfo *parent,
gchar *content_type,
gchar *content_encoding,
gchar *content_description,
gchar *content_id,
gchar *content_disposition,
gchar *content_location,
const gchar *filename,
guint offset,
guint length);
static gint procmime_parse_mimecontent(MimeInfo *mimeinfo,
const gchar *original_msgid,
const gchar *disposition_notification_hdr,
gboolean short_scan);
static inline gint procmime_parse_mimepart(MimeInfo *parent,
static int procmime_parse_mimepart(MimeInfo *parent,
gchar *content_type,
gchar *content_encoding,
gchar *content_description,
@ -1493,20 +1461,7 @@ static inline gint procmime_parse_mimepart(MimeInfo *parent,
const gchar *filename,
guint offset,
guint length,
gboolean short_scan)
{
gint result = 0;
MimeInfo *childinfo = procmime_parse_mimehdrs(parent,
content_type, content_encoding,
content_description, content_id,
content_disposition, content_location,
filename, offset, length);
result = procmime_parse_mimecontent(childinfo,
original_msgid, disposition_notification_hdr,
short_scan);
return result;
}
gboolean short_scan);
static void procmime_parse_message_rfc822(MimeInfo *mimeinfo, gboolean short_scan)
{
@ -1532,7 +1487,6 @@ static void procmime_parse_message_rfc822(MimeInfo *mimeinfo, gboolean short_sca
FILE *fp;
gchar *tmp;
gint len = 0;
GPtrArray *additional_headers = NULL;
procmime_decode_content(mimeinfo);
@ -1546,65 +1500,52 @@ static void procmime_parse_message_rfc822(MimeInfo *mimeinfo, gboolean short_sca
claws_fclose(fp);
return;
}
additional_headers = g_ptr_array_new_with_free_func(procheader_header_free);
procheader_get_all_header_fields(fp, hentry, additional_headers);
procheader_get_header_fields(fp, hentry);
if (hentry[0].body != NULL) {
tmp = conv_unmime_header(hentry[0].body, NULL, FALSE);
g_free(hentry[0].body);
hentry[0].body = tmp;
}
g_free(hentry[0].body);
hentry[0].body = tmp;
}
if (hentry[2].body != NULL) {
tmp = conv_unmime_header(hentry[2].body, NULL, FALSE);
g_free(hentry[2].body);
hentry[2].body = tmp;
}
g_free(hentry[2].body);
hentry[2].body = tmp;
}
if (hentry[4].body != NULL) {
tmp = conv_unmime_header(hentry[4].body, NULL, FALSE);
g_free(hentry[4].body);
hentry[4].body = tmp;
}
g_free(hentry[4].body);
hentry[4].body = tmp;
}
if (hentry[5].body != NULL) {
tmp = conv_unmime_header(hentry[5].body, NULL, FALSE);
g_free(hentry[5].body);
hentry[5].body = tmp;
}
g_free(hentry[5].body);
hentry[5].body = tmp;
}
if (hentry[7].body != NULL) {
tmp = conv_unmime_header(hentry[7].body, NULL, FALSE);
g_free(hentry[7].body);
hentry[7].body = tmp;
}
g_free(hentry[7].body);
hentry[7].body = tmp;
}
if (hentry[8].body != NULL) {
tmp = conv_unmime_header(hentry[8].body, NULL, FALSE);
g_free(hentry[8].body);
hentry[8].body = tmp;
}
g_free(hentry[8].body);
hentry[8].body = tmp;
}
content_start = ftell(fp);
claws_fclose(fp);
len = mimeinfo->length - (content_start - mimeinfo->offset);
if (len < 0)
len = 0;
MimeInfo *childinfo = procmime_parse_mimehdrs(mimeinfo,
procmime_parse_mimepart(mimeinfo,
hentry[0].body, hentry[1].body,
hentry[2].body, hentry[3].body,
hentry[4].body, hentry[5].body,
hentry[7].body, hentry[8].body,
mimeinfo->data.filename, content_start,
len);
if (g_hash_table_lookup(childinfo->typeparameters, "protected-headers")) {
for (int i = 0; i < additional_headers->len; i ++ ) {
Header *hdr = g_ptr_array_index(additional_headers,i);
procmime_mimeinfo_add_extra_header(childinfo, hdr);
}
}
procmime_parse_mimecontent(childinfo,
hentry[7].body, hentry[8].body,
short_scan);
g_ptr_array_free(additional_headers,TRUE);
len, short_scan);
for (i = 0; i < (sizeof hentry / sizeof hentry[0]); i++) {
g_free(hentry[i].body);
hentry[i].body = NULL;
@ -1644,9 +1585,9 @@ static void procmime_parse_disposition_notification(MimeInfo *mimeinfo,
procheader_get_header_fields(fp, hentry);
}
claws_fclose(fp);
claws_fclose(fp);
if (!hentry[0].body || !hentry[1].body) {
if (!hentry[0].body || !hentry[1].body) {
debug_print("MsgId %s, Disp %s\n",
hentry[0].body ? hentry[0].body:"(nil)",
hentry[1].body ? hentry[1].body:"(nil)");
@ -1687,8 +1628,8 @@ bail:
}
}
#define FILL_HEADERS() { \
gchar *tmp; \
#define GET_HEADERS() { \
procheader_get_header_fields(fp, hentry); \
if (hentry[0].body != NULL) { \
tmp = conv_unmime_header(hentry[0].body, NULL, FALSE); \
g_free(hentry[0].body); \
@ -1739,14 +1680,14 @@ static void procmime_parse_multipart(MimeInfo *mimeinfo, gboolean short_scan)
{"Disposition:",
NULL, TRUE},
{NULL, NULL, FALSE}};
gchar *tmp;
gchar *boundary;
gint boundary_len = 0, lastoffset = -1;
gint boundary_len = 0, lastoffset = -1, i;
gchar buf[BUFFSIZE];
FILE *fp;
int result = 0;
gboolean start_found = FALSE;
gboolean end_found = FALSE;
GPtrArray *additional_headers = NULL;
boundary = g_hash_table_lookup(mimeinfo->typeparameters, "boundary");
if (!boundary)
@ -1778,29 +1719,16 @@ static void procmime_parse_multipart(MimeInfo *mimeinfo, gboolean short_scan)
gint len = (ftell(fp) - strlen(buf)) - lastoffset - 1;
if (len < 0)
len = 0;
MimeInfo *childinfo = procmime_parse_mimehdrs(mimeinfo,
result = procmime_parse_mimepart(mimeinfo,
hentry[0].body, hentry[1].body,
hentry[2].body, hentry[3].body,
hentry[4].body, hentry[5].body,
mimeinfo->data.filename, lastoffset,
len);
if (additional_headers && g_hash_table_lookup(childinfo->typeparameters, "protected-headers")) {
for (int i = 0; i < additional_headers->len; i ++ ) {
Header *hdr = g_ptr_array_steal_index(additional_headers,i);
procmime_mimeinfo_add_extra_header(childinfo, hdr);
}
g_ptr_array_free(additional_headers, TRUE);
}
result = procmime_parse_mimecontent(childinfo,
hentry[6].body, hentry[7].body,
short_scan);
MimeInfo *last_child = g_node_last_child(mimeinfo->node)->data;
if (last_child && last_child->protected_headers) {
mimeinfo->protected_headers = last_child->protected_headers;
last_child->protected_headers = NULL;
}
mimeinfo->data.filename, lastoffset,
len, short_scan);
if (result == 1 && short_scan)
break;
}
if (buf[2 + boundary_len] == '-' &&
@ -1808,22 +1736,15 @@ static void procmime_parse_multipart(MimeInfo *mimeinfo, gboolean short_scan)
end_found = TRUE;
break;
}
for (HeaderEntry *curheader = &hentry[0]; curheader->name != NULL; curheader++) {
g_free(curheader->body);
curheader->body = NULL;
for (i = 0; i < (sizeof hentry / sizeof hentry[0]) ; i++) {
g_free(hentry[i].body);
hentry[i].body = NULL;
}
if(additional_headers)
g_ptr_array_free(additional_headers, TRUE);
additional_headers = g_ptr_array_new_with_free_func(procheader_header_free);
procheader_get_all_header_fields(fp, hentry, additional_headers);
FILL_HEADERS();
GET_HEADERS();
lastoffset = ftell(fp);
}
}
if(additional_headers)
g_ptr_array_free(additional_headers, TRUE);
if (start_found && !end_found && lastoffset != -1) {
gint len = (ftell(fp) - strlen(buf)) - lastoffset - 1;
@ -1835,18 +1756,13 @@ static void procmime_parse_multipart(MimeInfo *mimeinfo, gboolean short_scan)
hentry[6].body, hentry[7].body,
mimeinfo->data.filename, lastoffset,
len, short_scan);
MimeInfo *last_child = g_node_last_child(mimeinfo->node)->data;
if (last_child && last_child->protected_headers) {
mimeinfo->protected_headers = last_child->protected_headers;
last_child->protected_headers = NULL;
}
}
mimeinfo->broken = TRUE;
}
for (HeaderEntry *curheader = &hentry[0]; curheader->name != NULL; curheader++) {
g_free(curheader->body);
curheader->body = NULL;
for (i = 0; i < (sizeof hentry / sizeof hentry[0]); i++) {
g_free(hentry[i].body);
hentry[i].body = NULL;
}
claws_fclose(fp);
}
@ -2129,18 +2045,24 @@ static gboolean procmime_mimeparser_parse(MimeParser *parser, MimeInfo *mimeinfo
return parser->parse(parser, mimeinfo);
}
static MimeInfo *procmime_parse_mimehdrs(MimeInfo *parent,
static int procmime_parse_mimepart(MimeInfo *parent,
gchar *content_type,
gchar *content_encoding,
gchar *content_description,
gchar *content_id,
gchar *content_disposition,
gchar *content_location,
const gchar *original_msgid,
const gchar *disposition_notification_hdr,
const gchar *filename,
guint offset,
guint length)
guint length,
gboolean short_scan)
{
MimeInfo *mimeinfo;
MimeParser *parser = NULL;
gboolean parsed = FALSE;
int result = 0;
/* Create MimeInfo */
mimeinfo = procmime_mimeinfo_new();
@ -2153,7 +2075,7 @@ static MimeInfo *procmime_parse_mimehdrs(MimeInfo *parent,
* with enormous messages
*/
procmime_mimeinfo_free_all(&mimeinfo);
return NULL;
return -1;
}
g_node_append(parent->node, mimeinfo->node);
}
@ -2204,16 +2126,6 @@ static MimeInfo *procmime_parse_mimehdrs(MimeInfo *parent,
} else
mimeinfo->disposition = DISPOSITIONTYPE_UNKNOWN;
return mimeinfo;
}
static gint procmime_parse_mimecontent(MimeInfo *mimeinfo,
const gchar *original_msgid,
const gchar *disposition_notification_hdr,
gboolean short_scan)
{
MimeParser *parser = NULL;
gboolean parsed = FALSE;
/* Call parser for mime type */
if ((parser = procmime_get_mimeparser_for_type(mimeinfo->type, mimeinfo->subtype)) != NULL) {
parsed = procmime_mimeparser_parse(parser, mimeinfo);
@ -2252,7 +2164,8 @@ static gint procmime_parse_mimecontent(MimeInfo *mimeinfo,
break;
}
}
return 0;
return result;
}
static gchar *typenames[] = {

View file

@ -156,8 +156,6 @@ struct _MimeInfo
SignatureData *sig_data;
gboolean broken;
GPtrArray *protected_headers;
};
#define IS_BOUNDARY(s, bnd, len) \
@ -201,8 +199,6 @@ void procmime_scan_content_description (MimeInfo *mimeinfo,
void procmime_scan_subject (MimeInfo *mimeinfo,
const gchar *subject);
MimeInfo *procmime_scan_mime_header (FILE *fp);
void procmime_mimeinfo_add_extra_header (MimeInfo *mimeinfo,
Header *header);
gboolean procmime_decode_content (MimeInfo *mimeinfo);
gboolean procmime_encode_content (MimeInfo *mimeinfo, EncodingType encoding);

View file

@ -864,21 +864,6 @@ MsgInfo *procmsg_get_msginfo_from_identifier(const gchar *id)
return msginfo;
}
void helper (gpointer data, gpointer user_data) {
MsgInfo * msginfo = (MsgInfo *)user_data;
Header * header = (Header *)data;
if ( procheader_headername_equal(header->name, "Subject") ) {
g_message("Updating msginfo from protected header %s -> %s", header->name, header->body);
if ( msginfo->subject )
g_free(msginfo->subject);
msginfo->subject=g_strdup(header->body);
}
}
void procmsg_update_msginfo_headers(MsgInfo * msginfo, GPtrArray *protected_headers){
g_ptr_array_foreach(protected_headers, helper, msginfo);
}
static GSList *procmsg_list_sort_by_account(FolderItem *queue, GSList *list)
{
GSList *result = NULL;
@ -2597,3 +2582,83 @@ void procmsg_msginfo_clear_tags(MsgInfo *msginfo)
folder_item_commit_tags(msginfo->folder, msginfo, NULL, unset);
g_slist_free(unset);
}
static GPtrArray *extract_headers(FILE *fp)
{
gchar buf[BUFFSIZE];
GPtrArray *headers, *sorted_headers;
Header *header;
gint i;
cm_return_val_if_fail(fp != NULL, NULL);
headers = procheader_get_header_array(fp);
sorted_headers = g_ptr_array_new();
for (i = 0; i < headers->len; i++) {
header = g_ptr_array_index(headers, i);
if (!procheader_header_is_internal(header->name))
g_ptr_array_add(sorted_headers, header);
else
procheader_header_free(header);
}
g_ptr_array_free(headers, TRUE);
return sorted_headers;
}
static gchar *extract_subject(MimeInfo *mimeinfo)
{
GPtrArray *headers = NULL;
FILE *fp;
gchar *subject = NULL;
Header *header;
gint i;
if (mimeinfo->content == MIMECONTENT_MEM)
fp = str_open_as_stream(mimeinfo->data.mem);
else
fp = claws_fopen(mimeinfo->data.filename, "rb");
if (!fp) {
FILE_OP_ERROR(mimeinfo->data.filename, "claws_fopen");
return FALSE;
}
if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeinfo->data.filename, "fseek");
claws_fclose(fp);
return FALSE;
}
headers = extract_headers(fp);
if (headers) {
for (i = 0; i < headers->len; i++) {
header = g_ptr_array_index(headers, i);
if (!strcmp(header->name, "Subject:")) {
subject = g_strdup(header->body);
break;
}
}
procheader_header_array_destroy(headers);
}
claws_fclose(fp);
if(subject)
unfold_line(subject);
return subject;
}
gchar *procmsg_extract_subject(MimeInfo *mimeinfo)
{
GNode *iter;
gchar *subject = extract_subject(mimeinfo);
if(subject && strcmp(subject, "...") != 0)
return subject;
g_free(subject);
for (iter = g_node_first_child(mimeinfo->node) ; iter != NULL ;
iter = g_node_next_sibling(iter)) {
subject = procmsg_extract_subject((MimeInfo *) iter->data);
if(subject && strcmp(subject, "...") != 0)
return subject;
g_free(subject);
}
return NULL;
}

View file

@ -405,5 +405,6 @@ gchar *procmsg_msginfo_get_identifier(MsgInfo *msginfo);
gchar *procmsg_msginfo_get_avatar(MsgInfo *msginfo, gint type);
void procmsg_msginfo_add_avatar(MsgInfo *msginfo, gint type, const gchar *data);
void procmsg_update_msginfo_headers(MsgInfo * msginfo, GPtrArray *protected_headers);
gchar *procmsg_extract_subject(MimeInfo *mimeinfo);
#endif /* __PROCMSG_H__ */

View file

@ -949,14 +949,10 @@ static gboolean do_pix_draw(GtkWidget *widget, cairo_t *cr,
mw = mainwindow_get_mainwindow();
if (mw != NULL && mw->menubar != NULL) {
cairo_t *cr;
GdkRGBA color;
GdkColor color = gtk_widget_get_style(mw->menubar)->base[GTK_STATE_SELECTED];
GtkStyleContext *context = gtk_widget_get_style_context (mw->menubar);
gtk_style_context_lookup_color (context, "selected_bg_color", &color);
cairo_region_t * creg = cairo_region_create();
GdkDrawingContext * dctx = gdk_window_begin_draw_frame (drawable, creg);
cr = gdk_drawing_context_get_cairo_context (dctx);
gdk_cairo_set_source_rgba (cr, &color);
cr = gdk_cairo_create(drawable);
gdk_cairo_set_source_color(cr, &color);
cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
cairo_set_line_width(cr, 1.);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
@ -964,8 +960,7 @@ static gboolean do_pix_draw(GtkWidget *widget, cairo_t *cr,
cairo_rectangle(cr, data->border_x-2, data->border_y-2,
data->base_width+3, data->base_height+3);
cairo_stroke(cr);
gdk_window_end_draw_frame (drawable, dctx);
cairo_region_destroy (creg);
cairo_destroy(cr);
}
}

View file

@ -150,10 +150,6 @@ static GtkCMCTreeNode *summary_find_next_flagged_msg
MsgPermFlags flags,
gboolean start_from_next);
static GtkCMCTreeNode *summary_find_msg_by_msgnum
(SummaryView *summaryview,
guint msgnum);
static void summary_update_status (SummaryView *summaryview);
/* display functions */
@ -2473,7 +2469,7 @@ static GtkCMCTreeNode *summary_find_next_flagged_msg(SummaryView *summaryview,
return node;
}
static GtkCMCTreeNode *summary_find_msg_by_msgnum(SummaryView *summaryview,
GtkCMCTreeNode *summary_find_msg_by_msgnum(SummaryView *summaryview,
guint msgnum)
{
GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);

View file

@ -338,4 +338,8 @@ gboolean summary_is_list(SummaryView *summaryview);
gboolean summaryview_search_root_progress(gpointer data, guint at, guint matched, guint total);
gboolean summary_is_opened_message_selected(SummaryView *summaryview);
gboolean summary_has_opened_message(SummaryView *summaryview);
GtkCMCTreeNode *summary_find_msg_by_msgnum
(SummaryView *summaryview,
guint msgnum);
#endif /* __SUMMARY_H__ */

View file

@ -71,12 +71,6 @@
#include "avatars.h"
#include "file-utils.h"
static GdkRGBA header_bgcolors[3] = {
{1, 1, 1, 1},
{0.5, 1, 0.5, 1},
{1, 1, 0.5, 1}
};
static GdkRGBA quote_colors[3] = {
{0, 0, 0, 1},
{0, 0, 0, 1},
@ -173,13 +167,7 @@ static void textview_write_link (TextView *textview,
static GPtrArray *textview_scan_header (TextView *textview,
FILE *fp);
static void textview_show_header (TextView *textview,
GPtrArray *headers,
GPtrArray *protected_headers);
static void textview_sort_headers (GPtrArray *headers,
GPtrArray *target);
static void textview_append_single_header (TextView *textview,
Header *header,
gint verified);
GPtrArray *headers);
static void textview_zoom(GtkWidget *widget, gboolean zoom_in);
static void textview_zoom_in(GtkWidget *widget, gpointer data);
@ -450,34 +438,10 @@ static void textview_create_tags(GtkTextView *text, TextView *textview)
"font-desc", font_desc,
"left-margin", 3,
"left-margin-set", TRUE,
"background-rgba", &header_bgcolors[0],
NULL);
gtk_text_buffer_create_tag(buffer, "header_verified",
"pixels-above-lines", 0,
"pixels-above-lines-set", TRUE,
"pixels-below-lines", 0,
"pixels-below-lines-set", TRUE,
"font-desc", font_desc,
"left-margin", 3,
"left-margin-set", TRUE,
"background-rgba", &header_bgcolors[1],
NULL);
gtk_text_buffer_create_tag(buffer, "header_modified",
"pixels-above-lines", 0,
"pixels-above-lines-set", TRUE,
"pixels-below-lines", 0,
"pixels-below-lines-set", TRUE,
"font-desc", font_desc,
"left-margin", 3,
"left-margin-set", TRUE,
"background-rgba", &header_bgcolors[2],
NULL);
gtk_text_buffer_create_tag(buffer, "header_title",
"font-desc", bold_font_desc,
NULL);
gtk_text_buffer_create_tag(buffer, "header_title_original",
"font-desc", font_desc,
NULL);
tag = gtk_text_buffer_create_tag(buffer, "hlink",
"pixels-above-lines", 0,
"pixels-above-lines-set", TRUE,
@ -672,6 +636,39 @@ void textview_show_part(TextView *textview, MimeInfo *mimeinfo, FILE *fp)
END_TIMING();
}
static gboolean textview_process_headers(TextView *textview, MimeInfo *mimeinfo,
gint charcount, GtkTextBuffer *buffer, GtkTextIter iter)
{
GPtrArray *headers = NULL;
FILE *fp;
if (mimeinfo->content == MIMECONTENT_MEM)
fp = str_open_as_stream(mimeinfo->data.mem);
else
fp = claws_fopen(mimeinfo->data.filename, "rb");
if (!fp) {
FILE_OP_ERROR(mimeinfo->data.filename, "claws_fopen");
return FALSE;
}
if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeinfo->data.filename, "fseek");
claws_fclose(fp);
return FALSE;
}
headers = textview_scan_header(textview, fp);
if (headers) {
if (charcount > 0)
gtk_text_buffer_insert(buffer, &iter, "\n", 1);
if (procmime_mimeinfo_parent(mimeinfo) == NULL &&
!prefs_common.display_header_pane)
textview_show_tags(textview);
textview_show_header(textview, headers);
procheader_header_array_destroy(headers);
}
claws_fclose(fp);
return TRUE;
}
static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
{
GtkAllocation allocation;
@ -679,7 +676,6 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
GtkTextBuffer *buffer;
GtkTextIter iter, start_iter;
gchar buf[BUFFSIZE];
GPtrArray *headers = NULL;
const gchar *name;
gchar *content_type;
gint charcount;
@ -696,6 +692,7 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
return;
}
if (mimeinfo->type == MIMETYPE_MULTIPART) {
textview_process_headers(textview, mimeinfo, charcount, buffer, iter);
END_TIMING();
return;
}
@ -703,50 +700,7 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
textview->prev_quote_level = -1;
if ((mimeinfo->type == MIMETYPE_MESSAGE) && !g_ascii_strcasecmp(mimeinfo->subtype, "rfc822")) {
FILE *fp;
if (mimeinfo->content == MIMECONTENT_MEM)
fp = str_open_as_stream(mimeinfo->data.mem);
else
fp = claws_fopen(mimeinfo->data.filename, "rb");
if (!fp) {
FILE_OP_ERROR(mimeinfo->data.filename, "claws_fopen");
END_TIMING();
return;
}
if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeinfo->data.filename, "fseek");
claws_fclose(fp);
END_TIMING();
return;
}
headers = textview_scan_header(textview, fp);
if (headers) {
if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeinfo->data.filename, "fseek");
claws_fclose(fp);
END_TIMING();
return;
}
if (charcount > 0)
gtk_text_buffer_insert(buffer, &iter, "\n", 1);
if (procmime_mimeinfo_parent(mimeinfo) == NULL &&
!prefs_common.display_header_pane)
textview_show_tags(textview);
if (mimeinfo->protected_headers) {
MsgInfo * msginfo = textview->messageview->msginfo;
GPtrArray *protected_headers = g_ptr_array_new();
textview_sort_headers(mimeinfo->protected_headers, protected_headers);
procmsg_update_msginfo_headers(msginfo, protected_headers);
textview_show_header(textview, headers, protected_headers);
g_ptr_array_free(protected_headers, TRUE);
g_ptr_array_free(mimeinfo->protected_headers, TRUE);
mimeinfo->protected_headers = NULL;
} else
textview_show_header(textview, headers, NULL);
g_ptr_array_free(headers, TRUE);
}
claws_fclose(fp);
textview_process_headers(textview, mimeinfo, charcount, buffer, iter);
END_TIMING();
return;
}
@ -827,8 +781,6 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
END_TIMING();
GTK_EVENTS_FLUSH();
}
} else if (mimeinfo->type == MIMETYPE_TEXT &&
!g_ascii_strcasecmp(mimeinfo->subtype, "rfc822-headers")) {
} else if (mimeinfo->type == MIMETYPE_TEXT) {
if (prefs_common.display_header && (charcount > 0))
gtk_text_buffer_insert(buffer, &iter, "\n", 1);
@ -1969,48 +1921,31 @@ void textview_set_position(TextView *textview, gint pos)
gtkut_text_view_set_position(text, pos);
}
static void textview_copy_headers_without_internal(GPtrArray *headers, GPtrArray *target) {
while(headers->len) {
Header *header = g_ptr_array_steal_index(headers, 0);
if (!procheader_header_is_internal(header->name))
g_ptr_array_add(target, header);
else
procheader_header_free(header);
}
}
static void textview_sort_headers(GPtrArray *headers, GPtrArray *sorted_headers) {
GSList *disphdr_list;
for (disphdr_list = prefs_common.disphdr_list; disphdr_list != NULL;
disphdr_list = disphdr_list->next) {
DisplayHeaderProp *dp =
(DisplayHeaderProp *)disphdr_list->data;
gint i;
for (i = 0; i < headers->len; i++) {
Header *header;
header = g_ptr_array_index(headers, i);
if (procheader_headername_equal(header->name,
dp->name)) {
header = g_ptr_array_steal_index(headers, i);
if (dp->hidden)
procheader_header_free(header);
else
g_ptr_array_add(sorted_headers, header);
i--;
}
}
}
}
static GPtrArray *textview_scan_header(TextView *textview, FILE *fp)
{
gchar buf[BUFFSIZE];
GPtrArray *headers, *sorted_headers;
GSList *disphdr_list;
Header *header;
gint i;
cm_return_val_if_fail(fp != NULL, NULL);
if (prefs_common.show_all_headers) {
headers = procheader_get_header_array(fp);
sorted_headers = g_ptr_array_new();
for (i = 0; i < headers->len; i++) {
header = g_ptr_array_index(headers, i);
if (!procheader_header_is_internal(header->name))
g_ptr_array_add(sorted_headers, header);
else
procheader_header_free(header);
}
g_ptr_array_free(headers, TRUE);
return sorted_headers;
}
if (!prefs_common.display_header) {
gchar buf[BUFFSIZE];
while (claws_fgets(buf, sizeof(buf), fp) != NULL)
if (buf[0] == '\r' || buf[0] == '\n') break;
return NULL;
@ -2018,13 +1953,43 @@ static GPtrArray *textview_scan_header(TextView *textview, FILE *fp)
headers = procheader_get_header_array(fp);
sorted_headers = g_ptr_array_new_with_free_func(procheader_header_free);
if (prefs_common.show_all_headers || prefs_common.show_other_header)
textview_copy_headers_without_internal(headers, sorted_headers);
else
textview_sort_headers(headers, sorted_headers);
sorted_headers = g_ptr_array_new();
for (disphdr_list = prefs_common.disphdr_list; disphdr_list != NULL;
disphdr_list = disphdr_list->next) {
DisplayHeaderProp *dp =
(DisplayHeaderProp *)disphdr_list->data;
for (i = 0; i < headers->len; i++) {
header = g_ptr_array_index(headers, i);
if (procheader_headername_equal(header->name,
dp->name)) {
if (dp->hidden)
procheader_header_free(header);
else
g_ptr_array_add(sorted_headers, header);
g_ptr_array_remove_index(headers, i);
i--;
}
}
}
if (prefs_common.show_other_header) {
for (i = 0; i < headers->len; i++) {
header = g_ptr_array_index(headers, i);
unfold_line(header->body);
if (!procheader_header_is_internal(header->name)) {
g_ptr_array_add(sorted_headers, header);
} else {
procheader_header_free(header);
}
}
g_ptr_array_free(headers, TRUE);
} else
procheader_header_array_destroy(headers);
g_ptr_array_free(headers, TRUE);
return sorted_headers;
}
@ -2298,62 +2263,85 @@ static void textview_show_tags(TextView *textview)
"header", "tags", NULL);
}
#define HEADER_NOT_VERIFIABLE 0
#define HEADER_NOT_VERIFIED -(i+1)
#define HEADER_VERIFIED (i+1)
static gint textview_verify_protected_header(Header *header, GPtrArray *protected_headers)
static void textview_show_header(TextView *textview, GPtrArray *headers)
{
gint verified = HEADER_NOT_VERIFIABLE;
GtkTextView *text = GTK_TEXT_VIEW(textview->text);
GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
GtkTextIter iter;
Header *header;
gint i;
if (protected_headers != NULL) {
for (i=0; i<protected_headers->len; i++) {
Header *hdr = (Header *)g_ptr_array_index(protected_headers,i);
if (!procheader_headername_equal(header->name, hdr->name))
continue;
verified = -(i+1);
if (g_ascii_strncasecmp(hdr->body,header->body,
strlen(hdr->body) < strlen(header->body) ?
strlen(hdr->body) : strlen(header->body)) == 0) {
verified = -verified;
break;
}
}
}
return verified;
}
static void textview_show_header(TextView *textview, GPtrArray *headers , GPtrArray *protected_headers)
{
Header *header, *phdr;
gint i;
gint verified,display;
cm_return_if_fail(headers != NULL);
for (i = 0; i < headers->len; i++) {
header = g_ptr_array_index(headers, i);
cm_return_if_fail(header->name != NULL);
verified = textview_verify_protected_header(header, protected_headers);
if (verified != HEADER_NOT_VERIFIABLE) {
phdr = g_ptr_array_index(protected_headers, abs(verified) - 1);
if (verified < 0)
textview_append_single_header(textview,phdr,1);
procheader_header_free(phdr);
g_ptr_array_remove_index(protected_headers, abs(verified) - 1);
gtk_text_buffer_get_end_iter (buffer, &iter);
if(prefs_common.trans_hdr == TRUE) {
gchar *hdr = g_strndup(header->name, strlen(header->name) - 1);
gchar *trans_hdr = gettext(hdr);
gtk_text_buffer_insert_with_tags_by_name(buffer,
&iter, trans_hdr, -1,
"header_title", "header", NULL);
gtk_text_buffer_insert_with_tags_by_name(buffer,
&iter, ":", 1, "header_title", "header", NULL);
g_free(hdr);
} else {
gtk_text_buffer_insert_with_tags_by_name(buffer,
&iter, header->name,
-1, "header_title", "header", NULL);
}
if (header->name[strlen(header->name) - 1] != ' ')
gtk_text_buffer_insert_with_tags_by_name
(buffer, &iter, " ", 1,
"header_title", "header", NULL);
display = (verified > 0) ? 1 : (verified < 0) ? -1 : 0;
textview_append_single_header(textview, header, display);
}
if (protected_headers) {
for (i = 0; i < protected_headers->len; i++) {
textview_append_single_header(textview,
g_ptr_array_index(protected_headers, i),
i+1);
if (procheader_headername_equal(header->name, "Subject") ||
procheader_headername_equal(header->name, "From") ||
procheader_headername_equal(header->name, "To") ||
procheader_headername_equal(header->name, "Cc") ||
procheader_headername_equal(header->name, "Bcc") ||
procheader_headername_equal(header->name, "Reply-To") ||
procheader_headername_equal(header->name, "Sender") ||
procheader_headername_equal(header->name, "Resent-From") ||
procheader_headername_equal(header->name, "Resent-To"))
unfold_line(header->body);
if (procheader_headername_equal(header->name, "Date") &&
prefs_common.msgview_date_format) {
gchar hbody[80];
procheader_date_parse(hbody, header->body, sizeof(hbody));
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name
(buffer, &iter, hbody, -1, "header", NULL);
} else if ((procheader_headername_equal(header->name, "X-Mailer") ||
procheader_headername_equal(header->name,
"X-Newsreader")) &&
(strstr(header->body, "Claws Mail") != NULL ||
strstr(header->body, "Sylpheed-Claws") != NULL)) {
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name
(buffer, &iter, header->body, -1,
"header", "emphasis", NULL);
} else {
gboolean hdr =
procheader_headername_equal(header->name, "From") ||
procheader_headername_equal(header->name, "To") ||
procheader_headername_equal(header->name, "Cc") ||
procheader_headername_equal(header->name, "Bcc") ||
procheader_headername_equal(header->name, "Reply-To") ||
procheader_headername_equal(header->name, "Sender") ||
procheader_headername_equal(header->name, "Resent-From") ||
procheader_headername_equal(header->name, "Resent-To");
textview_make_clickable_parts(textview, "header",
"hlink", header->body,
hdr);
}
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "\n", 1,
"header", NULL);
}
textview_show_avatar(textview);
@ -2362,87 +2350,6 @@ static void textview_show_header(TextView *textview, GPtrArray *headers , GPtrAr
textview_show_contact_pic(textview);
}
static void textview_append_single_header(TextView *textview, Header *header, gint verified)
{
GtkTextView *text = GTK_TEXT_VIEW(textview->text);
GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
GtkTextIter iter;
gchar *header_tag;
if (verified > 0)
header_tag = "header_verified";
else if (verified < 0)
header_tag = "header_modified";
else
header_tag = "header";
gtk_text_buffer_get_end_iter (buffer, &iter);
if(prefs_common.trans_hdr == TRUE) {
gchar *hdr = g_strndup(header->name, strlen(header->name) - 1);
gchar *trans_hdr = gettext(hdr);
gtk_text_buffer_insert_with_tags_by_name(buffer,
&iter, trans_hdr, -1,
"header_title", header_tag, NULL);
gtk_text_buffer_insert_with_tags_by_name(buffer,
&iter, ":", 1, "header_title", header_tag, NULL);
g_free(hdr);
} else {
gtk_text_buffer_insert_with_tags_by_name(buffer,
&iter, header->name,
-1, "header_title", header_tag, NULL);
}
if (header->name[strlen(header->name) - 1] != ' ')
gtk_text_buffer_insert_with_tags_by_name
(buffer, &iter, " ", 1,
"header_title", header_tag, NULL);
if (procheader_headername_equal(header->name, "Subject") ||
procheader_headername_equal(header->name, "From") ||
procheader_headername_equal(header->name, "To") ||
procheader_headername_equal(header->name, "Cc") ||
procheader_headername_equal(header->name, "Bcc") ||
procheader_headername_equal(header->name, "Reply-To") ||
procheader_headername_equal(header->name, "Sender") ||
procheader_headername_equal(header->name, "Resent-From") ||
procheader_headername_equal(header->name, "Resent-To"))
unfold_line(header->body);
if (procheader_headername_equal(header->name, "Date") &&
prefs_common.msgview_date_format) {
gchar hbody[80];
procheader_date_parse(hbody, header->body, sizeof(hbody));
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name
(buffer, &iter, hbody, -1, header_tag, NULL);
} else if ((procheader_headername_equal(header->name, "X-Mailer") ||
procheader_headername_equal(header->name,
"X-Newsreader")) &&
(strstr(header->body, "Claws Mail") != NULL ||
strstr(header->body, "Sylpheed-Claws") != NULL)) {
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name
(buffer, &iter, header->body, -1,
header_tag, "emphasis", NULL);
} else {
gboolean hdr =
procheader_headername_equal(header->name, "From") ||
procheader_headername_equal(header->name, "To") ||
procheader_headername_equal(header->name, "Cc") ||
procheader_headername_equal(header->name, "Bcc") ||
procheader_headername_equal(header->name, "Reply-To") ||
procheader_headername_equal(header->name, "Sender") ||
procheader_headername_equal(header->name, "Resent-From") ||
procheader_headername_equal(header->name, "Resent-To");
textview_make_clickable_parts(textview, header_tag,
"hlink", header->body,
hdr);
}
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "\n", 1,
header_tag, NULL);
}
gboolean textview_search_string(TextView *textview, const gchar *str,
gboolean case_sens)
{