e-mail-formatter-quote-headers.c 8.31 KB
Newer Older
Dan Vrátil's avatar
Dan Vrátil committed
1 2 3
/*
 * e-mail-formatter-quote-headers.c
 *
4 5 6
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation.
Dan Vrátil's avatar
Dan Vrátil committed
7
 *
8 9 10 11
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
Dan Vrátil's avatar
Dan Vrátil committed
12
 *
13 14
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Dan Vrátil's avatar
Dan Vrátil committed
15 16 17
 *
 */

18
#include "evolution-config.h"
Dan Vrátil's avatar
Dan Vrátil committed
19

20
#include <string.h>
Dan Vrátil's avatar
Dan Vrátil committed
21 22 23 24
#include <glib/gi18n-lib.h>

#include <camel/camel.h>

25
#include <e-util/e-util.h>
26
#include <libemail-engine/libemail-engine.h>
27 28 29 30

#include "e-mail-formatter-quote.h"
#include "e-mail-formatter-utils.h"
#include "e-mail-inline-filter.h"
31
#include "e-mail-part-headers.h"
Dan Vrátil's avatar
Dan Vrátil committed
32

33 34
#define HEADER_PREFIX "<div class=\"-x-evo-paragraph\" data-headers>"
#define HEADER_SUFFIX "</div>"
35

36 37
typedef EMailFormatterExtension EMailFormatterQuoteHeaders;
typedef EMailFormatterExtensionClass EMailFormatterQuoteHeadersClass;
Dan Vrátil's avatar
Dan Vrátil committed
38

39 40
GType e_mail_formatter_quote_headers_get_type (void);

41
G_DEFINE_TYPE (
Dan Vrátil's avatar
Dan Vrátil committed
42 43
	EMailFormatterQuoteHeaders,
	e_mail_formatter_quote_headers,
44
	E_TYPE_MAIL_FORMATTER_QUOTE_EXTENSION)
Dan Vrátil's avatar
Dan Vrátil committed
45

46 47 48 49 50
static const gchar *formatter_mime_types[] = {
	"application/vnd.evolution.headers",
	NULL
};

51 52
static void
emfqe_format_text_header (EMailFormatter *emf,
53 54 55 56 57
                          GString *buffer,
                          const gchar *label,
                          const gchar *value,
                          guint32 flags,
                          gint is_html)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
{
	const gchar *html;
	gchar *mhtml = NULL;

	if (value == NULL)
		return;

	while (*value == ' ')
		value++;

	if (!is_html)
		html = mhtml = camel_text_to_html (value, 0, 0);
	else
		html = value;

73 74
	g_string_append_printf (buffer, HEADER_PREFIX);

75 76
	if ((flags & E_MAIL_FORMATTER_HEADER_FLAG_BOLD) &&
	    !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NO_FORMATTING))
77
		g_string_append_printf (
78
			buffer, "<b>%s</b>: %s", label, html);
79 80
	else
		g_string_append_printf (
81 82 83
			buffer, "%s: %s", label, html);

	g_string_append_printf (buffer, HEADER_SUFFIX);
84 85 86 87 88 89 90 91 92 93 94 95 96

	g_free (mhtml);
}

/* XXX: This is copied in e-mail-formatter-utils.c */
static const gchar *addrspec_hdrs[] = {
	"Sender", "From", "Reply-To", "To", "Cc", "Bcc",
	"Resent-Sender", "Resent-From", "Resent-Reply-To",
	"Resent-To", "Resent-Cc", "Resent-Bcc", NULL
};

static void
emfqe_format_header (EMailFormatter *formatter,
97
		     EMailFormatterContext *context,
98
                     GString *buffer,
99
                     EMailPart *part,
100
                     const gchar *header_name,
101
                     const gchar *charset)
102
{
103
	CamelMimePart *mime_part;
104
	EMailFormatterHeaderFlags flags;
105
	gchar *canon_name, *buf, *value = NULL;
106 107 108 109 110
	const gchar *txt, *label;
	gboolean addrspec = FALSE;
	gint is_html = FALSE;
	gint i;

111 112 113 114 115
	/* Skip Face header in prints, which includes also message forward */
	if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING &&
	    g_ascii_strcasecmp (header_name, "Face") == 0)
		return;

116 117
	flags = E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE;

118 119 120
	if ((context->flags & E_MAIL_FORMATTER_HEADER_FLAG_NO_FORMATTING) != 0)
		flags |= E_MAIL_FORMATTER_HEADER_FLAG_NO_FORMATTING;

121 122
	canon_name = g_alloca (strlen (header_name) + 1);
	strcpy (canon_name, header_name);
123
	e_mail_formatter_canon_header_name (canon_name);
124

125 126 127 128
	/* Never quote Bcc/Resent-Bcc headers. */
	if (g_str_equal (canon_name, "Bcc"))
		return;
	if (g_str_equal (canon_name, "Resent-Bcc"))
129 130
		return;

131 132
	mime_part = e_mail_part_ref_mime_part (part);

133
	for (i = 0; addrspec_hdrs[i]; i++) {
134
		if (g_str_equal (canon_name, addrspec_hdrs[i])) {
135 136 137 138 139
			addrspec = TRUE;
			break;
		}
	}

140
	label = _(canon_name);
141 142

	if (addrspec) {
143
		CamelMedium *medium;
144 145
		struct _camel_header_address *addrs;
		GString *html;
146
		gchar *fmt_charset;
147

148 149 150
		medium = CAMEL_MEDIUM (mime_part);
		txt = camel_medium_get_header (medium, canon_name);
		if (txt == NULL)
151 152
			return;

153 154 155
		fmt_charset = e_mail_formatter_dup_charset (formatter);
		if (!fmt_charset)
			fmt_charset = e_mail_formatter_dup_default_charset (formatter);
156

157
		buf = camel_header_unfold (txt);
158 159
		addrs = camel_header_address_decode (txt, fmt_charset);
		g_free (fmt_charset);
160

161 162 163 164 165 166 167 168 169
		if (addrs == NULL) {
			g_free (buf);
			return;
		}

		g_free (buf);

		html = g_string_new ("");
		e_mail_formatter_format_address (formatter, html,
170
			addrs, canon_name, FALSE, FALSE);
171 172 173 174 175
		camel_header_address_unref (addrs);
		txt = value = html->str;
		g_string_free (html, FALSE);
		flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
		is_html = TRUE;
176 177 178 179 180 181

	} else if (g_str_equal (canon_name, "Subject")) {
		CamelMimeMessage *message;

		message = CAMEL_MIME_MESSAGE (mime_part);
		txt = camel_mime_message_get_subject (message);
182 183
		label = _("Subject");
		flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
184 185 186 187 188

	} else if (g_str_equal (canon_name, "X-Evolution-Mailer")) {
		CamelMedium *medium;

		medium = CAMEL_MEDIUM (mime_part);
189
		txt = camel_medium_get_header (medium, "user-agent");
190
		if (txt == NULL)
191
			txt = camel_medium_get_header (medium, "x-mailer");
192 193 194 195 196 197
		if (txt == NULL)
			txt = camel_medium_get_header (medium, "x-newsreader");
		if (txt == NULL)
			txt = camel_medium_get_header (medium, "x-mimeole");
		if (txt == NULL)
			return;
198 199 200 201 202

		txt = value = camel_header_format_ctext (txt, charset);

		label = _("Mailer");
		flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
203 204 205 206

	} else if (g_str_equal (canon_name, "Date") ||
		   g_str_equal (canon_name, "Resent-Date")) {
		CamelMedium *medium;
207
		GSettings *settings;
208 209 210 211

		medium = CAMEL_MEDIUM (mime_part);
		txt = camel_medium_get_header (medium, canon_name);
		if (txt == NULL)
212 213 214
			return;

		flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
215

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
		settings = e_util_ref_settings ("org.gnome.evolution.mail");
		if (g_settings_get_boolean (settings, "composer-reply-credits-utc-to-localtime")) {
			time_t date;
			gint offset = 0;

			date = camel_header_decode_date (txt, &offset);
			if (date > 0 && !offset) {
				struct tm gmtm, lctm;
				time_t gmtt, lctt;

				gmtime_r (&date, &gmtm);
				localtime_r (&date, &lctm);

				gmtt = mktime (&gmtm);
				lctt = mktime (&lctm);

				offset = (lctt - gmtt) * 100 / 3600;

				value = camel_header_format_date (date, offset);

				if (value && *value)
					txt = value;
			}
		}
		g_object_unref (settings);
241
	} else {
242 243 244 245
		CamelMedium *medium;

		medium = CAMEL_MEDIUM (mime_part);
		txt = camel_medium_get_header (medium, canon_name);
246 247 248 249 250 251 252 253
		buf = camel_header_unfold (txt);
		txt = value = camel_header_decode_string (txt, charset);
		g_free (buf);
	}

	emfqe_format_text_header (formatter, buffer, label, txt, flags, is_html);

	g_free (value);
254 255

	g_object_unref (mime_part);
256 257
}

Dan Vrátil's avatar
Dan Vrátil committed
258 259 260 261 262
static gboolean
emqfe_headers_format (EMailFormatterExtension *extension,
                      EMailFormatter *formatter,
                      EMailFormatterContext *context,
                      EMailPart *part,
263
                      GOutputStream *stream,
Dan Vrátil's avatar
Dan Vrátil committed
264 265 266
                      GCancellable *cancellable)
{
	CamelContentType *ct;
267
	CamelMimePart *mime_part;
Dan Vrátil's avatar
Dan Vrátil committed
268 269
	const gchar *charset;
	GString *buffer;
270 271
	gchar **default_headers;
	guint ii, length = 0;
Dan Vrátil's avatar
Dan Vrátil committed
272

273
	g_return_val_if_fail (E_IS_MAIL_PART_HEADERS (part), FALSE);
Dan Vrátil's avatar
Dan Vrátil committed
274

275 276 277
	mime_part = e_mail_part_ref_mime_part (part);

	ct = camel_mime_part_get_content_type (mime_part);
Dan Vrátil's avatar
Dan Vrátil committed
278 279 280 281 282
	charset = camel_content_type_param (ct, "charset");
	charset = camel_iconv_charset_name (charset);

	buffer = g_string_new ("");

283
	/* dump selected headers */
Dan Vrátil's avatar
Dan Vrátil committed
284

285 286 287 288
	default_headers = e_mail_part_headers_dup_default_headers (
		E_MAIL_PART_HEADERS (part));
	if (default_headers != NULL)
		length = g_strv_length (default_headers);
Dan Vrátil's avatar
Dan Vrátil committed
289

290 291
	for (ii = 0; ii < length; ii++)
		emfqe_format_header (
292
			formatter, context, buffer, part,
293
			default_headers[ii], charset);
294

295
	g_strfreev (default_headers);
296

297 298 299
	g_string_append (buffer, HEADER_PREFIX);
	g_string_append (buffer, "<br>");
	g_string_append (buffer, HEADER_SUFFIX);
Dan Vrátil's avatar
Dan Vrátil committed
300

301 302
	g_output_stream_write_all (
		stream, buffer->str, buffer->len, NULL, cancellable, NULL);
Dan Vrátil's avatar
Dan Vrátil committed
303 304 305

	g_string_free (buffer, TRUE);

306 307
	g_object_unref (mime_part);

Dan Vrátil's avatar
Dan Vrátil committed
308 309 310 311
	return TRUE;
}

static void
312
e_mail_formatter_quote_headers_class_init (EMailFormatterExtensionClass *class)
Dan Vrátil's avatar
Dan Vrátil committed
313
{
314
	class->mime_types = formatter_mime_types;
315
	class->priority = G_PRIORITY_HIGH;
316
	class->format = emqfe_headers_format;
Dan Vrátil's avatar
Dan Vrátil committed
317 318 319
}

static void
320
e_mail_formatter_quote_headers_init (EMailFormatterExtension *extension)
Dan Vrátil's avatar
Dan Vrátil committed
321 322
{
}