Merge branch 'master' into tizen_2.1
[platform/core/connectivity/bluetooth-agent.git] / map-agent / map_bmessage.c
1 /*
2  * bluetooth-agent
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <glib.h>
23
24 #include <ITapiNetText.h>
25
26 #include <map_bmessage.h>
27 #include <bluetooth_map_agent.h>
28
29 #define CRLF_LEN 2
30 #define BT_SMS_DATA_MAX_LEN 165
31
32 #define BMSG_TAG "BEGIN:BMSG\r\n"
33 #define VER_TAG "VERSION:"
34 #define STATUS_TAG "STATUS:"
35 #define TYPE_TAG "TYPE:"
36 #define FOLDER_TAG "FOLDER:"
37 #define VCARD_BEGIN_TAG "BEGIN:VCARD\r\n"
38 #define VCARD_END_TAG "END:VCARD\r\n"
39 #define VCARD_N_TAG "N:"
40 #define VCARD_FN_TAG "FN:"
41 #define VCARD_TEL_TAG "TEL:"
42 #define VCARD_EMAIL_TAG "EMAIL:"
43 #define BENV_TAG "BEGIN:BENV\r\n"
44 #define BBODY_TAG "BEGIN:BBODY\r\n"
45 #define MSG_TAG "BEGIN:MSG\r\n"
46 #define PARTID_TAG "PARTID:"
47 #define ENCODING_TAG "ENCODING:"
48 #define CHARSET_TAG "CHARSET:"
49 #define LANGUAGE_TAG "LANGUAGE:"
50 #define LENGTH_TAG "LENGTH:"
51
52
53 void print_bmsg(struct bmsg_data *bmsg)
54 {
55         if (bmsg == NULL)
56                 return;
57
58         struct benv_data *env_data = NULL;
59
60         DBG("bmsg->version = %s", bmsg->version);
61         DBG("bmsg->status = %s", bmsg->status);
62         DBG("bmsg->type = %s", bmsg->type);
63         DBG("bmsg->folder = %s", bmsg->folder);
64         DBG("bmsg->originator_vcard_data->version = %s",
65                                         bmsg->originator_vcard_data->version);
66         DBG("bmsg->originator_vcard_data->n = %s",
67                                         bmsg->originator_vcard_data->n);
68
69         int i = 0;
70         env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
71         while (env_data != NULL) {
72
73                 DBG("env_data = %d", env_data->encapsulation_level);
74                 int k = 0;
75                 struct bmsg_vcard *rvcard;
76
77                 rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
78
79                 while (rvcard != NULL) {
80                         k++;
81
82                         if (rvcard->version != NULL)
83                                 DBG("vcard->version = %s\n", rvcard->version);
84                         if (rvcard->n != NULL)
85                                 DBG("vcard->n = %s\n", rvcard->n);
86                         if (rvcard->fn != NULL)
87                                 DBG("vcard->fn = %s\n", rvcard->fn);
88                         if (rvcard->tel != NULL)
89                                 DBG("vcard->tel = %s\n", rvcard->tel);
90                         if (rvcard->email != NULL)
91                                 DBG("vcard->email = %s\n", rvcard->email);
92
93                         rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
94                 }
95
96                 if (env_data->body_content != NULL) {
97                         DBG("env_data->body_content->length = %"
98                                                 G_GUINT64_FORMAT "\n",
99                                                 env_data->body_content->length);
100                         DBG("env_data->body_content->msg = %s\n",
101                                                 env_data->body_content->msg);
102                 }
103
104                 i++;
105
106                 if (i > 2)
107                         break;
108
109                 env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
110         }
111 }
112
113 static gchar *__bt_unpack_gsm7bit_msg(const char* pdu, int in_len)
114 {
115         int i;
116         int pos = 0;
117         int shift = 0;
118         gchar data[BT_SMS_DATA_MAX_LEN + 1] = {0,};
119
120         for (i = 0; i < in_len; i++) {
121                 if (shift == 0) {
122                         data[i] = pdu[pos] & 0x7F;
123
124                         shift = 7;
125                         pos++;
126                 } else {
127                         data[i] = (pdu[pos - 1] >> shift) |
128                                                 (pdu[pos] << (8 - shift));
129                         data[i] &= 0x7F;
130
131                         shift--;
132                         if (shift > 0)
133                                 pos++;
134                 }
135         }
136
137         DBG("msg = %s\n", data);
138         return g_strdup(data);
139 }
140
141 static gchar *__bt_get_msg_body_from_pdu(gchar *pdu, guint64 pdu_len)
142 {
143         int index = 0;
144         int i;
145         int j = 0;
146         int dcs;
147         int udh = 0;
148         int coding_scheme;
149         int phone_num_len = 0;
150         char temp[3];
151         char msg_data[BT_SMS_DATA_MAX_LEN + 1] = {0,};
152         unsigned char pdu_data[TAPI_NETTEXT_MSG_SIZE_MAX] = {0,};
153
154         for (i = 0; i < (pdu_len - 1);) {
155                 snprintf(temp, sizeof(temp), "%c%c", pdu[i], pdu[i+1]);
156
157                 pdu_data[j] = g_ascii_strtoull(temp, NULL, 16);
158                 DBG("pdu_data = %02x\n", pdu_data[j]);
159                 j++;
160                 i = i + 2;
161         }
162
163         DBG("pdu[%d] = %x\n", index, pdu_data[index]);
164         if (pdu[index] == 0x00)
165                 index++;
166         else
167                 index = index + pdu_data[index];
168
169         /* TP-MTI */
170         index = index + 1;
171
172         if (pdu_data[index] & 0x40)
173                 udh = 1;
174
175         DBG("udh = %d", udh);
176
177         /* TP-MR */
178         index = index + 1;
179
180         /* phone number length */
181         index = index + 1;
182         DBG("pdu[%d] = %x\n", index, pdu_data[index]);
183
184         if ((pdu_data[index] % 2) == 0)
185                 phone_num_len = pdu_data[index] / 2;
186         else
187                 phone_num_len = pdu_data[index] / 2 + 1;
188
189         DBG("phone_num_len [%d]\n", phone_num_len);
190
191         /* phone number type */
192         index = index + 1;
193
194         /* phone_num_len/2 encoded phone num length */
195         index = index + phone_num_len;
196
197         /* TP-PID */
198         index = index + 1;
199
200         /* TP-DCS */
201         index = index + 1;
202
203         dcs = pdu_data[index];
204         coding_scheme = (dcs & 0x0C) >> 2;
205         DBG("coding_scheme = %d\n", coding_scheme);
206
207         /* TP-VP */
208         index = index + 1;
209
210         /* TP-UDL */
211         index = index + 1;
212         int udl = pdu_data[index];
213         DBG("udl = %x\n", udl);
214
215         /* message body */
216         index = index + 1;
217
218         memcpy(msg_data, (void*)&pdu_data[index], udl);
219
220         return __bt_unpack_gsm7bit_msg(msg_data, udl);
221 }
222
223 char *bmsg_get_msg_folder(struct bmsg_data *bmsg)
224 {
225         return g_strdup(bmsg->folder);
226 }
227
228 char *bmsg_get_msg_body(struct bmsg_data *bmsg, gboolean utf)
229 {
230         struct benv_data *env_data;
231         int i = 0;
232
233         env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
234
235         while (env_data != NULL) {
236                 if (env_data->body_content != NULL) {
237                         DBG("env_data->body_content->msg = %s\n",
238                                                 env_data->body_content->msg);
239                         DBG("env_data->body_content->length = %"
240                                                 G_GUINT64_FORMAT "\n",
241                                                 env_data->body_content->length);
242
243                         if (utf == FALSE) {
244                                 return __bt_get_msg_body_from_pdu(
245                                                 env_data->body_content->msg,
246                                                 env_data->body_content->length);
247                         } else {
248                                 return g_strndup(
249                                                 env_data->body_content->msg,
250                                                 env_data->body_content->length);
251                         }
252                 }
253
254                 i++;
255                 if (i > 2)
256                         break;
257
258                 env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
259         }
260
261         return NULL;
262 }
263
264 GSList *bmsg_get_msg_recepients(struct bmsg_data *bmsg)
265 {
266         struct benv_data *env_data;
267         GSList *receiver = NULL;
268         int i = 0;
269
270         env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
271
272         while (env_data != NULL) {
273
274                 DBG("env_data = %d", env_data->encapsulation_level);
275                 int k = 0;
276                 struct bmsg_vcard *rvcard;
277
278                 rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
279                 while (rvcard != NULL) {
280                         k++;
281
282                         if (rvcard->tel != NULL) {
283                                 DBG("vcard->tel = %s\n", rvcard->tel);
284                                 receiver = g_slist_append(receiver,
285                                                                 rvcard->tel);
286                         }
287
288                         rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
289                 }
290
291                 i++;
292                 if (i > 2)
293                         break;
294
295                 env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
296         }
297
298         return receiver;
299 }
300
301 void bmsg_free_vcard_data(struct bmsg_vcard *vcard_data)
302 {
303         if (vcard_data == NULL)
304                 return;
305
306         g_free(vcard_data->version);
307         g_free(vcard_data->n);
308         g_free(vcard_data->fn);
309         g_free(vcard_data->tel);
310         g_free(vcard_data->email);
311         g_free(vcard_data);
312
313         return;
314 }
315
316 void bmsg_free_bmsg(struct bmsg_data *bmsg)
317 {
318         struct benv_data *env_data;
319         int i = 0;
320
321         if (bmsg == NULL)
322                 return;
323
324         g_free(bmsg->version);
325         g_free(bmsg->status);
326         g_free(bmsg->type);
327         g_free(bmsg->folder);
328         bmsg_free_vcard_data(bmsg->originator_vcard_data);
329
330         if (bmsg->envelope_data == NULL)
331                 goto done;
332
333         if (bmsg->envelope_data->env_data == NULL)
334                 goto done;
335
336         env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
337         while (env_data != NULL) {
338
339                 DBG("env_data = %d", env_data->encapsulation_level);
340                 int k = 0;
341                 struct bmsg_vcard *rvcard;
342
343                 rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
344
345                 while (rvcard != NULL) {
346                         k++;
347                         bmsg_free_vcard_data(rvcard);
348                         rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
349                 }
350
351                 if (env_data->body_content != NULL) {
352                         g_free(env_data->body_content->encoding);
353                         g_free(env_data->body_content->charset);
354                         g_free(env_data->body_content->language);
355                         g_free(env_data->body_content->msg);
356                         g_free(env_data->body_content);
357                 }
358
359                 g_free(env_data);
360                 i++;
361
362                 env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
363         }
364
365 done:
366         g_free(bmsg);
367 }
368
369 gchar *bmsg_get_parse_sub_block(char **sub_block_data, char *element)
370 {
371         gchar *start;
372         gchar *end;
373         gchar *block_start;
374         gchar *block_end;
375         gchar *sub_block = NULL;
376         size_t offset;
377         size_t len;
378
379         DBG("");
380
381         start = g_strdup_printf("BEGIN:%s\r\n", element);
382         end = g_strdup_printf("END:%s\r\n", element);
383         offset = strlen(start);
384
385         block_start = g_strstr_len(*sub_block_data, offset, start);
386         if (block_start == NULL)
387                 goto done;
388
389         if (!g_strcmp0(start, VCARD_BEGIN_TAG))
390                 block_end = g_strstr_len(*sub_block_data, -1,  end);
391         else
392                 block_end = g_strrstr(*sub_block_data, end);
393
394         if (block_end == NULL)
395                 goto done;
396
397         len = block_end - block_start - offset;
398         sub_block = g_strndup(block_start + offset, len);
399         *sub_block_data = *sub_block_data + strlen(sub_block) + strlen(start) +
400                                                                  strlen(end);
401 done:
402         g_free(start);
403         g_free(end);
404         return sub_block;
405 }
406
407 gchar *bmsg_get_tag_data(char **block_data, char *element)
408 {
409         gchar *end = "\r\n";
410         gchar *block_start;
411         gchar *block_end;
412         gchar *sub_block;
413         size_t offset;
414         size_t len;
415
416         DBG("");
417
418         if (*block_data == NULL || element == NULL)
419                 return NULL;
420
421         block_start = g_strstr_len(*block_data, -1, element);
422         if (block_start == NULL)
423                 return NULL;
424
425         offset = strlen(element);
426
427         block_end = g_strstr_len(block_start+offset, -1, end);
428         if (block_end == NULL)
429                 return NULL;
430
431         len = block_end - block_start - offset;
432         sub_block = g_strndup(block_start + offset, len);
433         *block_data = *block_data + offset + len + CRLF_LEN;
434
435         return sub_block;
436 }
437
438 struct bmsg_bbody *bmsg_get_bbody_data(gchar *block_data)
439 {
440         gchar *bbody_block_data_start;
441         gchar *temp;
442         struct bmsg_bbody *bbody;
443         DBG("");
444
445         bbody_block_data_start = block_data;
446
447         bbody = g_new0(struct bmsg_bbody, 1);
448
449         temp = bmsg_get_tag_data(&block_data, PARTID_TAG);
450         if (temp != NULL) {
451                 bbody->part_id = (guint16)g_ascii_strtoull(temp, NULL, 10);
452                 g_free(temp);
453         }
454
455         bbody->encoding = bmsg_get_tag_data(&block_data, ENCODING_TAG);
456         bbody->charset = bmsg_get_tag_data(&block_data, CHARSET_TAG);
457         bbody->language = bmsg_get_tag_data(&block_data, LANGUAGE_TAG);
458
459         temp = bmsg_get_tag_data(&block_data, LENGTH_TAG);
460
461         if (temp != NULL) {
462                 bbody->length = g_ascii_strtoull(temp, NULL, 10);
463                 g_free(temp);
464         }
465
466         bbody->msg = bmsg_get_parse_sub_block(&block_data, "MSG");
467
468         g_free(bbody_block_data_start);
469
470         return bbody;
471 }
472
473 struct bmsg_vcard *bmsg_get_vcard_data(gchar *sub_block_data)
474 {
475         gchar *vcard_block_data_start;
476         struct bmsg_vcard *vcard;
477         DBG("");
478
479         vcard_block_data_start = sub_block_data;
480
481         vcard = g_new0(struct bmsg_vcard, 1);
482
483         vcard->version = bmsg_get_tag_data(&sub_block_data, VER_TAG);
484         vcard->n = bmsg_get_tag_data(&sub_block_data, VCARD_N_TAG);
485         vcard->fn = bmsg_get_tag_data(&sub_block_data, VCARD_FN_TAG);
486         vcard->tel = bmsg_get_tag_data(&sub_block_data, VCARD_TEL_TAG);
487         vcard->email = bmsg_get_tag_data(&sub_block_data, VCARD_EMAIL_TAG);
488
489         g_free(vcard_block_data_start);
490
491         return vcard;
492 }
493
494 struct benv_data *bmsg_get_env_encapsulation_data(gchar **sub_block_data)
495 {
496         gchar *is_valid;
497         gchar *bbody_data = NULL;
498         static guint8 lvl = 1;
499
500         is_valid = g_strstr_len(*sub_block_data, strlen(VCARD_BEGIN_TAG),
501                                                         VCARD_BEGIN_TAG);
502         if (is_valid == NULL)
503                 return NULL;
504
505         if (lvl > 3)
506                 return NULL;
507
508         struct benv_data *rec_data = g_new0(struct benv_data, 1);
509
510         rec_data->encapsulation_level = lvl;
511         lvl++;
512
513         while (is_valid != NULL) {
514                 gchar *vcard_data = NULL;
515                 struct bmsg_vcard *vcard;
516
517                 vcard_data = bmsg_get_parse_sub_block(sub_block_data, "VCARD");
518                 if (vcard_data == NULL) {
519                         DBG("parse error\n");
520                         g_free(rec_data);
521                         return NULL;
522                 }
523                 vcard = bmsg_get_vcard_data(vcard_data);
524
525                 rec_data->recipient_vcard = g_slist_append(
526                                                 rec_data->recipient_vcard,
527                                                 vcard);
528
529                 is_valid = g_strstr_len(*sub_block_data,
530                                                 strlen(VCARD_BEGIN_TAG),
531                                                 VCARD_BEGIN_TAG);
532         }
533
534         is_valid = g_strstr_len(*sub_block_data, strlen(BBODY_TAG), BBODY_TAG);
535
536         if (!is_valid)
537                 return rec_data;
538
539         bbody_data = bmsg_get_parse_sub_block(sub_block_data, "BBODY");
540         if (bbody_data == NULL) {
541                 DBG("parse error\n");
542                 return rec_data;
543         }
544
545         rec_data->body_content = bmsg_get_bbody_data(bbody_data);
546
547         return rec_data;
548 }
549
550 struct bmsg_envelope *bmsg_get_envelope_data(gchar **block_data)
551 {
552         gchar *env_block_data_start;
553         gchar *sub_block_data;
554         struct bmsg_envelope *envelope_data;
555         struct benv_data *rec_data;
556
557         env_block_data_start = *block_data;
558
559         envelope_data = g_new0(struct bmsg_envelope, 1);
560
561         sub_block_data = bmsg_get_parse_sub_block(block_data, "BENV");
562
563         while (sub_block_data) {
564
565                 rec_data = bmsg_get_env_encapsulation_data(&sub_block_data);
566
567                 while (rec_data) {
568                         envelope_data->env_data = g_slist_append(
569                                                         envelope_data->env_data,
570                                                         rec_data);
571
572                         rec_data = bmsg_get_env_encapsulation_data(
573                                                         &sub_block_data);
574                 }
575                 sub_block_data = bmsg_get_parse_sub_block(&sub_block_data,
576                                                                         "BENV");
577         }
578         g_free(sub_block_data);
579
580         return envelope_data;
581 }
582
583 struct bmsg_data *bmsg_parse(gchar *buf)
584 {
585         gchar *block_data;
586         gchar *sub_block_data;
587         gchar *block_data_start;
588         struct bmsg_data *bmsg;
589
590         DBG("");
591
592         block_data = bmsg_get_parse_sub_block(&buf, "BMSG");
593         if (block_data == NULL)
594                 return NULL;
595
596         block_data_start = block_data;
597
598         bmsg = g_new0(struct bmsg_data, 1);
599
600         bmsg->version = bmsg_get_tag_data(&block_data, VER_TAG);
601         if (bmsg->version == NULL)
602                 goto parse_fail;
603
604         bmsg->status = bmsg_get_tag_data(&block_data, STATUS_TAG);
605         if (bmsg->status == NULL)
606                 goto parse_fail;
607
608         bmsg->type = bmsg_get_tag_data(&block_data, TYPE_TAG);
609         if (bmsg->type == NULL)
610                 goto parse_fail;
611
612         bmsg->folder = bmsg_get_tag_data(&block_data, FOLDER_TAG);
613         if (bmsg->folder == NULL)
614                 goto parse_fail;
615
616         sub_block_data = bmsg_get_parse_sub_block(&block_data, "VCARD");
617         if (sub_block_data == NULL)
618                 goto parse_fail;
619
620         bmsg->originator_vcard_data = bmsg_get_vcard_data(sub_block_data);
621         if (bmsg->originator_vcard_data == NULL)
622                 goto parse_fail;
623
624         bmsg->envelope_data = bmsg_get_envelope_data(&block_data);
625         if (bmsg->envelope_data == NULL)
626                 goto parse_fail;
627
628         g_free(block_data_start);
629
630         DBG("Parse done");
631         print_bmsg(bmsg);
632
633         return bmsg;
634
635 parse_fail:
636         DBG("Parse fail");
637         bmsg_free_bmsg(bmsg);
638
639         return NULL;
640 }
641