1 /*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9 * for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
13 *
14 *
15 * Authors:
16 * JP Rosevear <jpr@novell.com>
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #include "evolution-config.h"
23
24 #include <string.h>
25 #include <gtk/gtk.h>
26 #include <glib/gi18n.h>
27
28 #include "e-mail-parser-itip.h"
29
30 #include <shell/e-shell.h>
31
32 #include <em-format/e-mail-extension-registry.h>
33 #include <em-format/e-mail-parser-extension.h>
34 #include <em-format/e-mail-part.h>
35
36 #include "e-mail-part-itip.h"
37 #include "itip-view.h"
38
39 #define d(x)
40
41 typedef EMailParserExtension EMailParserItip;
42 typedef EMailParserExtensionClass EMailParserItipClass;
43
44 typedef EExtension EMailParserItipLoader;
45 typedef EExtensionClass EMailParserItipLoaderClass;
46
47 GType e_mail_parser_itip_get_type (void);
48
49 G_DEFINE_DYNAMIC_TYPE (
50 EMailParserItip,
51 e_mail_parser_itip,
52 E_TYPE_MAIL_PARSER_EXTENSION)
53
54 static const gchar *parser_mime_types[] = {
55 "text/calendar",
56 "application/ics",
57 NULL
58 };
59
60 static void
empe_itip_wrap_attachment(EMailParser * parser,GString * part_id,ICalProperty * prop,const gchar * content,GQueue * queue)61 empe_itip_wrap_attachment (EMailParser *parser,
62 GString *part_id,
63 ICalProperty *prop,
64 const gchar *content,
65 GQueue *queue)
66 {
67 CamelMimePart *opart;
68 CamelDataWrapper *dw;
69 ICalParameter *param;
70 const gchar *mime_type = NULL, *tmp;
71
72 opart = camel_mime_part_new ();
73
74 param = i_cal_property_get_first_parameter (prop, I_CAL_FILENAME_PARAMETER);
75
76 if (param) {
77 tmp = i_cal_parameter_get_filename (param);
78
79 if (tmp && *tmp)
80 camel_mime_part_set_filename (opart, tmp);
81
82 g_object_unref (param);
83 }
84
85 param = i_cal_property_get_first_parameter (prop, I_CAL_FMTTYPE_PARAMETER);
86
87 if (param)
88 mime_type = i_cal_parameter_get_fmttype (param);
89
90 if (!mime_type || !*mime_type)
91 mime_type = "application/octet-stream";
92
93 camel_mime_part_set_content (opart, content, strlen (content), mime_type);
94 camel_mime_part_set_encoding (opart, CAMEL_TRANSFER_ENCODING_BASE64);
95
96 dw = camel_medium_get_content (CAMEL_MEDIUM (opart));
97 camel_data_wrapper_set_encoding (dw, CAMEL_TRANSFER_ENCODING_BASE64);
98
99 e_mail_parser_wrap_as_attachment (parser, opart, part_id, queue);
100
101 g_clear_object (¶m);
102 g_object_unref (opart);
103 }
104
105 static void
empe_itip_extract_attachments(EMailParser * parser,const gchar * vcalendar_str,GString * part_id,GQueue * queue)106 empe_itip_extract_attachments (EMailParser *parser,
107 const gchar *vcalendar_str,
108 GString *part_id,
109 GQueue *queue)
110 {
111 ICalComponent *vcalendar, *ical_comp;
112 ICalCompIter *iter;
113
114 if (!vcalendar_str)
115 return;
116
117 vcalendar = i_cal_parser_parse_string (vcalendar_str);
118
119 if (!vcalendar)
120 return;
121
122 iter = i_cal_component_begin_component (vcalendar, I_CAL_ANY_COMPONENT);
123 ical_comp = i_cal_comp_iter_deref (iter);
124 if (ical_comp) {
125 ICalComponentKind kind;
126
127 kind = i_cal_component_isa (ical_comp);
128 if (kind != I_CAL_VEVENT_COMPONENT &&
129 kind != I_CAL_VTODO_COMPONENT &&
130 kind != I_CAL_VFREEBUSY_COMPONENT &&
131 kind != I_CAL_VJOURNAL_COMPONENT) {
132 do {
133 g_clear_object (&ical_comp);
134 ical_comp = i_cal_comp_iter_next (iter);
135 if (!ical_comp)
136 break;
137 kind = i_cal_component_isa (ical_comp);
138 } while (ical_comp &&
139 kind != I_CAL_VEVENT_COMPONENT &&
140 kind != I_CAL_VTODO_COMPONENT &&
141 kind != I_CAL_VFREEBUSY_COMPONENT &&
142 kind != I_CAL_VJOURNAL_COMPONENT);
143 }
144 }
145
146 g_clear_object (&iter);
147
148 if (ical_comp) {
149 ICalProperty *prop;
150 gint len, index = 0;
151
152 len = part_id->len;
153
154 for (prop = i_cal_component_get_first_property (ical_comp, I_CAL_ATTACH_PROPERTY);
155 prop;
156 g_object_unref (prop), prop = i_cal_component_get_next_property (ical_comp, I_CAL_ATTACH_PROPERTY)) {
157 ICalAttach *attach;
158
159 attach = i_cal_property_get_attach (prop);
160
161 if (attach && !i_cal_attach_get_is_url (attach)) {
162 const gchar *content;
163
164 content = (const gchar *) i_cal_attach_get_data (attach);
165
166 if (content) {
167 g_string_append_printf (part_id, ".attachment.%d", index);
168
169 empe_itip_wrap_attachment (parser, part_id, prop, content, queue);
170
171 g_string_truncate (part_id, len);
172 index++;
173 }
174 }
175
176 g_clear_object (&attach);
177 }
178 }
179
180 g_clear_object (&ical_comp);
181 g_clear_object (&vcalendar);
182 }
183
184 static gboolean
empe_itip_parse(EMailParserExtension * extension,EMailParser * parser,CamelMimePart * part,GString * part_id,GCancellable * cancellable,GQueue * out_mail_parts)185 empe_itip_parse (EMailParserExtension *extension,
186 EMailParser *parser,
187 CamelMimePart *part,
188 GString *part_id,
189 GCancellable *cancellable,
190 GQueue *out_mail_parts)
191 {
192 EMailPartItip *itip_part;
193 CamelDataWrapper *content;
194 CamelStream *stream;
195 GByteArray *byte_array;
196 gint len;
197 const CamelContentDisposition *disposition;
198 GQueue work_queue = G_QUEUE_INIT;
199
200 len = part_id->len;
201 g_string_append_printf (part_id, ".itip");
202
203 itip_part = e_mail_part_itip_new (part, part_id->str);
204 itip_part->itip_mime_part = g_object_ref (part);
205
206 /* This is non-gui thread. Download the part for using in the main thread */
207 content = camel_medium_get_content ((CamelMedium *) part);
208
209 byte_array = g_byte_array_new ();
210 stream = camel_stream_mem_new_with_byte_array (byte_array);
211 camel_data_wrapper_decode_to_stream_sync (content, stream, NULL, NULL);
212
213 if (byte_array->len == 0)
214 itip_part->vcalendar = NULL;
215 else
216 itip_part->vcalendar = g_strndup (
217 (gchar *) byte_array->data, byte_array->len);
218
219 g_object_unref (stream);
220
221 g_queue_push_tail (&work_queue, itip_part);
222
223 disposition = camel_mime_part_get_content_disposition (part);
224 if (disposition &&
225 (g_strcmp0 (disposition->disposition, "attachment") == 0)) {
226 e_mail_parser_wrap_as_attachment (
227 parser, part, part_id, &work_queue);
228 }
229
230 e_queue_transfer (&work_queue, out_mail_parts);
231
232 empe_itip_extract_attachments (parser, itip_part->vcalendar, part_id, &work_queue);
233 e_queue_transfer (&work_queue, out_mail_parts);
234
235 g_string_truncate (part_id, len);
236
237 return TRUE;
238 }
239
240 static void
e_mail_parser_itip_class_init(EMailParserExtensionClass * class)241 e_mail_parser_itip_class_init (EMailParserExtensionClass *class)
242 {
243 class->mime_types = parser_mime_types;
244 class->flags = E_MAIL_PARSER_EXTENSION_INLINE_DISPOSITION;
245 class->parse = empe_itip_parse;
246 }
247
248 static void
e_mail_parser_itip_class_finalize(EMailParserExtensionClass * class)249 e_mail_parser_itip_class_finalize (EMailParserExtensionClass *class)
250 {
251 }
252
253 static void
e_mail_parser_itip_init(EMailParserExtension * class)254 e_mail_parser_itip_init (EMailParserExtension *class)
255 {
256 }
257
258 void
e_mail_parser_itip_type_register(GTypeModule * type_module)259 e_mail_parser_itip_type_register (GTypeModule *type_module)
260 {
261 e_mail_parser_itip_register_type (type_module);
262 }
263