ed9b27e945038a6b0032f6c1a178f8faddd32fa2
[modest] / src / modest-tny-transport-actions.c
1 /* modest-tny-transport-actions.c */
2
3 /* insert (c)/licensing information) */
4
5 #include <tny-msg.h>
6 #include <tny-msg-iface.h>                      
7 #include <tny-msg-mime-part.h>
8 #include <tny-msg-mime-part-iface.h>            
9 #include <tny-stream-iface.h>
10 #include <tny-msg-header.h>
11 #include <tny-msg-header-iface.h>
12 #include <tny-account-iface.h>  
13 #include <tny-account-store-iface.h>
14 #include <tny-transport-account-iface.h>        
15 #include <tny-transport-account.h>
16 #include <tny-stream-camel.h>
17 #include <tny-fs-stream.h>
18 #include <string.h>
19 #include <camel/camel-folder.h>
20 #include <camel/camel.h>
21 #include <camel/camel-folder-summary.h>
22
23 #include "modest-tny-transport-actions.h"
24 #include "modest-tny-attachment.h"
25 /* include other impl specific header files */
26
27 /* 'private'/'protected' functions */
28 static void                              modest_tny_transport_actions_class_init   (ModestTnyTransportActionsClass *klass);
29 static void                              modest_tny_transport_actions_init         (ModestTnyTransportActions *obj);
30 static void                              modest_tny_transport_actions_finalize     (GObject *obj);
31 static gboolean                          is_ascii                                  (const gchar *s);
32 static char *                            get_content_type                          (const gchar *s);
33
34 /* list my signals */
35 enum {
36         /* MY_SIGNAL_1, */
37         /* MY_SIGNAL_2, */
38         LAST_SIGNAL
39 };
40
41 typedef struct _ModestTnyTransportActionsPrivate ModestTnyTransportActionsPrivate;
42 struct _ModestTnyTransportActionsPrivate {
43         /* my private members go here, eg. */
44         /* gboolean frobnicate_mode; */
45 };
46 #define MODEST_TNY_TRANSPORT_ACTIONS_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
47                                                           MODEST_TYPE_TNY_TRANSPORT_ACTIONS, \
48                                                           ModestTnyTransportActionsPrivate))
49 /* globals */
50 static GObjectClass *parent_class = NULL;
51
52 /* uncomment the following if you have defined any signals */
53 /* static guint signals[LAST_SIGNAL] = {0}; */
54
55 GType
56 modest_tny_transport_actions_get_type (void)
57 {
58         static GType my_type = 0;
59         if (!my_type) {
60                 static const GTypeInfo my_info = {
61                         sizeof(ModestTnyTransportActionsClass),
62                         NULL,           /* base init */
63                         NULL,           /* base finalize */
64                         (GClassInitFunc) modest_tny_transport_actions_class_init,
65                         NULL,           /* class finalize */
66                         NULL,           /* class data */
67                         sizeof(ModestTnyTransportActions),
68                         1,              /* n_preallocs */
69                         (GInstanceInitFunc) modest_tny_transport_actions_init,
70                 };
71                 my_type = g_type_register_static (G_TYPE_OBJECT,
72                                                   "ModestTnyTransportActions",
73                                                   &my_info, 0);
74         }
75         return my_type;
76 }
77
78 static void
79 modest_tny_transport_actions_class_init (ModestTnyTransportActionsClass *klass)
80 {
81         GObjectClass *gobject_class;
82         gobject_class = (GObjectClass*) klass;
83
84         parent_class            = g_type_class_peek_parent (klass);
85         gobject_class->finalize = modest_tny_transport_actions_finalize;
86
87         g_type_class_add_private (gobject_class, sizeof(ModestTnyTransportActionsPrivate));
88
89         /* signal definitions go here, e.g.: */
90 /*      signals[MY_SIGNAL_1] = */
91 /*              g_signal_new ("my_signal_1",....); */
92 /*      signals[MY_SIGNAL_2] = */
93 /*              g_signal_new ("my_signal_2",....); */
94 /*      etc. */
95 }
96
97 static void
98 modest_tny_transport_actions_init (ModestTnyTransportActions *obj)
99 {
100 /* uncomment the following if you init any of the private data */
101 /*      ModestTnyTransportActionsPrivate *priv = MODEST_TNY_TRANSPORT_ACTIONS_GET_PRIVATE(obj); */
102
103 /*      initialize this object, eg.: */
104 /*      priv->frobnicate_mode = FALSE; */
105 }
106
107 static void
108 modest_tny_transport_actions_finalize (GObject *obj)
109 {
110 /*      free/unref instance resources here */
111 }
112
113 GObject*
114 modest_tny_transport_actions_new (void)
115 {
116         return G_OBJECT(g_object_new(MODEST_TYPE_TNY_TRANSPORT_ACTIONS, NULL));
117 }
118
119 static gboolean
120 is_ascii(const gchar *s)
121 {
122         while (s[0]) {
123                 if (s[0] & 128 || s[0] < 32)
124                         return FALSE;
125                 s++;
126         }
127         return TRUE;
128 }
129
130 static char *
131 get_content_type(const gchar *s)
132 {
133         GString *type;
134         
135         type = g_string_new("text/plain");
136         if (!is_ascii(s)) {
137                 if (g_utf8_validate(s, -1, NULL)) {
138                         g_string_append(type, "; charset=\"utf-8\"");
139                 } else {
140                         /* it should be impossible to reach this, but better safe than sorry */
141                         g_warning("invalid utf8 in message");
142                         g_string_append(type, "; charset=\"latin1\"");
143                 }
144         }
145         return g_string_free(type, FALSE);
146 }
147
148 gboolean
149 modest_tny_transport_actions_send_message (ModestTnyTransportActions *self,
150                                            TnyTransportAccountIface *transport_account,
151                                            const gchar *from,
152                                            const gchar *to,
153                                            const gchar *cc,
154                                            const gchar *bcc,
155                                            const gchar *subject,
156                                            const gchar *body,
157                                            const GList *attachments_list)
158 {
159         TnyMsgIface *new_msg;
160         TnyMsgMimePartIface *attachment_part, *text_body_part;
161         TnyMsgHeaderIface *headers;
162         TnyStreamIface *text_body_stream, *attachment_stream;
163         ModestTnyAttachment *attachment;
164         GList *pos;
165         gchar *content_type;
166         const gchar *attachment_content_type;
167         const gchar *attachment_filename;
168         
169         new_msg          = TNY_MSG_IFACE(tny_msg_new ());
170         headers          = TNY_MSG_HEADER_IFACE(tny_msg_header_new ());
171         text_body_stream = TNY_STREAM_IFACE (tny_stream_camel_new
172                                              (camel_stream_mem_new_with_buffer
173                                               (body, strlen(body))));
174         
175         tny_msg_header_iface_set_from (TNY_MSG_HEADER_IFACE (headers), from);
176         tny_msg_header_iface_set_to (TNY_MSG_HEADER_IFACE (headers), to);
177         tny_msg_header_iface_set_cc (TNY_MSG_HEADER_IFACE (headers), cc);
178         tny_msg_header_iface_set_bcc (TNY_MSG_HEADER_IFACE (headers), bcc);
179         tny_msg_header_iface_set_subject (TNY_MSG_HEADER_IFACE (headers), subject);
180         tny_msg_iface_set_header (new_msg, headers);
181
182         
183         content_type = get_content_type(body);
184         
185         if (attachments_list == NULL) {
186                 tny_stream_iface_reset (text_body_stream);
187                 tny_msg_mime_part_iface_construct_from_stream (TNY_MSG_MIME_PART_IFACE(new_msg),
188                                                                text_body_stream, content_type);
189                 tny_stream_iface_reset (text_body_stream);
190         } else {
191                 text_body_part = TNY_MSG_MIME_PART_IFACE (tny_msg_mime_part_new(
192                                                           camel_mime_part_new()));
193                 tny_stream_iface_reset (text_body_stream);
194                 tny_msg_mime_part_iface_construct_from_stream (text_body_part,
195                                                                text_body_stream,
196                                                                content_type);
197                 tny_stream_iface_reset (text_body_stream);
198                 tny_msg_iface_add_part(new_msg, text_body_part);
199                 //g_object_unref (G_OBJECT(text_body_part));
200         }
201         
202         for (    pos = (GList *)attachments_list;
203                  pos;
204                  pos = pos->next    ) {
205                 attachment = pos->data;
206                 attachment_filename = modest_tny_attachment_get_name(attachment);
207                 attachment_stream = modest_tny_attachment_get_stream(attachment);
208                 attachment_part = TNY_MSG_MIME_PART_IFACE (tny_msg_mime_part_new (
209                                                                 camel_mime_part_new()));
210                 
211                 attachment_content_type = modest_tny_attachment_get_mime_type(attachment);
212                                  
213                 tny_msg_mime_part_iface_construct_from_stream (attachment_part,
214                                                                attachment_stream,
215                                                                attachment_content_type);
216                 tny_stream_iface_reset (attachment_stream);
217                 
218                 tny_msg_mime_part_iface_set_filename(attachment_part, attachment_filename);
219                 
220                 tny_msg_iface_add_part (new_msg, attachment_part);
221                 //g_object_unref(G_OBJECT(attachment_part));
222                 //close(file);
223         }
224         
225         tny_transport_account_iface_send (transport_account, new_msg);
226
227         g_object_unref (G_OBJECT(text_body_stream));
228         g_object_unref (G_OBJECT(headers));
229         g_object_unref (G_OBJECT(new_msg));
230         g_free(content_type);
231
232         return TRUE;    
233 }