Fix 64bit dlog format error
[platform/core/connectivity/bluetooth-agent.git] / map-agent / bluetooth_map_sms.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  *               Syam Sidhardhan <s.syam@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 <bluetooth_map_agent.h>
25 #include <map_bmessage.h>
26
27 /*Messaging Header Files*/
28 #include "msg.h"
29 #include "msg_storage.h"
30 #include "msg_storage_types.h"
31 #include "msg_transport.h"
32 #include "msg_transport_types.h"
33 #include "msg_types.h"
34
35 #include <glib.h>
36
37 #define BT_MAP_STATUS_CB "sent status callback"
38 #define BT_MAP_MSG_CB "sms message callback"
39 #define BT_MAP_DELETED_FOLDER_NAME "DELETED"
40 #define BT_MAP_SENT_FOLDER_NAME "SENT"
41 #define BT_MAP_MSG_TEMPLATE "TEMPLATE"
42
43 #define BT_MAP_MSG_INFO_MAX 256
44 #define BT_MAP_MSG_HANDLE_MAX 21
45 #define BT_MAP_TIMESTAMP_MAX_LEN 16
46 #define BT_MAP_MSG_BODY_MAX 1024
47
48 #define BEGIN_BMSEG "BEGIN:BMSG\r\n"
49 #define END_BMSEG "END:BMSG\r\n"
50 #define BMSEG_VERSION "VERSION:1.0\r\n"
51 #define MSEG_STATUS "STATUS:%s\r\n"
52 #define MSEG_TYPE "TYPE:%s\r\n"
53 #define FOLDER_PATH "FOLDER:%s\r\n"
54 #define VCARD "BEGIN:VCARD\r\nVERSION:2.1\r\nN:%s\r\nTEL:%s\r\nEND:VCARD\r\n"
55 #define BEGIN_BENV "BEGIN:BENV\r\n"
56 #define END_BENV "END:BENV\r\n"
57 #define BEGIN_BBODY "BEGIN:BBODY\r\n"
58 #define END_BBODY "END:BBODY\r\n"
59 #define ENCODING "ENCODING:%s\r\n"
60 #define CHARSET "CHARSET:%s\r\n"
61 #define LANGUAGE "LANGUAGE:%s\r\n"
62 #define LENGTH "LENGTH:%d\r\n"
63 #define MSG_BODY "BEGIN:MSG\r\n%s\r\nEND:MSG\r\n"
64 #define MSG_BODY_BEGIN "BEGIN:MSG\r\n"
65 #define MSG_BODY_END "\r\nEND:MSG\r\n"
66
67 static msg_handle_t g_msg_handle = NULL;
68 extern guint64 current_push_map_id;
69
70 static int __bt_get_sms_folder_id(char *folder_path)
71 {
72         FN_START;
73         int folder_id = -1;
74         int i;
75         char *folder;
76         msg_struct_list_s folder_list = {0,};
77         msg_error_t err;
78         msg_struct_t p_folder;
79         DBG_SECURE("folder_path %s\n", folder_path);
80
81         folder = strrchr(folder_path, '/');
82         if (NULL == folder)
83                 folder = folder_path;
84         else
85                 folder++;
86
87         err = msg_get_folder_list(g_msg_handle, &folder_list);
88         if (err != MSG_SUCCESS)
89                 goto done;
90
91         for (i = 0; i < folder_list.nCount; i++) {
92                 char folder_name[BT_MAP_MSG_INFO_MAX] = {0, };
93
94                 p_folder = folder_list.msg_struct_info[i];
95
96                 err = msg_get_str_value(p_folder, MSG_FOLDER_INFO_NAME_STR,
97                                         folder_name, BT_MAP_MSG_INFO_MAX);
98                 if (err != MSG_SUCCESS)
99                         continue;
100
101                 DBG_SECURE("folder_name %s\n", folder_name);
102                 if (!g_ascii_strncasecmp(folder_name, folder, strlen(folder))) {
103                         err = msg_get_int_value(p_folder,
104                                         MSG_FOLDER_INFO_ID_INT,
105                                         &folder_id);
106                         if (err != MSG_SUCCESS)
107                                 goto done;
108
109                         DBG("folder_id %d", folder_id);
110                         break;
111                 }
112         }
113
114 done:
115         if (folder_list.msg_struct_info)
116                 msg_release_list_struct(&folder_list);
117
118         FN_END;
119         return folder_id;
120
121 }
122
123
124 static void __bt_add_deleted_folder(void)
125 {
126         FN_START;
127         msg_error_t err;
128         msg_struct_t folder_info = msg_create_struct(MSG_STRUCT_FOLDER_INFO);
129
130         err = msg_set_int_value(folder_info, MSG_FOLDER_INFO_TYPE_INT,
131                                                 MSG_FOLDER_TYPE_USER_DEF);
132         if (err != MSG_SUCCESS) {
133                 /* LCOV_EXCL_START */
134                 ERR("Failed adding type %d", err);
135                 msg_release_struct(&folder_info);
136                 return;
137                 /* LCOV_EXCL_STOP */
138         }
139
140         err = msg_set_str_value(folder_info, MSG_FOLDER_INFO_NAME_STR,
141                                         "DELETED", MAX_FOLDER_NAME_SIZE);
142         if (err != MSG_SUCCESS) {
143                 /* LCOV_EXCL_START */
144                 ERR("Failed adding str %d", err);
145                 msg_release_struct(&folder_info);
146                 return;
147                 /* LCOV_EXCL_STOP */
148         }
149
150         err = msg_add_folder(g_msg_handle, folder_info);
151         if (err != MSG_SUCCESS) {
152                 /* LCOV_EXCL_START */
153                 ERR("Failed adding folder %d", err);
154                 msg_release_struct(&folder_info);
155                 return;
156                 /* LCOV_EXCL_STOP */
157         }
158
159         msg_release_struct(&folder_info);
160         FN_END;
161 }
162
163 /* LCOV_EXCL_START */
164 static void __bluetooth_map_msg_incoming_status_cb(msg_handle_t handle,
165                                                         msg_struct_t msg,
166                                                         void *user_param)
167 {
168         FN_START;
169         int msg_id = 0;
170         int msg_type = 0;
171         int ret;
172
173         guint64 uid;
174
175         if (is_mns_connected() == FALSE) {
176                 INFO("MNS Client not connected");
177                 return;
178         }
179
180         ret = msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &msg_type);
181         if (ret != MSG_SUCCESS)
182                 return;
183
184         if (msg_type != MSG_TYPE_SMS) {
185                 INFO("Not a SMS");
186                 return;
187         }
188
189         ret = msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &msg_id);
190         if (ret != MSG_SUCCESS)
191                 return;
192
193         uid = _bt_add_id(msg_id, BT_MAP_ID_SMS);
194
195         _bt_mns_client_event_notify("NewMessage", uid,
196                                                 "TELECOM/MSG/INBOX", "",
197                                                 "SMS_GSM");
198
199         FN_END;
200 }
201
202 static void __bluetooth_map_msg_sent_status_cb(msg_handle_t handle,
203                                                         msg_struct_t msg,
204                                                         void *user_param)
205 {
206         FN_START;
207         int ret;
208         int status;
209
210         if (is_mns_connected() == FALSE) {
211                 INFO("MNS Client not connected");
212                 return;
213         }
214
215         ret = msg_get_int_value(msg, MSG_SENT_STATUS_NETWORK_STATUS_INT,
216                                                                 &status);
217         if (ret != MSG_SUCCESS)
218                 return;
219
220         if (status == MSG_NETWORK_SEND_SUCCESS) {
221                 INFO("MSG SENT SUCCESS !!! ");
222                 _bt_mns_client_event_notify("MessageShift",
223                                         current_push_map_id,
224                                         "TELECOM/MSG/SENT",
225                                         "TELECOM/MSG/OUTBOX",
226                                         "SMS_GSM");
227
228                 _bt_mns_client_event_notify("SendingSuccess",
229                                         current_push_map_id,
230                                         "TELECOM/MSG/SENT", "",
231                                         "SMS_GSM");
232         } else {
233                 ERR("MSG SENT FAIL !!! [%d]", status);
234                 _bt_mns_client_event_notify("SendingFailure",
235                                         current_push_map_id,
236                                         "TELECOM/MSG/OUTBOX", "",
237                                         "SMS_GSM");
238         }
239
240         FN_END;
241 }
242 /* LCOV_EXCL_STOP */
243
244 gboolean _bt_map_sms_get_supported_folders(gboolean folders[FOLDER_COUNT][MSG_TYPES])
245 {
246         FN_START;
247         char folder_name[BT_MAP_MSG_INFO_MAX] = {0,};
248         int i;
249         int ret;
250         gboolean msg_ret = TRUE;
251
252         msg_struct_list_s folder_list = {0,};
253         msg_struct_t p_folder;
254
255         if (g_msg_handle == NULL) {
256                 msg_ret = FALSE;
257                 goto done;
258         }
259
260         /* LCOV_EXCL_START */
261         if (msg_get_folder_list(g_msg_handle, &folder_list) != MSG_SUCCESS) {
262                 msg_ret = FALSE;
263                 goto done;
264         }
265
266         for (i = 0; i < folder_list.nCount; i++) {
267                 p_folder = folder_list.msg_struct_info[i];
268                 memset(folder_name, 0x00, BT_MAP_MSG_INFO_MAX);
269
270                 ret = msg_get_str_value(p_folder, MSG_FOLDER_INFO_NAME_STR,
271                                         folder_name, BT_MAP_MSG_INFO_MAX);
272                 if (ret != MSG_SUCCESS)
273                         continue;
274
275                 DBG("%d. %s", i, folder_name);
276                 if (g_strstr_len(folder_name, -1, BT_MAP_MSG_TEMPLATE) ||
277                                 g_strstr_len(folder_name, -1, "CBMSGBOX") ||
278                                 g_strstr_len(folder_name, -1, "SPAMBOX"))
279                         continue;
280
281                 if (!g_ascii_strncasecmp(folder_name, BT_MAP_SENT_FOLDER_NAME,
282                                         strlen(BT_MAP_SENT_FOLDER_NAME))) {
283                         memset(folder_name, 0, sizeof(folder_name));
284                         g_strlcpy(folder_name, BT_MAP_SENT_FOLDER_NAME,
285                                                         sizeof(folder_name));
286                         folders[BT_MSG_SENT][BT_MSG_SOURCE_SMS] = TRUE;
287                         DBG("SENT");
288                 } else if (!g_ascii_strcasecmp(folder_name, "INBOX")) {
289                         folders[BT_MSG_INBOX][BT_MSG_SOURCE_SMS] = TRUE;
290                         DBG("INBOX");
291                 } else if (!g_ascii_strcasecmp(folder_name, "OUTBOX")) {
292                         folders[BT_MSG_OUTBOX][BT_MSG_SOURCE_SMS] = TRUE;
293                         DBG("OUTBOX");
294                 } else if (!g_ascii_strcasecmp(folder_name, "DRAFT")) {
295                         folders[BT_MSG_DRAFT][BT_MSG_SOURCE_SMS] = TRUE;
296                         DBG("DRAFT");
297                 } else if (!g_ascii_strcasecmp(folder_name, "DELETED")) {
298                         folders[BT_MSG_DELETED][BT_MSG_SOURCE_SMS] = TRUE;
299                         DBG("DELETED");
300                 }
301         }
302         /* LCOV_EXCL_STOP */
303
304 done:
305
306         if (folder_list.msg_struct_info)
307                 msg_release_list_struct(&folder_list); /* LCOV_EXCL_LINE */
308
309         FN_END;
310         return msg_ret;
311 }
312
313 gboolean _bt_map_sms_set_read_status(int msg_id, gboolean read_status)
314 {
315         FN_START;
316         msg_error_t msg_err;
317
318         msg_err = msg_update_read_status(g_msg_handle, msg_id,
319                                                         read_status);
320         if (msg_err != MSG_SUCCESS) {
321                 ERR("Failed to Set Read Status");
322                 return FALSE;
323
324         }
325         FN_END;
326         return TRUE;
327 }
328
329 /* LCOV_EXCL_START */
330 static gchar *__bt_get_sms_folder_name(int id)
331 {
332         FN_START;
333         int ret;
334         int i;
335         int folder_id;
336         gboolean path_found = FALSE;
337         char folder_name[BT_MAP_MSG_INFO_MAX] = {0,};
338
339         msg_struct_list_s folder_list = {0,};
340         msg_struct_t p_folder;
341
342         ret = msg_get_folder_list(g_msg_handle, &folder_list);
343         if (ret != MSG_SUCCESS)
344                 return g_strdup("TELECOM/MSG");
345
346         if (folder_list.msg_struct_info == NULL)
347                 return g_strdup("TELECOM/MSG");
348
349         for (i = 0; i < folder_list.nCount; i++) {
350                 p_folder = folder_list.msg_struct_info[i];
351
352                 ret = msg_get_int_value(p_folder,
353                                         MSG_FOLDER_INFO_ID_INT,
354                                         &folder_id);
355                 if (ret != MSG_SUCCESS)
356                         break;
357                 DBG("folder_id %d, id = %d", folder_id, id);
358                 if (folder_id == id) {
359                         ret = msg_get_str_value(p_folder,
360                                         MSG_FOLDER_INFO_NAME_STR,
361                                         folder_name, BT_MAP_MSG_INFO_MAX);
362                         if (ret != MSG_SUCCESS)
363                                 break;
364
365                         path_found = TRUE;
366                         DBG_SECURE("folder_name %s", folder_name);
367                         break;
368                 }
369         }
370
371         if (folder_list.msg_struct_info) {
372                 ret = msg_release_list_struct(&folder_list);
373                 ERR("Err %d", ret);
374         }
375
376         FN_END;
377         if (path_found != TRUE)
378                 return g_strdup("TELECOM/MSG");
379         else
380                 return g_strdup_printf("TELECOM/MSG/%s", folder_name);
381 }
382 /* LCOV_EXCL_STOP */
383
384 gboolean _bt_map_set_sms_delete_status(int msg_id, gboolean delete_status)
385 {
386         FN_START;
387         int folder_id;
388         int del_folder_id;
389         int err;
390         gchar *folder_name = NULL;
391         guint64 map_id;
392         msg_struct_t msg = NULL;
393         msg_struct_t send_opt = NULL;
394
395
396         if (msg_id == -1)
397                 goto fail;
398
399         /* LCOV_EXCL_START */
400         if (g_msg_handle == NULL)
401                 goto fail;
402
403         msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
404         if (msg == NULL)
405                 goto fail;
406
407         send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
408         if (send_opt == NULL)
409                 goto fail;
410
411         err = msg_get_message(g_msg_handle,
412                                         (msg_message_id_t)msg_id,
413                                         msg, send_opt);
414         if (err != MSG_SUCCESS)
415                 goto fail;
416
417         err = msg_get_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT,
418                                                         &folder_id);
419         if (err != MSG_SUCCESS)
420                 goto fail;
421
422         folder_name = __bt_get_sms_folder_name(folder_id);
423         del_folder_id = __bt_get_sms_folder_id(BT_MAP_DELETED_FOLDER_NAME);
424         map_id = _bt_validate_uid(msg_id, BT_MAP_ID_SMS);
425
426         DBG("msg_id = %d, delete_status = %d\n", msg_id, delete_status);
427
428         if (del_folder_id == -1) {
429                 ERR("Delete folder not present");
430                 if (delete_status == TRUE) {
431                         err = msg_delete_message(g_msg_handle, msg_id);
432                         if (err != MSG_SUCCESS)
433                                 goto fail;
434                 }
435         } else {
436                 if (delete_status == TRUE) {
437                         err = msg_move_msg_to_folder(g_msg_handle, msg_id, del_folder_id);
438                         if (err == MSG_SUCCESS) {
439                                 _bt_mns_client_event_notify("MessageShift",
440                                                 map_id,
441                                                 "TELECOM/MSG/DELETED",
442                                                 folder_name,
443                                                 "SMS_GSM");
444                         }
445                 } else {
446                         if (folder_id != del_folder_id) {
447                                 DBG("Message not in delete folder");
448                                 goto fail;
449                         }
450
451                         err = msg_move_msg_to_folder(g_msg_handle, msg_id, MSG_INBOX_ID);
452                         if (err == MSG_SUCCESS) {
453                                 _bt_mns_client_event_notify("MessageShift",
454                                                 map_id,
455                                                 "TELECOM/MSG/INBOX",
456                                                 "TELECOM/MSG/DELETED",
457                                                 "SMS_GSM");
458                         }
459                 }
460         }
461
462         g_free(folder_name);
463         msg_release_struct(&msg);
464         msg_release_struct(&send_opt);
465
466         FN_END;
467         return TRUE;
468         /* LCOV_EXCL_STOP */
469
470 fail:
471         g_free(folder_name);
472
473         msg_release_struct(&msg);
474         msg_release_struct(&send_opt);
475
476         ERR("Failed to Delete SMS");
477         return FALSE;
478 }
479
480 /* LCOV_EXCL_START */
481 static msg_error_t __bt_send_sms(int msg_id, msg_struct_t p_msg, msg_struct_t p_send_opt)
482 {
483         FN_START;
484         msg_error_t err;
485         msg_struct_t p_req;
486
487         p_req = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
488
489         msg_set_int_value(p_msg, MSG_MESSAGE_ID_INT, msg_id);
490         msg_set_struct_handle(p_req, MSG_REQUEST_MESSAGE_HND, p_msg);
491         msg_set_struct_handle(p_req, MSG_REQUEST_SENDOPT_HND, p_send_opt);
492
493         err = msg_sms_send_message(g_msg_handle, p_req);
494         if (err != MSG_SUCCESS)
495                 ERR("Failed msg_sms_send_message %d", err);
496
497         msg_release_struct(&p_req);
498         FN_END;
499         return err;
500 }
501
502 static int __bt_push_sms(gboolean send, int folder_id, char *body,
503                 GSList *recepients, msg_send_option_t *option)
504 {
505         FN_START;
506         msg_struct_t msg_info = NULL;
507         msg_struct_t send_opt = NULL;
508         msg_error_t err;
509
510         int msg_id = -1;
511
512         msg_info = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
513         if (msg_info == NULL)
514                 goto fail;
515
516         err = msg_set_int_value(msg_info, MSG_MESSAGE_TYPE_INT, MSG_TYPE_SMS);
517         if (err != MSG_SUCCESS)
518                 goto fail;
519
520         if (body) {
521                 err = msg_set_str_value(msg_info,
522                                         MSG_MESSAGE_SMS_DATA_STR,
523                                         body, strlen(body));
524                 if (err != MSG_SUCCESS)
525                         goto fail;
526         } else {
527                 err = msg_set_str_value(msg_info, MSG_MESSAGE_SMS_DATA_STR,
528                                                                 NULL, 0);
529                 if (err != MSG_SUCCESS)
530                         goto fail;
531         }
532
533         DBG("folder_id  %d\n", folder_id);
534         err = msg_set_int_value(msg_info, MSG_MESSAGE_FOLDER_ID_INT,
535                                                                 folder_id);
536         if (err != MSG_SUCCESS)
537                 goto fail;
538
539         while (recepients) {
540                 msg_struct_t tmp_addr;
541                 char *address = recepients->data;
542                 if (address == NULL) {
543                         ERR("[ERROR] address is value NULL, skip");
544                         recepients = g_slist_next(recepients);
545                         continue;
546                 }
547
548                 msg_list_add_item(msg_info,
549                                 MSG_MESSAGE_ADDR_LIST_HND, &tmp_addr);
550
551                 msg_set_int_value(tmp_addr,
552                                 MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
553                                 MSG_RECIPIENTS_TYPE_TO);
554
555                 msg_set_str_value(tmp_addr,
556                                 MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
557                                 address, strlen(address));
558
559                 recepients = g_slist_next(recepients);
560         }
561
562         send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
563
564         err = msg_set_bool_value(send_opt, MSG_SEND_OPT_SETTING_BOOL, true);
565         if (err != MSG_SUCCESS)
566                 goto fail;
567
568         /* Do not keep a copy
569         err = msg_set_bool_value(send_opt, MSG_SEND_OPT_KEEPCOPY_BOOL,
570                         option->save_copy);
571         */
572         err = msg_set_bool_value(send_opt, MSG_SEND_OPT_KEEPCOPY_BOOL,
573                         true);
574         if (err != MSG_SUCCESS)
575                 goto fail;
576
577         msg_id = msg_add_message(g_msg_handle, msg_info, send_opt);
578         DBG("msg_id = %d\n", msg_id);
579
580         if (send == TRUE)
581                 __bt_send_sms(msg_id, msg_info, send_opt);
582
583
584 fail:
585         msg_release_struct(&msg_info);
586         msg_release_struct(&send_opt);
587         FN_END;
588         return msg_id;
589 }
590
591 gboolean _bt_map_push_sms_data(struct bmsg_data *bmsg_info,
592                 msg_send_option_t *option, char *folder)
593 {
594         FN_START;
595         int id = -1;
596         int folder_id;
597         char *body = NULL;
598         GSList *recepients = NULL;
599         gboolean send = FALSE;
600
601         DBG("Length of Folder String: %zd", strlen(bmsg_info->folder));
602         if (strlen(bmsg_info->folder) == 0) {
603                 DBG("No Folder Info. Default to OUTBOX");
604                 bmsg_info->folder = g_strdup(folder);
605         }
606
607         folder_id = __bt_get_sms_folder_id(bmsg_info->folder);
608         if (folder_id == -1)
609                 goto done;
610
611         if (folder_id == MSG_OUTBOX_ID)
612                 send = TRUE;
613
614         body = bmsg_get_msg_body(bmsg_info, option->native);
615         if (body == NULL)
616                 goto done;
617
618         recepients = bmsg_get_msg_recepients(bmsg_info, BT_MAP_ID_SMS);
619
620         id = __bt_push_sms(send, folder_id, body, recepients, option);
621         if (id == -1)
622                 goto done;
623
624         _bt_update_id(current_push_map_id, id, BT_MAP_ID_SMS);
625
626 done:
627         g_free(body);
628         g_slist_free(recepients);
629
630         if (id == -1) {
631                 FN_END;
632                 return FALSE;
633         }
634
635         FN_END;
636         return TRUE;
637 }
638
639
640 static char *__bt_prepare_msg_bmseg(msg_struct_t msg_info, gboolean attach,
641                                                         gboolean transcode)
642 {
643         FN_START;
644         int ret;
645         int m_type = MSG_TYPE_SMS;
646         int folder_id;
647         int count;
648         int dptime = 0;
649         int j;
650         bool read_status = false;
651         char msg_body[BT_MAP_MSG_BODY_MAX] = {0,};
652         char addr_value[MAX_ADDRESS_VAL_LEN] = {0,};
653         char name_value[MAX_DISPLAY_NAME_LEN] = {0,};
654
655         msg_list_handle_t addr_list = NULL;
656         msg_struct_t addr_info = NULL;
657
658         GString *msg;
659         gchar *folder_path = NULL;
660         gchar *msg_pdu;
661
662         msg = g_string_new(BEGIN_BMSEG);
663         g_string_append(msg, BMSEG_VERSION);
664
665         ret = msg_get_bool_value(msg_info, MSG_MESSAGE_READ_BOOL, &read_status);
666         if (ret == MSG_SUCCESS)
667                 INFO("read_status %d\n", read_status);
668
669         if (read_status)
670                 g_string_append_printf(msg, MSEG_STATUS, "READ");
671         else
672                 g_string_append_printf(msg, MSEG_STATUS, "UNREAD");
673
674         ret = msg_get_int_value(msg_info, MSG_MESSAGE_TYPE_INT, &m_type);
675         if (ret == MSG_SUCCESS) {
676                 INFO("m_type %d\n", m_type);
677                  g_string_append_printf(msg, MSEG_TYPE, "SMS_GSM");
678         }
679
680         ret = msg_get_int_value(msg_info, MSG_MESSAGE_FOLDER_ID_INT,
681                                                         &folder_id);
682         if (ret == MSG_SUCCESS) {
683                 DBG("folder_id %d\n", folder_id);
684
685                 folder_path = __bt_get_sms_folder_name(folder_id);
686                 g_string_append_printf(msg, FOLDER_PATH, folder_path);
687         }
688
689         ret = msg_get_list_handle(msg_info, MSG_MESSAGE_ADDR_LIST_HND,
690                                                 (void **)&addr_list);
691         if (ret == MSG_SUCCESS) {
692                 count = msg_list_length(addr_list);
693                 DBG("count %d \n", count);
694
695                 if (count > 0) {
696                         addr_info = (msg_struct_t)msg_list_nth_data(addr_list,
697                                                                         0);
698
699                         msg_get_str_value(addr_info,
700                                         MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
701                                         addr_value, MAX_ADDRESS_VAL_LEN);
702                         DBG_SECURE("addr_value %s\n", addr_value);
703                         msg_get_str_value(addr_info,
704                                         MSG_ADDRESS_INFO_DISPLAYNAME_STR,
705                                         name_value, MAX_DISPLAY_NAME_LEN);
706                         if (!strlen(name_value))
707                                 g_stpcpy(name_value, addr_value);
708
709                         DBG_SECURE("name_value %s\n", name_value);
710
711                         g_string_append_printf(msg, VCARD, name_value,
712                                                                 addr_value);
713                 }
714         }
715
716         g_string_append(msg, BEGIN_BENV);
717         g_string_append(msg, BEGIN_BBODY);
718
719         if (transcode) {
720                 g_string_append_printf(msg, CHARSET, "UTF-8");
721
722
723                 ret = msg_get_str_value(msg_info,
724                                         MSG_MESSAGE_SMS_DATA_STR,
725                                         msg_body, BT_MAP_MSG_BODY_MAX);
726                 if (ret == MSG_SUCCESS) {
727 #ifdef ARCH64
728                         g_string_append_printf(msg, LENGTH, (int)(unsigned int)strlen(msg_body));
729 #else
730                         g_string_append_printf(msg, LENGTH, strlen(msg_body));
731 #endif
732                         g_string_append_printf(msg, MSG_BODY, msg_body);
733                 }
734         } else {
735                 g_string_append_printf(msg, ENCODING, "G-7BIT");
736                 g_string_append_printf(msg, CHARSET, "native");
737
738                 msg_get_int_value(msg_info,
739                                 MSG_MESSAGE_DISPLAY_TIME_INT, &dptime);
740
741                 ret = msg_get_str_value(msg_info, MSG_MESSAGE_SMS_DATA_STR,
742                                         msg_body, BT_MAP_MSG_BODY_MAX);
743                 if (ret == MSG_SUCCESS) {
744                         int msg_pdu_len = 0;
745                         msg_pdu = _bt_get_sms_pdu_from_msg_data(addr_value,
746                                                         msg_body, dptime,
747                                                         &msg_pdu_len);
748                         if (msg_pdu) {
749                                 DBG("msg_pdu_len = %d", msg_pdu_len);
750
751                                 g_string_append_printf(msg, LENGTH, msg_pdu_len);
752                                 g_string_append(msg, MSG_BODY_BEGIN);
753                                 for (j = 0; j < msg_pdu_len; j++)
754                                         g_string_append_printf(msg, "%02x",
755                                                                         msg_pdu[j]);
756
757                                 g_string_append(msg, MSG_BODY_END);
758                                 g_free(msg_pdu);
759                         }
760                 }
761         }
762
763         g_string_append(msg, END_BBODY);
764         g_string_append(msg, END_BENV);
765         g_string_append(msg, END_BMSEG);
766         g_free(folder_path);
767
768         FN_END;
769         return g_string_free(msg, FALSE);
770 }
771 /* LCOV_EXCL_STOP */
772
773 gboolean _bt_map_get_sms_message(int message_id, gboolean attach,
774                 gboolean transcode, gboolean first_request, gchar **bmseg)
775 {
776         FN_START;
777         msg_error_t msg_err;
778         msg_struct_t msg = NULL;
779         msg_struct_t send_opt = NULL;
780
781         DBG("message_id %d \n", message_id);
782         DBG("attach %d \n", attach);
783         DBG("transcode %d \n", transcode);
784         DBG("first_request %d \n", first_request);
785
786         if (g_msg_handle == NULL)
787                 goto fail;
788
789         msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
790         if (!msg)
791                 goto fail;
792
793         /* LCOV_EXCL_START */
794         send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
795         if (!send_opt)
796                 goto fail;
797
798         msg_err = msg_get_message(g_msg_handle,
799                                         (msg_message_id_t)message_id,
800                                         msg, send_opt);
801         if (msg_err != MSG_SUCCESS)
802                 goto fail;
803
804         *bmseg = __bt_prepare_msg_bmseg(msg, attach, transcode);
805         msg_release_struct(&msg);
806         msg_release_struct(&send_opt);
807
808         FN_END;
809         return TRUE;
810         /* LCOV_EXCL_STOP */
811
812 fail:
813
814         if (msg)
815                 msg_release_struct(&msg); /* LCOV_EXCL_LINE */
816
817         if (send_opt)
818                 msg_release_struct(&send_opt); /* LCOV_EXCL_LINE */
819
820         ERR("Unable to Get SMS Message");
821         return FALSE;
822 }
823
824 /* LCOV_EXCL_START */
825 static char *__bt_get_truncated_utf8_string(char *src)
826 {
827         FN_START;
828         char *p = src;
829         char *next;
830         char dest[BT_MAP_SUBJECT_MAX_LEN] = {0,};
831         int count;
832         int i = 0;
833
834         if (src == NULL)
835                 return NULL;
836
837         while (*p != '\0' && i < sizeof(dest)) {
838                 next = g_utf8_next_char(p);
839                 count = next - p;
840
841                 while (count > 0 && ((i + count) < sizeof(dest))) {
842                         dest[i++] = *p;
843                         p++;
844                         count--;
845                 }
846                 p = next;
847         }
848
849         FN_END;
850         return g_strdup(dest);
851 }
852
853
854 static message_info_t *__bt_message_info_get(msg_struct_t msg_struct_handle,
855                                                         guint8 subject_len)
856 {
857         FN_START;
858         message_info_t *msg_info = NULL;
859         int ret;
860         int msg_id;
861         guint64 uid;
862         time_t dptime;
863         int m_type = 0;
864         int data_size;
865         int priority;
866         int direction_type;
867         int count;
868         bool protect_status = 0;
869         bool read_status = 0;
870
871         char msg_handle[BT_MAP_MSG_HANDLE_MAX] = {0,};
872         char msg_datetime[BT_MAP_TIMESTAMP_MAX_LEN] = {0,};
873         char msg_size[5] = {0,};
874         char msg_body[BT_MAP_MSG_BODY_MAX] = {0,};
875         char addr_value[MAX_ADDRESS_VAL_LEN] = {0,};
876         char name_value[MAX_DISPLAY_NAME_LEN] = {0,};
877
878         msg_info = g_new0(message_info_t, 1);
879         msg_info->text = FALSE;
880         msg_info->protect = FALSE;
881         msg_info->read = FALSE;
882         msg_info->priority = FALSE;
883
884         msg_struct_t msg = NULL;
885         msg_struct_t send_opt = NULL;
886         msg_list_handle_t addr_list = NULL;
887         msg_struct_t addr_info = NULL;
888
889         ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_ID_INT, &msg_id);
890         if (ret != MSG_SUCCESS)
891                 ERR("Could not get Message ID");
892
893         uid = _bt_add_id(msg_id, BT_MAP_ID_SMS);
894 #ifdef ARCH64
895         snprintf(msg_handle, sizeof(msg_handle), "%lx", uid);
896 #else
897         snprintf(msg_handle, sizeof(msg_handle), "%llx", uid);
898 #endif
899         DBG("HANDLE: %s, MAP Id: %llu, MSG ID:%d", msg_handle, (unsigned long long int)uid, msg_id);
900         msg_info->handle = g_strdup(msg_handle);
901
902         msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
903         if (msg == NULL)
904                 goto next;
905
906         send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
907         if (send_opt == NULL)
908                 goto next;
909
910         ret = msg_get_message(g_msg_handle,
911                                                 (msg_message_id_t)msg_id,
912                                                 msg, send_opt);
913         if (ret != MSG_SUCCESS) {
914                 DBG("ret = %d\n", ret);
915                 goto next;
916         }
917
918         ret = msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND,
919                                                         (void **)&addr_list);
920         if (ret != MSG_SUCCESS) {
921                 DBG("ret = %d\n", ret);
922                 goto next;
923         }
924
925         count = msg_list_length(addr_list);
926
927         if (count != 0) {
928                 addr_info = (msg_struct_t)msg_list_nth_data(addr_list, 0);
929
930                 ret = msg_get_str_value(addr_info,
931                                         MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
932                                         addr_value, MAX_ADDRESS_VAL_LEN);
933                 if (ret == MSG_SUCCESS)
934                         DBG_SECURE("addr_value %s\n", addr_value);
935
936                 ret = msg_get_str_value(addr_info,
937                                         MSG_ADDRESS_INFO_DISPLAYNAME_STR,
938                                         name_value, MAX_DISPLAY_NAME_LEN);
939
940                 if (ret == MSG_SUCCESS)
941                         DBG_SECURE("name_value %s\n", name_value);
942
943                 if (!strlen(name_value))
944                         g_stpcpy(name_value, addr_value);
945
946                 DBG_SECURE("name_value %s\n", name_value);
947         }
948
949         ret = msg_get_int_value(msg, MSG_MESSAGE_DIRECTION_INT,
950                                                 &direction_type);
951         if (ret != MSG_SUCCESS)
952                 goto next;
953
954         if (direction_type == MSG_DIRECTION_TYPE_MT) {
955                 msg_info->sender_name = g_strdup(name_value);
956                 msg_info->sender_addressing = g_strdup(addr_value);
957                 msg_info->recipient_name = g_strdup("Unknown");
958                 msg_info->recipient_addressing = g_strdup("0000");
959         } else {
960                 msg_info->sender_name = g_strdup("Unknown");
961                 msg_info->sender_addressing = g_strdup("0000");
962                 msg_info->recipient_name = g_strdup(name_value);
963                 msg_info->recipient_addressing = g_strdup(addr_value);
964         }
965
966 next:
967         msg_release_struct(&msg);
968         msg_release_struct(&send_opt);
969
970         ret = msg_get_int_value(msg_struct_handle,
971                                 MSG_MESSAGE_DISPLAY_TIME_INT, (int *)&dptime);
972         if (ret == MSG_SUCCESS)
973                 _get_msg_timestamp(&dptime, msg_datetime);
974
975         DBG("Got date time: %s", msg_datetime);
976
977         msg_info->datetime = g_strdup(msg_datetime);
978         msg_info->time = dptime; // for sorting
979
980         ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_TYPE_INT,
981                                                                 &m_type);
982         if (ret == MSG_SUCCESS)
983                 DBG("m_type %d\n", m_type);
984
985         msg_info->type = g_strdup("SMS_GSM");
986
987         ret = msg_get_str_value(msg_struct_handle,
988                                 MSG_MESSAGE_SMS_DATA_STR, msg_body,
989                                 BT_MAP_MSG_BODY_MAX);
990         if (ret == MSG_SUCCESS) {
991                 DBG_SECURE("SMS subject %s", msg_body);
992                 if (strlen(msg_body)) {
993                         char *subject;
994                         msg_info->text = TRUE;
995                         subject = __bt_get_truncated_utf8_string(msg_body);
996                         msg_info->subject = g_strndup(subject, subject_len);
997                         g_free(subject);
998                 }
999         }
1000
1001         ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_DATA_SIZE_INT,
1002                                                                 &data_size);
1003         if (ret == MSG_SUCCESS)
1004                 snprintf(msg_size, sizeof(msg_size), "%d", data_size);
1005
1006         msg_info->size = g_strdup(msg_size);
1007
1008         msg_info->reception_status = g_strdup("complete");
1009         msg_info->attachment_size = g_strdup("0");
1010
1011         ret = msg_get_bool_value(msg_struct_handle, MSG_MESSAGE_PROTECTED_BOOL,
1012                                                         &protect_status);
1013         if (ret == MSG_SUCCESS) {
1014                 if (protect_status)
1015                         msg_info->protect = TRUE;
1016         }
1017
1018         ret = msg_get_bool_value(msg_struct_handle, MSG_MESSAGE_READ_BOOL,
1019                                                                 &read_status);
1020         if (ret == MSG_SUCCESS) {
1021                 if (read_status)
1022                         msg_info->read = TRUE;
1023         }
1024
1025         ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_PRIORITY_INT,
1026                                                                 &priority);
1027         if (ret == MSG_SUCCESS) {
1028                 if (priority == MSG_MESSAGE_PRIORITY_HIGH)
1029                         msg_info->priority = TRUE;
1030         }
1031
1032         FN_END;
1033         return msg_info;
1034 }
1035
1036 gboolean _bt_map_get_sms_message_list(gchar *folder, guint16 max,
1037                 guint8 subject_len, map_msg_filter_t *filter,
1038                 GSList **sms_list, guint64 *count, gboolean *newmsg)
1039 {
1040         FN_START;
1041         int i = 0;
1042         int ret = 0;
1043         int folder_id = -1;
1044         guint64 local_count;
1045         bool read;
1046
1047         msg_struct_list_s folder_list = {0,};
1048         msg_struct_list_s msg_list = {0,};
1049         msg_struct_t list_cond;
1050         GSList *list = NULL;
1051         int msg_count;
1052
1053         DBG("Folder:%s Max:%d", folder, max);
1054         if (max == 0)
1055                 max = 1024;
1056
1057         ret = msg_get_folder_list(g_msg_handle, &folder_list);
1058         if (ret != MSG_SUCCESS)
1059                 goto fail;
1060
1061         for (i = 0; i < folder_list.nCount; i++) {
1062                 char f_name[BT_MAP_MSG_INFO_MAX] = {0, };
1063                 msg_struct_t p_folder = folder_list.msg_struct_info[i];
1064
1065                 ret = msg_get_str_value(p_folder, MSG_FOLDER_INFO_NAME_STR,
1066                                         f_name, BT_MAP_MSG_INFO_MAX);
1067                 if (ret  != MSG_SUCCESS)
1068                         continue;
1069
1070                 if (!g_ascii_strncasecmp(f_name, folder, strlen(folder))) {
1071                         ret = msg_get_int_value(p_folder, MSG_FOLDER_INFO_ID_INT,
1072                                                                 &folder_id);
1073                         if (ret != MSG_SUCCESS)
1074                                 goto fail;
1075
1076                         DBG("folder_id %d \n", folder_id);
1077
1078                         break;
1079                 }
1080         }
1081
1082         if (folder_id == -1)
1083                 goto fail;
1084
1085         list_cond = msg_create_struct(MSG_STRUCT_MSG_LIST_CONDITION);
1086         ret = msg_set_int_value(list_cond,
1087                                 MSG_LIST_CONDITION_FOLDER_ID_INT,
1088                                 folder_id);
1089         if (ret != MSG_SUCCESS)
1090                 goto fail;
1091
1092         ret = msg_set_int_value(list_cond,
1093                                 MSG_LIST_CONDITION_MSGTYPE_INT, MSG_TYPE_SMS);
1094         if (ret != MSG_SUCCESS)
1095                 goto fail;
1096
1097         ret = msg_get_message_list2(g_msg_handle, list_cond, &msg_list);
1098
1099         msg_release_struct(&list_cond);
1100
1101         if (ret != MSG_SUCCESS)
1102                 goto fail;
1103
1104         local_count = (guint64)msg_list.nCount;
1105         DBG("msg_list.nCount: %d, count:%llu", msg_list.nCount, (unsigned long long int)local_count);
1106         for (i = 0; i < local_count; i++) {
1107                 msg_get_bool_value(msg_list.msg_struct_info[i],
1108                                         MSG_MESSAGE_READ_BOOL, &read);
1109                 if (read == false) {
1110                         *newmsg = TRUE;
1111                         break;
1112                 }
1113         }
1114
1115         DBG("count = %llu, newmsg = %d, max = %d", (unsigned long long int)local_count, *newmsg, max);
1116
1117         for (i = 0, msg_count = 0; i < local_count && msg_count < max; i++) {
1118                 message_info_t *msg_info;
1119
1120                 msg_info = __bt_message_info_get(msg_list.msg_struct_info[i],
1121                                                                 subject_len);
1122
1123                 if (!_bt_verify_read_status(msg_info, filter->read_status) ||
1124                                 !_bt_verify_receiver(msg_info, filter->recipient) ||
1125                                 !_bt_verify_sender(msg_info, filter->originator) ||
1126                                 !_bt_verify_time(msg_info, filter) ||
1127                                 !_bt_filter_priority(msg_info, filter->priority) ||
1128                                 !_bt_validate_msg_data(msg_info)) {
1129                         _bt_message_info_free((gpointer)msg_info);
1130                         continue;
1131                 }
1132
1133                 list = g_slist_append(list, msg_info);
1134                 msg_count++;
1135         }
1136
1137         if (folder_list.msg_struct_info)
1138                 ret = msg_release_list_struct(&folder_list);
1139
1140         if (msg_list.msg_struct_info)
1141                 ret = msg_release_list_struct(&msg_list);
1142
1143         *count = local_count;
1144         *sms_list = list;
1145         FN_END;
1146         return TRUE;
1147
1148 fail:
1149         if (folder_list.msg_struct_info)
1150                 ret = msg_release_list_struct(&folder_list);
1151
1152         if (msg_list.msg_struct_info)
1153                 ret = msg_release_list_struct(&msg_list);
1154
1155         ERR("Getting SMS List Failed");
1156         return FALSE;
1157 }
1158 /* LCOV_EXCL_STOP */
1159
1160 void _bt_map_stop_sms_service(void)
1161 {
1162         FN_START;
1163         msg_error_t err =  MSG_SUCCESS;
1164         int folder_id;
1165
1166         folder_id = __bt_get_sms_folder_id(BT_MAP_DELETED_FOLDER_NAME);
1167         if (folder_id != -1) {
1168                 err = msg_delete_folder(g_msg_handle, folder_id);
1169                 if (err != MSG_SUCCESS)
1170                         ERR("Delete folder failed"); /* LCOV_EXCL_LINE */
1171         }
1172
1173         if (g_msg_handle) {
1174                 msg_close_msg_handle(&g_msg_handle);
1175                 g_msg_handle = NULL;
1176         }
1177
1178         FN_END;
1179 }
1180
1181 gboolean _bt_map_start_sms_service(void)
1182 {
1183         FN_START;
1184         msg_error_t err;
1185
1186         err = msg_open_msg_handle(&g_msg_handle);
1187         if (err != MSG_SUCCESS) {
1188                 /* LCOV_EXCL_START */
1189                 ERR("msg_open_msg_handle error = %d\n", err);
1190                 return FALSE;
1191                 /* LCOV_EXCL_STOP */
1192         }
1193
1194         if (__bt_get_sms_folder_id(BT_MAP_DELETED_FOLDER_NAME) == -1)
1195                 __bt_add_deleted_folder();
1196
1197         err = msg_reg_sms_message_callback(g_msg_handle,
1198                                         __bluetooth_map_msg_incoming_status_cb,
1199                                         0, (void *)BT_MAP_MSG_CB);
1200         if (err != MSG_SUCCESS) {
1201                 /* LCOV_EXCL_START */
1202                 ERR("msg_reg_sms_message_callback error  = %d\n", err);
1203                 return FALSE;
1204                 /* LCOV_EXCL_STOP */
1205         }
1206
1207         err = msg_reg_sent_status_callback(g_msg_handle,
1208                                         __bluetooth_map_msg_sent_status_cb,
1209                                         NULL);
1210         if (err != MSG_SUCCESS) {
1211                 /* LCOV_EXCL_START */
1212                 ERR("msg_reg_sent_status_callback error  = %d\n", err);
1213                 return FALSE;
1214                 /* LCOV_EXCL_STOP */
1215         }
1216
1217         FN_END;
1218         return TRUE;
1219 }