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