* changed forward as attachment, see ml
[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         GList *pos;
249         
250         for (pos = list; pos; pos = pos->next)
251                 if (pos->data)
252                         g_object_unref(pos->data);
253         g_list_free(list);
254         return;
255 }
256
257
258 ModestTnyAttachment *
259 modest_tny_attachment_new_from_mime_part(TnyMsgMimePartIface *part)
260 {
261         TnyStreamIface *mem_stream;
262         ModestTnyAttachment *self;
263         
264         mem_stream = TNY_STREAM_IFACE(tny_stream_camel_new(camel_stream_mem_new()));
265         self = modest_tny_attachment_new();
266         tny_msg_mime_part_iface_decode_to_stream(part, mem_stream);
267         tny_stream_iface_reset(mem_stream);
268         modest_tny_attachment_set_stream(self, mem_stream);
269         modest_tny_attachment_set_mime_type(self,
270                                             tny_msg_mime_part_iface_get_content_type(part));
271         modest_tny_attachment_set_name(self,
272                                             tny_msg_mime_part_iface_get_filename(part));
273         return self;
274 }
275
276 ModestTnyAttachment *
277 modest_tny_attachment_new_from_message(const TnyMsgIface *msg)
278 {
279         TnyStreamIface *mem_stream, *msg_stream;
280         ModestTnyAttachment *self;
281         gint res;
282         
283         mem_stream = TNY_STREAM_IFACE(tny_stream_camel_new(camel_stream_mem_new()));
284         msg_stream = tny_msg_mime_part_iface_get_stream(TNY_MSG_MIME_PART_IFACE(msg));
285         printf("ping\n");
286         tny_stream_iface_reset(msg_stream);
287         res = tny_stream_iface_write_to_stream(msg_stream, mem_stream);
288         //tny_msg_mime_part_iface_write_to_stream(TNY_MSG_MIME_PART_IFACE(msg), mem_stream);
289         printf("pong, %d\n", res);
290         tny_stream_iface_reset(msg_stream);
291         tny_stream_iface_reset(mem_stream);
292         self = modest_tny_attachment_new();
293         modest_tny_attachment_set_stream(self, mem_stream);
294         modest_tny_attachment_set_mime_type(self, "message/rfc822");
295         modest_tny_attachment_set_name(self, "original message");
296         return self;
297 }
298
299 GList *
300 modest_tny_attachment_new_list_from_msg(const TnyMsgIface *msg, gboolean with_body)
301 {
302         GList *list = NULL;
303         const GList *attachments = NULL;
304         TnyMsgMimePartIface *part;
305         ModestTnyAttachment *att;
306         
307 #if 0   
308         if (with_body) {
309                 /* TODO: make plain over html configurable */
310                 part = modest_tny_msg_actions_find_body_part ((TnyMsgIface *)msg, "text/plain");
311                 if (!part) 
312                         part = modest_tny_msg_actions_find_body_part ((TnyMsgIface *)msg, "text/html");
313                 if (part) {
314                         att = modest_tny_attachment_new_from_mime_part(part);
315                         /* TODO: i18n */
316                         modest_tny_attachment_set_name(att, "original message");
317                         list = g_list_append(list, att);
318                 }
319         }
320 #endif
321         if (with_body) {
322                 list = g_list_append(list, modest_tny_attachment_new_from_message(msg));
323         } else {
324                 attachments = tny_msg_iface_get_parts((TnyMsgIface *)msg);
325         }
326         while (attachments) {
327                 part = attachments->data;
328                 if (tny_msg_mime_part_iface_is_attachment(part)) {
329                         att = modest_tny_attachment_new_from_mime_part(part);
330                         list = g_list_append(list, att);
331                 }
332                 attachments = attachments->next;
333         }
334         return list;
335 }