No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-formatter-utils.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-formatter-utils.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-mail-formatter-utils.h
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 #ifdef HAVE_CONFIG
20 #include <config.h>
21 #endif
22
23 #include "e-mail-formatter-utils.h"
24
25 #include <camel/camel.h>
26
27 #include <libemail-engine/e-mail-utils.h>
28 #include <libemail-engine/mail-config.h>
29 #include <e-util/e-util.h>
30 #include <e-util/e-datetime-format.h>
31 #include <libedataserver/libedataserver.h>
32
33 #include <glib/gi18n.h>
34
35 #include <string.h>
36
37 static const gchar *addrspec_hdrs[] = {
38 "Sender", "From", "Reply-To", "To", "Cc", "Bcc",
39 "Resent-Sender", "Resent-From", "Resent-Reply-To",
40 "Resent-To", "Resent-Cc", "Resent-Bcc", NULL
41 };
42
43 void
44 e_mail_formatter_format_text_header (EMailFormatter *formatter,
45 GString *buffer,
46 const gchar *label,
47 const gchar *value,
48 guint32 flags)
49 {
50 const gchar *fmt, *html;
51 gchar *mhtml = NULL;
52 gboolean is_rtl;
53
54 if (value == NULL)
55 return;
56
57 while (*value == ' ')
58 value++;
59
60 if (!(flags & E_MAIL_FORMATTER_HEADER_FLAG_HTML))
61 html = mhtml = camel_text_to_html (
62 value,
63 e_mail_formatter_get_text_format_flags (formatter), 0);
64 else
65 html = value;
66
67 is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
68
69 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOCOLUMNS) {
70 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_BOLD) {
71 fmt = "<tr class=\"header-item\" style=\"display: %s\"><td><b>%s:</b> %s</td></tr>";
72 } else {
73 fmt = "<tr class=\"header-item\" style=\"display: %s\"><td>%s: %s</td></tr>";
74 }
75 } else if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NODEC) {
76 if (is_rtl)
77 fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th valign=top align=\"left\" nowrap>%1$s<b> </b></th></tr>";
78 else
79 fmt = "<tr class=\"header-item\" style=\"display: %s\"><th align=\"right\" valign=\"top\" nowrap>%s<b> </b></th><td valign=top>%s</td></tr>";
80 } else {
81 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_BOLD) {
82 if (is_rtl)
83 fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th align=\"left\" nowrap>%1$s:<b> </b></th></tr>";
84 else
85 fmt = "<tr class=\"header-item\" style=\"display: %s\"><th align=\"right\" valign=\"top\" nowrap>%s:<b> </b></th><td>%s</td></tr>";
86 } else {
87 if (is_rtl)
88 fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%\">%2$s</td><td align=\"left\" nowrap>%1$s:<b> </b></td></tr>";
89 else
90 fmt = "<tr class=\"header-item\" style=\"display: %s\"><td align=\"right\" valign=\"top\" nowrap>%s:<b> </b></td><td>%s</td></tr>";
91 }
92 }
93
94 g_string_append_printf (
95 buffer, fmt,
96 (flags & E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN ? "none" : "table-row"), label, html);
97
98 g_free (mhtml);
99 }
100
101 gchar *
102 e_mail_formatter_format_address (EMailFormatter *formatter,
103 GString *out,
104 struct _camel_header_address *a,
105 gchar *field,
106 gboolean no_links,
107 gboolean elipsize)
108 {
109 guint32 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
110 gchar *name, *mailto, *addr;
111 gint i = 0;
112 gchar *str = NULL;
113 gint limit = mail_config_get_address_count ();
114
115 while (a) {
116 if (a->name)
117 name = camel_text_to_html (a->name, flags, 0);
118 else
119 name = NULL;
120
121 switch (a->type) {
122 case CAMEL_HEADER_ADDRESS_NAME:
123 if (name && *name) {
124 gchar *real, *mailaddr;
125
126 if (strchr (a->name, ',') || strchr (a->name, ';'))
127 g_string_append_printf (out, ""%s"", name);
128 else
129 g_string_append (out, name);
130
131 g_string_append (out, " <");
132
133 /* rfc2368 for mailto syntax and url encoding extras */
134 if ((real = camel_header_encode_phrase ((guchar *) a->name))) {
135 mailaddr = g_strdup_printf ("%s <%s>", real, a->v.addr);
136 g_free (real);
137 mailto = camel_url_encode (mailaddr, "?=&()");
138 g_free (mailaddr);
139 } else {
140 mailto = camel_url_encode (a->v.addr, "?=&()");
141 }
142 } else {
143 mailto = camel_url_encode (a->v.addr, "?=&()");
144 }
145 addr = camel_text_to_html (a->v.addr, flags, 0);
146 if (no_links)
147 g_string_append_printf (out, "%s", addr);
148 else
149 g_string_append_printf (out, "<a href=\"mailto:%s\">%s</a>", mailto, addr);
150 g_free (mailto);
151 g_free (addr);
152
153 if (name && *name)
154 g_string_append (out, ">");
155 break;
156 case CAMEL_HEADER_ADDRESS_GROUP:
157 g_string_append_printf (out, "%s: ", name);
158 e_mail_formatter_format_address (
159 formatter, out, a->v.members, field,
160 no_links, elipsize);
161 g_string_append_printf (out, ";");
162 break;
163 default:
164 g_warning ("Invalid address type");
165 break;
166 }
167
168 g_free (name);
169
170 i++;
171 a = a->next;
172 if (a)
173 g_string_append (out, ", ");
174
175 if (!elipsize)
176 continue;
177
178 /* Let us add a '...' if we have more addresses */
179 if (limit > 0 && i == limit && a != NULL) {
180 const gchar *id = NULL;
181
182 if (strcmp (field, _("To")) == 0) {
183 id = "to";
184 } else if (strcmp (field, _("Cc")) == 0) {
185 id = "cc";
186 } else if (strcmp (field, _("Bcc")) == 0) {
187 id = "bcc";
188 }
189
190 if (id) {
191 g_string_append_printf (
192 out,
193 "<span id=\"__evo-moreaddr-%s\" "
194 "style=\"display: none;\">", id);
195 str = g_strdup_printf (
196 "<img src=\"evo-file://%s/plus.png\" "
197 "id=\"__evo-moreaddr-img-%s\" class=\"navigable\">",
198 EVOLUTION_IMAGESDIR, id);
199 }
200 }
201 }
202
203 if (elipsize && str) {
204 const gchar *id = NULL;
205
206 if (strcmp (field, _("To")) == 0) {
207 id = "to";
208 } else if (strcmp (field, _("Cc")) == 0) {
209 id = "cc";
210 } else if (strcmp (field, _("Bcc")) == 0) {
211 id = "bcc";
212 }
213
214 if (id) {
215 g_string_append_printf (
216 out,
217 "</span>"
218 "<span class=\"navigable\" "
219 "id=\"__evo-moreaddr-ellipsis-%s\" "
220 "style=\"display: inline;\">...</span>",
221 id);
222 }
223 }
224
225 return str;
226 }
227
228 void
229 e_mail_formatter_canon_header_name (gchar *name)
230 {
231 gchar *inptr = name;
232
233 /* canonicalise the header name... first letter is
234 * capitalised and any letter following a '-' also gets
235 * capitalised */
236
237 if (*inptr >= 'a' && *inptr <= 'z')
238 *inptr -= 0x20;
239
240 inptr++;
241
242 while (*inptr) {
243 if (inptr[-1] == '-' && *inptr >= 'a' && *inptr <= 'z')
244 *inptr -= 0x20;
245 else if (*inptr >= 'A' && *inptr <= 'Z')
246 *inptr += 0x20;
247
248 inptr++;
249 }
250 }
251
252 void
253 e_mail_formatter_format_header (EMailFormatter *formatter,
254 GString *buffer,
255 CamelMedium *part,
256 struct _camel_header_raw *header,
257 guint32 flags,
258 const gchar *charset)
259 {
260 gchar *name, *buf, *value = NULL;
261 const gchar *label, *txt;
262 gboolean addrspec = FALSE;
263 gchar *str_field = NULL;
264 gint i;
265
266 name = g_alloca (strlen (header->name) + 1);
267 strcpy (name, header->name);
268 e_mail_formatter_canon_header_name (name);
269
270 for (i = 0; addrspec_hdrs[i]; i++) {
271 if (!strcmp (name, addrspec_hdrs[i])) {
272 addrspec = TRUE;
273 break;
274 }
275 }
276
277 label = _(name);
278
279 if (addrspec) {
280 struct _camel_header_address *addrs;
281 GString *html;
282 gchar *img;
283 const gchar *charset = e_mail_formatter_get_charset (formatter) ?
284 e_mail_formatter_get_charset (formatter) :
285 e_mail_formatter_get_default_charset (formatter);
286
287 buf = camel_header_unfold (header->value);
288 if (!(addrs = camel_header_address_decode (buf, charset))) {
289 g_free (buf);
290 return;
291 }
292
293 g_free (buf);
294
295 html = g_string_new ("");
296 img = e_mail_formatter_format_address (
297 formatter, html, addrs, (gchar *) label,
298 (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS),
299 !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE));
300
301 if (img) {
302 str_field = g_strdup_printf ("%s: %s", label, img);
303 label = str_field;
304 flags |= E_MAIL_FORMATTER_HEADER_FLAG_NODEC;
305 g_free (img);
306 }
307
308 camel_header_address_list_clear (&addrs);
309 txt = value = html->str;
310 g_string_free (html, FALSE);
311
312 flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML | E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
313 } else if (!strcmp (name, "Subject")) {
314 buf = camel_header_unfold (header->value);
315 txt = value = camel_header_decode_string (buf, charset);
316 g_free (buf);
317
318 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
319 } else if (!strcmp (name, "X-evolution-mailer")) {
320 /* pseudo-header */
321 label = _("Mailer");
322 txt = value = camel_header_format_ctext (header->value, charset);
323 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
324 } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) {
325 gint msg_offset, local_tz;
326 time_t msg_date;
327 struct tm local;
328 gchar *html;
329 gboolean hide_real_date;
330
331 hide_real_date = !e_mail_formatter_get_show_real_date (formatter);
332
333 txt = header->value;
334 while (*txt == ' ' || *txt == '\t')
335 txt++;
336
337 html = camel_text_to_html (
338 txt,
339 e_mail_formatter_get_text_format_flags (formatter), 0);
340
341 msg_date = camel_header_decode_date (txt, &msg_offset);
342 e_localtime_with_offset (msg_date, &local, &local_tz);
343
344 /* Convert message offset to minutes (e.g. -0400 --> -240) */
345 msg_offset = ((msg_offset / 100) * 60) + (msg_offset % 100);
346 /* Turn into offset from localtime, not UTC */
347 msg_offset -= local_tz / 60;
348
349 /* value will be freed at the end */
350 if (!hide_real_date && !msg_offset) {
351 /* No timezone difference; just show the real Date: header */
352 txt = value = html;
353 } else {
354 gchar *date_str;
355
356 date_str = e_datetime_format_format (
357 "mail", "header",
358 DTFormatKindDateTime, msg_date);
359
360 if (hide_real_date) {
361 /* Show only the local-formatted date, losing all timezone
362 * information like Outlook does. Should we attempt to show
363 * it somehow? */
364 txt = value = date_str;
365 } else {
366 txt = value = g_strdup_printf ("%s (<I>%s</I>)", html, date_str);
367 g_free (date_str);
368 }
369 g_free (html);
370 }
371 flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML |
372 E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
373 } else if (!strcmp (name, "Newsgroups")) {
374 struct _camel_header_newsgroup *ng, *scan;
375 GString *html;
376
377 buf = camel_header_unfold (header->value);
378
379 if (!(ng = camel_header_newsgroups_decode (buf))) {
380 g_free (buf);
381 return;
382 }
383
384 g_free (buf);
385
386 html = g_string_new ("");
387 scan = ng;
388 while (scan) {
389 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS)
390 g_string_append_printf (html, "%s", scan->newsgroup);
391 else
392 g_string_append_printf (
393 html, "<a href=\"news:%s\">%s</a>",
394 scan->newsgroup, scan->newsgroup);
395 scan = scan->next;
396 if (scan)
397 g_string_append_printf (html, ", ");
398 }
399
400 camel_header_newsgroups_free (ng);
401
402 txt = html->str;
403 g_string_free (html, FALSE);
404 flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML |
405 E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
406 } else if (!strcmp (name, "Received") || !strncmp (name, "X-", 2)) {
407 /* don't unfold Received nor extension headers */
408 txt = value = camel_header_decode_string (header->value, charset);
409 } else {
410 /* don't unfold Received nor extension headers */
411 buf = camel_header_unfold (header->value);
412 txt = value = camel_header_decode_string (buf, charset);
413 g_free (buf);
414 }
415
416 e_mail_formatter_format_text_header (formatter, buffer, label, txt, flags);
417
418 g_free (value);
419 g_free (str_field);
420 }
421
422 GSList *
423 e_mail_formatter_find_rfc822_end_iter (GSList *iter)
424 {
425 EMailPart *part;
426 gchar *end;
427
428 part = iter->data;
429 end = g_strconcat (part->id, ".end", NULL);
430 for (; iter != NULL; iter = g_slist_next (iter)) {
431 part = iter->data;
432 if (!part)
433 continue;
434
435 if (g_strcmp0 (part->id, end) == 0) {
436 g_free (end);
437 return iter;
438 }
439 }
440 g_free (end);
441 return iter;
442 }
443
444 gchar *
445 e_mail_formatter_parse_html_mnemonics (const gchar *label,
446 gchar **access_key)
447 {
448 const gchar *pos = NULL;
449 gchar ak = 0;
450 GString *html_label = NULL;
451
452 pos = strstr (label, "_");
453 if (pos != NULL) {
454 ak = pos[1];
455
456 /* Convert to uppercase */
457 if (ak >= 'a')
458 ak = ak - 32;
459
460 html_label = g_string_new ("");
461 g_string_append_len (html_label, label, pos - label);
462 g_string_append_printf (html_label, "<u>%c</u>", pos[1]);
463 g_string_append (html_label, &pos[2]);
464
465 if (access_key) {
466 if (ak) {
467 *access_key = g_strdup_printf ("%c", ak);
468 } else {
469 *access_key = NULL;
470 }
471 }
472
473 } else {
474 html_label = g_string_new (label);
475
476 if (access_key) {
477 *access_key = NULL;
478 }
479 }
480
481 return g_string_free (html_label, FALSE);
482 }