65fadc7a21a5513634af1825f8283019d1e53c26
[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: %llu\n", (unsigned long long int)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 = %llu, uid = %d, MsgType=%d", (unsigned long long int)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 buf_len = 0;
586         int month;
587
588         if (!localtime_r(ltime, &local_time))
589                 return;
590
591         year = local_time.tm_year + 1900; /* years since 1900 */
592         month = local_time.tm_mon + 1; /* months since January */
593         buf_len = snprintf(timestamp, 16, "%04hu%02hu%02huT%02hu%02hu%02hu",(unsigned short int)year, (unsigned short int)month,
594                                         (unsigned short int)local_time.tm_mday, (unsigned short int)local_time.tm_hour,
595                                         (unsigned short int)local_time.tm_min, (unsigned short int)local_time.tm_sec);
596
597         if (buf_len < 0)
598                 ERR("Encoding error occured in snprintf");
599
600         FN_END;
601 }
602
603 /* LCOV_EXCL_START */
604 time_t _get_time_t_from_timestamp(char *timestamp)
605 {
606         struct tm local_time;
607         int year;
608         int month;
609         time_t int_time;
610
611         int ymd; /* year, month, day */
612         int hms; /* hour, min, sec */
613         char *ptr, *ptr2;
614
615         ymd = strtol(timestamp, &ptr, 10);
616         hms = strtol(ptr + 1, &ptr2, 10);
617
618         /* Initialize local_time */
619         memset(&local_time, 0, sizeof(struct tm));
620
621         /* parse year, month, day */
622         local_time.tm_mday = ymd % 100;
623         ymd = (ymd - local_time.tm_mday) / 100;
624         month = ymd % 100;
625         year = (ymd - month) / 100;
626
627         /* parse hour, minute, sec */
628         local_time.tm_sec = hms % 100;
629         hms = (hms - local_time.tm_sec) / 100;
630         local_time.tm_min = hms % 100;
631         local_time.tm_hour = (hms - local_time.tm_min) / 100;
632
633         local_time.tm_year = year - 1900;
634         local_time.tm_mon = month - 1;
635
636         int_time = mktime(&local_time);
637         return int_time;
638 }
639 /* LCOV_EXCL_STOP */
640
641 gboolean _bt_verify_time(message_info_t *msg_info, map_msg_filter_t *filter)
642 {
643         struct tm local_time = { 0, };
644         time_t start;
645         time_t end;
646
647         /* Set 19710101T000000 as Start Date */
648         local_time.tm_year = 1971 - 1900;
649         local_time.tm_mon = 0;
650         local_time.tm_mday = 1;
651         start = mktime(&local_time);
652
653         /* Set 20380101T000000 as End Date */
654         local_time.tm_year = 2038 - 1900;
655         local_time.tm_mon = 0;
656         local_time.tm_mday = 1;
657         end = mktime(&local_time);
658
659         if (filter->period_begin)
660                 start = _get_time_t_from_timestamp(filter->period_begin);
661
662         if (filter->period_end)
663                 end = _get_time_t_from_timestamp(filter->period_end);
664
665         if (msg_info->time >= start && msg_info->time <= end)
666                 return TRUE;
667
668         return FALSE;
669 }
670
671 #define SET_TON_NPI(dest, ton, npi) {   \
672         dest = 0x80;                    \
673         dest |= (ton & 0x07) << 4;      \
674         dest |= npi & 0x0F;             \
675 }
676
677 /* LCOV_EXCL_START */
678 static int __bt_ascii_to_upper(int ch)
679 {
680         return (('a' <= (ch) && (ch) <= 'z') ? ((ch) - ('a'-'A')) : (ch));
681 }
682
683 static int __bt_sms_pack_gsm_code(gchar *p_out, const char *data, int in_len)
684 {
685         FN_START;
686         int i;
687         int pos;
688         int shift = 0;
689
690         for (pos = 0, i = 0; i < in_len; pos++, i++) {
691                 /* pack the low bits */
692                 p_out[pos] = data[i] >> shift;
693
694                 if (i + 1 < in_len) {
695                         /* pack the high bits using the low bits
696                            of the next character */
697                         p_out[pos] |= data[i+1] << (7 - shift);
698
699                         shift++;
700
701                         if (shift == 7) {
702                                 shift = 0;
703                                 i++;
704                         }
705                 }
706         }
707
708         FN_END;
709         return pos;
710 }
711
712 static void __bt_sms_conv_digit_to_bcd(gchar *p_bcd, char *p_digits, int digit_len)
713 {
714         FN_START;
715         int i;
716         int j;
717         int digit;
718         unsigned char higher;
719         unsigned char lower;
720
721         if (p_bcd == NULL || p_digits == NULL)
722                 return;
723
724         /* 0123456789 -> 1032547698 */
725         for (i = 0, j = 0; i < digit_len; i = i + 2, j++) {
726                 if (p_digits[i] == '*')
727                         digit = 0x0A;
728                 else if (p_digits[i] == '#')
729                         digit = 0x0B;
730                 else if (__bt_ascii_to_upper(p_digits[i]) == 'P')
731                         digit = 0x0C;
732                 else
733                         digit = (int) (p_digits[i] - '0');
734
735                 lower = digit & 0x0F;
736
737                 if (digit_len != i + 1) {
738                         if (p_digits[i+1] == '*')
739                                 digit = 0x0A;
740                         else if (p_digits[i+1] == '#')
741                                 digit = 0x0B;
742                         else if (__bt_ascii_to_upper(p_digits[i+1]) == 'P')
743                                 digit = 0x0C;
744                         else
745                                 digit = (int) (p_digits[i+1] - '0');
746
747                         higher = digit & 0x0F;
748                 } else {
749                         higher = 0xFF;
750                 }
751
752                 p_bcd[j] = (higher << 4) | lower;
753         }
754         FN_END;
755 }
756
757 static int  __bt_sms_encode_addr(gchar *addr_field, char *dial_num,
758                                 int dial_num_len, int ton, int npi)
759 {
760         FN_START;
761         int index = 0;
762
763         if (dial_num == NULL || addr_field == NULL)
764                 return -1;
765
766         if (dial_num[0] == '+') {
767                 dial_num++;
768                 dial_num_len--;
769                 ton = SMS_TON_INTERNATIONAL;
770         }
771
772         if (ton != SMS_TON_ALPHA_NUMERIC) {
773                 /* Origination address length address length */
774                 addr_field[index++] = (unsigned char)dial_num_len;
775         } else {
776                 addr_field[index] = (unsigned char)
777                                         (((dial_num_len * 7 + 7) / 8) * 2);
778
779                 if (((dial_num_len * 7) % 8) <= 4)
780                         addr_field[index]--;
781
782                 index++;
783         }
784
785         SET_TON_NPI(addr_field[index], ton, npi);
786         index++; /* SET_TON_NPI */
787
788         if (ton != SMS_TON_ALPHA_NUMERIC) {
789                 __bt_sms_conv_digit_to_bcd(&addr_field[index],
790                                         (char *)dial_num, dial_num_len);
791
792                 if (dial_num_len % 2)
793                         index += (dial_num_len / 2) + 1;
794                 else
795                         index += dial_num_len / 2;
796         } else {
797                 index += __bt_sms_pack_gsm_code(&addr_field[index],
798                                                 dial_num, (int)dial_num_len);
799         }
800
801         FN_END;
802         return index;
803 }
804
805 static int __bt_sms_encode_time(gchar *addr_field, time_t *tm)
806 {
807         FN_START;
808         int index = 0;
809         struct tm ltime;
810         int year;
811         int month;
812
813         if (!localtime_r(tm, &ltime))
814                 return index;
815
816         year = ltime.tm_year + 1900; /* years since 1900 */
817         year = year % 100;
818         month = ltime.tm_mon + 1; /* months since January */
819
820         addr_field[index++] = ((year % 10)  << 4) + (year / 10);
821         addr_field[index++] = ((month % 10) << 4) + (month / 10);
822         addr_field[index++] = ((ltime.tm_mday % 10) << 4) +
823                                                         (ltime.tm_mday / 10);
824         addr_field[index++] = ((ltime.tm_hour % 10) << 4) +
825                                                         (ltime.tm_hour / 10);
826         addr_field[index++] = ((ltime.tm_min % 10) << 4) + (ltime.tm_min / 10);
827         addr_field[index++] = ((ltime.tm_sec % 10) << 4) + (ltime.tm_sec / 10);
828         addr_field[index] = 0x00;
829
830         FN_END;
831         return index;
832 }
833
834 gchar *_bt_get_sms_pdu_from_msg_data(gchar *number,
835                                                 char *msg, time_t tm,
836                                                 int *msg_pdu_len)
837 {
838         FN_START;
839         gchar packet[TAPI_NETTEXT_MSG_SIZE_MAX] = {0,};
840         int index = 0;
841
842         packet[index] = 0x00; /* Since SCA is unknown for stored messages */
843         index++;
844
845         /* TP-MTI : Type of message */
846         packet[index] = 0x00;   /* SMS-DELIVER PDU */
847
848         /* TP-MMS bit is set to 1 as we support only SMS */
849         packet[index] |= 0x04;
850         index++;
851
852         /* TP-OA : Mobile originating address */
853         index += __bt_sms_encode_addr(packet+index,
854                                         number, strlen(number),
855                                         g_sca_info->Ton, g_sca_info->Npi);
856
857         /* TP-PID : Since we use only SMS so set to 0 */
858         packet[index++] = 0x00;
859
860         /* TP-DCS : Data Coding Scheme, default value set */
861         packet[index++] = 0x00;
862
863         /* TP-SCTS : Message timestamp */
864         index += __bt_sms_encode_time(packet+index, &tm);
865         index++;
866         /* TP-UDL : Message body length */
867         packet[index++] = strlen(msg);
868
869         /* TP-UD : Message body */
870         index += __bt_sms_pack_gsm_code(packet + index, msg, strlen(msg));
871
872         *msg_pdu_len = index;
873
874         FN_END;
875         return g_memdup(packet, index);
876 }
877
878 static void __bt_get_sms_sca(TapiHandle *handle, int result, void *data,
879                                                         void *user_data)
880 {
881         FN_START;
882         TelSmsAddressInfo_t *scaInfo = data;
883
884         DBG("__bt_get_sms_sca 0x%x", result);
885
886         if (data == NULL) {
887                 g_sca_info = g_malloc0(sizeof(TelSmsAddressInfo_t));
888                 g_sca_info->Ton = 0;
889                 g_sca_info->Npi = 0;
890                 g_sca_info->DialNumLen = 0;
891                 return;
892         }
893
894         g_sca_info = g_malloc0(sizeof(TelSmsAddressInfo_t));
895         g_sca_info->Ton = scaInfo->Ton;
896         g_sca_info->Npi = scaInfo->Npi;
897         g_sca_info->DialNumLen = scaInfo->DialNumLen;
898         FN_END;
899 }
900 /* LCOV_EXCL_STOP */
901
902 void _bt_message_info_free(gpointer data)
903 {
904         FN_START;
905         message_info_t *msg_info = (message_info_t *)data;
906         g_free(msg_info->handle);
907         g_free(msg_info->subject);
908         g_free(msg_info->datetime);
909         g_free(msg_info->sender_name);
910         g_free(msg_info->sender_addressing);
911         g_free(msg_info->replyto_addressing);
912         g_free(msg_info->recipient_name);
913         g_free(msg_info->recipient_addressing);
914         g_free(msg_info->type);
915         g_free(msg_info->reception_status);
916         g_free(msg_info->size);
917         g_free(msg_info->attachment_size);
918         g_free(msg_info);
919         FN_END;
920 }
921
922 /* LCOV_EXCL_START */
923 static gboolean __bluetooth_map_start_service()
924 {
925         FN_START;
926         gboolean sms;
927         gboolean email;
928
929         sms = _bt_map_start_sms_service();
930         email = _bt_map_start_email_service();
931         if (sms && email)
932                 return TRUE;
933
934         FN_END;
935         return FALSE;
936 }
937 /* LCOV_EXCL_STOP */
938
939 static gboolean __bt_validate_utf8(char **text)
940 {
941         FN_START;
942         if (g_utf8_validate(*text, -1, NULL))
943                 return TRUE;
944
945         /* LCOV_EXCL_START */
946         FN_END;
947         return FALSE;
948         /* LCOV_EXCL_STOP */
949 }
950
951 gboolean _bt_validate_msg_data(message_info_t *msg_info)
952 {
953         FN_START;
954         if (msg_info == NULL)
955                 return FALSE;
956
957         if (msg_info->subject)
958                 return __bt_validate_utf8(&msg_info->subject);
959
960         if (msg_info->sender_name)
961                 return __bt_validate_utf8(&msg_info->sender_name);
962
963         /* LCOV_EXCL_START */
964         if (msg_info->sender_addressing)
965                 return __bt_validate_utf8(&msg_info->sender_addressing);
966
967         if (msg_info->replyto_addressing)
968                 return __bt_validate_utf8(&msg_info->replyto_addressing);
969
970         if (msg_info->recipient_name)
971                 return __bt_validate_utf8(&msg_info->recipient_name);
972
973         if (msg_info->recipient_addressing)
974                 return __bt_validate_utf8(&msg_info->recipient_addressing);
975
976         FN_END;
977         return TRUE;
978         /* LCOV_EXCL_STOP */
979 }
980
981 /* LCOV_EXCL_START */
982 static void __bt_mns_client_connect(char *address)
983 {
984         FN_START;
985         GDBusConnection *connection;
986         GVariantBuilder builder;
987         GVariant *args;
988         GVariant *param;
989         GVariant *value;
990         GError *error = NULL;
991         const char *session_path;
992
993         if (g_mns_proxy) {
994                 DBG_SECURE("MNS Client already connected to %s", address);
995                 return;
996         }
997
998         connection = __bt_map_get_gdbus_connection();
999         if (connection == NULL) {
1000                 DBG("Could not get GDBus Connection");
1001                 return;
1002         }
1003
1004         g_mns_proxy = g_dbus_proxy_new_sync(connection,
1005                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1006                         OBEX_CLIENT_SERVICE, OBEX_CLIENT_PATH,
1007                         OBEX_CLIENT_INTERFACE, NULL, &error);
1008
1009         if (!g_mns_proxy) {
1010                 ERR("Failed to get a proxy for D-Bus");
1011                 return;
1012         }
1013
1014         /* Create Hash*/
1015         g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
1016         g_variant_builder_add(&builder, "{sv}", "Target",
1017                                         g_variant_new("s", "MNS"));
1018         args = g_variant_builder_end(&builder);
1019
1020         param = g_variant_new("(s@a{sv})", address, args);
1021
1022         value = g_dbus_proxy_call_sync(g_mns_proxy,
1023                         "CreateSession", param, G_DBUS_CALL_FLAGS_NONE, -1,
1024                         NULL, &error);
1025         if (value == NULL) {
1026                 /* dBUS-RPC is failed */
1027                 ERR("dBUS-RPC is failed");
1028                 if (error != NULL) {
1029                         /* dBUS gives error cause */
1030                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1031                                 error->code, error->message);
1032
1033                         g_clear_error(&error);
1034                 }
1035                 g_object_unref(g_mns_proxy);
1036                 g_mns_proxy = NULL;
1037                 return;
1038         }
1039
1040         g_variant_get(value, "(&o)", &session_path);
1041         g_mns_path = g_strdup(session_path);
1042         DBG("g_mns_path = %s\n", g_mns_path);
1043
1044         g_variant_unref(value);
1045         FN_END;
1046 }
1047
1048 static void __bt_mns_client_disconnect()
1049 {
1050         FN_START;
1051         GError *error = NULL;
1052         GVariant *value;
1053
1054         if (!g_mns_proxy) {
1055                 ERR("No proxy to disconnect");
1056                 return;
1057         }
1058
1059         value = g_dbus_proxy_call_sync(g_mns_proxy,
1060                         "RemoveSession", g_variant_new("(o)", g_mns_path),
1061                         G_DBUS_CALL_FLAGS_NONE, -1,
1062                         NULL, &error);
1063
1064         if (value == NULL) {
1065                 /* dBUS-RPC is failed */
1066                 ERR("dBUS-RPC is failed: Could not remove MAP session");
1067                 if (error != NULL) {
1068                         /* dBUS gives error cause */
1069                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1070                                 error->code, error->message);
1071
1072                         g_clear_error(&error);
1073                 }
1074                 return;
1075         }
1076
1077         g_free(g_mns_path);
1078         g_mns_path = NULL;
1079
1080         g_object_unref(g_mns_proxy);
1081         g_mns_proxy = NULL;
1082
1083         g_variant_unref(value);
1084         FN_END;
1085 }
1086 /* LCOV_EXCL_STOP */
1087
1088 void _bt_mns_client_event_notify(gchar *event, guint64 handle,
1089                                         gchar *folder, gchar *old_folder,
1090                                         gchar *msg_type)
1091 {
1092         FN_START;
1093         GError *error = NULL;
1094         GDBusProxy *mns_proxy;
1095         GDBusConnection *connection = NULL;
1096         GVariant *value;
1097
1098         if (!g_mns_proxy) {
1099                 ERR("No client proxy");
1100                 return;
1101         }
1102
1103         /* LCOV_EXCL_START */
1104         connection = __bt_map_get_gdbus_connection();
1105         if (connection == NULL) {
1106                 DBG("Could not get GDBus Connection");
1107                 return;
1108         }
1109
1110         mns_proxy = g_dbus_proxy_new_sync(connection,
1111                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1112                         OBEX_CLIENT_SERVICE, g_mns_path,
1113                         MNS_CLIENT_INTERFACE, NULL, &error);
1114         if (mns_proxy == NULL) {
1115                 ERR("Failed to get a proxy for D-Bus\n");
1116                 return;
1117         }
1118
1119         value = g_dbus_proxy_call_sync(mns_proxy, "SendEvent",
1120                         g_variant_new("(stsss)", event, handle, folder, old_folder, msg_type),
1121                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1122         if (value == NULL) {
1123                 /* dBUS-RPC is failed */
1124                 ERR("dBUS-RPC is failed: SendEvent failed");
1125                 if (error != NULL) {
1126                         /* dBUS gives error cause */
1127                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1128                                 error->code, error->message);
1129
1130                         g_clear_error(&error);
1131                 }
1132                 g_object_unref(mns_proxy);
1133                 return;
1134         }
1135
1136         g_variant_unref(value);
1137         g_object_unref(mns_proxy);
1138         FN_END;
1139         /* LCOV_EXCL_STOP */
1140 }
1141
1142 /* LCOV_EXCL_START */
1143 static gchar *__bt_get_map_folder(int folder)
1144 {
1145         switch (folder) {
1146         case BT_MSG_INBOX:
1147                 return g_strdup("INBOX");
1148         case BT_MSG_SENT:
1149                 return g_strdup("SENT");
1150         case BT_MSG_OUTBOX:
1151                 return g_strdup("OUTBOX");
1152         case BT_MSG_DRAFT:
1153                 return g_strdup("DRAFT");
1154         case BT_MSG_DELETED:
1155                 return g_strdup("DELETED");
1156         }
1157         return NULL;
1158 }
1159
1160 static GList *_bt_map_merge_sorted(GSList *sms_list, GSList *email_list)
1161 {
1162         GList *list = NULL;
1163         message_info_t *sms;
1164         message_info_t *email;
1165
1166 /* **********************Note from glib documentation**************************
1167  * g_list_append() has to traverse the entire list to find the end, which
1168  * is inefficient when adding multiple elements. A common idiom to avoid the
1169  * inefficiency is to use g_list_prepend() and reverse the list with
1170  * g_list_reverse() when all elements have been added.
1171  * ***************************************************************************/
1172
1173         while (sms_list && email_list) {
1174                 sms = sms_list->data;
1175                 email = email_list->data;
1176
1177                 if (sms->time > email->time) {
1178                         list = g_list_prepend(list, sms);
1179                         sms_list = g_slist_next(sms_list);
1180                 } else {
1181                         list = g_list_prepend(list, email);
1182                         email_list = g_slist_next(email_list);
1183                 }
1184         }
1185
1186         while (sms_list) {
1187                 sms = sms_list->data;
1188                 list = g_list_prepend(list, sms);
1189                 sms_list = g_slist_next(sms_list);
1190         }
1191         while (email_list) {
1192                 email = email_list->data;
1193                 list = g_list_prepend(list, email);
1194                 email_list = g_slist_next(email_list);
1195         }
1196
1197         list = g_list_reverse(list);
1198         return list;
1199 }
1200
1201 static GVariant *__bt_map_get_folder_tree(GError **err)
1202 {
1203         GVariant *folder_list = NULL;
1204         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
1205         int i;
1206         gboolean sms_ret = TRUE;
1207         gboolean email_ret = TRUE;
1208
1209         sms_ret = _bt_map_sms_get_supported_folders(folders_supported);
1210         email_ret = _bt_map_email_get_supported_folders(folders_supported);
1211
1212         if (sms_ret || email_ret) {
1213                 for (i = 0; i < 5; i++) {
1214                         if (folders_supported[i][BT_MSG_SOURCE_SMS] ||
1215                                         folders_supported[i][BT_MSG_SOURCE_EMAIL]) {
1216                                 g_variant_builder_add(builder, "(s)", __bt_get_map_folder(i));
1217                         }
1218                 }
1219
1220                 folder_list = g_variant_new("(a(s))", builder);
1221         } else {
1222                 *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1223                                                 "InternalError");
1224         }
1225
1226         g_variant_builder_unref(builder);
1227         return folder_list;
1228 }
1229
1230 static GVariant *__bt_map_get_message_list(char *folder_name, guint16 max,
1231                                 guint16 offset, guint8 subject_len,
1232                                 map_msg_filter_t *filter, GError **err)
1233 {
1234         FN_START;
1235         GVariant *message_list = NULL;
1236         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssssssssssbsbbbbs)"));
1237         GSList *sms_list = NULL;
1238         GSList *email_list = NULL;
1239         gboolean sms_ret = TRUE;
1240         gboolean email_ret = TRUE;
1241         guint64 count = 0;
1242         guint64 count_sms = 0;
1243         guint64 count_email = 0;
1244         gboolean newmsg = FALSE;
1245         char *folder = NULL;
1246
1247         DBG("Folder:%s Max:%d", folder_name, max);
1248         if (!folder_name)
1249                 goto fail;
1250
1251         /* In case of parent folders send empty message listing */
1252         /*
1253         if (g_ascii_strncasecmp(folder_name, "/telecom/msg/", strlen("/telecom/msg/")))
1254                 goto fail;
1255          */
1256
1257         folder = strrchr(folder_name, '/');
1258         if (NULL == folder)
1259                 folder = folder_name;
1260         else
1261                 folder++;
1262         DBG("Filter Type: %d", filter->type);
1263         if ((filter->type & FILTER_TYPE_SMS_GSM) == 0) { /* Check if SMS is requested */
1264                 if (!g_ascii_strncasecmp(folder, "SENT", strlen("SENT"))) {
1265                         /* Failed Sent SMS are stored in OUTBOX.
1266                          * Hence, Fetch both SENT and OUTBOX */
1267                         gboolean sent_ret = _bt_map_get_sms_message_list("SENT",
1268                                                 max + offset, subject_len, filter,
1269                                                 &sms_list, &count_sms, &newmsg);
1270                         gboolean outbox_ret = _bt_map_get_sms_message_list("OUTBOX",
1271                                                 max + offset, subject_len, filter,
1272                                                 &sms_list, &count_sms, &newmsg);
1273                         sms_ret = (sent_ret || outbox_ret);
1274                 } else {
1275                         sms_ret = _bt_map_get_sms_message_list(folder,
1276                                         max + offset, subject_len, filter,
1277                                         &sms_list, &count_sms, &newmsg);
1278                 }
1279         }
1280
1281         if ((filter->type & FILTER_TYPE_EMAIL) == 0) { /* Check if EMAIL is requested */
1282                 email_ret = _bt_map_get_email_list(folder,
1283                                 max + offset, subject_len, filter,
1284                                 &email_list, &count_email, &newmsg);
1285         }
1286
1287         if (sms_ret || email_ret) {
1288                 GList *list = _bt_map_merge_sorted(sms_list, email_list);
1289                 GList *pos = NULL;
1290                 int i;
1291                 message_info_t *msg_info = NULL;
1292
1293                 g_slist_free(sms_list);
1294                 g_slist_free(email_list);
1295
1296                 count = count_sms + count_email;
1297
1298                 pos = g_list_nth(list, offset);
1299                 for (i = offset; pos && i < max + offset; i++) {
1300                         msg_info = pos->data;
1301                         g_variant_builder_add(builder, "(ssssssssssbsbbbbs)",
1302                                                 msg_info->handle,
1303                                                 msg_info->subject,
1304                                                 msg_info->datetime,
1305                                                 msg_info->sender_name,
1306                                                 msg_info->sender_addressing,
1307                                                 msg_info->recipient_name,
1308                                                 msg_info->recipient_addressing,
1309                                                 msg_info->type,
1310                                                 msg_info->size,
1311                                                 msg_info->reception_status,
1312                                                 msg_info->text,
1313                                                 msg_info->attachment_size,
1314                                                 msg_info->priority,
1315                                                 msg_info->read,
1316                                                 msg_info->sent,
1317                                                 msg_info->protect,
1318                                                 msg_info->replyto_addressing);
1319
1320                         pos = g_list_next(pos);
1321                 }
1322
1323                 message_list = g_variant_new("(bta(ssssssssssbsbbbbs))",
1324                                 newmsg, count, builder);
1325                 g_variant_builder_unref(builder);
1326                 g_list_free_full(list, _bt_message_info_free);
1327
1328                 return message_list;
1329         }
1330
1331 fail:
1332         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1333                                         "InternalError");
1334         g_variant_builder_unref(builder);
1335         ERR("fail -");
1336         return NULL;
1337 }
1338
1339 static GVariant *__bt_map_get_message(char *message_name, gboolean attach,
1340                 gboolean transcode, gboolean first_request, GError **err)
1341 {
1342         FN_START;
1343         GVariant *message = NULL;
1344         int message_id = 0;
1345         gboolean val_ret;
1346         gchar *bmseg = NULL;
1347
1348         struct id_info *handle_info = __bt_get_uid(message_name);
1349         if (handle_info == NULL)
1350                 return FALSE;
1351
1352         message_id = handle_info->uid;
1353         if (handle_info->msg_type == BT_MAP_ID_SMS)
1354                 val_ret = _bt_map_get_sms_message(message_id, attach, transcode, first_request, &bmseg);
1355         else
1356                 val_ret = _bt_map_get_email_message(message_id, attach, transcode, first_request, &bmseg);
1357
1358         if (val_ret) {
1359                 message = g_variant_new("(bs)", FALSE, bmseg);
1360                 g_free(bmseg);
1361                 FN_END;
1362                 return message;
1363         }
1364
1365         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1366                                                         "InternalError");
1367         ERR("fail - \n");
1368         return NULL;
1369 }
1370
1371 static GVariant *__bt_map_push_message(gboolean save_copy, gboolean retry_send,
1372                 gboolean native, char *folder_name, GError **err)
1373 {
1374         FN_START;
1375         guint64 handle = 0;
1376
1377         DBG_SECURE("folder_name = %s\n", folder_name);
1378
1379         handle = _bt_add_id(-1, BT_MAP_ID_SMS);
1380         current_push_map_id = handle;
1381         push_folder = g_strdup(folder_name);
1382
1383         /* FALSE : Keep messages in Sent folder */
1384         /* TRUE : don't keep messages in sent folder */
1385         opt.save_copy = save_copy;
1386         DBG("opt.save_copy = %d\n", opt.save_copy);
1387
1388         /* FALSE : don't retry */
1389         /* TRUE  : retry */
1390         opt.retry_send = retry_send;
1391         DBG("opt.retry_send = %d\n", opt.retry_send);
1392
1393         /* FALSE : native */
1394         /* TRUE : UTF-8 */
1395         opt.native = native;
1396         DBG("opt.native = %d\n", opt.native);
1397
1398         return g_variant_new("(t)", handle);
1399         FN_END;
1400 }
1401
1402 static GVariant *__bt_map_push_message_data(char *bmseg, GError **err)
1403 {
1404         FN_START;
1405         gboolean ret = FALSE;
1406
1407         DBG_SECURE("BMSG: %s", bmseg);
1408
1409         struct bmsg_data *bmsg_info = NULL;
1410
1411         bmsg_info = bmsg_parse(bmseg);
1412         if (bmsg_info) {
1413                 if (!g_ascii_strcasecmp(bmsg_info->type, "SMS_GSM"))
1414                         ret = _bt_map_push_sms_data(bmsg_info, &opt, push_folder);
1415                 else if (!g_ascii_strcasecmp(bmsg_info->type, "EMAIL"))
1416                         ret = _bt_map_push_email_data(bmsg_info, &opt, push_folder);
1417
1418                 bmsg_free_bmsg(bmsg_info);
1419         }
1420
1421         g_free(push_folder);
1422         push_folder = NULL;
1423         if (ret) {
1424                 INFO("Message Successfully Sent or Saved");
1425                 return NULL;
1426         }
1427
1428         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1429                                                 "InternalError");
1430         ERR("Error in sending or saving Message");
1431         return NULL;
1432 }
1433
1434 /* Dummy Implementation */
1435 static GVariant *__bt_map_update_message(GError **err)
1436 {
1437         return g_variant_new("(b)", TRUE);
1438 }
1439
1440 static GVariant *__bt_map_set_read_status(char *handle, gboolean read_status, GError **err)
1441 {
1442         FN_START;
1443         int msg_id;
1444         gboolean val_ret;
1445
1446         struct id_info *handle_info = __bt_get_uid(handle);
1447         if (handle_info == NULL)
1448                 goto fail;
1449
1450         msg_id = handle_info->uid;
1451         DBG("msg_id = %d,  read_status = %d\n", msg_id, read_status);
1452         if (handle_info->msg_type == BT_MAP_ID_SMS)
1453                 val_ret = _bt_map_sms_set_read_status(msg_id, read_status);
1454         else
1455                 val_ret = _bt_map_set_email_read_status(msg_id, read_status);
1456
1457         if (val_ret) {
1458                 FN_END;
1459                 return NULL;
1460         }
1461
1462 fail:
1463         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1464                                                         "InternalError");
1465         ERR("fail -\n");
1466         return NULL;
1467 }
1468
1469 static GVariant *__bt_map_set_delete_status(char *handle, gboolean delete_status, GError **err)
1470 {
1471         FN_START;
1472         int msg_id = 0;
1473         gboolean val_ret;
1474
1475         struct id_info *handle_info = __bt_get_uid(handle);
1476         if (handle_info == NULL)
1477                 goto fail;
1478
1479         msg_id = handle_info->uid;
1480         if (handle_info->msg_type == BT_MAP_ID_SMS)
1481                 val_ret = _bt_map_set_sms_delete_status(msg_id, delete_status);
1482         else
1483                 val_ret = _bt_map_set_email_delete_status(msg_id, delete_status);
1484
1485         if (val_ret) {
1486                 FN_END;
1487                 return NULL;
1488         }
1489
1490 fail:
1491         *err = __bt_map_error(BT_MAP_AGENT_ERROR_INTERNAL,
1492                                                         "InternalError");
1493         ERR("fail -\n");
1494         return NULL;
1495 }
1496
1497 static void __bt_map_noti_registration(char *remote_addr, gboolean status)
1498 {
1499         FN_START;
1500         DBG_SECURE("remote_addr = %s \n", remote_addr);
1501
1502         if (status == TRUE)
1503                 __bt_mns_client_connect(remote_addr);
1504         else
1505                 __bt_mns_client_disconnect();
1506 }
1507
1508 static void __bt_map_destroy_agent(void)
1509 {
1510         g_main_loop_quit(g_mainloop);
1511 }
1512
1513 static GDBusNodeInfo *__bt_map_create_method_node_info
1514                                         (const gchar *introspection_data)
1515 {
1516         GError *err = NULL;
1517         GDBusNodeInfo *node_info = NULL;
1518
1519         if (introspection_data == NULL)
1520                 return NULL;
1521
1522         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1523
1524         if (err) {
1525                 ERR("Unable to create node: %s", err->message);
1526                 g_clear_error(&err);
1527         }
1528         return node_info;
1529 }
1530
1531 static gboolean __bt_map_dbus_init(void)
1532 {
1533         guint owner_id;
1534         guint map_id;
1535         GDBusNodeInfo *node_info;
1536         GError *error = NULL;
1537         GDBusConnection *gdbus_conn = __bt_map_get_gdbus_connection();
1538
1539         if (gdbus_conn == NULL) {
1540                 ERR("Error in creating the gdbus connection");
1541                 return FALSE;
1542         }
1543
1544         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1545                         BT_MAP_SERVICE_NAME,
1546                         G_BUS_NAME_OWNER_FLAGS_NONE,
1547                         NULL, NULL, NULL,
1548                         NULL, NULL);
1549         DBG("owner_id is [%d]", owner_id);
1550
1551         node_info = __bt_map_create_method_node_info(
1552                         map_agent_introspection_xml);
1553         if (node_info == NULL)
1554                 return FALSE;
1555
1556         map_id = g_dbus_connection_register_object(gdbus_conn, BT_MAP_SERVICE_OBJECT_PATH,
1557                                         node_info->interfaces[0],
1558                                         &method_table,
1559                                         NULL, NULL, &error);
1560
1561         g_dbus_node_info_unref(node_info);
1562
1563         if (map_id == 0) {
1564                 ERR("Failed to register: %s", error->message);
1565                 g_error_free(error);
1566                 return FALSE;
1567         }
1568
1569         return TRUE;
1570 }
1571
1572 int main(void)
1573 {
1574         FN_START;
1575         int ret;
1576         DBG("Starting Bluetooth MAP agent");
1577
1578         //g_type_init();
1579
1580         g_mainloop = g_main_loop_new(NULL, FALSE);
1581
1582         if (g_mainloop == NULL) {
1583                 ERR("Couldn't create GMainLoop\n");
1584                 return EXIT_FAILURE;
1585         }
1586
1587         if (__bt_map_dbus_init() == FALSE)
1588                 goto failure;
1589
1590         if (__bluetooth_map_start_service() == FALSE)
1591                 goto failure;
1592
1593         g_tapi_handle = tel_init(NULL);
1594         if (!g_tapi_handle)
1595                 goto failure;
1596
1597         ret = tel_get_sms_sca(g_tapi_handle, 0, __bt_get_sms_sca, NULL);
1598         if (ret != TAPI_API_SUCCESS) {
1599                 ERR("TAPI err = %d", ret);
1600                 goto failure;
1601         }
1602
1603         g_main_loop_run(g_mainloop);
1604
1605  failure:
1606
1607         __bt_remove_list(id_list);
1608
1609         tel_deinit(g_tapi_handle);
1610         g_free(g_sca_info);
1611
1612         __bt_mns_client_disconnect();
1613
1614         if (map_dbus_conn)
1615                 g_object_unref(map_dbus_conn);
1616
1617         _bt_map_stop_sms_service();
1618         _bt_map_stop_email_service();
1619
1620         DBG("Bluetooth MAP agent Terminated successfully\n");
1621         FN_END;
1622         return EXIT_FAILURE;
1623 }
1624 /* LCOV_EXCL_STOP */