1 /* Copyright (c) 2007, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "modest-dbus-callbacks.h"
31 #include "modest-runtime.h"
32 #include "modest-account-mgr.h"
33 #include "modest-account-mgr-helpers.h"
34 #include "modest-tny-account.h"
35 #include "widgets/modest-msg-edit-window.h"
36 #include "modest-tny-msg.h"
37 #include <libgnomevfs/gnome-vfs-utils.h>
51 on_idle_send_mail(gpointer user_data)
53 SendMailIdleData *idle_data = (SendMailIdleData*)user_data;
55 /* Get the TnyTransportAccount so we can instantiate a mail operation: */
56 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
57 gchar *account_name = modest_account_mgr_get_default_account (account_mgr);
59 g_printerr ("modest: no account found\n");
62 TnyTransportAccount *transport_account = NULL;
64 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
65 (modest_runtime_get_account_store(),
69 if (!transport_account) {
70 g_printerr ("modest: no transport account found for '%s'\n", account_name);
73 /* Create the mail operation: */
74 if (transport_account) {
75 /* Use the mail operation: */
76 gchar * from = modest_account_mgr_get_from_string (account_mgr,
79 g_printerr ("modest: no from address for account '%s'\n", account_name);
81 ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND);
82 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
84 modest_mail_operation_send_new_mail (mail_operation,
87 idle_data->to, idle_data->cc, idle_data->bcc, idle_data->subject,
88 idle_data->body, /* plain_body */
90 NULL, /* attachments_list, GSList of TnyMimePart. */
94 g_object_unref (G_OBJECT (mail_operation));
97 g_object_unref (G_OBJECT (transport_account));
100 g_free (account_name);
102 /* Free the idle data: */
103 g_free (idle_data->to);
104 g_free (idle_data->cc);
105 g_free (idle_data->bcc);
106 g_free (idle_data->subject);
107 g_free (idle_data->body);
110 return FALSE; /* Do not call this callback again. */
113 static gint on_send_mail(GArray * arguments, gpointer data, osso_rpc_t * retval)
115 if (arguments->len != MODEST_DEBUS_SEND_MAIL_ARGS_COUNT)
118 /* Use g_idle to context-switch into the application's thread: */
119 SendMailIdleData *idle_data = g_new0(SendMailIdleData, 1); /* Freed in the idle callback. */
121 /* Get the arguments: */
122 osso_rpc_t val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_SEND_MAIL_ARG_TO);
123 idle_data->to = g_strdup (val.value.s);
125 val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_SEND_MAIL_ARG_CC);
126 idle_data->cc = g_strdup (val.value.s);
128 val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_SEND_MAIL_ARG_BCC);
129 idle_data->bcc = g_strdup (val.value.s);
131 val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_SEND_MAIL_ARG_SUBJECT);
132 idle_data->subject = g_strdup (val.value.s);
134 val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_SEND_MAIL_ARG_BODY);
135 idle_data->body = g_strdup (val.value.s);
137 /* printf(" debug: to=%s\n", idle_data->to); */
138 g_idle_add(on_idle_send_mail, (gpointer)idle_data);
140 /* Note that we cannot report failures during sending,
141 * because that would be asynchronous. */
146 * @uri An escaped URI. URIs should always be escaped.
147 * @len The length of the @uri string, or -1 if the string is null terminated.
149 * Decode a URI, or URI fragment, as per RFC 1738.
150 * http://www.ietf.org/rfc/rfc1738.txt
152 * Return value: An unescaped string. This should be freed with g_free().
154 static gchar* uri_unescape(const gchar* uri, size_t len)
162 /* Allocate an extra string so we can be sure that it is null-terminated,
163 * so we can use gnome_vfs_unescape_string().
164 * This is not efficient. */
165 gchar * escaped_nullterminated = g_strndup (uri, len);
166 gchar *result = gnome_vfs_unescape_string (escaped_nullterminated, NULL);
167 g_free (escaped_nullterminated);
172 /** uri_parse_mailto:
173 * @mailto A mailto URI, with the mailto: prefix.
174 * @list_items_and_values: A pointer to a list that should be filled with item namesand value strings,
175 * with each name item being followed by a value item. This list should be freed with g_slist_free) after
176 * all the string items have been freed. This parameter may be NULL.
177 * Parse a mailto URI as per RFC2368.
178 * http://www.ietf.org/rfc/rfc2368.txt
180 * Return value: The to address, unescaped. This should be freed with g_free().
182 static gchar* uri_parse_mailto (const gchar* mailto, GSList** list_items_and_values)
184 const gchar* start_to = NULL;
185 /* Remove the mailto: prefix:
186 * 7 is the length of "mailto:": */
187 if (strncmp (mailto, "mailto:", 7) == 0) {
188 start_to = mailto + 7;
194 /* Look for ?, or the end of the string, marking the end of the to address: */
195 const size_t len_to = strcspn (start_to, "?");
196 gchar* result_to = uri_unescape (start_to, len_to);
197 printf("debug: result_to=%s\n", result_to);
199 /* Get any other items: */
200 const size_t len_mailto = strlen (start_to);
201 const gchar* p = start_to + len_to + 1; /* parsed so far. */
202 const gchar* end = start_to + len_mailto;
203 /* GSList *items = NULL; */
204 const gchar* start_item_name = p;
205 size_t len_item_name = 0;
206 const gchar* start_item_value = NULL;
209 /* Looking for the end of a name; */
210 if (start_item_name) {
211 const size_t len = strcspn (p, "="); /* Returns whole string if none found. */
213 /* This marks the end of a name and the start of the value: */
216 /* Skip over the name and mark the start of the value: */
217 p += (len + 1); /* Skip over the = */
218 start_item_value = p;
222 /* Looking for the end of a value: */
223 if (start_item_value) {
224 const size_t len = strcspn (p, "?"); /* Returns whole string if none found. */
225 /* ? marks the start of a new item: */
227 if (start_item_name && len_item_name) {
228 /* Finish the previously-started item: */
229 gchar *item_value = uri_unescape (start_item_value, len);
230 gchar *item_name = g_strndup (start_item_name, len_item_name);
231 /* printf ("debug: item name=%s, value=%s\n", item_name, item_value); */
233 /* Append the items to the list */
234 if(list_items_and_values) {
235 *list_items_and_values = g_slist_append (*list_items_and_values, item_name);
236 *list_items_and_values = g_slist_append (*list_items_and_values, item_value);
240 /* Skip over the value and mark the start of a possible new name/value pair: */
241 p += (len + 1); /* Skip over the ? */
244 start_item_value = NULL;
255 on_idle_mail_to(gpointer user_data)
257 /* This is based on the implemenation of main.c:start_uil(): */
259 gchar *uri = (gchar*)user_data;
260 GSList *list_names_and_values = NULL;
261 gchar *to = uri_parse_mailto (uri, &list_names_and_values);
263 /* Get the TnyTransportAccount so we can instantiate a mail operation: */
264 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
265 gchar *account_name = modest_account_mgr_get_default_account (account_mgr);
267 g_printerr ("modest: no account found\n");
270 TnyAccount *account = NULL;
272 account = modest_tny_account_store_get_transport_account_for_open_connection (
273 modest_runtime_get_account_store(), account_name);
277 g_printerr ("modest: failed to get tny account folder'\n", account_name);
279 gchar * from = modest_account_mgr_get_from_string (account_mgr,
282 g_printerr ("modest: no from address for account '%s'\n", account_name);
284 const gchar *cc = NULL;
285 const gchar *bcc = NULL;
286 const gchar *subject = NULL;
287 const gchar *body = NULL;
289 /* Get the relevant items from the list: */
290 GSList *list = list_names_and_values;
292 const gchar * name = (const gchar*)list->data;
293 GSList *list_value = g_slist_next (list);
294 const gchar * value = (const gchar*)list_value->data;
296 if (strcmp (name, "cc") == 0) {
298 } else if (strcmp (name, "bcc") == 0) {
300 } else if (strcmp (name, "subject") == 0) {
302 } else if (strcmp (name, "body") == 0) {
306 /* Go to the next pair: */
308 list = g_slist_next (list_value);
313 /* Create the message: */
314 TnyMsg *msg = modest_tny_msg_new (to, from,
315 cc, bcc, subject, body,
316 NULL /* attachments */);
319 g_printerr ("modest: failed to create message\n");
322 /* Add the message to a folder and show its UI for editing: */
323 TnyFolder *folder = modest_tny_account_get_special_folder (account,
324 TNY_FOLDER_TYPE_DRAFTS);
326 g_printerr ("modest: failed to find Drafts folder\n");
329 tny_folder_add_msg (folder, msg, NULL); /* TODO: check err */
331 ModestWindow *win = modest_msg_edit_window_new (msg, account_name);
332 gtk_widget_show_all (GTK_WIDGET (win));
334 g_object_unref (G_OBJECT(folder));
337 g_object_unref (G_OBJECT(msg));
340 g_object_unref (G_OBJECT(account));
344 g_free (account_name);
346 /* Free the list, as required by the uri_parse_mailto() documentation: */
347 if (list_names_and_values)
348 g_slist_foreach (list_names_and_values, (GFunc)g_free, NULL);
349 g_slist_free (list_names_and_values);
355 return FALSE; /* Do not call this callback again. */
358 static gint on_mail_to(GArray * arguments, gpointer data, osso_rpc_t * retval)
360 if (arguments->len != MODEST_DEBUS_MAIL_TO_ARGS_COUNT)
363 /* Use g_idle to context-switch into the application's thread: */
365 /* Get the arguments: */
366 osso_rpc_t val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_MAIL_TO_ARG_URI);
367 gchar *uri = g_strdup (val.value.s);
369 /* printf(" debug: to=%s\n", idle_data->to); */
370 g_idle_add(on_idle_mail_to, (gpointer)uri);
372 /* Note that we cannot report failures during sending,
373 * because that would be asynchronous. */
379 on_idle_open_message(gpointer user_data)
381 gchar *uri = (gchar*)user_data;
383 g_message ("not implemented yet %s", __FUNCTION__);
386 return FALSE; /* Do not call this callback again. */
389 static gint on_open_message(GArray * arguments, gpointer data, osso_rpc_t * retval)
391 if (arguments->len != MODEST_DEBUS_OPEN_MESSAGE_ARGS_COUNT)
394 /* Use g_idle to context-switch into the application's thread: */
396 /* Get the arguments: */
397 osso_rpc_t val = g_array_index(arguments, osso_rpc_t, MODEST_DEBUS_OPEN_MESSAGE_ARG_URI);
398 gchar *uri = g_strdup (val.value.s);
400 /* printf(" debug: to=%s\n", idle_data->to); */
401 g_idle_add(on_idle_open_message, (gpointer)uri);
403 /* Note that we cannot report failures during sending,
404 * because that would be asynchronous. */
408 /* Callback for normal D-BUS messages */
409 gint modest_dbus_req_handler(const gchar * interface, const gchar * method,
410 GArray * arguments, gpointer data,
414 printf("debug: modest_dbus_req_handler()\n");
415 printf("debug: method received: %s\n", method);
417 if (g_ascii_strcasecmp(method, MODEST_DBUS_METHOD_SEND_MAIL) == 0) {
418 return on_send_mail (arguments, data, retval);
419 } else if (g_ascii_strcasecmp(method, MODEST_DBUS_METHOD_MAIL_TO) == 0) {
420 return on_mail_to (arguments, data, retval);
421 } else if (g_ascii_strcasecmp(method, MODEST_DBUS_METHOD_OPEN_MESSAGE) == 0) {
422 return on_open_message (arguments, data, retval);