* Simple UTF8 support for string comparison.
[modest] / src / modest-tny-attachment.c
1 /* modest-tny-attachment.c */
2
3 /* insert (c)/licensing information) */
4
5 #include "modest-tny-attachment.h"
6 #include "modest-tny-msg-actions.h"
7
8 #include <tny-stream-camel.h>
9 #include <tny-fs-stream.h>
10 #include <camel/camel.h>
11
12
13 /* include other impl specific header files */
14
15 /* 'private'/'protected' functions */
16 static void                       modest_tny_attachment_class_init    (ModestTnyAttachmentClass *klass);
17 static void                       modest_tny_attachment_init          (ModestTnyAttachment *obj);
18 static void                       modest_tny_attachment_finalize      (GObject *obj);
19
20 /* list my signals */
21 enum {
22         /* MY_SIGNAL_1, */
23         /* MY_SIGNAL_2, */
24         LAST_SIGNAL
25 };
26
27 typedef struct _ModestTnyAttachmentPrivate ModestTnyAttachmentPrivate;
28 struct _ModestTnyAttachmentPrivate {
29         gchar *name;
30         gchar *filename;
31         gchar *mime_type;
32         gchar *disposition;
33         gchar *content_id;
34         TnyStreamIface *stream;
35 };
36 #define MODEST_TNY_ATTACHMENT_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
37                                                    MODEST_TYPE_TNY_ATTACHMENT, \
38                                                    ModestTnyAttachmentPrivate))
39 /* globals */
40 static GObjectClass *parent_class = NULL;
41
42 /* uncomment the following if you have defined any signals */
43 /* static guint signals[LAST_SIGNAL] = {0}; */
44
45 GType
46 modest_tny_attachment_get_type (void)
47 {
48         static GType my_type = 0;
49         if (!my_type) {
50                 static const GTypeInfo my_info = {
51                         sizeof(ModestTnyAttachmentClass),
52                         NULL,           /* base init */
53                         NULL,           /* base finalize */
54                         (GClassInitFunc) modest_tny_attachment_class_init,
55                         NULL,           /* class finalize */
56                         NULL,           /* class data */
57                         sizeof(ModestTnyAttachment),
58                         1,              /* n_preallocs */
59                         (GInstanceInitFunc) modest_tny_attachment_init,
60                 };
61                 my_type = g_type_register_static (G_TYPE_OBJECT,
62                                                   "ModestTnyAttachment",
63                                                   &my_info, 0);
64         }
65         return my_type;
66 }
67
68 static void
69 modest_tny_attachment_class_init (ModestTnyAttachmentClass *klass)
70 {
71         GObjectClass *gobject_class;
72         gobject_class = (GObjectClass*) klass;
73
74         parent_class            = g_type_class_peek_parent (klass);
75         gobject_class->finalize = modest_tny_attachment_finalize;
76
77         g_type_class_add_private (gobject_class, sizeof(ModestTnyAttachmentPrivate));
78
79         /* signal definitions go here, e.g.: */
80 /*      signals[MY_SIGNAL_1] = */
81 /*              g_signal_new ("my_signal_1",....); */
82 /*      signals[MY_SIGNAL_2] = */
83 /*              g_signal_new ("my_signal_2",....); */
84 /*      etc. */
85 }
86
87 static void
88 modest_tny_attachment_init (ModestTnyAttachment *obj)
89 {
90         ModestTnyAttachmentPrivate *priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(obj);
91
92         priv->name = NULL;
93         priv->filename = NULL;
94         priv->mime_type = NULL;
95         priv->disposition = NULL;
96         priv->content_id = NULL;
97         priv->stream = NULL;
98 }
99
100 static void
101 modest_tny_attachment_finalize (GObject *obj)
102 {
103         ModestTnyAttachmentPrivate *priv;
104         
105         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(MODEST_TNY_ATTACHMENT(obj));
106         g_free(priv->name);
107         g_free(priv->mime_type);
108         g_free(priv->disposition);
109         g_free(priv->content_id);
110         if (priv->stream)
111                 g_object_unref(G_OBJECT(priv->stream));
112 }
113
114 ModestTnyAttachment *
115 modest_tny_attachment_new (void)
116 {
117         return MODEST_TNY_ATTACHMENT(G_OBJECT(g_object_new(MODEST_TYPE_TNY_ATTACHMENT, NULL)));
118 }
119
120
121 void
122 modest_tny_attachment_set_name (ModestTnyAttachment *self, const gchar * thing)
123 {
124         ModestTnyAttachmentPrivate *priv;
125         
126         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
127         g_free(priv->name);
128         priv->name = g_strdup(thing);
129 }
130
131 const gchar *
132 modest_tny_attachment_get_name (ModestTnyAttachment *self)
133 {
134         ModestTnyAttachmentPrivate *priv;
135         
136         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
137         if (!priv->name)
138                 if (priv->filename)
139                         priv->name = g_path_get_basename(priv->filename);
140         return priv->name;
141 }
142
143
144 void
145 modest_tny_attachment_set_filename (ModestTnyAttachment *self, const gchar * thing)
146 {
147         ModestTnyAttachmentPrivate *priv;
148         
149         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
150         g_free(priv->filename);
151         priv->filename = g_strdup(thing);
152 }
153
154 const gchar *
155 modest_tny_attachment_get_filename (ModestTnyAttachment *self)
156 {
157         ModestTnyAttachmentPrivate *priv;
158         
159         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
160         return priv->filename;
161 }
162
163
164 void
165 modest_tny_attachment_set_mime_type (ModestTnyAttachment *self, const gchar * thing)
166 {
167         ModestTnyAttachmentPrivate *priv;
168         
169         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
170         g_free(priv->mime_type);
171         priv->mime_type = g_strdup(thing);
172 }
173
174 const gchar *
175 modest_tny_attachment_get_mime_type (ModestTnyAttachment *self)
176 {
177         ModestTnyAttachmentPrivate *priv;
178         
179         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
180         return priv->mime_type;
181 }
182
183
184
185 void
186 modest_tny_attachment_guess_mime_type (ModestTnyAttachment *self)
187 {
188         ModestTnyAttachmentPrivate *priv;
189         gchar *suffixes[] = {".jpg", ".gif", ".mp3", NULL};
190         gchar *types[]    = {"image/jpeg", "image/gif", "audio/mpeg", NULL};
191         gint pos;
192         
193         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
194         if (!priv->filename)
195                 return;
196         
197         for (pos = 0 ; suffixes[pos] ; pos++) {
198                 if (g_str_has_suffix(priv->filename, suffixes[pos]))
199                         break;
200         }
201         
202         g_free(priv->mime_type);
203         if (suffixes[pos])
204                 priv->mime_type = g_strdup(types[pos]);
205         else
206                 priv->mime_type = NULL;
207 }
208
209 static TnyStreamIface *
210 make_stream_from_file(const gchar * filename)
211 {
212         gint file;
213         
214         file = open(filename, O_RDONLY);
215         if (file < 0)
216                 return NULL;
217
218         return TNY_STREAM_IFACE(tny_stream_camel_new(camel_stream_fs_new_with_fd(file)));
219 }
220
221 void
222 modest_tny_attachment_set_stream(ModestTnyAttachment *self, TnyStreamIface *thing)
223 {
224         ModestTnyAttachmentPrivate *priv;
225         
226         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
227         if (priv->stream)
228                 g_object_unref(G_OBJECT(priv->stream));
229         priv->stream = thing;
230 }
231
232 TnyStreamIface *
233 modest_tny_attachment_get_stream (ModestTnyAttachment *self)
234 {
235         ModestTnyAttachmentPrivate *priv;
236         
237         priv = MODEST_TNY_ATTACHMENT_GET_PRIVATE(self);
238         if (!priv->stream)
239                 if (priv->filename)
240                         priv->stream = make_stream_from_file(priv->filename);
241         return priv->stream;
242 }
243
244
245 void
246 modest_tny_attachment_free_list(GList *list)
247 {
248         /* this is pretty generic for a GList of GObjects */
249         GList *pos;
250         
251         for (pos = list; pos; pos = pos->next)
252                 if (pos->data)
253                         g_object_unref(pos->data);
254         g_list_free(list);
255         return;
256 }
257
258
259 ModestTnyAttachment *
260 modest_tny_attachment_new_from_mime_part(TnyMsgMimePartIface *part)
261 {
262         TnyStreamIface *mem_stream;
263         ModestTnyAttachment *self;
264         
265         mem_stream = TNY_STREAM_IFACE(tny_stream_camel_new(camel_stream_mem_new()));
266         self = modest_tny_attachment_new();
267         tny_msg_mime_part_iface_decode_to_stream(part, mem_stream);
268         tny_stream_iface_reset(mem_stream);
269         modest_tny_attachment_set_stream(self, mem_stream);
270         modest_tny_attachment_set_mime_type(self,
271                                             tny_msg_mime_part_iface_get_content_type(part));
272         modest_tny_attachment_set_name(self,
273                                             tny_msg_mime_part_iface_get_filename(part));
274         return self;
275 }
276
277 ModestTnyAttachment *
278 modest_tny_attachment_new_from_message(const TnyMsgIface *msg)
279 {
280         TnyStreamIface *mem_stream, *msg_stream;
281         ModestTnyAttachment *self;
282         gint res;
283         
284         mem_stream = TNY_STREAM_IFACE(tny_stream_camel_new(camel_stream_mem_new()));
285         msg_stream = tny_msg_mime_part_iface_get_stream(TNY_MSG_MIME_PART_IFACE(msg));
286         printf("ping\n");
287         tny_stream_iface_reset(msg_stream);
288         res = tny_stream_iface_write_to_stream(msg_stream, mem_stream);
289         //tny_msg_mime_part_iface_write_to_stream(TNY_MSG_MIME_PART_IFACE(msg), mem_stream);
290         printf("pong, %d\n", res);
291         tny_stream_iface_reset(msg_stream);
292         tny_stream_iface_reset(mem_stream);
293         self = modest_tny_attachment_new();
294         modest_tny_attachment_set_stream(self, mem_stream);
295         modest_tny_attachment_set_mime_type(self, "message/rfc822");
296         modest_tny_attachment_set_name(self, "original message");
297         return self;
298 }
299
300 GList *
301 modest_tny_attachment_new_list_from_msg(const TnyMsgIface *msg, gboolean with_body)
302 {
303         GList *list = NULL;
304         const GList *attachments = NULL;
305         TnyMsgMimePartIface *part;
306         ModestTnyAttachment *att;
307         
308 #if 0   
309         if (with_body) {
310                 /* TODO: make plain over html configurable */
311                 part = modest_tny_msg_actions_find_body_part ((TnyMsgIface *)msg, "text/plain");
312                 if (!part) 
313                         part = modest_tny_msg_actions_find_body_part ((TnyMsgIface *)msg, "text/html");
314                 if (part) {
315                         att = modest_tny_attachment_new_from_mime_part(part);
316                         /* TODO: i18n */
317                         modest_tny_attachment_set_name(att, "original message");
318                         list = g_list_append(list, att);
319                 }
320         }
321 #endif
322         if (with_body) {
323                 list = g_list_append(list, modest_tny_attachment_new_from_message(msg));
324         } else {
325                 attachments = tny_msg_iface_get_parts((TnyMsgIface *)msg);
326         }
327         while (attachments) {
328                 part = attachments->data;
329                 if (tny_msg_mime_part_iface_is_attachment(part)) {
330                         att = modest_tny_attachment_new_from_mime_part(part);
331                         list = g_list_append(list, att);
332                 }
333                 attachments = attachments->next;
334         }
335         return list;
336 }