2 * e-mail-formatter-attachment.c
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "evolution-config.h"
20 #include <glib/gi18n-lib.h>
22 #include <shell/e-shell.h>
23 #include <shell/e-shell-window.h>
25 #include "e-mail-formatter-extension.h"
26 #include "e-mail-inline-filter.h"
27 #include "e-mail-part-attachment.h"
28 #include "e-mail-part-utils.h"
32 typedef EMailFormatterExtension EMailFormatterAttachment
;
33 typedef EMailFormatterExtensionClass EMailFormatterAttachmentClass
;
35 GType
e_mail_formatter_attachment_get_type (void);
38 EMailFormatterAttachment
,
39 e_mail_formatter_attachment
,
40 E_TYPE_MAIL_FORMATTER_EXTENSION
)
42 static const gchar
*formatter_mime_types
[] = {
43 E_MAIL_PART_ATTACHMENT_MIME_TYPE
,
44 "application/vnd.evolution.attachment-button",
49 emfe_attachment_format (EMailFormatterExtension
*extension
,
50 EMailFormatter
*formatter
,
51 EMailFormatterContext
*context
,
53 GOutputStream
*stream
,
54 GCancellable
*cancellable
)
58 EMailExtensionRegistry
*registry
;
60 EMailPartAttachment
*empa
;
61 CamelMimePart
*mime_part
;
62 CamelMimeFilterToHTMLFlags flags
;
63 GOutputStream
*content_stream
= NULL
;
65 gint icon_width
, icon_height
;
67 gpointer attachment_ptr
= NULL
;
68 const gchar
*attachment_part_id
;
71 g_return_val_if_fail (E_IS_MAIL_PART_ATTACHMENT (part
), FALSE
);
73 empa
= (EMailPartAttachment
*) part
;
74 part_id
= e_mail_part_get_id (part
);
76 if ((context
->mode
== E_MAIL_FORMATTER_MODE_NORMAL
) ||
77 (context
->mode
== E_MAIL_FORMATTER_MODE_PRINTING
) ||
78 (context
->mode
== E_MAIL_FORMATTER_MODE_ALL_HEADERS
)) {
79 EAttachment
*attachment
;
82 attachment
= e_mail_part_attachment_ref_attachment (E_MAIL_PART_ATTACHMENT (part
));
83 attachment_ptr
= attachment
;
85 head
= g_queue_peek_head_link (&part
->validities
);
87 for (link
= head
; link
!= NULL
; link
= g_list_next (link
)) {
88 EMailPartValidityPair
*pair
= link
->data
;
93 if ((pair
->validity_type
& E_MAIL_PART_VALIDITY_SIGNED
) != 0)
94 e_attachment_set_signed (
96 pair
->validity
->sign
.status
);
98 if ((pair
->validity_type
& E_MAIL_PART_VALIDITY_ENCRYPTED
) != 0)
99 e_attachment_set_encrypted (
101 pair
->validity
->encrypt
.status
);
104 e_attachment_set_initially_shown (attachment
, e_mail_part_should_show_inline (part
));
106 e_mail_formatter_claim_attachment (formatter
, attachment
);
108 g_object_unref (attachment
);
111 registry
= e_mail_formatter_get_extension_registry (formatter
);
113 extensions
= e_mail_extension_registry_get_for_mime_type (
114 registry
, empa
->snoop_mime_type
);
115 if (extensions
== NULL
)
116 extensions
= e_mail_extension_registry_get_fallback (
117 registry
, empa
->snoop_mime_type
);
119 /* If the attachment is requested as RAW, then call the
120 * handler directly and do not append any other code. */
121 if ((context
->mode
== E_MAIL_FORMATTER_MODE_RAW
) ||
122 (context
->mode
== E_MAIL_FORMATTER_MODE_PRINTING
)) {
124 gboolean success
= FALSE
;
126 if (extensions
== NULL
)
129 if (context
->mode
== E_MAIL_FORMATTER_MODE_PRINTING
) {
131 EAttachment
*attachment
;
132 GFileInfo
*file_info
;
133 const gchar
*display_name
;
136 attachment
= e_mail_part_attachment_ref_attachment (
137 E_MAIL_PART_ATTACHMENT (part
));
139 file_info
= e_attachment_ref_file_info (attachment
);
141 display_name
= g_file_info_get_display_name (file_info
);
145 description
= e_attachment_dup_description (attachment
);
146 if (description
!= NULL
&& *description
!= '\0') {
147 name
= g_strdup_printf (
148 "<h2>Attachment: %s (%s)</h2>\n",
149 description
, display_name
);
151 name
= g_strdup_printf (
152 "<h2>Attachment: %s</h2>\n",
156 g_output_stream_write_all (
157 stream
, name
, strlen (name
),
158 NULL
, cancellable
, NULL
);
160 g_free (description
);
163 g_clear_object (&attachment
);
164 g_clear_object (&file_info
);
167 head
= g_queue_peek_head_link (extensions
);
169 for (link
= head
; link
!= NULL
; link
= g_list_next (link
)) {
170 success
= e_mail_formatter_extension_format (
171 E_MAIL_FORMATTER_EXTENSION (link
->data
),
172 formatter
, context
, part
, stream
, cancellable
);
180 /* E_MAIL_FORMATTER_MODE_NORMAL: */
182 mime_part
= e_mail_part_ref_mime_part (part
);
183 text
= e_mail_part_describe (mime_part
, empa
->snoop_mime_type
);
184 flags
= e_mail_formatter_get_text_format_flags (formatter
);
185 html
= camel_text_to_html (
186 text
, flags
& CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS
, 0);
188 g_object_unref (mime_part
);
190 if (empa
->part_id_with_attachment
)
191 attachment_part_id
= empa
->part_id_with_attachment
;
193 attachment_part_id
= part_id
;
195 button_id
= g_strconcat (attachment_part_id
, ".attachment_button", NULL
);
197 if (!gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON
, &icon_width
, &icon_height
)) {
202 if (extensions
!= NULL
) {
203 gboolean success
= FALSE
;
205 content_stream
= g_memory_output_stream_new_resizable ();
207 if (empa
->part_id_with_attachment
!= NULL
) {
208 EMailPart
*attachment_view_part
;
210 attachment_view_part
= e_mail_part_list_ref_part (
212 empa
->part_id_with_attachment
);
214 /* Avoid recursion. */
215 if (attachment_view_part
== part
)
216 g_clear_object (&attachment_view_part
);
218 if (attachment_view_part
!= NULL
) {
219 success
= e_mail_formatter_format_as (
221 attachment_view_part
,
222 content_stream
, NULL
,
224 g_object_unref (attachment_view_part
);
230 head
= g_queue_peek_head_link (extensions
);
232 for (link
= head
; link
!= NULL
; link
= g_list_next (link
)) {
233 success
= e_mail_formatter_extension_format (
234 E_MAIL_FORMATTER_EXTENSION (link
->data
),
236 part
, content_stream
,
243 e_mail_part_attachment_set_expandable (empa
, success
);
246 icon_uri
= e_mail_part_build_uri (
247 e_mail_part_list_get_folder (context
->part_list
),
248 e_mail_part_list_get_message_uid (context
->part_list
),
249 "part_id", G_TYPE_STRING
, part_id
,
250 "attachment_icon", G_TYPE_POINTER
, attachment_ptr
,
251 "size", G_TYPE_INT
, icon_width
,
254 /* XXX Wild guess at the initial size. */
255 buffer
= g_string_sized_new (8192);
257 g_string_append_printf (
259 "<div class=\"attachment\">"
260 "<table width=\"100%%\" border=\"0\" style=\"border-spacing: 0px\">"
261 "<tr valign=\"middle\">"
262 "<td align=\"left\" width=\"1px\" style=\"white-space:pre;\">"
263 "<button type=\"button\" class=\"attachment-expander\" id=\"%s\" value=\"%p\" data=\"%s\" style=\"vertical-align:middle; margin:0px;\">"
264 "<img id=\"attachment-expander-img-%p\" src=\"gtk-stock://%s?size=%d\" width=\"%dpx\" height=\"%dpx\" style=\"vertical-align:middle;\">"
265 "<img src=\"%s\" width=\"%dpx\" height=\"%dpx\" style=\"vertical-align:middle;\">"
267 "<button type=\"button\" class=\"attachment-menu\" id=\"%s\" value=\"%p\" style=\"vertical-align:middle; margin:0px;\">"
268 "<img src=\"gtk-stock://x-evolution-arrow-down?size=%d\" width=\"%dpx\" height=\"%dpx\" style=\"vertical-align:middle;\">"
270 "</td><td align=\"left\">%s</td></tr>",
271 part_id
, attachment_ptr
, html
, attachment_ptr
,
272 e_mail_part_should_show_inline (part
) ? "go-down" : e_mail_part_attachment_get_expandable (empa
) ? "go-next" : "go-top",
273 GTK_ICON_SIZE_BUTTON
, icon_width
, icon_height
,
274 icon_uri
, icon_width
, icon_height
,
275 part_id
, attachment_ptr
, GTK_ICON_SIZE_BUTTON
, icon_width
, icon_height
,
282 if (content_stream
&& e_mail_part_attachment_get_expandable (empa
)) {
283 gchar
*wrapper_element_id
;
287 wrapper_element_id
= g_strdup_printf ("attachment-wrapper-%p", attachment_ptr
);
289 data
= g_memory_output_stream_get_data (
290 G_MEMORY_OUTPUT_STREAM (content_stream
));
291 size
= g_memory_output_stream_get_data_size (
292 G_MEMORY_OUTPUT_STREAM (content_stream
));
294 g_string_append_printf (
296 "<tr><td colspan=\"2\">"
297 "<div class=\"attachment-wrapper\" id=\"%s\"",
300 if (e_mail_part_should_show_inline (part
)) {
301 g_string_append (buffer
, ">");
302 g_string_append_len (buffer
, data
, size
);
304 gchar
*inner_html_data
;
306 inner_html_data
= g_markup_escape_text (data
, size
);
308 g_string_append_printf (buffer
, " related-part-id=\"%s\" inner-html-data=\"%s\">",
309 attachment_part_id
, inner_html_data
);
311 g_free (inner_html_data
);
314 g_string_append (buffer
, "</div></td></tr>");
316 g_free (wrapper_element_id
);
319 g_clear_object (&content_stream
);
321 g_string_append (buffer
, "</table></div>");
323 g_output_stream_write_all (
324 stream
, buffer
->str
, buffer
->len
, NULL
, cancellable
, NULL
);
326 g_string_free (buffer
, TRUE
);
332 e_mail_formatter_attachment_class_init (EMailFormatterExtensionClass
*class)
334 class->display_name
= _("Attachment");
335 class->description
= _("Display as attachment");
336 class->mime_types
= formatter_mime_types
;
337 class->priority
= G_PRIORITY_LOW
;
338 class->format
= emfe_attachment_format
;
342 e_mail_formatter_attachment_init (EMailFormatterExtension
*extension
)