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