Replace g_memdup to g_memdup2
[platform/core/connectivity/bluetooth-agent.git] / map-agent / bluetooth_map_agent.c
1 /*
2  * Bluetooth-agent
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <glib.h>
29 #include <gio/gio.h>
30 #include <time.h>
31 #include "vconf.h"
32 #include "vconf-keys.h"
33
34 #include <sys/types.h>
35 #include <fcntl.h>
36
37 /*Messaging Header Files*/
38 #include "msg.h"
39 #include "msg_storage.h"
40 #include "msg_storage_types.h"
41 #include "msg_transport.h"
42 #include "msg_transport_types.h"
43 #include "msg_types.h"
44
45 #include <TelSms.h>
46 #include <TapiUtility.h>
47 #include <ITapiNetText.h>
48 #include <bluetooth_map_agent.h>
49 #include <bluetooth_map_email.h>
50 #include <bluetooth_map_sms.h>
51 #include <map_bmessage.h>
52
53 #define OBEX_CLIENT_SERVICE "org.bluez.obex"
54 #define OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1"
55 #define OBEX_CLIENT_PATH "/org/bluez/obex"
56 #define MNS_CLIENT_INTERFACE "org.openobex.MessageNotification"
57
58 #define BT_MAP_NEW_MESSAGE "NewMessage"
59 #define BT_MAP_STATUS_CB "sent status callback"
60 #define BT_MAP_MSG_CB "sms message callback"
61 #define BT_MNS_OBJECT_PATH "/org/bluez/mns"
62 #define BT_MNS_INTERFACE "org.bluez.mns"
63 #define BT_MAP_SENT_FOLDER_NAME "SENT"
64 #define BT_MAP_MSG_TEMPLATE "TEMPLATE"
65 #define BT_MAP_DELETED_FOLDER_NAME "DELETED"
66 #define BT_MAP_MSG_INFO_MAX 256
67 #define BT_MAP_MSG_HANDLE_MAX 21
68 #define BT_MAP_TIMESTAMP_MAX_LEN 16
69 #define BT_MAP_MSG_BODY_MAX 1024
70 #define BT_MSG_UPDATE   0
71 #define BT_MSG_DELETE   1
72 #define BT_SMS 0
73
74 static TapiHandle *g_tapi_handle;
75 static TelSmsAddressInfo_t *g_sca_info;
76
77 GSList *id_list = NULL;
78 guint64 current_push_map_id;
79 char *push_folder;
80 msg_send_option_t opt;
81
82 typedef enum {
83         SMS_TON_UNKNOWN = 0,            /* unknown */
84         SMS_TON_INTERNATIONAL = 1,      /* international number */
85         SMS_TON_NATIONAL = 2,           /* national number */
86         SMS_TON_NETWORK_SPECIFIC = 3, /* network specific number */
87         SMS_TON_DEDICATED_ACCESS = 4, /* subscriber number */
88         SMS_TON_ALPHA_NUMERIC = 5,      /* alphanumeric, GSM 7-bit default */
89         SMS_TON_ABBREVIATED_NUMBER = 6, /* abbreviated number */
90         SMS_TON_RESERVED_FOR_EXT = 7 /* reserved for extension */
91 } bt_sim_type_of_num_t;
92
93 struct id_info {
94         guint64 map_id;
95         int uid;
96         int msg_type;
97 };
98
99 /* Store supported folders in SMS and EMAIL */
100 gboolean folders_supported[FOLDER_COUNT][MSG_TYPES] = { {FALSE, FALSE}, };
101
102 GMainLoop *g_mainloop;
103 static char *g_mns_path;
104 static GDBusConnection *map_dbus_conn;
105 static GDBusProxy *g_mns_proxy;
106
107 static const gchar map_agent_introspection_xml[] =
108 "<node name='/'>"
109 "       <interface name='org.bluez.MapAgent'>"
110 "               <method name='GetFolderTree'>"
111 "                       <arg type='a(s)' name='folder_list' direction='out'/>"
112 "               </method>"
113 "               <method name='GetMessageList'>"
114 "                       <arg type='s' name='folder_name'/>"
115 "                       <arg type='q' name='max'/>"
116 "                       <arg type='q' name='offset'/>"
117 "                       <arg type='y' name='subject_len'/>"
118 "                       <arg type='a{sv}' name='filters'/>"
119 "                       <arg type='b' name='newmessage' direction='out'/>"
120 "                       <arg type='t' name='count' direction='out'/>"
121 "                       <arg type='a(ssssssssssbsbbbbs)' name='msg_list' direction='out'/>"
122 "               </method>"
123 "               <method name='GetMessage'>"
124 "                       <arg type='s' name='message_name'/>"
125 "                       <arg type='b' name='attach'/>"
126 "                       <arg type='b' name='transcode'/>"
127 "                       <arg type='b' name='first_request'/>"
128 "                       <arg type='b' name='fraction_deliver' direction='out'/>"
129 "                       <arg type='s' name='msg_body' direction='out'/>"
130 "               </method>"
131 "               <method name='PushMessage'>"
132 "                       <arg type='b' name='save_copy'/>"
133 "                       <arg type='b' name='retry_send'/>"
134 "                       <arg type='b' name='native'/>"
135 "                       <arg type='s' name='folder_name'/>"
136 "                       <arg type='t' name='handle' direction='out'/>"
137 "               </method>"
138 "               <method name='PushMessageData'>"
139 "                       <arg type='s' name='bmsg'/>"
140 "               </method>"
141 "               <method name='UpdateMessage'>"
142 "                       <arg type='u' name='update_err' direction='out'/>"
143 "               </method>"
144 "               <method name='SetReadStatus'>"
145 "                       <arg type='s' name='handle'/>"
146 "                       <arg type='b' name='read_status'/>"
147 "                       <arg type='u' name='update_err' direction='out'/>"
148 "               </method>"
149 "               <method name='SetDeleteStatus'>"
150 "                       <arg type='s' name='handle'/>"
151 "                       <arg type='b' name='delete_status'/>"
152 "                       <arg type='u' name='update_err' direction='out'/>"
153 "               </method>"
154 "               <method name='NotiRegistration'>"
155 "                       <arg type='s' name='remote_addr'/>"
156 "                       <arg type='b' name='status'/>"
157 "                       <arg type='u' name='update_err' direction='out'/>"
158 "               </method>"
159 "               <method name='DestroyAgent'>"
160 "               </method>"
161 "       </interface>"
162 "</node>";
163
164 /* Method Prototypes */
165 static GVariant *__bt_map_get_folder_tree(GError **err);
166 static GVariant *__bt_map_get_message_list(char *folder_name, guint16 max,
167                                 guint16 offset, guint8 subject_len,
168                                 map_msg_filter_t *filter, GError **err);
169 static GVariant *__bt_map_get_message(char *message_name, gboolean attach,
170                 gboolean transcode, gboolean first_request, GError **err);
171 static GVariant *__bt_map_push_message(gboolean save_copy,  gboolean retry_send,
172                 gboolean native, char *folder_name, GError **err);
173 static GVariant *__bt_map_push_message_data(char *bmseg, GError **err);
174 static GVariant *__bt_map_update_message(GError **err);
175 static GVariant *__bt_map_set_read_status(char *handle, gboolean read_status, GError **err);
176 static GVariant *__bt_map_set_delete_status(char *handle, gboolean delete_status, GError **err);
177 static void __bt_map_noti_registration(char *remote_addr, gboolean status);
178 static void __bt_map_destroy_agent(void);
179
180 /* LCOV_EXCL_START */
181 /* Create GError from error code and error message */
182 static GError *__bt_map_error(int error_code, char *error_message)
183 {
184         return g_error_new(g_quark_from_string("MAP Agent"),
185                         error_code, "MAP Agent Error: %s", error_message);
186 }
187
188 static map_msg_filter_t __bt_map_get_filters(GVariant *filters)
189 {
190         map_msg_filter_t filter = { 0, };
191         GVariantIter iter;
192         GVariant *value;
193         gchar *key;
194
195         g_variant_iter_init(&iter, filters);
196         while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
197                 if (!g_strcmp0(key, "ParameterMask")) {
198                         filter.parameter_mask = g_variant_get_uint32(value);
199                         DBG("ParameterMask :%u", filter.parameter_mask);
200                 } else if (!g_strcmp0(key, "FilterMessageType")) {
201                         filter.type = g_variant_get_byte(value);
202                         DBG("FilterMessageType :%u", filter.type);
203                 } else if (!g_strcmp0(key, "FilterPeriodBegin")) {
204                         g_variant_get(value, "s", &filter.period_begin);
205                         DBG("FilterPeriodBegin :%s", filter.period_begin);
206                 } else if (!g_strcmp0(key, "FilterPeriodEnd")) {
207                         g_variant_get(value, "s", &filter.period_end);
208                         DBG("FilterPeriodEnd :%s", filter.period_end);
209                 } else if (!g_strcmp0(key, "FilterReadStatus")) {
210                         filter.read_status = g_variant_get_byte(value);
211                         DBG("FilterReadStatus :%u", filter.read_status);
212                 } else if (!g_strcmp0(key, "FilterRecipient")) {
213                         g_variant_get(value, "s", &filter.recipient);
214                         DBG("FilterRecipient :%s", filter.recipient);
215                 } else if (!g_strcmp0(key, "FilterOriginator")) {
216                         g_variant_get(value, "s", &filter.originator);
217                         DBG("FilterOriginator :%s", filter.originator);
218                 } else if (!g_strcmp0(key, "FilterPriority")) {
219                         filter.priority = g_variant_get_byte(value);
220                         DBG("FilterPriority :%u", filter.priority);
221                 }
222         }
223         return filter;
224 }
225
226 static void __bt_map_agent_method(GDBusConnection *connection,
227                         const gchar *sender,
228                         const gchar *object_path,
229                         const gchar *interface_name,
230                         const gchar *method_name,
231                         GVariant *parameters,
232                         GDBusMethodInvocation *invocation,
233                         gpointer user_data)
234 {
235         FN_START;
236
237         INFO("method %s", method_name);
238         INFO("object_path %s", object_path);
239         GError *err = NULL;
240
241         if (g_strcmp0(method_name, "GetFolderTree") == 0) {
242                 GVariant *folder_list = NULL;
243
244                 folder_list = __bt_map_get_folder_tree(&err);
245                 if (err)
246                         goto fail;
247
248                 g_dbus_method_invocation_return_value(invocation, folder_list);
249         } else if (g_strcmp0(method_name, "GetMessageList") == 0) {
250                 GVariant *message_list = NULL;
251                 guint16 max;
252                 guint16 offset;
253                 guint8 subject_len;
254                 gchar *folder_name;
255                 GVariant *filters = NULL;
256                 map_msg_filter_t filter = { 0, };
257
258                 g_variant_get(parameters, "(&sqqy@a{sv})", &folder_name,
259                                 &max, &offset, &subject_len, &filters);
260
261                 DBG("MAX:%d Offset:%d SubjectLen:%d", max, offset, subject_len);
262                 if (subject_len == 0)
263                         subject_len = BT_MAP_SUBJECT_MAX_LEN;
264
265                 filter = __bt_map_get_filters(filters);
266                 message_list = __bt_map_get_message_list(folder_name, max,
267                                 offset, subject_len, &filter, &err);
268
269                 if (err)
270                         goto fail;
271
272                 g_dbus_method_invocation_return_value(invocation, message_list);
273         } else if (g_strcmp0(method_name, "GetMessage") == 0) {
274                 GVariant *message = NULL;
275                 gchar *message_name;
276                 gboolean attach;
277                 gboolean transcode;
278                 gboolean first_request;
279
280                 g_variant_get(parameters, "(&sbbb)", &message_name,
281                                 &attach, &transcode, &first_request);
282
283                 message = __bt_map_get_message(message_name, attach,
284                                 transcode, first_request, &err);
285                 if (err)
286                         goto fail;
287
288                 g_dbus_method_invocation_return_value(invocation, message);
289         } else if (g_strcmp0(method_name, "PushMessage") == 0) {
290                 GVariant *handle = NULL;
291                 gboolean save_copy;
292                 gboolean retry_send;
293                 gboolean native;
294                 gchar *folder_name;
295
296                 g_variant_get(parameters, "(bbb&s)", &save_copy,
297                                 &retry_send, &native, &folder_name);
298
299                 handle = __bt_map_push_message(save_copy, retry_send,
300                                 native, folder_name, &err);
301                 if (err)
302                         goto fail;
303
304                 g_dbus_method_invocation_return_value(invocation, handle);
305         } else if (g_strcmp0(method_name, "PushMessageData") == 0) {
306                 gchar *bmseg;
307
308                 g_variant_get(parameters, "(&s)", &bmseg);
309
310                 __bt_map_push_message_data(bmseg, &err);
311                 if (err)
312                         goto fail;
313
314                 g_dbus_method_invocation_return_value(invocation, NULL);
315         } else if (g_strcmp0(method_name, "UpdateMessage") == 0) {
316                 GVariant *update = NULL;
317
318                 update = __bt_map_update_message(&err);
319                 if (err)
320                         goto fail;
321
322                 g_dbus_method_invocation_return_value(invocation, update);
323         } else if (g_strcmp0(method_name, "SetReadStatus") == 0) {
324                 gchar *handle;
325                 gboolean read_status;
326
327                 g_variant_get(parameters, "(&sb)", &handle, &read_status);
328
329                 __bt_map_set_read_status(handle, read_status, &err);
330                 if (err)
331                         goto fail;
332
333                 g_dbus_method_invocation_return_value(invocation, NULL);
334         } else if (g_strcmp0(method_name, "SetDeleteStatus") == 0) {
335                 gchar *handle;
336                 gboolean delete_status;
337
338                 g_variant_get(parameters, "(&sb)", &handle, &delete_status);
339
340                 __bt_map_set_delete_status(handle, delete_status, &err);
341                 if (err)
342                         goto fail;
343
344                 g_dbus_method_invocation_return_value(invocation, NULL);
345         } else if (g_strcmp0(method_name, "NotiRegistration") == 0) {
346                 char *remote_addr;
347                 gboolean status;
348                 g_variant_get(parameters, "(&sb)", &remote_addr, &status);
349
350                 __bt_map_noti_registration(remote_addr, status);
351                 g_dbus_method_invocation_return_value(invocation, NULL);
352         } else if (g_strcmp0(method_name, "DestroyAgent") == 0) {
353                 g_dbus_method_invocation_return_value(invocation, NULL);
354                 __bt_map_destroy_agent();
355         }
356
357         INFO("-");
358         return;
359
360 fail:
361         g_dbus_method_invocation_return_gerror(invocation, err);
362         g_error_free(err);
363         INFO("-");
364 }
365
366 static const GDBusInterfaceVTable method_table = {
367         __bt_map_agent_method,
368         NULL,
369         NULL,
370 };
371
372 static GDBusConnection *__bt_map_get_gdbus_connection(void)
373 {
374         FN_START;
375
376         GError *err = NULL;
377
378         if (map_dbus_conn)
379                 return map_dbus_conn;
380
381         map_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
382         if (!map_dbus_conn) {
383                 if (err) {
384                         ERR("Unable to connect to dbus: %s", err->message);
385                         g_clear_error(&err);
386                 }
387                 return NULL;
388         }
389
390         FN_END;
391         return map_dbus_conn;
392 }
393 /* LCOV_EXCL_STOP */
394
395 gboolean is_mns_connected(void)
396 {
397         if (!g_mns_proxy)
398                 return FALSE;
399         else
400                 return TRUE; /* LCOV_EXCL_LINE */
401 }
402
403 guint64 _bt_validate_uid(int uid, int msg_type)
404 {
405         FN_START;
406         struct id_info *info;
407         GSList *list = id_list;
408
409         while (list) {
410                 info = list->data;
411
412                 if (info && info->uid == uid && info->msg_type == msg_type) {
413                         DBG("UID = %d, MessageType=%d", uid, msg_type);
414                         return info->map_id;
415                 }
416
417                 list = g_slist_next(list); /* LCOV_EXCL_LINE */
418         }
419
420         FN_END;
421         return 0;
422 }
423
424 guint64 _bt_add_id(int uid, int msg_type)
425 {
426         FN_START;
427         static guint64 map_id;
428         struct id_info *info;
429         guint64 test;
430
431         DBG("Add id: %d, MsgType:%d", uid, msg_type);
432         test = _bt_validate_uid(uid, msg_type);
433         DBG("test: %llu\n", (unsigned long long int)test);
434         if (test)
435                 return test;
436
437         info = g_new0(struct id_info, 1);
438
439         map_id++;
440
441         info->map_id = map_id;
442         info->uid = uid;
443         info->msg_type = msg_type;
444         DBG("map_id = %llu, uid = %d, MsgType=%d", (unsigned long long int)info->map_id, info->uid, msg_type);
445
446         id_list = g_slist_append(id_list, info);
447
448         FN_END;
449         return map_id;
450 }
451
452 /* LCOV_EXCL_START */
453 static struct id_info *__bt_get_id(guint64 map_id)
454 {
455         FN_START;
456         struct id_info *info;
457         GSList *list = id_list;
458
459         while (list) {
460                 info = list->data;
461
462                 if (info->map_id == map_id)
463                         return info;
464
465                 list = g_slist_next(list);
466         }
467
468         FN_END;
469         return NULL;
470 }
471
472 static struct id_info *__bt_get_uid(gchar *handle)
473 {
474         FN_START;
475         guint64 map_id;
476         struct id_info *handle_info;
477
478         if (handle == NULL)
479                 return NULL;
480
481         map_id = g_ascii_strtoull(handle, NULL, 16);
482         if (!map_id)
483                 return NULL;
484
485         handle_info = __bt_get_id(map_id);
486
487         FN_END;
488         return handle_info;
489 }
490 /* LCOV_EXCL_STOP */
491
492 int _bt_update_id(guint64 map_id, int new_uid, int msg_type)
493 {
494         FN_START;
495         struct id_info *info;
496         GSList *list = id_list;
497
498         while (list) {
499                 /* LCOV_EXCL_START */
500                 info = list->data;
501
502                 if (info->map_id == map_id) {
503                         info->uid = new_uid;
504                         info->msg_type = msg_type;
505                         return map_id;
506                 }
507
508                 list = g_slist_next(list);
509                 /* LCOV_EXCL_STOP */
510         }
511
512         FN_END;
513         return -1;
514 }
515
516 /* LCOV_EXCL_START */
517 static void __bt_remove_list(GSList *id_list)
518 {
519         FN_START;
520         if (!id_list)
521                 return;
522
523         DBG("Removing id list\n");
524         g_slist_free_full(id_list, g_free);
525         FN_END;
526 }
527 /* LCOV_EXCL_STOP */
528
529 gboolean _bt_verify_sender(message_info_t *msg_info, char *sender)
530 {
531         if (!sender)
532                 return TRUE;
533
534         if (!g_strcmp0(sender, "*"))
535                 return TRUE;
536
537         if (g_strrstr(msg_info->sender_name, sender) ||
538                         g_strrstr(msg_info->sender_addressing, sender))
539                 return TRUE;
540
541         return FALSE;
542 }
543
544 gboolean _bt_verify_receiver(message_info_t *msg_info, char *receiver)
545 {
546         if (!receiver)
547                 return TRUE;
548
549         if (!g_strcmp0(receiver, "*"))
550                 return TRUE;
551
552         if (g_strrstr(msg_info->recipient_name, receiver) ||
553                         g_strrstr(msg_info->recipient_addressing, receiver))
554                 return TRUE;
555
556         return FALSE;
557 }
558
559 gboolean _bt_verify_read_status(message_info_t *msg_info, guint8 read_status)
560 {
561         if (read_status == FILTER_READ_STATUS_ALL ||
562                         ((read_status == FILTER_READ_STATUS_UNREAD) && msg_info->read == FALSE) ||
563                         ((read_status == FILTER_READ_STATUS_READ) && msg_info->read == TRUE))
564                 return TRUE;
565
566         return FALSE;
567 }
568
569 gboolean _bt_filter_priority(message_info_t *msg_info, guint8 priority)
570 {
571         if (priority == FILTER_PRIORITY_ALL ||
572                         ((priority == FILTER_PRIORITY_HIGH) && msg_info->priority == TRUE) ||
573                         ((priority == FILTER_PRIORITY_LOW) && msg_info->priority == FALSE))
574                 return TRUE;
575
576         return FALSE;
577 }
578
579 void _get_msg_timestamp(time_t *ltime, char *timestamp)
580 {
581         FN_START;
582         struct tm local_time;
583         int year;
584         int buf_len = 0;
585         int month;
586
587         if (!localtime_r(ltime, &local_time))
588                 return;
589
590         year = local_time.tm_year + 1900; /* years since 1900 */
591         month = local_time.tm_mon + 1; /* months since January */
592         buf_len = snprintf(timestamp, 16, "%04hu%02hu%02huT%02hu%02hu%02hu",(unsigned short int)year, (unsigned short int)month,
593                                         (unsigned short int)local_time.tm_mday, (unsigned short int)local_time.tm_hour,
594                                         (unsigned short int)local_time.tm_min, (unsigned short int)local_time.tm_sec);
595
596         if (buf_len < 0)
597                 ERR("Encoding error occured in snprintf");
598
599         FN_END;
600 }
601
602 /* LCOV_EXCL_START */
603 time_t _get_time_t_from_timestamp(char *timestamp)
604 {
605         struct tm local_time;
606         int year;
607         int month;
608         time_t int_time;
609
610         int ymd; /* year, month, day */
611         int hms; /* hour, min, sec */
612         char *ptr, *ptr2;
613
614         ymd = strtol(timestamp, &ptr, 10);
615         hms = strtol(ptr + 1, &ptr2, 10);
616
617         /* Initialize local_time */
618         memset(&local_time, 0, sizeof(struct tm));
619
620         /* parse year, month, day */
621         local_time.tm_mday = ymd % 100;
622         ymd = (ymd - local_time.tm_mday) / 100;
623         month = ymd % 100;
624         year = (ymd - month) / 100;
625
626         /* parse hour, minute, sec */
627         local_time.tm_sec = hms % 100;
628         hms = (hms - local_time.tm_sec) / 100;
629         local_time.tm_min = hms % 100;
630         local_time.tm_hour = (hms - local_time.tm_min) / 100;
631
632         local_time.tm_year = year - 1900;
633         local_time.tm_mon = month - 1;
634
635         int_time = mktime(&local_time);
636         return int_time;
637 }
638 /* LCOV_EXCL_STOP */
639
640 gboolean _bt_verify_time(message_info_t *msg_info, map_msg_filter_t *filter)
641 {
642         struct tm local_time = { 0, };
643         time_t start;
644         time_t end;
645
646         /* Set 19710101T000000 as Start Date */
647         local_time.tm_year = 1971 - 1900;
648         local_time.tm_mon = 0;
649         local_time.tm_mday = 1;
650         start = mktime(&local_time);
651
652         /* Set 20380101T000000 as End Date */
653         local_time.tm_year = 2038 - 1900;
654         local_time.tm_mon = 0;
655         local_time.tm_mday = 1;
656         end = mktime(&local_time);
657
658         if (filter->period_begin)
659                 start = _get_time_t_from_timestamp(filter->period_begin);
660
661         if (filter->period_end)
662                 end = _get_time_t_from_timestamp(filter->period_end);
663
664         if (msg_info->time >= start && msg_info->time <= end)
665                 return TRUE;
666
667         return FALSE;
668 }
669
670 #define SET_TON_NPI(dest, ton, npi) {   \
671         dest = 0x80;                    \
672         dest |= (ton & 0x07) << 4;      \
673         dest |= npi & 0x0F;             \
674 }
675
676 /* LCOV_EXCL_START */
677 static int __bt_ascii_to_upper(int ch)
678 {
679         return (('a' <= (ch) && (ch) <= 'z') ? ((ch) - ('a'-'A')) : (ch));
680 }
681
682 static int __bt_sms_pack_gsm_code(gchar *p_out, const char *data, int in_len)
683 {
684         FN_START;
685         int i;
686         int pos;
687         int shift = 0;
688
689         for (pos = 0, i = 0; i < in_len; pos++, i++) {
690                 /* pack the low bits */
691                 p_out[pos] = data[i] >> shift;
692
693                 if (i + 1 < in_len) {
694                         /* pack the high bits using the low bits
695                            of the next character */
696                         p_out[pos] |= data[i+1] << (7 - shift);
697
698                         shift++;
699
700                         if (shift == 7) {
701                                 shift = 0;
702                                 i++;
703                         }
704                 }
705         }
706
707         FN_END;
708         return pos;
709 }
710
711 static void __bt_sms_conv_digit_to_bcd(gchar *p_bcd, char *p_digits, int digit_len)
712 {
713         FN_START;
714         int i;
715         int j;
716         int digit;
717         unsigned char higher;
718         unsigned char lower;
719
720         if (p_bcd == NULL || p_digits == NULL)
721                 return;
722
723         /* 0123456789 -> 1032547698 */
724         for (i = 0, j = 0; i < digit_len; i = i + 2, j++) {
725                 if (p_digits[i] == '*')
726                         digit = 0x0A;
727                 else if (p_digits[i] == '#')
728                         digit = 0x0B;
729                 else if (__bt_ascii_to_upper(p_digits[i]) == 'P')
730                         digit = 0x0C;
731                 else
732                         digit = (int) (p_digits[i] - '0');
733
734                 lower = digit & 0x0F;
735
736                 if (digit_len != i + 1) {
737                         if (p_digits[i+1] == '*')
738                                 digit = 0x0A;
739                         else if (p_digits[i+1] == '#')
740                                 digit = 0x0B;
741                         else if (__bt_ascii_to_upper(p_digits[i+1]) == 'P')
742                                 digit = 0x0C;
743                         else
744                                 digit = (int) (p_digits[i+1] - '0');
745
746                         higher = digit & 0x0F;
747                 } else {
748                         higher = 0xFF;
749                 }
750
751                 p_bcd[j] = (higher << 4) | lower;
752         }
753         FN_END;
754 }
755
756 static int  __bt_sms_encode_addr(gchar *addr_field, char *dial_num,
757                                 int dial_num_len, int ton, int npi)
758 {
759         FN_START;
760         int index = 0;
761
762         if (dial_num == NULL || addr_field == NULL)
763                 return -1;
764
765         if (dial_num[0] == '+') {
766                 dial_num++;
767                 dial_num_len--;
768                 ton = SMS_TON_INTERNATIONAL;
769         }
770
771         if (ton != SMS_TON_ALPHA_NUMERIC) {
772                 /* Origination address length address length */
773                 addr_field[index++] = (unsigned char)dial_num_len;
774         } else {
775                 addr_field[index] = (unsigned char)
776                                         (((dial_num_len * 7 + 7) / 8) * 2);
777
778                 if (((dial_num_len * 7) % 8) <= 4)
779                         addr_field[index]--;
780
781                 index++;
782         }
783
784         SET_TON_NPI(addr_field[index], ton, npi);
785         index++; /* SET_TON_NPI */
786
787         if (ton != SMS_TON_ALPHA_NUMERIC) {
788                 __bt_sms_conv_digit_to_bcd(&addr_field[index],
789                                         (char *)dial_num, dial_num_len);
790
791                 if (dial_num_len % 2)
792                         index += (dial_num_len / 2) + 1;
793                 else
794                         index += dial_num_len / 2;
795         } else {
796                 index += __bt_sms_pack_gsm_code(&addr_field[index],
797                                                 dial_num, (int)dial_num_len);
798         }
799
800         FN_END;
801         return index;
802 }
803
804 static int __bt_sms_encode_time(gchar *addr_field, time_t *tm)
805 {
806         FN_START;
807         int index = 0;
808         struct tm ltime;
809         int year;
810         int month;
811
812         if (!localtime_r(tm, &ltime))
813                 return index;
814
815         year = ltime.tm_year + 1900; /* years since 1900 */
816         year = year % 100;
817         month = ltime.tm_mon + 1; /* months since January */
818
819         addr_field[index++] = ((year % 10)  << 4) + (year / 10);
820         addr_field[index++] = ((month % 10) << 4) + (month / 10);
821         addr_field[index++] = ((ltime.tm_mday % 10) << 4) +
822                                                         (ltime.tm_mday / 10);
823         addr_field[index++] = ((ltime.tm_hour % 10) << 4) +
824                                                         (ltime.tm_hour / 10);
825         addr_field[index++] = ((ltime.tm_min % 10) << 4) + (ltime.tm_min / 10);
826         addr_field[index++] = ((ltime.tm_sec % 10) << 4) + (ltime.tm_sec / 10);
827         addr_field[index] = 0x00;
828
829         FN_END;
830         return index;
831 }
832
833 gchar *_bt_get_sms_pdu_from_msg_data(gchar *number,
834                                                 char *msg, time_t tm,
835                                                 int *msg_pdu_len)
836 {
837         FN_START;
838         gchar packet[TAPI_NETTEXT_MSG_SIZE_MAX] = {0,};
839         int index = 0;
840
841         packet[index] = 0x00; /* Since SCA is unknown for stored messages */
842         index++;
843
844         /* TP-MTI : Type of message */
845         packet[index] = 0x00;   /* SMS-DELIVER PDU */
846
847         /* TP-MMS bit is set to 1 as we support only SMS */
848         packet[index] |= 0x04;
849         index++;
850
851         /* TP-OA : Mobile originating address */
852         index += __bt_sms_encode_addr(packet+index,
853                                         number, strlen(number),
854                                         g_sca_info->Ton, g_sca_info->Npi);
855
856         /* TP-PID : Since we use only SMS so set to 0 */
857         packet[index++] = 0x00;
858
859         /* TP-DCS : Data Coding Scheme, default value set */
860         packet[index++] = 0x00;
861
862         /* TP-SCTS : Message timestamp */
863         index += __bt_sms_encode_time(packet+index, &tm);
864         index++;
865         /* TP-UDL : Message body length */
866         packet[index++] = strlen(msg);
867
868         /* TP-UD : Message body */
869         index += __bt_sms_pack_gsm_code(packet + index, msg, strlen(msg));
870
871         *msg_pdu_len = index;
872
873         FN_END;
874         return g_memdup2(packet, index);
875 }
876
877 static void __bt_get_sms_sca(TapiHandle *handle, int result, void *data,
878                                                         void *user_data)
879 {
880         FN_START;
881         TelSmsAddressInfo_t *scaInfo = data;
882
883         DBG("__bt_get_sms_sca 0x%x", result);
884
885         if (data == NULL) {
886                 g_sca_info = g_malloc0(sizeof(TelSmsAddressInfo_t));
887                 g_sca_info->Ton = 0;
888                 g_sca_info->Npi = 0;
889                 g_sca_info->DialNumLen = 0;
890                 return;
891         }
892
893         g_sca_info = g_malloc0(sizeof(TelSmsAddressInfo_t));
894         g_sca_info->Ton = scaInfo->Ton;
895         g_sca_info->Npi = scaInfo->Npi;
896         g_sca_info->DialNumLen = scaInfo->DialNumLen;
897         FN_END;
898 }
899 /* LCOV_EXCL_STOP */
900
901 void _bt_message_info_free(gpointer data)
902 {
903         FN_START;
904         message_info_t *msg_info = (message_info_t *)data;
905         g_free(msg_info->handle);
906         g_free(msg_info->subject);
907         g_free(msg_info->datetime);
908         g_free(msg_info->sender_name);
909         g_free(msg_info->sender_addressing);
910         g_free(msg_info->replyto_addressing);
911         g_free(msg_info->recipient_name);
912         g_free(msg_info->recipient_addressing);
913         g_free(msg_info->type);
914         g_free(msg_info->reception_status);
915         g_free(msg_info->size);
916         g_free(msg_info->attachment_size);
917         g_free(msg_info);
918         FN_END;
919 }
920
921 /* LCOV_EXCL_START */
922 static gboolean __bluetooth_map_start_service()
923 {
924         FN_START;
925         gboolean sms;
926         gboolean email;
927
928         sms = _bt_map_start_sms_service();
929         email = _bt_map_start_email_service();
930         if (sms && email)
931                 return TRUE;
932
933         FN_END;
934         return FALSE;
935 }
936 /* LCOV_EXCL_STOP */
937
938 static gboolean __bt_validate_utf8(char **text)
939 {
940         FN_START;
941         if (g_utf8_validate(*text, -1, NULL))
942                 return TRUE;
943
944         /* LCOV_EXCL_START */
945         FN_END;
946         return FALSE;
947         /* LCOV_EXCL_STOP */
948 }
949
950 gboolean _bt_validate_msg_data(message_info_t *msg_info)
951 {
952         FN_START;
953         if (msg_info == NULL)
954                 return FALSE;
955
956         if (msg_info->subject)
957                 return __bt_validate_utf8(&msg_info->subject);
958
959         if (msg_info->sender_name)
960                 return __bt_validate_utf8(&msg_info->sender_name);
961
962         /* LCOV_EXCL_START */
963         if (msg_info->sender_addressing)
964                 return __bt_validate_utf8(&msg_info->sender_addressing);
965
966         if (msg_info->replyto_addressing)
967                 return __bt_validate_utf8(&msg_info->replyto_addressing);
968
969         if (msg_info->recipient_name)
970                 return __bt_validate_utf8(&msg_info->recipient_name);
971
972         if (msg_info->recipient_addressing)
973                 return __bt_validate_utf8(&msg_info->recipient_addressing);
974
975         FN_END;
976         return TRUE;
977         /* LCOV_EXCL_STOP */
978 }
979
980 /* LCOV_EXCL_START */
981 static void __bt_mns_client_connect(char *address)
982 {
983         FN_START;
984         GDBusConnection *connection;
985         GVariantBuilder builder;
986         GVariant *args;
987         GVariant *param;
988         GVariant *value;
989         GError *error = NULL;
990         const char *session_path;
991
992         if (g_mns_proxy) {
993                 DBG_SECURE("MNS Client already connected to %s", address);
994                 return;
995         }
996
997         connection = __bt_map_get_gdbus_connection();
998         if (connection == NULL) {
999                 DBG("Could not get GDBus Connection");
1000                 return;
1001         }
1002
1003         g_mns_proxy = g_dbus_proxy_new_sync(connection,
1004                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1005                         OBEX_CLIENT_SERVICE, OBEX_CLIENT_PATH,
1006                         OBEX_CLIENT_INTERFACE, NULL, &error);
1007
1008         if (!g_mns_proxy) {
1009                 ERR("Failed to get a proxy for D-Bus");
1010                 return;
1011         }
1012
1013         /* Create Hash*/
1014         g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
1015         g_variant_builder_add(&builder, "{sv}", "Target",
1016                                         g_variant_new("s", "MNS"));
1017         args = g_variant_builder_end(&builder);
1018
1019         param = g_variant_new("(s@a{sv})", address, args);
1020
1021         value = g_dbus_proxy_call_sync(g_mns_proxy,
1022                         "CreateSession", param, G_DBUS_CALL_FLAGS_NONE, -1,
1023                         NULL, &error);
1024         if (value == NULL) {
1025                 /* dBUS-RPC is failed */
1026                 ERR("dBUS-RPC is failed");
1027                 if (error != NULL) {
1028                         /* dBUS gives error cause */
1029                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1030                                 error->code, error->message);
1031
1032                         g_clear_error(&error);
1033                 }
1034                 g_object_unref(g_mns_proxy);
1035                 g_mns_proxy = NULL;
1036                 return;
1037         }
1038
1039         g_variant_get(value, "(&o)", &session_path);
1040         g_mns_path = g_strdup(session_path);
1041         DBG("g_mns_path = %s\n", g_mns_path);
1042
1043         g_variant_unref(value);
1044         FN_END;
1045 }
1046
1047 static void __bt_mns_client_disconnect()
1048 {
1049         FN_START;
1050         GError *error = NULL;
1051         GVariant *value;
1052
1053         if (!g_mns_proxy) {
1054                 ERR("No proxy to disconnect");
1055                 return;
1056         }
1057
1058         value = g_dbus_proxy_call_sync(g_mns_proxy,
1059                         "RemoveSession", g_variant_new("(o)", g_mns_path),
1060                         G_DBUS_CALL_FLAGS_NONE, -1,
1061                         NULL, &error);
1062
1063         if (value == NULL) {
1064                 /* dBUS-RPC is failed */
1065                 ERR("dBUS-RPC is failed: Could not remove MAP session");
1066                 if (error != NULL) {
1067                         /* dBUS gives error cause */
1068                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1069                                 error->code, error->message);
1070
1071                         g_clear_error(&error);
1072                 }
1073                 return;
1074         }
1075
1076         g_free(g_mns_path);
1077         g_mns_path = NULL;
1078
1079         g_object_unref(g_mns_proxy);
1080         g_mns_proxy = NULL;
1081
1082         g_variant_unref(value);
1083         FN_END;
1084 }
1085 /* LCOV_EXCL_STOP */
1086
1087 void _bt_mns_client_event_notify(gchar *event, guint64 handle,
1088                                         gchar *folder, gchar *old_folder,
1089                                         gchar *msg_type)
1090 {
1091         FN_START;
1092         GError *error = NULL;
1093         GDBusProxy *mns_proxy;
1094         GDBusConnection *connection = NULL;
1095         GVariant *value;
1096
1097         if (!g_mns_proxy) {
1098                 ERR("No client proxy");
1099                 return;
1100         }
1101
1102         /* LCOV_EXCL_START */
1103         connection = __bt_map_get_gdbus_connection();
1104         if (connection == NULL) {
1105                 DBG("Could not get GDBus Connection");
1106                 return;
1107         }
1108
1109         mns_proxy = g_dbus_proxy_new_sync(connection,
1110                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1111                         OBEX_CLIENT_SERVICE, g_mns_path,
1112                         MNS_CLIENT_INTERFACE, NULL, &error);
1113         if (mns_proxy == NULL) {
1114                 ERR("Failed to get a proxy for D-Bus\n");
1115                 return;
1116         }
1117
1118         value = g_dbus_proxy_call_sync(mns_proxy, "SendEvent",
1119                         g_variant_new("(stsss)", event, handle, folder, old_folder, msg_type),
1120                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1121         if (value == NULL) {
1122                 /* dBUS-RPC is failed */
1123                 ERR("dBUS-RPC is failed: SendEvent failed");
1124                 if (error != NULL) {
1125                         /* dBUS gives error cause */
1126                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1127                                 error->code, error->message);
1128
1129                         g_clear_error(&error);
1130                 }
1131                 g_object_unref(mns_proxy);
1132                 return;
1133         }
1134
1135         g_variant_unref(value);
1136         g_object_unref(mns_proxy);
1137         FN_END;
1138         /* LCOV_EXCL_STOP */
1139 }
1140
1141 /* LCOV_EXCL_START */
1142 static gchar *__bt_get_map_folder(int folder)
1143 {
1144         switch (folder) {
1145         case BT_MSG_INBOX:
1146                 return g_strdup("INBOX");
1147         case BT_MSG_SENT:
1148                 return g_strdup("SENT");
1149         case BT_MSG_OUTBOX:
1150                 return g_strdup("OUTBOX");
1151         case BT_MSG_DRAFT:
1152                 return g_strdup("DRAFT");
1153         case BT_MSG_DELETED:
1154                 return g_strdup("DELETED");
1155         }
1156         return NULL;
1157 }
1158
1159 static GList *_bt_map_merge_sorted(GSList *sms_list, GSList *email_list)
1160 {
1161         GList *list = NULL;
1162         message_info_t *sms;
1163         message_info_t *email;
1164
1165 /* **********************Note from glib documentation**************************
1166  * g_list_append() has to traverse the entire list to find the end, which
1167  * is inefficient when adding multiple elements. A common idiom to avoid the
1168  * inefficiency is to use g_list_prepend() and reverse the list with
1169  * g_list_reverse() when all elements have been added.
1170  * ***************************************************************************/
1171
1172         while (sms_list && email_list) {
1173                 sms = sms_list->data;
1174                 email = email_list->data;
1175
1176                 if (sms->time > email->time) {
1177                         list = g_list_prepend(list, sms);
1178                         sms_list = g_slist_next(sms_list);
1179                 } else {
1180                         list = g_list_prepend(list, email);
1181                         email_list = g_slist_next(email_list);
1182                 }
1183         }
1184
1185         while (sms_list) {
1186                 sms = sms_list->data;
1187                 list = g_list_prepend(list, sms);
1188                 sms_list = g_slist_next(sms_list);
1189         }
1190         while (email_list) {
1191                 email = email_list->data;
1192                 list = g_list_prepend(list, email);
1193                 email_list = g_slist_next(email_list);
1194         }
1195
1196         list = g_list_reverse(list);
1197         return list;
1198 }
1199
1200 static GVariant *__bt_map_get_folder_tree(GError **err)
1201 {
1202         GVariant *folder_list = NULL;
1203         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
1204         int i;
1205         gboolean sms_ret = TRUE;
1206         gboolean email_ret = TRUE;
1207
1208         sms_ret = _bt_map_sms_get_supported_folders(folders_supported);
1209         email_ret = _bt_map_email_get_supported_folders(folders_supported);
1210
1211         if (sms_ret || email_ret) {
1212                 for (i = 0; i < 5; i++) {
1213                         if (folders_supported[i][BT_MSG_SOURCE_SMS] ||
1214                                         folders_supported[i][BT_MSG_SOURCE_EMAIL]) {
1215                                 g_variant_builder_add(builder, "(s)", __bt_get_map_folder(i));
1216                         }
1217                 }
1218
1219                 folder_list = g_variant_new("(a(s))", builder);
1220         } else {
1221                 *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1222                                                 "InternalError");
1223         }
1224
1225         g_variant_builder_unref(builder);
1226         return folder_list;
1227 }
1228
1229 static GVariant *__bt_map_get_message_list(char *folder_name, guint16 max,
1230                                 guint16 offset, guint8 subject_len,
1231                                 map_msg_filter_t *filter, GError **err)
1232 {
1233         FN_START;
1234         GVariant *message_list = NULL;
1235         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssssssssssbsbbbbs)"));
1236         GSList *sms_list = NULL;
1237         GSList *email_list = NULL;
1238         gboolean sms_ret = TRUE;
1239         gboolean email_ret = TRUE;
1240         guint64 count = 0;
1241         guint64 count_sms = 0;
1242         guint64 count_email = 0;
1243         gboolean newmsg = FALSE;
1244         char *folder = NULL;
1245
1246         DBG("Folder:%s Max:%d", folder_name, max);
1247         if (!folder_name)
1248                 goto fail;
1249
1250         /* In case of parent folders send empty message listing */
1251         /*
1252         if (g_ascii_strncasecmp(folder_name, "/telecom/msg/", strlen("/telecom/msg/")))
1253                 goto fail;
1254          */
1255
1256         folder = strrchr(folder_name, '/');
1257         if (NULL == folder)
1258                 folder = folder_name;
1259         else
1260                 folder++;
1261         DBG("Filter Type: %d", filter->type);
1262         if ((filter->type & FILTER_TYPE_SMS_GSM) == 0) { /* Check if SMS is requested */
1263                 if (!g_ascii_strncasecmp(folder, "SENT", strlen("SENT"))) {
1264                         /* Failed Sent SMS are stored in OUTBOX.
1265                          * Hence, Fetch both SENT and OUTBOX */
1266                         gboolean sent_ret = _bt_map_get_sms_message_list("SENT",
1267                                                 max + offset, subject_len, filter,
1268                                                 &sms_list, &count_sms, &newmsg);
1269                         gboolean outbox_ret = _bt_map_get_sms_message_list("OUTBOX",
1270                                                 max + offset, subject_len, filter,
1271                                                 &sms_list, &count_sms, &newmsg);
1272                         sms_ret = (sent_ret || outbox_ret);
1273                 } else {
1274                         sms_ret = _bt_map_get_sms_message_list(folder,
1275                                         max + offset, subject_len, filter,
1276                                         &sms_list, &count_sms, &newmsg);
1277                 }
1278         }
1279
1280         if ((filter->type & FILTER_TYPE_EMAIL) == 0) { /* Check if EMAIL is requested */
1281                 email_ret = _bt_map_get_email_list(folder,
1282                                 max + offset, subject_len, filter,
1283                                 &email_list, &count_email, &newmsg);
1284         }
1285
1286         if (sms_ret || email_ret) {
1287                 GList *list = _bt_map_merge_sorted(sms_list, email_list);
1288                 GList *pos = NULL;
1289                 int i;
1290                 message_info_t *msg_info = NULL;
1291
1292                 g_slist_free(sms_list);
1293                 g_slist_free(email_list);
1294
1295                 count = count_sms + count_email;
1296
1297                 pos = g_list_nth(list, offset);
1298                 for (i = offset; pos && i < max + offset; i++) {
1299                         msg_info = pos->data;
1300                         g_variant_builder_add(builder, "(ssssssssssbsbbbbs)",
1301                                                 msg_info->handle,
1302                                                 msg_info->subject,
1303                                                 msg_info->datetime,
1304                                                 msg_info->sender_name,
1305                                                 msg_info->sender_addressing,
1306                                                 msg_info->recipient_name,
1307                                                 msg_info->recipient_addressing,
1308                                                 msg_info->type,
1309                                                 msg_info->size,
1310                                                 msg_info->reception_status,
1311                                                 msg_info->text,
1312                                                 msg_info->attachment_size,
1313                                                 msg_info->priority,
1314                                                 msg_info->read,
1315                                                 msg_info->sent,
1316                                                 msg_info->protect,
1317                                                 msg_info->replyto_addressing);
1318
1319                         pos = g_list_next(pos);
1320                 }
1321
1322                 message_list = g_variant_new("(bta(ssssssssssbsbbbbs))",
1323                                 newmsg, count, builder);
1324                 g_variant_builder_unref(builder);
1325                 g_list_free_full(list, _bt_message_info_free);
1326
1327                 return message_list;
1328         }
1329
1330 fail:
1331         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1332                                         "InternalError");
1333         g_variant_builder_unref(builder);
1334         ERR("fail -");
1335         return NULL;
1336 }
1337
1338 static GVariant *__bt_map_get_message(char *message_name, gboolean attach,
1339                 gboolean transcode, gboolean first_request, GError **err)
1340 {
1341         FN_START;
1342         GVariant *message = NULL;
1343         int message_id = 0;
1344         gboolean val_ret;
1345         gchar *bmseg = NULL;
1346
1347         struct id_info *handle_info = __bt_get_uid(message_name);
1348         if (handle_info == NULL)
1349                 return FALSE;
1350
1351         message_id = handle_info->uid;
1352         if (handle_info->msg_type == BT_MAP_ID_SMS)
1353                 val_ret = _bt_map_get_sms_message(message_id, attach, transcode, first_request, &bmseg);
1354         else
1355                 val_ret = _bt_map_get_email_message(message_id, attach, transcode, first_request, &bmseg);
1356
1357         if (val_ret) {
1358                 message = g_variant_new("(bs)", FALSE, bmseg);
1359                 g_free(bmseg);
1360                 FN_END;
1361                 return message;
1362         }
1363
1364         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1365                                                         "InternalError");
1366         ERR("fail - \n");
1367         return NULL;
1368 }
1369
1370 static GVariant *__bt_map_push_message(gboolean save_copy, gboolean retry_send,
1371                 gboolean native, char *folder_name, GError **err)
1372 {
1373         FN_START;
1374         guint64 handle = 0;
1375
1376         DBG_SECURE("folder_name = %s\n", folder_name);
1377
1378         handle = _bt_add_id(-1, BT_MAP_ID_SMS);
1379         current_push_map_id = handle;
1380         push_folder = g_strdup(folder_name);
1381
1382         /* FALSE : Keep messages in Sent folder */
1383         /* TRUE : don't keep messages in sent folder */
1384         opt.save_copy = save_copy;
1385         DBG("opt.save_copy = %d\n", opt.save_copy);
1386
1387         /* FALSE : don't retry */
1388         /* TRUE  : retry */
1389         opt.retry_send = retry_send;
1390         DBG("opt.retry_send = %d\n", opt.retry_send);
1391
1392         /* FALSE : native */
1393         /* TRUE : UTF-8 */
1394         opt.native = native;
1395         DBG("opt.native = %d\n", opt.native);
1396
1397         return g_variant_new("(t)", handle);
1398         FN_END;
1399 }
1400
1401 static GVariant *__bt_map_push_message_data(char *bmseg, GError **err)
1402 {
1403         FN_START;
1404         gboolean ret = FALSE;
1405
1406         DBG_SECURE("BMSG: %s", bmseg);
1407
1408         struct bmsg_data *bmsg_info = NULL;
1409
1410         bmsg_info = bmsg_parse(bmseg);
1411         if (bmsg_info) {
1412                 if (!g_ascii_strcasecmp(bmsg_info->type, "SMS_GSM"))
1413                         ret = _bt_map_push_sms_data(bmsg_info, &opt, push_folder);
1414                 else if (!g_ascii_strcasecmp(bmsg_info->type, "EMAIL"))
1415                         ret = _bt_map_push_email_data(bmsg_info, &opt, push_folder);
1416
1417                 bmsg_free_bmsg(bmsg_info);
1418         }
1419
1420         g_free(push_folder);
1421         push_folder = NULL;
1422         if (ret) {
1423                 INFO("Message Successfully Sent or Saved");
1424                 return NULL;
1425         }
1426
1427         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1428                                                 "InternalError");
1429         ERR("Error in sending or saving Message");
1430         return NULL;
1431 }
1432
1433 /* Dummy Implementation */
1434 static GVariant *__bt_map_update_message(GError **err)
1435 {
1436         return g_variant_new("(b)", TRUE);
1437 }
1438
1439 static GVariant *__bt_map_set_read_status(char *handle, gboolean read_status, GError **err)
1440 {
1441         FN_START;
1442         int msg_id;
1443         gboolean val_ret;
1444
1445         struct id_info *handle_info = __bt_get_uid(handle);
1446         if (handle_info == NULL)
1447                 goto fail;
1448
1449         msg_id = handle_info->uid;
1450         DBG("msg_id = %d,  read_status = %d\n", msg_id, read_status);
1451         if (handle_info->msg_type == BT_MAP_ID_SMS)
1452                 val_ret = _bt_map_sms_set_read_status(msg_id, read_status);
1453         else
1454                 val_ret = _bt_map_set_email_read_status(msg_id, read_status);
1455
1456         if (val_ret) {
1457                 FN_END;
1458                 return NULL;
1459         }
1460
1461 fail:
1462         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1463                                                         "InternalError");
1464         ERR("fail -\n");
1465         return NULL;
1466 }
1467
1468 static GVariant *__bt_map_set_delete_status(char *handle, gboolean delete_status, GError **err)
1469 {
1470         FN_START;
1471         int msg_id = 0;
1472         gboolean val_ret;
1473
1474         struct id_info *handle_info = __bt_get_uid(handle);
1475         if (handle_info == NULL)
1476                 goto fail;
1477
1478         msg_id = handle_info->uid;
1479         if (handle_info->msg_type == BT_MAP_ID_SMS)
1480                 val_ret = _bt_map_set_sms_delete_status(msg_id, delete_status);
1481         else
1482                 val_ret = _bt_map_set_email_delete_status(msg_id, delete_status);
1483
1484         if (val_ret) {
1485                 FN_END;
1486                 return NULL;
1487         }
1488
1489 fail:
1490         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1491                                                         "InternalError");
1492         ERR("fail -\n");
1493         return NULL;
1494 }
1495
1496 static void __bt_map_noti_registration(char *remote_addr, gboolean status)
1497 {
1498         FN_START;
1499         DBG_SECURE("remote_addr = %s \n", remote_addr);
1500
1501         if (status == TRUE)
1502                 __bt_mns_client_connect(remote_addr);
1503         else
1504                 __bt_mns_client_disconnect();
1505 }
1506
1507 static void __bt_map_destroy_agent(void)
1508 {
1509         g_main_loop_quit(g_mainloop);
1510 }
1511
1512 static GDBusNodeInfo *__bt_map_create_method_node_info
1513                                         (const gchar *introspection_data)
1514 {
1515         GError *err = NULL;
1516         GDBusNodeInfo *node_info = NULL;
1517
1518         if (introspection_data == NULL)
1519                 return NULL;
1520
1521         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1522
1523         if (err) {
1524                 ERR("Unable to create node: %s", err->message);
1525                 g_clear_error(&err);
1526         }
1527         return node_info;
1528 }
1529
1530 static gboolean __bt_map_dbus_init(void)
1531 {
1532         guint owner_id;
1533         guint map_id;
1534         GDBusNodeInfo *node_info;
1535         GError *error = NULL;
1536         GDBusConnection *gdbus_conn = __bt_map_get_gdbus_connection();
1537
1538         if (gdbus_conn == NULL) {
1539                 ERR("Error in creating the gdbus connection");
1540                 return FALSE;
1541         }
1542
1543         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1544                         BT_MAP_SERVICE_NAME,
1545                         G_BUS_NAME_OWNER_FLAGS_NONE,
1546                         NULL, NULL, NULL,
1547                         NULL, NULL);
1548         DBG("owner_id is [%d]", owner_id);
1549
1550         node_info = __bt_map_create_method_node_info(
1551                         map_agent_introspection_xml);
1552         if (node_info == NULL)
1553                 return FALSE;
1554
1555         map_id = g_dbus_connection_register_object(gdbus_conn, BT_MAP_SERVICE_OBJECT_PATH,
1556                                         node_info->interfaces[0],
1557                                         &method_table,
1558                                         NULL, NULL, &error);
1559
1560         g_dbus_node_info_unref(node_info);
1561
1562         if (map_id == 0) {
1563                 ERR("Failed to register: %s", error->message);
1564                 g_error_free(error);
1565                 return FALSE;
1566         }
1567
1568         return TRUE;
1569 }
1570
1571 int main(void)
1572 {
1573         FN_START;
1574         int ret;
1575         DBG("Starting Bluetooth MAP agent");
1576
1577         //g_type_init();
1578
1579         g_mainloop = g_main_loop_new(NULL, FALSE);
1580
1581         if (g_mainloop == NULL) {
1582                 ERR("Couldn't create GMainLoop\n");
1583                 return EXIT_FAILURE;
1584         }
1585
1586         if (__bt_map_dbus_init() == FALSE)
1587                 goto failure;
1588
1589         if (__bluetooth_map_start_service() == FALSE)
1590                 goto failure;
1591
1592         g_tapi_handle = tel_init(NULL);
1593         if (!g_tapi_handle)
1594                 goto failure;
1595
1596         ret = tel_get_sms_sca(g_tapi_handle, 0, __bt_get_sms_sca, NULL);
1597         if (ret != TAPI_API_SUCCESS) {
1598                 ERR("TAPI err = %d", ret);
1599                 goto failure;
1600         }
1601
1602         g_main_loop_run(g_mainloop);
1603
1604  failure:
1605
1606         __bt_remove_list(id_list);
1607
1608         tel_deinit(g_tapi_handle);
1609         g_free(g_sca_info);
1610
1611         __bt_mns_client_disconnect();
1612
1613         if (map_dbus_conn)
1614                 g_object_unref(map_dbus_conn);
1615
1616         _bt_map_stop_sms_service();
1617         _bt_map_stop_email_service();
1618
1619         DBG("Bluetooth MAP agent Terminated successfully\n");
1620         FN_END;
1621         return EXIT_FAILURE;
1622 }
1623 /* LCOV_EXCL_STOP */