2007-06-03 Christian Kellner <ckellner@openismus.com>
[modest] / libmodest-dbus-client / libmodest-dbus-client.c
1 /* Copyright (c) 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30 #include "libmodest-dbus-client.h"
31 #include <dbus_api/modest-dbus-api.h> /* For the API strings. */
32
33 //#define DBUS_API_SUBJECT_TO_CHANGE 1
34 #include <dbus/dbus.h>
35 #include <dbus/dbus-glib-lowlevel.h>
36 #include <string.h>
37
38 gboolean
39 libmodest_dbus_client_send_mail (osso_context_t *osso_context, const gchar *to, const gchar *cc, 
40         const gchar *bcc, const gchar* subject, const gchar* body, GSList *attachments)
41 {
42         osso_rpc_t retval;
43         const osso_return_t ret = osso_rpc_run_with_defaults(osso_context, 
44                    MODEST_DBUS_NAME, 
45                    MODEST_DBUS_METHOD_SEND_MAIL, &retval, 
46                    DBUS_TYPE_STRING, to, 
47                    DBUS_TYPE_STRING, cc, 
48                    DBUS_TYPE_STRING, bcc, 
49                    DBUS_TYPE_STRING, subject, 
50                    DBUS_TYPE_STRING, body, 
51                    DBUS_TYPE_INVALID);
52                 
53         if (ret != OSSO_OK) {
54                 printf("debug: osso_rpc_run() failed.\n");
55                 return FALSE;
56         } else {
57                 printf("debug: osso_rpc_run() succeeded.\n");
58         }
59         
60         osso_rpc_free_val(&retval);
61         
62         return TRUE;
63 }
64         
65 gboolean 
66 libmodest_dbus_client_mail_to (osso_context_t *osso_context, const gchar *mailto_uri)
67 {
68         osso_rpc_t retval;
69         const osso_return_t ret = osso_rpc_run_with_defaults(osso_context, 
70                    MODEST_DBUS_NAME, 
71                    MODEST_DBUS_METHOD_MAIL_TO, &retval, 
72                    DBUS_TYPE_STRING, mailto_uri, 
73                    DBUS_TYPE_INVALID);
74                 
75         if (ret != OSSO_OK) {
76                 printf("debug: osso_rpc_run() failed.\n");
77                 return FALSE;
78         } else {
79                 printf("debug: osso_rpc_run() succeeded.\n");
80         }
81         
82         osso_rpc_free_val(&retval);
83         
84         return TRUE;
85 }
86
87 gboolean
88 libmodest_dbus_client_compose_mail (osso_context_t *osso_context, const gchar *to, const gchar *cc, 
89         const gchar *bcc, const gchar* subject, const gchar* body, GSList *attachments)
90 {
91         osso_rpc_t retval;
92         gchar *attachments_str = NULL;
93         gchar *tmp = NULL;
94         GSList *next = NULL;
95         
96         attachments_str = g_strdup( (gchar *) attachments->data );
97         
98         for (next = g_slist_next(attachments); next != NULL; next = g_slist_next(next))
99         {
100                 tmp = g_strconcat(attachments_str, ",", (gchar *) (next->data), NULL);
101                 g_free(attachments_str);
102                 attachments_str = tmp;
103                 if (attachments_str == NULL) {
104                         return OSSO_ERROR;
105                 }
106         }
107
108         const osso_return_t ret = osso_rpc_run_with_defaults(osso_context, 
109                    MODEST_DBUS_NAME, 
110                    MODEST_DBUS_METHOD_COMPOSE_MAIL, &retval, 
111                    DBUS_TYPE_STRING, to, 
112                    DBUS_TYPE_STRING, cc, 
113                    DBUS_TYPE_STRING, bcc, 
114                    DBUS_TYPE_STRING, subject, 
115                    DBUS_TYPE_STRING, body,
116                    DBUS_TYPE_STRING, attachments_str,
117                    DBUS_TYPE_INVALID);
118                 
119         if (ret != OSSO_OK) {
120                 printf("debug: osso_rpc_run() failed.\n");
121                 return FALSE;
122         } else {
123                 printf("debug: osso_rpc_run() succeeded.\n");
124         }
125         
126         osso_rpc_free_val(&retval);
127         
128         return TRUE;
129 }
130
131 gboolean 
132 libmodest_dbus_client_open_message (osso_context_t *osso_context, const gchar *mail_uri)
133 {
134         osso_rpc_t retval;
135         const osso_return_t ret = osso_rpc_run_with_defaults(osso_context, 
136                    MODEST_DBUS_NAME, 
137                    MODEST_DBUS_METHOD_OPEN_MESSAGE, &retval, 
138                    DBUS_TYPE_STRING, mail_uri, 
139                    DBUS_TYPE_INVALID);
140                 
141         if (ret != OSSO_OK) {
142                 printf("debug: osso_rpc_run() failed.\n");
143                 return FALSE;
144         } else {
145                 printf("debug: osso_rpc_run() succeeded.\n");
146         }
147         
148         osso_rpc_free_val(&retval);
149         
150         return TRUE;
151 }
152
153 gboolean 
154 libmodest_dbus_client_send_and_receive (osso_context_t *osso_context)
155 {
156         osso_rpc_t retval;
157         const osso_return_t ret = osso_rpc_run_with_defaults(osso_context, 
158                    MODEST_DBUS_NAME, 
159                    MODEST_DBUS_METHOD_SEND_RECEIVE, &retval, 
160                    DBUS_TYPE_INVALID);
161                 
162         if (ret != OSSO_OK) {
163                 printf("debug: osso_rpc_run() failed.\n");
164                 return FALSE;
165         } else {
166                 printf("debug: osso_rpc_run() succeeded.\n");
167         }
168         
169         osso_rpc_free_val(&retval);
170         
171         return TRUE;
172 }
173
174 gboolean
175 libmodest_dbus_client_delete_message (osso_context_t   *osso_ctx,
176                                       const char       *msg_uri)
177 {
178         osso_rpc_t    retval;
179         osso_return_t ret;
180        
181         ret = osso_rpc_run_with_defaults (osso_ctx, 
182                                           MODEST_DBUS_NAME, 
183                                           MODEST_DBUS_METHOD_DELETE_MESSAGE, &retval, 
184                                           DBUS_TYPE_STRING, msg_uri, 
185                                           DBUS_TYPE_INVALID);
186                 
187         if (ret != OSSO_OK) {
188                 g_debug ("debug: osso_rpc_run() failed.\n");
189         } else {
190                 g_debug ("debug: osso_rpc_run() succeeded.\n");
191         }
192         
193         osso_rpc_free_val (&retval);
194
195         return ret == OSSO_OK;
196 }
197
198 void
199 modest_search_hit_free (ModestSearchHit *hit)
200 {
201         g_free (hit->msgid);
202         g_slice_free (ModestSearchHit, hit);
203 }
204
205 void
206 modest_search_hit_list_free (GList *hits)
207 {
208         GList *iter;
209
210         for (iter = hits; iter; iter = iter->next) {
211                 modest_search_hit_free ((ModestSearchHit *) iter->data);
212         }
213
214         g_list_free (hits);
215 }
216
217 static char *
218 _dbus_iter_get_string_or_null (DBusMessageIter *iter)
219 {
220         const char *string;
221         char       *ret;
222
223         dbus_message_iter_get_basic (iter, &string);
224         
225         ret = NULL;
226         if (string && strlen (string)) {
227                 ret = g_strdup (string);
228         }
229
230         return ret;
231 }
232
233 static guint64
234 _dbus_iter_get_uint64 (DBusMessageIter *iter)
235 {
236         dbus_uint64_t ui64v;
237         guint64       ret;
238
239         ui64v = 0;
240         dbus_message_iter_get_basic (iter, &ui64v);
241
242         ret = (guint64) ui64v;
243
244         return ret;
245 }
246
247
248 static gint64
249 _dbus_iter_get_int64 (DBusMessageIter *iter)
250 {
251         dbus_int64_t i64v;
252         gint64       ret;
253
254         i64v = 0;
255         dbus_message_iter_get_basic (iter, &i64v);
256
257         ret = (gint64) i64v;
258
259         return ret;
260 }
261
262 static gboolean
263 _dbus_iter_get_boolean (DBusMessageIter *iter)
264
265 {
266         dbus_bool_t  val;
267         gboolean     ret;
268
269         val = FALSE;
270         dbus_message_iter_get_basic (iter, &val);
271
272         ret = (gboolean) val;
273
274         return ret;
275 }
276
277
278 static ModestSearchHit *
279 dbus_message_iter_get_search_hit (DBusMessageIter *parent)
280 {
281         ModestSearchHit *hit;
282         DBusMessageIter  child;
283         dbus_bool_t      res;
284         int              arg_type;
285         gboolean         error;
286
287         error = FALSE;
288         hit = g_slice_new0 (ModestSearchHit);
289
290         arg_type = dbus_message_iter_get_arg_type (parent);
291
292         if (arg_type != 'r') {
293                 return NULL;
294         }
295
296         dbus_message_iter_recurse (parent, &child);
297         
298         /* msgid  */
299         arg_type = dbus_message_iter_get_arg_type (&child);
300
301         if (arg_type != DBUS_TYPE_STRING) {
302                 error = TRUE;
303                 goto out;
304         }
305
306         hit->msgid = _dbus_iter_get_string_or_null (&child);
307
308         res = dbus_message_iter_next (&child);
309         if (res == FALSE) {
310                 error = TRUE;
311                 goto out;
312         }
313
314         /* subject  */
315         arg_type = dbus_message_iter_get_arg_type (&child);
316
317         if (arg_type != DBUS_TYPE_STRING) {
318                 error = TRUE;
319                 goto out;
320         }
321
322         hit->subject = _dbus_iter_get_string_or_null (&child);
323
324         res = dbus_message_iter_next (&child);
325         if (res == FALSE) {
326                 error = TRUE;
327                 goto out;
328         }
329
330         /* folder  */
331         arg_type = dbus_message_iter_get_arg_type (&child);
332
333         if (arg_type != DBUS_TYPE_STRING) {
334                 error = TRUE;
335                 goto out;
336         }
337
338         hit->folder = _dbus_iter_get_string_or_null (&child);
339
340         res = dbus_message_iter_next (&child);
341         if (res == FALSE) {
342                 error = TRUE;
343                 goto out;
344         }
345
346         /* sender  */
347         arg_type = dbus_message_iter_get_arg_type (&child);
348
349         if (arg_type != DBUS_TYPE_STRING) {
350                 error = TRUE;
351                 goto out;
352         }
353
354         hit->sender = _dbus_iter_get_string_or_null (&child);
355
356         res = dbus_message_iter_next (&child);
357         if (res == FALSE) {
358                 error = TRUE;
359                 goto out;
360         }
361
362         /* msize  */
363         arg_type = dbus_message_iter_get_arg_type (&child);
364
365         if (arg_type != DBUS_TYPE_UINT64) {
366                 error = TRUE;
367                 goto out;
368         }
369
370         hit->msize = _dbus_iter_get_uint64 (&child);
371
372         res = dbus_message_iter_next (&child);
373         if (res == FALSE) {
374                 error = TRUE;
375                 goto out;
376         }
377
378         /* has_attachment  */
379         arg_type = dbus_message_iter_get_arg_type (&child);
380
381         if (arg_type != DBUS_TYPE_BOOLEAN) {
382                 error = TRUE;
383                 goto out;
384         }
385
386         hit->has_attachment = _dbus_iter_get_boolean (&child); 
387
388         res = dbus_message_iter_next (&child);
389         if (res == FALSE) {
390                 error = TRUE;
391                 goto out;
392         }
393
394         /* is_unread  */
395         arg_type = dbus_message_iter_get_arg_type (&child);
396
397         if (arg_type != DBUS_TYPE_BOOLEAN) {
398                 error = TRUE;
399                 goto out;
400         }
401
402         hit->is_unread = _dbus_iter_get_boolean (&child);  
403
404         res = dbus_message_iter_next (&child);
405         if (res == FALSE) {
406                 error = TRUE;
407                 goto out;
408         }
409
410         /* msize  */
411         arg_type = dbus_message_iter_get_arg_type (&child);
412
413         if (arg_type != DBUS_TYPE_INT64) {
414                 error = TRUE;
415                 goto out;
416         }
417
418         hit->timestamp = _dbus_iter_get_int64 (&child); 
419
420         res = dbus_message_iter_next (&child);
421         if (res == TRUE) {
422                 error = TRUE;
423                 goto out;
424         }       
425
426 out:
427         if (error) {
428                 g_warning ("Error during unmarshaling");
429                 modest_search_hit_free (hit);
430                 hit = NULL;
431         }
432
433         return hit;
434 }
435
436
437 gboolean
438 libmodest_dbus_client_search (osso_context_t          *osso_ctx,
439                               const gchar             *query,
440                               const gchar             *folder,
441                               time_t                   start_date,
442                               time_t                   end_date,
443                               guint32                  min_size,
444                               ModestDBusSearchFlags    flags,
445                               GList                  **hits)
446 {
447
448         DBusMessage *msg;
449         dbus_bool_t res;
450         DBusError err;
451         DBusConnection *con;
452         DBusMessageIter iter;
453         DBusMessageIter child;
454         DBusMessage *reply = NULL;
455         gint timeout;
456         int          arg_type;
457         dbus_int64_t sd_v;
458         dbus_int64_t ed_v;
459         dbus_int32_t flags_v;
460         dbus_uint32_t size_v;
461
462
463         con = osso_get_dbus_connection (osso_ctx);
464
465         if (con == NULL) {
466                 g_warning ("Could not get dbus connection\n");
467                 return FALSE;
468
469         }
470
471
472         msg = dbus_message_new_method_call (MODEST_DBUS_SERVICE,
473                                             MODEST_DBUS_OBJECT,
474                                             MODEST_DBUS_IFACE,
475                                             MODEST_DBUS_METHOD_SEARCH);
476
477         if (msg == NULL) {
478                 //ULOG_ERR_F("dbus_message_new_method_call failed");
479                 return OSSO_ERROR;
480         }
481
482         sd_v = start_date;
483         ed_v = end_date;
484         flags_v = (dbus_int32_t) flags;
485         size_v = (dbus_uint32_t) min_size;
486
487         res  = dbus_message_append_args (msg,
488                                          DBUS_TYPE_STRING, &query,
489                                          DBUS_TYPE_STRING, &folder,
490                                          DBUS_TYPE_INT64, &sd_v,
491                                          DBUS_TYPE_INT64, &ed_v,
492                                          DBUS_TYPE_INT32, &flags_v,
493                                          DBUS_TYPE_UINT32, &size_v,
494                                          DBUS_TYPE_INVALID);
495
496         dbus_message_set_auto_start (msg, TRUE);
497
498         dbus_error_init (&err);
499
500         timeout = 1000; //XXX
501         osso_rpc_get_timeout (osso_ctx, &timeout);
502
503         reply = dbus_connection_send_with_reply_and_block (con,
504                                                            msg, 
505                                                            timeout,
506                                                            &err);
507
508         dbus_message_unref (msg);
509
510
511         if (reply == NULL) {
512             //ULOG_ERR_F("dbus_connection_send_with_reply_and_block error: %s", err.message);
513             //XXX to GError?! 
514             return FALSE;
515         }
516
517         switch (dbus_message_get_type (reply)) {
518
519                 case DBUS_MESSAGE_TYPE_ERROR:
520                         dbus_set_error_from_message (&err, reply);
521                         //XXX to GError?!
522                         dbus_error_free (&err);
523                         dbus_message_unref (reply);
524                         return FALSE;
525
526                 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
527                         /* ok we are good to go
528                          * lets drop outa here and handle that */
529                         break;
530                 default:
531                         //ULOG_WARN_F("got unknown message type as reply");
532                         //retval->type = DBUS_TYPE_STRING;
533                         //retval->value.s = g_strdup("Invalid return value");
534                         //XXX to GError?! 
535                         dbus_message_unref (reply);
536                         return FALSE;
537         }
538
539         g_debug ("message return");
540
541         dbus_message_iter_init (reply, &iter);
542         arg_type = dbus_message_iter_get_arg_type (&iter);
543         
544         dbus_message_iter_recurse (&iter, &child);
545
546         do {
547                 ModestSearchHit *hit;
548
549                 hit = dbus_message_iter_get_search_hit (&child);
550
551                 if (hit) {
552                         *hits = g_list_prepend (*hits, hit);    
553                 }
554
555         } while (dbus_message_iter_next (&child));
556
557         dbus_message_unref (reply);
558
559
560         /* TODO: This is from osso source, do we need it? */
561 #if 0
562         /* Tell TaskNavigator to show "launch banner" */
563         msg = dbus_message_new_method_call (TASK_NAV_SERVICE,
564                                             APP_LAUNCH_BANNER_METHOD_PATH,
565                                             APP_LAUNCH_BANNER_METHOD_INTERFACE,
566                                             APP_LAUNCH_BANNER_METHOD);
567
568         if (msg == NULL) {
569                 g_warn ("dbus_message_new_method_call failed");
570         }
571
572
573
574         dbus_message_append_args (msg,
575                                   DBUS_TYPE_STRING,
576                                   &service,
577                                   DBUS_TYPE_INVALID);
578
579         b = dbus_connection_send (conn, msg, NULL);
580
581         if (b == NULL) {
582                 ULOG_WARN_F("dbus_connection_send failed");
583         }
584
585         dbus_message_unref (msg);
586 #endif
587
588         return TRUE;
589 }
590