Fix p2p bug and various warnings
[profile/ivi/neard.git] / src / ndef.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30
31 #include <glib.h>
32
33 #include <gdbus.h>
34
35 #include "near.h"
36
37 enum record_tnf {
38         RECORD_TNF_EMPTY     = 0x00,
39         RECORD_TNF_WELLKNOWN = 0x01,
40         RECORD_TNF_MIME      = 0x02,
41         RECORD_TNF_URI       = 0x03,
42         RECORD_TNF_EXTERNAL  = 0x04,
43         RECORD_TNF_UNKNOWN   = 0x05,
44         RECORD_TNF_UNCHANGED = 0x06,
45 };
46
47 #define RECORD_ACTION_DO   0x00
48 #define RECORD_ACTION_SAVE 0x01
49 #define RECORD_ACTION_EDIT 0x02
50
51 #define RECORD_MB_BIT(val)  ((val & 0x80) >> 7)
52 #define RECORD_ME_BIT(val)  ((val & 0x40) >> 6)
53 #define RECORD_CF_BIT(val)  ((val & 0x20) >> 5)
54 #define RECORD_SR_BIT(val)  ((val & 0x10) >> 4)
55 #define RECORD_IL_BIT(val)  ((val & 0x8)  >> 3)
56 #define RECORD_TNF_BIT(val) (val & 0x7)
57
58 #define NDEF_MSG_MIN_LENGTH 0x03
59 #define NDEF_PAYLOAD_LENGTH_OFFSET 0x02
60
61 #define RECORD_MB    0x80
62 #define RECORD_ME    0x40
63 #define RECORD_CF    0x20
64 #define RECORD_SR    0x10
65 #define RECORD_IL    0x08
66 #define RECORD_TNF_EMPTY_SET(val)     ((val & ~0x7) | RECORD_TNF_EMPTY)
67 #define RECORD_TNF_WKT_SET(val)       ((val & ~0x7) | RECORD_TNF_WELLKNOWN)
68 #define RECORD_TNF_MIME_SET(val)      ((val & ~0x7) | RECORD_TNF_MIME)
69 #define RECORD_TNF_URI_SET(val)       ((val & ~0x7) | RECORD_TNF_URI)
70 #define RECORD_TNF_EXTERNAL_SET(val)  ((val & ~0x7) | RECORD_TNF_EXTERNAL)
71 #define RECORD_TNF_UKNOWN_SET(val)    ((val & ~0x7) | RECORD_TNF_UNKNOWN)
72 #define RECORD_TNF_UNCHANGED_SET(val) ((val & ~0x7) | RECORD_TNF_UNCHANGED)
73
74 #define NDEF_MSG_SHORT_RECORD_MAX_LENGTH 0xFF
75 #define NDEF_TEXT_RECORD_TYPE_NAME_HEX_VALUE 0x54
76 #define NDEF_TEXT_RECORD_UTF16_STATUS 0x80
77
78 enum record_type {
79         RECORD_TYPE_WKT_SMART_POSTER          =   0x01,
80         RECORD_TYPE_WKT_URI                   =   0x02,
81         RECORD_TYPE_WKT_TEXT                  =   0x03,
82         RECORD_TYPE_WKT_SIZE                  =   0x04,
83         RECORD_TYPE_WKT_TYPE                  =   0x05,
84         RECORD_TYPE_WKT_ACTION                =   0x06,
85         RECORD_TYPE_WKT_HANDOVER_REQUEST      =   0x07,
86         RECORD_TYPE_WKT_HANDOVER_SELECT       =   0x08,
87         RECORD_TYPE_WKT_HANDOVER_CARRIER      =   0x09,
88         RECORD_TYPE_WKT_ALTERNATIVE_CARRIER   =   0x0a,
89         RECORD_TYPE_WKT_COLLISION_RESOLUTION  =   0x0b,
90         RECORD_TYPE_WKT_ERROR                 =   0x0c,
91         RECORD_TYPE_MIME_TYPE                 =   0x0d,
92         RECORD_TYPE_UNKNOWN                   =   0xfe,
93         RECORD_TYPE_ERROR                     =   0xff
94 };
95
96 #define RECORD_TYPE_WKT "urn:nfc:wkt:"
97 #define RECORD_TYPE_EXTERNAL "urn:nfc:ext:"
98
99 struct near_ndef_record_header {
100         uint8_t mb;
101         uint8_t me;
102         uint8_t cf;
103         uint8_t sr;
104         uint8_t il;
105         uint8_t tnf;
106         uint8_t il_length;
107         uint8_t *il_field;
108         uint32_t payload_len;
109         uint32_t offset;
110         uint8_t type_len;
111         enum record_type rec_type;
112         char *type_name;
113         uint32_t header_len;
114 };
115
116 struct near_ndef_text_record {
117         char *encoding;
118         char *language_code;
119         char *data;
120 };
121
122 struct near_ndef_uri_record {
123         uint8_t identifier;
124
125         uint32_t  field_length;
126         uint8_t  *field;
127 };
128
129 struct near_ndef_sp_record {
130         struct near_ndef_uri_record *uri;
131
132         uint8_t number_of_title_records;
133         struct near_ndef_text_record **title_records;
134
135         uint32_t size; /* from Size record*/
136         char *type;    /* from Type record*/
137         char *action;
138         /* TODO add icon and other records fields*/
139 };
140
141 struct near_ndef_mime_record {
142         char *type;
143 };
144
145 enum carrier_power_state {
146         CPS_INACTIVE                    =   0x00,
147         CPS_ACTIVE                      =   0x01,
148         CPS_ACTIVATING                  =   0x02,
149         CPS_UNKNOWN                     =   0x03,
150 };
151
152 /* Handover record definitions */
153
154 /* alternative record (AC) */
155 #define AC_RECORD_PAYLOAD_LEN   4
156
157 struct near_ndef_ac_record {
158         enum carrier_power_state cps;   /* carrier power state */
159
160         uint8_t cdr_len;        /* carrier data reference length: 0x01 */
161         uint8_t cdr;            /* carrier data reference */
162         uint8_t adata_refcount; /* auxiliary data reference count */
163
164         /* !: if adata_refcount == 0, then there's no data reference */
165         uint16_t **adata;       /* auxiliary data reference */
166 };
167
168 /*
169  * carrier data (see cdr in near_ndef_ac_record )
170  * These settings can be retrieved from mime, carrier records, etc...
171  */
172 struct near_ndef_carrier_data {
173         uint8_t cdr;            /* carrier data reference */
174         uint8_t *data;
175         size_t data_len;
176 };
177
178 /* Default Handover version */
179 #define HANDOVER_VERSION        0x12
180
181 /* General Handover Request/Select record */
182 struct near_ndef_ho_record {
183         uint8_t version;                /* version id */
184         uint16_t collision_record;      /* collision record */
185
186         uint8_t number_of_ac_records;   /* At least 1 ac is needed */
187         struct near_ndef_ac_record **ac_records;
188
189         /* Optional records */
190         uint16_t *err_record;   /* not NULL if present */
191
192         uint8_t number_of_cfg_records;  /* extra NDEF records */
193         struct near_ndef_mime_record **cfg_records;
194 };
195
196 struct near_ndef_record {
197         char *path;
198
199         struct near_ndef_record_header *header;
200
201         /* WKT record */
202         struct near_ndef_text_record *text;
203         struct near_ndef_uri_record  *uri;
204         struct near_ndef_sp_record   *sp;
205
206         /* MIME type */
207         struct near_ndef_mime_record *mime;
208
209         /* HANDOVER type */
210         struct near_ndef_ho_record   *ho;
211
212         char *type;
213
214         uint8_t *data;
215         size_t data_len;
216 };
217
218 static DBusConnection *connection = NULL;
219
220 static inline void fillb8(uint8_t *ptr, uint32_t len)
221 {
222         (*(uint8_t *)(ptr)) = ((uint8_t)(len));
223 }
224
225 static inline void fillb16(uint8_t *ptr, uint32_t len)
226 {
227         fillb8((ptr), (uint16_t)(len) >> 8);
228         fillb8((uint8_t *)(ptr) + 1, len);
229 }
230
231 static inline void fillb32(uint8_t *ptr, uint32_t len)
232 {
233         fillb16((ptr), (uint32_t)(len) >> 16);
234         fillb16((uint8_t *)(ptr) + 2, (uint32_t)(len));
235 }
236
237 char *__near_ndef_record_get_path(struct near_ndef_record *record)
238 {
239         return record->path;
240 }
241
242 char *__near_ndef_record_get_type(struct near_ndef_record *record)
243 {
244         return record->type;
245 }
246
247 static void append_text_record(struct near_ndef_text_record *text,
248                                         DBusMessageIter *dict)
249 {
250         DBG("");
251
252         if (text == NULL || dict == NULL)
253                 return;
254
255         if (text->encoding != NULL)
256                 near_dbus_dict_append_basic(dict, "Encoding",
257                                                 DBUS_TYPE_STRING,
258                                                 &(text->encoding));
259
260         if (text->language_code != NULL)
261                 near_dbus_dict_append_basic(dict, "Language",
262                                                 DBUS_TYPE_STRING,
263                                                 &(text->language_code));
264
265         if (text->data != NULL)
266                 near_dbus_dict_append_basic(dict, "Representation",
267                                                 DBUS_TYPE_STRING,
268                                                 &(text->data));
269 }
270
271 static const char *uri_prefixes[NFC_MAX_URI_ID + 1] = {
272         "",
273         "http://www.",
274         "https://www.",
275         "http://",
276         "https://",
277         "tel:",
278         "mailto:",
279         "ftp://anonymous:anonymous@",
280         "ftp://ftp.",
281         "ftps://",
282         "sftp://",
283         "smb://",
284         "nfs://",
285         "ftp://",
286         "dav://",
287         "news:",
288         "telnet://",
289         "imap:",
290         "rstp://",
291         "urn:",
292         "pop:",
293         "sip:",
294         "sips:",
295         "tftp:",
296         "btspp://",
297         "btl2cap://",
298         "btgoep://",
299         "tcpobex://",
300         "irdaobex://",
301         "file://",
302         "urn:epc:id:",
303         "urn:epc:tag:",
304         "urn:epc:pat:",
305         "urn:epc:raw:",
306         "urn:epc:",
307         "urn:nfc:",
308 };
309
310 const char *__near_ndef_get_uri_prefix(uint8_t id)
311 {
312         if (id > NFC_MAX_URI_ID)
313                 return NULL;
314
315         return uri_prefixes[id];
316 }
317
318 static void append_uri_record(struct near_ndef_uri_record *uri,
319                                         DBusMessageIter *dict)
320 {
321         char *value;
322         const char *prefix = NULL;
323
324         DBG("");
325
326         if (uri == NULL || dict == NULL)
327                 return;
328
329         if (uri->identifier > NFC_MAX_URI_ID) {
330                 near_error("Invalid URI identifier 0x%x", uri->identifier);
331                 return;
332         }
333
334         prefix = uri_prefixes[uri->identifier];
335
336         DBG("URI prefix %s", prefix);
337
338         value = g_strdup_printf("%s%.*s", prefix, uri->field_length,
339                                                          uri->field);
340
341         near_dbus_dict_append_basic(dict, "URI", DBUS_TYPE_STRING, &value);
342
343         g_free(value);
344 }
345
346 static void append_smart_poster_record(struct near_ndef_sp_record *sp,
347                                                 DBusMessageIter *dict)
348 {
349         uint8_t i;
350
351         DBG("");
352
353         if (sp == NULL || dict == NULL)
354                 return;
355
356         if (sp->action != NULL)
357                 near_dbus_dict_append_basic(dict, "Action", DBUS_TYPE_STRING,
358                                                         &(sp->action));
359
360         if (sp->uri != NULL)
361                 append_uri_record(sp->uri, dict);
362
363         if (sp->title_records != NULL &&
364                         sp->number_of_title_records > 0) {
365                 for (i = 0; i < sp->number_of_title_records; i++)
366                         append_text_record(sp->title_records[i], dict);
367         }
368
369         if (sp->type != NULL)
370                 near_dbus_dict_append_basic(dict, "MIMEType", DBUS_TYPE_STRING,
371                                                                 &(sp->type));
372
373         if (sp->size > 0)
374                 near_dbus_dict_append_basic(dict, "Size", DBUS_TYPE_UINT32,
375                                                         &(sp->size));
376 }
377
378 static void append_mime_record(struct near_ndef_mime_record *mime,
379                                         DBusMessageIter *dict)
380 {
381         DBG("");
382
383         if (mime == NULL || dict == NULL)
384                 return;
385
386         if (mime->type != NULL)
387                 near_dbus_dict_append_basic(dict, "MIME",
388                                                 DBUS_TYPE_STRING,
389                                                 &(mime->type));
390 }
391
392 static void append_record(struct near_ndef_record *record,
393                                         DBusMessageIter *dict)
394 {
395         char *type;
396
397         DBG("");
398
399         if (record == NULL || dict == NULL)
400                 return;
401
402         switch (record->header->rec_type) {
403         case RECORD_TYPE_WKT_SIZE:
404         case RECORD_TYPE_WKT_TYPE:
405         case RECORD_TYPE_WKT_ACTION:
406         case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
407         case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
408         case RECORD_TYPE_WKT_ERROR:
409         case RECORD_TYPE_UNKNOWN:
410         case RECORD_TYPE_ERROR:
411                 break;
412
413         case RECORD_TYPE_WKT_TEXT:
414                 type = "Text";
415                 near_dbus_dict_append_basic(dict, "Type",
416                                         DBUS_TYPE_STRING, &type);
417                 append_text_record(record->text, dict);
418                 break;
419
420         case RECORD_TYPE_WKT_URI:
421                 type = "URI";
422                 near_dbus_dict_append_basic(dict, "Type",
423                                         DBUS_TYPE_STRING, &type);
424                 append_uri_record(record->uri, dict);
425                 break;
426
427         case RECORD_TYPE_WKT_SMART_POSTER:
428                 type = "SmartPoster";
429                 near_dbus_dict_append_basic(dict, "Type",
430                                         DBUS_TYPE_STRING, &type);
431                 append_smart_poster_record(record->sp, dict);
432                 break;
433
434         case RECORD_TYPE_WKT_HANDOVER_REQUEST:
435                 type = "HandoverRequest";
436                 near_dbus_dict_append_basic(dict, "Type",
437                                         DBUS_TYPE_STRING, &type);
438                 break;
439
440         case RECORD_TYPE_WKT_HANDOVER_SELECT:
441                 type = "HandoverSelect";
442                 near_dbus_dict_append_basic(dict, "Type",
443                                         DBUS_TYPE_STRING, &type);
444                 break;
445
446         case RECORD_TYPE_WKT_HANDOVER_CARRIER:
447                 type = "HandoverCarrier";
448                 near_dbus_dict_append_basic(dict, "Type",
449                                         DBUS_TYPE_STRING, &type);
450                 break;
451
452         case RECORD_TYPE_MIME_TYPE:
453                 type = "MIME Type (RFC 2046)";
454                 near_dbus_dict_append_basic(dict, "Type",
455                                         DBUS_TYPE_STRING, &type);
456                 append_mime_record(record->mime, dict);
457                 break;
458         }
459 }
460
461 static DBusMessage *get_properties(DBusConnection *conn,
462                                         DBusMessage *msg, void *data)
463 {
464         struct near_ndef_record *record = data;
465         DBusMessage *reply;
466         DBusMessageIter array, dict;
467
468         DBG("conn %p", conn);
469
470         if (conn == NULL || msg == NULL ||
471                 data == NULL)
472                 return NULL;
473
474         reply = dbus_message_new_method_return(msg);
475         if (reply == NULL)
476                 return NULL;
477
478         dbus_message_iter_init_append(reply, &array);
479
480         near_dbus_dict_open(&array, &dict);
481
482         append_record(record, &dict);
483
484         near_dbus_dict_close(&array, &dict);
485
486         return reply;
487 }
488
489 static const GDBusMethodTable record_methods[] = {
490         { GDBUS_METHOD("GetProperties",
491                                 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
492                                 get_properties) },
493         { },
494 };
495
496 static void free_text_record(struct near_ndef_text_record *text)
497 {
498         if (text == NULL)
499                 return;
500
501         g_free(text->encoding);
502         g_free(text->language_code);
503         g_free(text->data);
504         g_free(text);
505
506         text = NULL;
507 }
508
509 static void free_uri_record(struct near_ndef_uri_record *uri)
510 {
511         if (uri == NULL)
512                 return;
513
514         g_free(uri->field);
515         g_free(uri);
516
517         uri = NULL;
518 }
519
520 static void free_sp_record(struct near_ndef_sp_record *sp)
521 {
522         uint8_t i;
523
524         if (sp == NULL)
525                 return;
526
527         free_uri_record(sp->uri);
528
529         if (sp->title_records != NULL) {
530                 for (i = 0; i < sp->number_of_title_records; i++)
531                         free_text_record(sp->title_records[i]);
532         }
533
534         g_free(sp->title_records);
535         g_free(sp->type);
536         g_free(sp->action);
537         g_free(sp);
538
539         sp = NULL;
540 }
541
542 static void free_mime_record(struct near_ndef_mime_record *mime)
543 {
544         if (mime == NULL)
545                 return;
546
547         g_free(mime->type);
548         g_free(mime);
549
550         mime = NULL;
551 }
552
553 static void free_ac_record(struct near_ndef_ac_record *ac)
554 {
555         if (ac == NULL)
556                 return;
557
558         g_free(ac->adata);
559         g_free(ac);
560         ac = NULL;
561 }
562
563 static void free_ho_record(struct near_ndef_ho_record *ho)
564 {
565         int i;
566
567         if (ho == NULL)
568                 return;
569
570         if (ho->ac_records != NULL) {
571                 for (i = 0; i < ho->number_of_ac_records; i++)
572                         free_ac_record(ho->ac_records[i]);
573         }
574
575         g_free(ho->ac_records);
576         g_free(ho);
577
578         ho = NULL;
579 }
580
581 static void free_ndef_record(struct near_ndef_record *record)
582 {
583         if (record == NULL)
584                 return;
585
586         g_free(record->path);
587
588         if (record->header != NULL) {
589
590                 switch (record->header->rec_type) {
591                 case RECORD_TYPE_WKT_SIZE:
592                 case RECORD_TYPE_WKT_TYPE:
593                 case RECORD_TYPE_WKT_ACTION:
594                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
595                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
596                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
597                 case RECORD_TYPE_WKT_ERROR:
598                 case RECORD_TYPE_UNKNOWN:
599                 case RECORD_TYPE_ERROR:
600                         break;
601
602                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
603                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
604                         free_ho_record(record->ho);
605                         break;
606
607                 case RECORD_TYPE_WKT_TEXT:
608                         free_text_record(record->text);
609                         break;
610
611                 case RECORD_TYPE_WKT_URI:
612                         free_uri_record(record->uri);
613                         break;
614
615                 case RECORD_TYPE_WKT_SMART_POSTER:
616                         free_sp_record(record->sp);
617                         break;
618
619                 case RECORD_TYPE_MIME_TYPE:
620                         free_mime_record(record->mime);
621                 }
622
623                 g_free(record->header->il_field);
624                 g_free(record->header->type_name);
625         }
626
627         g_free(record->header);
628         g_free(record->type);
629         g_free(record->data);
630         g_free(record);
631         record = NULL;
632 }
633
634 void __near_ndef_record_free(struct near_ndef_record *record)
635 {
636         g_dbus_unregister_interface(connection, record->path,
637                                                 NFC_RECORD_INTERFACE);
638
639         free_ndef_record(record);
640 }
641
642 static char *action_to_string(uint8_t action)
643 {
644         switch (action) {
645         case RECORD_ACTION_DO:
646                 return "Do";
647         case RECORD_ACTION_SAVE:
648                 return "Save";
649         case RECORD_ACTION_EDIT:
650                 return "Edit";
651         default:
652                 near_error("Unknown action 0x%x", action);
653                 return NULL;
654         }
655 }
656
657 /**
658  * @brief returns record type for external type
659  * Validate type and type length and returns
660  * type.
661  *
662  * @param type    Type name in hex format
663  * @param type_lenth Type name length
664  *
665  * @return enum record type
666  */
667
668 static enum record_type get_external_record_type(uint8_t *type,
669                                                 size_t type_length)
670 {
671         DBG("");
672
673         if (strncmp((char *) type, BT_MIME_STRING_2_0,
674                                         strlen(BT_MIME_STRING_2_0)) == 0)
675                 return RECORD_TYPE_MIME_TYPE;
676         else
677                 return RECORD_TYPE_UNKNOWN;
678 }
679
680 /**
681  * @brief returns record type
682  * Validate type name format, type and type length and returns
683  * type.
684  *
685  * @param tnf     TypeNameFormat value
686  * @param type    Type name in hex format
687  * @param type_lenth Type name length
688  *
689  * @return enum record type
690  */
691
692 static enum record_type get_record_type(enum record_tnf tnf,
693                                 uint8_t *type, size_t type_length)
694 {
695         DBG("");
696
697         switch (tnf) {
698         case RECORD_TNF_EMPTY:
699         case RECORD_TNF_URI:
700         case RECORD_TNF_UNKNOWN:
701         case RECORD_TNF_UNCHANGED:
702                 break;
703
704         case RECORD_TNF_WELLKNOWN:
705                 if (type_length == 1) {
706                         if (type[0] == 'T')
707                                 return RECORD_TYPE_WKT_TEXT;
708                         else if (type[0] == 'U')
709                                 return RECORD_TYPE_WKT_URI;
710                         else if (type[0] == 's')
711                                 return RECORD_TYPE_WKT_SIZE;
712                         else if (type[0] == 't')
713                                 return RECORD_TYPE_WKT_TYPE;
714                         else
715                                 return RECORD_TYPE_UNKNOWN;
716
717                 } else if (type_length == 2) {
718                         if (strncmp((char *)type, "Sp", 2) == 0)
719                                 return RECORD_TYPE_WKT_SMART_POSTER;
720                         else if (strncmp((char *) type, "Hr", 2) == 0)
721                                 return RECORD_TYPE_WKT_HANDOVER_REQUEST;
722                         else if (strncmp((char *) type, "Hs", 2) == 0)
723                                 return RECORD_TYPE_WKT_HANDOVER_SELECT;
724                         else if (strncmp((char *) type, "Hc", 2) == 0)
725                                 return RECORD_TYPE_WKT_HANDOVER_CARRIER;
726                         else if (strncmp((char *) type, "ac", 2) == 0)
727                                 return RECORD_TYPE_WKT_ALTERNATIVE_CARRIER;
728                         else if (strncmp((char *) type, "cr", 2) == 0)
729                                 return RECORD_TYPE_WKT_COLLISION_RESOLUTION;
730                         else
731                                 return RECORD_TYPE_UNKNOWN;
732
733                 } else if (type_length == 3) {
734                         if (strncmp((char *)type, "act", 3) == 0)
735                                 return RECORD_TYPE_WKT_ACTION;
736                         else if (strncmp((char *)type, "err", 3) == 0)
737                                 return RECORD_TYPE_WKT_ERROR;
738                         else
739                                 return RECORD_TYPE_UNKNOWN;
740
741                 }
742
743         case RECORD_TNF_MIME:
744                 return RECORD_TYPE_MIME_TYPE;
745
746         case RECORD_TNF_EXTERNAL:
747                 return get_external_record_type(type, type_length);
748
749         }
750
751         return RECORD_TYPE_UNKNOWN;
752 }
753
754 static int build_record_type_string(struct near_ndef_record *rec)
755 {
756         uint8_t tnf;
757
758         DBG("");
759
760         if (rec == NULL || rec->header == NULL)
761                 return -EINVAL;
762
763         tnf = rec->header->tnf;
764
765         if (rec->header->rec_type == RECORD_TYPE_WKT_SMART_POSTER) {
766                 rec->type = g_strdup_printf(RECORD_TYPE_WKT "U");
767                 return 0;
768         }
769
770         switch (tnf) {
771         case RECORD_TNF_EMPTY:
772         case RECORD_TNF_UNKNOWN:
773         case RECORD_TNF_UNCHANGED:
774                 return -EINVAL;
775
776         case RECORD_TNF_URI:
777         case RECORD_TNF_MIME:
778                 rec->type = g_strndup(rec->header->type_name,
779                                       rec->header->type_len);
780                 break;
781
782         case RECORD_TNF_WELLKNOWN:
783                 rec->type = g_strdup_printf(RECORD_TYPE_WKT "%s",
784                                       rec->header->type_name);
785                 break;
786
787         case RECORD_TNF_EXTERNAL:
788                 rec->type = g_strdup_printf(RECORD_TYPE_EXTERNAL "%s",
789                                       rec->header->type_name);
790                 break;
791         }
792
793         return 0;
794 }
795
796 static uint8_t validate_record_begin_and_end_bits(uint8_t *msg_mb,
797                                         uint8_t *msg_me, uint8_t rec_mb,
798                                         uint8_t rec_me)
799 {
800         DBG("");
801
802         if (msg_mb == NULL || msg_me == NULL)
803                 return 0;
804
805         /* Validating record header begin and end bits
806          * eg: Single record: [mb:1,me:1]
807          *     Two records:   [mb:1,me:0 - mb:0,me:1]
808          *     Three or more records [mb:1,me:0 - mb:0,me:0 .. mb:0,me:1]
809          **/
810
811         if (rec_mb == 1) {
812                 if (*msg_mb != 1)
813                         *msg_mb = rec_mb;
814                 else
815                         return -EINVAL;
816
817         }
818
819         if (rec_me == 1) {
820                 if (*msg_me != 1) {
821                         if (*msg_mb == 1)
822                                 *msg_me = rec_me;
823                         else
824                                 return -EINVAL;
825
826                 } else
827                         return -EINVAL;
828
829         }
830
831         return 0;
832 }
833
834 /**
835  * @brief Parse the ndef record header.
836  *
837  * Parse the ndef record header and cache the begin, end, chunkflag,
838  * short-record and type-name-format bits. ID length and field, record
839  * type, payload length and offset (where payload byte starts in input
840  * parameter). Validate offset for every step forward against total
841  * available length.
842  *
843  * @note : Caller responsibility to free the memory.
844  *
845  * @param[in] rec      ndef byte stream
846  * @param[in] offset   record header offset
847  * @param[in] length   total length in byte stream
848  *
849  * @return struct near_ndef_record_header * RecordHeader on Success
850  *                                          NULL   on Failure
851  */
852 static struct near_ndef_record_header *parse_record_header(uint8_t *rec,
853                                         uint32_t offset, uint32_t length)
854 {
855         struct near_ndef_record_header *rec_header = NULL;
856         uint8_t *type = NULL;
857         uint32_t header_len = 0;
858
859         DBG("length %d", length);
860
861         if (rec == NULL || offset >= length)
862                 return NULL;
863
864         /* This check is for empty record. */
865         if ((length - offset) < NDEF_MSG_MIN_LENGTH)
866                 return NULL;
867
868         rec_header = g_try_malloc0(sizeof(struct near_ndef_record_header));
869         if (rec_header == NULL)
870                 return NULL;
871
872         rec_header->mb = RECORD_MB_BIT(rec[offset]);
873         rec_header->me = RECORD_ME_BIT(rec[offset]);
874         rec_header->sr = RECORD_SR_BIT(rec[offset]);
875         rec_header->il = RECORD_IL_BIT(rec[offset]);
876         rec_header->tnf = RECORD_TNF_BIT(rec[offset]);
877
878         DBG("mb %d me %d sr %d il %d tnf %d",
879                 rec_header->mb, rec_header->me, rec_header->sr,
880                 rec_header->il, rec_header->tnf);
881
882         offset++;
883         rec_header->type_len = rec[offset++];
884         header_len = 2; /* type length + header bits */
885
886         if (rec_header->sr == 1) {
887                 rec_header->payload_len = rec[offset++];
888                 header_len++;
889         } else {
890                 rec_header->payload_len =
891                         g_ntohl(*((uint32_t *)(rec + offset)));
892                 offset += 4;
893                 header_len += 4;
894
895                 if (offset >= length)
896                         goto fail;
897         }
898
899         DBG("payload length %d", rec_header->payload_len);
900
901         if (rec_header->il == 1) {
902                 rec_header->il_length = rec[offset++];
903                 header_len++;
904
905                 if (offset >= length)
906                         goto fail;
907         }
908
909         if (rec_header->type_len > 0) {
910                 if ((offset + rec_header->type_len) > length)
911                         goto fail;
912
913                 type = g_try_malloc0(rec_header->type_len);
914                 if (type == NULL)
915                         goto fail;
916
917                 memcpy(type, rec + offset, rec_header->type_len);
918                 offset += rec_header->type_len;
919                 header_len += rec_header->type_len;
920
921                 if (offset >= length)
922                         goto fail;
923         }
924
925         if (rec_header->il_length > 0) {
926                 if ((offset + rec_header->il_length) > length)
927                         goto fail;
928
929                 rec_header->il_field = g_try_malloc0(rec_header->il_length);
930                 if (rec_header->il_field == NULL)
931                         goto fail;
932
933                 memcpy(rec_header->il_field, rec + offset,
934                                         rec_header->il_length);
935                 offset += rec_header->il_length;
936                 header_len += rec_header->il_length;
937
938                 if (offset >= length)
939                         goto fail;
940         }
941
942         if ((offset + rec_header->payload_len) > length)
943                 goto fail;
944
945         rec_header->rec_type = get_record_type(rec_header->tnf, type,
946                                                         rec_header->type_len);
947         rec_header->offset = offset;
948         rec_header->header_len = header_len;
949         rec_header->type_name = g_strndup((char *) type, rec_header->type_len);
950
951         g_free(type);
952
953         return rec_header;
954
955 fail:
956         near_error("parsing record header failed");
957
958         g_free(type);
959         g_free(rec_header->il_field);
960         g_free(rec_header->type_name);
961         g_free(rec_header);
962
963         return NULL;
964 }
965
966 /**
967  * @brief Parse the Text record payload
968  *
969  * Parse the Text record.
970  *
971  * @param[in] rec     NDEF pointer set to record payload first byte
972  * @param[in] length  payload_len
973  *
974  * @return struct near_ndef_text_record * Record on Success
975  *                                       NULL   on Failure
976  */
977
978 static struct near_ndef_text_record *
979 parse_text_record(uint8_t *rec, uint32_t length)
980 {
981         struct near_ndef_text_record *text_record = NULL;
982         uint8_t status, lang_length;
983         uint32_t offset;
984
985         DBG("");
986
987         if (rec == NULL)
988                 return NULL;
989
990         offset = 0;
991         text_record = g_try_malloc0(sizeof(struct near_ndef_text_record));
992         if (text_record == NULL)
993                 return NULL;
994
995         /* 0x80 is used to get 7th bit value (0th bit is LSB) */
996         status = ((rec[offset] & 0x80) >> 7);
997
998         text_record->encoding = (status == 0) ?
999                                         g_strdup("UTF-8") : g_strdup("UTF-16");
1000
1001         /* 0x3F is used to get 5th-0th bits value (0th bit is LSB) */
1002         lang_length = (rec[offset] & 0x3F);
1003         offset++;
1004
1005         if (lang_length > 0) {
1006                 if ((offset + lang_length) >= length)
1007                         goto fail;
1008
1009                 text_record->language_code = g_strndup(
1010                                                 (char *)(rec + offset),
1011                                                 lang_length);
1012         } else {
1013                 text_record->language_code = NULL;
1014         }
1015
1016         offset += lang_length;
1017
1018         if ((length - lang_length - 1) > 0) {
1019                 text_record->data = g_strndup((char *)(rec + offset),
1020                                         length - lang_length - 1);
1021         } else {
1022                 text_record->data = NULL;
1023         }
1024
1025         if (offset >= length)
1026                 goto fail;
1027
1028         DBG("Encoding  '%s'", text_record->encoding);
1029         DBG("Language Code  '%s'", text_record->language_code);
1030         DBG("Data  '%s'", text_record->data);
1031
1032         return text_record;
1033
1034 fail:
1035         near_error("text record parsing failed");
1036         free_text_record(text_record);
1037
1038         return NULL;
1039 }
1040
1041 /**
1042  * @brief Parse the URI record payload
1043  *
1044  * Parse the URI record.
1045  *
1046  * @param[in] rec          NDEF pointer set to record payload first byte
1047  * @param[in] length  Payload length
1048  *
1049  * @return struct near_ndef_uri_record * Record on Success
1050  *                                       NULL   on Failure
1051  */
1052
1053 static struct near_ndef_uri_record *
1054 parse_uri_record(uint8_t *rec, uint32_t length)
1055 {
1056         struct near_ndef_uri_record *uri_record = NULL;
1057         uint32_t index, offset;
1058
1059         DBG("");
1060
1061         if (rec == NULL)
1062                 return NULL;
1063
1064         offset = 0;
1065         uri_record = g_try_malloc0(sizeof(struct near_ndef_uri_record));
1066         if (uri_record == NULL)
1067                 return NULL;
1068
1069         uri_record->identifier = rec[offset];
1070         offset++;
1071
1072         uri_record->field_length = length - 1;
1073
1074         if (uri_record->field_length > 0) {
1075                 uri_record->field = g_try_malloc0(uri_record->field_length);
1076                 if (uri_record->field == NULL)
1077                         goto fail;
1078
1079                 memcpy(uri_record->field, rec + offset,
1080                                 uri_record->field_length);
1081
1082                 for (index = 0; index < uri_record->field_length; index++) {
1083                         /* URI Record Type Definition 1.0 [3.2.3]
1084                          * Any character value within the URI between
1085                          * (and including) 0 and 31 SHALL be recorded as
1086                          * an error, and the URI record to be discarded */
1087                         if (uri_record->field[index] <= 31)
1088                                 goto fail;
1089                 }
1090
1091         }
1092
1093         DBG("Identifier  '0X%X'", uri_record->identifier);
1094         DBG("Field  '%.*s'", uri_record->field_length, uri_record->field);
1095
1096         return uri_record;
1097
1098 fail:
1099         near_error("uri record parsing failed");
1100         free_uri_record(uri_record);
1101
1102         return NULL;
1103 }
1104
1105 /**
1106  * @brief Validate titles records language code in Smartposter.
1107  * There must not be two or more records with the same language identifier.
1108  *
1109  * @param[in] GSList *  list of title records (struct near_ndef_text_record *)
1110  *
1111  * @return Zero on success
1112  *         Negative value on failure
1113  */
1114
1115 static int8_t validate_language_code_in_sp_record(GSList *titles)
1116 {
1117         uint8_t i, j, length;
1118         struct near_ndef_text_record *title1, *title2;
1119
1120         DBG("");
1121
1122         if (titles == NULL)
1123                 return -EINVAL;
1124
1125         length = g_slist_length(titles);
1126
1127         for (i = 0; i < length; i++) {
1128                 title1 = g_slist_nth_data(titles, i);
1129
1130                 for (j = i + 1; j < length; j++) {
1131                         title2 = g_slist_nth_data(titles, j);
1132
1133                         if ((title1->language_code == NULL) &&
1134                                         (title2->language_code == NULL))
1135                                 continue;
1136
1137                         if (g_strcmp0(title1->language_code,
1138                                         title2->language_code) == 0)
1139                                 return -EINVAL;
1140                 }
1141         }
1142
1143         return 0;
1144 }
1145
1146 /**
1147  * @brief Parse the smart poster record payload.
1148  *
1149  * Parse the smart poster record and cache the
1150  * data in respective fields of smart poster structure.
1151  *
1152  * @note Caller responsibility to free the memory.
1153  *
1154  * @param[in] rec         NDEF pointer set to record payload first byte
1155  * @param[in] length Record payload length
1156  *
1157  * @return struct near_ndef_sp_record * Record on Success
1158  *                                      NULL   on Failure
1159  */
1160
1161 static struct near_ndef_sp_record *
1162 parse_smart_poster_record(uint8_t *rec, uint32_t length)
1163 {
1164         struct near_ndef_sp_record *sp_record = NULL;
1165         struct near_ndef_record_header *rec_header = NULL;
1166         uint8_t mb = 0, me = 0, i;
1167         uint32_t offset;
1168         GSList *titles = NULL, *temp;
1169
1170         DBG("");
1171
1172         if (rec == NULL)
1173                 return NULL;
1174
1175         offset = 0;
1176         sp_record = g_try_malloc0(sizeof(struct near_ndef_sp_record));
1177         if (sp_record == NULL)
1178                 return NULL;
1179
1180         while (offset < length) {
1181
1182                 DBG("Record header : 0x%x", rec[offset]);
1183
1184                 rec_header = parse_record_header(rec, offset, length);
1185                 if (rec_header == NULL)
1186                         goto fail;
1187
1188                 if (validate_record_begin_and_end_bits(&mb, &me,
1189                                         rec_header->mb, rec_header->me) != 0) {
1190                         DBG("validate mb me failed");
1191                         goto fail;
1192                 }
1193
1194                 offset = rec_header->offset;
1195
1196                 switch (rec_header->rec_type) {
1197                 case RECORD_TYPE_WKT_SMART_POSTER:
1198                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
1199                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
1200                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
1201                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
1202                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
1203                 case RECORD_TYPE_MIME_TYPE:
1204                 case RECORD_TYPE_WKT_ERROR:
1205                 case RECORD_TYPE_UNKNOWN:
1206                 case RECORD_TYPE_ERROR:
1207                         break;
1208
1209                 case RECORD_TYPE_WKT_URI:
1210                         /* URI record should be only one. */
1211                         if (sp_record->uri != NULL)
1212                                 goto fail;
1213
1214                         sp_record->uri = parse_uri_record(rec + offset,
1215                                                 rec_header->payload_len);
1216                         if (sp_record->uri == NULL)
1217                                 goto fail;
1218
1219                         break;
1220
1221                 case RECORD_TYPE_WKT_TEXT:
1222                         /*
1223                          * Title records can zero or more. First fill the
1224                          * records in list and validate language identifier
1225                          * and then cache them into sp record structure.
1226                          */
1227                         {
1228                         struct near_ndef_text_record *title;
1229                         title = parse_text_record(rec + offset,
1230                                                 rec_header->payload_len);
1231                         if (title == NULL)
1232                                 goto fail;
1233
1234                         titles = g_slist_append(titles, title);
1235                         }
1236                         break;
1237
1238                 case RECORD_TYPE_WKT_SIZE:
1239                         /*
1240                          * If payload length is not exactly 4 bytes
1241                          * then record is wrong.
1242                          */
1243                         if (rec_header->payload_len != 4)
1244                                 goto fail;
1245
1246                         sp_record->size =
1247                                 g_ntohl(*((uint32_t *)(rec + offset)));
1248                         break;
1249
1250                 case RECORD_TYPE_WKT_TYPE:
1251
1252                         if (rec_header->payload_len > 0) {
1253                                 sp_record->type = g_try_malloc0(
1254                                                 rec_header->payload_len);
1255                                 if (sp_record->type == NULL)
1256                                         goto fail;
1257
1258                                 sp_record->type = g_strndup(
1259                                                 (char *) rec + offset,
1260                                                 rec_header->payload_len);
1261                         }
1262
1263                         break;
1264
1265                 case RECORD_TYPE_WKT_ACTION:
1266                         /*
1267                          * If the action record exists, payload should be
1268                          * single byte, otherwise consider it as error.
1269                          */
1270                         if (rec_header->payload_len != 1)
1271                                 goto fail;
1272
1273                         sp_record->action =
1274                                 g_strdup(action_to_string(rec[offset]));
1275
1276                         break;
1277                 }
1278
1279                 offset += rec_header->payload_len;
1280                 g_free(rec_header->il_field);
1281                 g_free(rec_header->type_name);
1282                 g_free(rec_header);
1283                 rec_header = NULL;
1284         }
1285
1286         /*
1287          * Code to fill smart poster record structure from
1288          * 'titles' list.
1289          */
1290         if (titles == NULL)
1291                 return sp_record;
1292
1293         if (validate_language_code_in_sp_record(titles) != 0) {
1294                 DBG("language code validation failed");
1295                 goto fail;
1296         }
1297
1298         temp = titles;
1299         sp_record->number_of_title_records = g_slist_length(temp);
1300         sp_record->title_records = g_try_malloc0(
1301                                 sp_record->number_of_title_records *
1302                                  sizeof(struct near_ndef_text_record *));
1303         if (sp_record->title_records == NULL)
1304                 goto fail;
1305
1306         for (i = 0; i < sp_record->number_of_title_records; i++) {
1307                 sp_record->title_records[i] = temp->data;
1308                 temp = temp->next;
1309         }
1310
1311         g_slist_free(titles);
1312         titles = NULL;
1313
1314         return sp_record;
1315
1316 fail:
1317         near_error("smart poster record parsing failed");
1318
1319         if (rec_header != NULL) {
1320                 g_free(rec_header->type_name);
1321                 g_free(rec_header->il_field);
1322                 g_free(rec_header);
1323         }
1324
1325         free_sp_record(sp_record);
1326         g_slist_free(titles);
1327
1328         return NULL;
1329 }
1330
1331 static struct near_ndef_mime_record *
1332 parse_mime_type(struct near_ndef_record *record,
1333                         uint8_t *ndef_data, size_t ndef_length, size_t offset,
1334                         uint32_t payload_length, near_bool_t action)
1335 {
1336         struct near_ndef_mime_record *mime = NULL;
1337         int err = 0;
1338
1339         DBG("");
1340
1341         if ((ndef_data == NULL) || ((offset + payload_length) > ndef_length))
1342                 return NULL;
1343
1344         mime = g_try_malloc0(sizeof(struct near_ndef_mime_record));
1345         if (mime == NULL)
1346                 return NULL;
1347
1348         mime->type = g_strdup(record->header->type_name);
1349
1350         DBG("MIME Type  '%s' action: %d", mime->type, action);
1351         if (strcmp(mime->type, BT_MIME_STRING_2_1) == 0) {
1352                 err = __near_bluetooth_parse_oob_record(BT_MIME_V2_1,
1353                                 &ndef_data[offset], action);
1354         } else if (strcmp(mime->type, BT_MIME_STRING_2_0) == 0) {
1355                 err = __near_bluetooth_parse_oob_record(BT_MIME_V2_0,
1356                                 &ndef_data[offset], action);
1357         }
1358
1359         if (err < 0) {
1360                 DBG("Parsing mime error %d", err);
1361                 g_free(mime->type);
1362                 g_free(mime);
1363                 return NULL;
1364         }
1365
1366         return mime;
1367 }
1368
1369 /* Set the MB/ME bit in message header */
1370 static uint8_t near_ndef_set_mb_me(uint8_t *hdr, near_bool_t first_rec,
1371                                                 near_bool_t last_rec)
1372 {
1373         /* Reset bits 0x40 and 0x80*/
1374         *hdr &= (0xFF & (~(RECORD_MB | RECORD_ME)));
1375
1376         /* Set if needed */
1377         if (first_rec == TRUE)
1378                 *hdr |= RECORD_MB;
1379         if (last_rec == TRUE)
1380                 *hdr |= RECORD_ME;
1381
1382         return *hdr;
1383 }
1384
1385 /**
1386  * @brief Allocates ndef message structure
1387  *
1388  * Allocates ndef message structure and fill message header byte,
1389  * type length byte, payload length and type name. Offset is payload
1390  * first byte (caller of this API can start filling their payload
1391  * from offset value).
1392  *
1393  * @note : caller responsibility to free the input and output
1394  *         parameters memory.
1395  *
1396  * @param[in] type_name    Record type name
1397  * @param[in] payload_len  Record payload length
1398  * @param[in] payload_id   Record payload id string
1399  * @param[in] payload_id_len  Record payload id string length
1400  * @param[in] tnf          Type name format to set
1401  * @param[in] first_rec    Message begin (MB) flag
1402  * @param[in] last_rec     Message end (ME) flag
1403  *
1404  * @return struct near_ndef_message * - Success
1405  *         NULL - Failure
1406  */
1407 static struct near_ndef_message *ndef_message_alloc_complete(char *type_name,
1408                 uint32_t payload_len,
1409                 char *payload_id,
1410                 uint8_t payload_id_len,
1411                 enum record_tnf tnf,
1412                 near_bool_t first_rec,
1413                 near_bool_t last_rec)
1414 {
1415         struct near_ndef_message *msg;
1416         uint8_t hdr = 0, type_len, sr_bit, il_bit, id_len;
1417
1418         msg = g_try_malloc0(sizeof(struct near_ndef_message));
1419         if (msg == NULL)
1420                 return NULL;
1421
1422         msg->length = 0;
1423         msg->offset = 0;
1424         msg->length++; /* record header*/
1425         msg->length++; /* type name length byte*/
1426
1427         type_len = (type_name != NULL) ? strlen(type_name) : 0;
1428         id_len = (payload_id != NULL) ? payload_id_len : 0;
1429         sr_bit =  (payload_len <= NDEF_MSG_SHORT_RECORD_MAX_LENGTH)
1430                                         ? TRUE : FALSE;
1431
1432         il_bit = (payload_id != NULL) ? TRUE : FALSE;
1433
1434         msg->length += (sr_bit == TRUE) ? 1 : 4;
1435         msg->length += (il_bit == TRUE) ? 1 : 0;
1436         msg->length += type_len;
1437         msg->length += payload_len;
1438         msg->length += id_len;
1439
1440         msg->data = g_try_malloc0(msg->length);
1441         if (msg->data == NULL)
1442                 goto fail;
1443
1444         /* Set MB ME bits */
1445         hdr = near_ndef_set_mb_me(&hdr, first_rec, last_rec);
1446
1447         if (sr_bit == TRUE)
1448                 hdr |= RECORD_SR;
1449
1450         hdr = RECORD_TNF_WKT_SET(hdr);
1451         if (il_bit == TRUE)
1452                 hdr |= RECORD_IL;
1453
1454         switch (tnf) {
1455         case RECORD_TNF_EMPTY:
1456                 hdr = RECORD_TNF_EMPTY_SET(hdr);
1457                 break;
1458
1459         case RECORD_TNF_URI:
1460                 hdr = RECORD_TNF_URI_SET(hdr);
1461                 break;
1462
1463         case RECORD_TNF_EXTERNAL:
1464                 hdr = RECORD_TNF_EXTERNAL_SET(hdr);
1465                 break;
1466         case RECORD_TNF_UNKNOWN:
1467                 hdr = RECORD_TNF_UKNOWN_SET(hdr);
1468                 break;
1469
1470         case RECORD_TNF_UNCHANGED:
1471                 hdr = RECORD_TNF_UNCHANGED_SET(hdr);
1472                 break;
1473
1474         case RECORD_TNF_WELLKNOWN:
1475                 hdr = RECORD_TNF_WKT_SET(hdr);
1476                 break;
1477
1478         case RECORD_TNF_MIME:
1479                 hdr = RECORD_TNF_MIME_SET(hdr);
1480                 break;
1481         }
1482
1483         msg->data[msg->offset++] = hdr;
1484         msg->data[msg->offset++] = type_len;
1485
1486         if (sr_bit == TRUE) {
1487                 msg->data[msg->offset++] = payload_len;
1488         } else {
1489                 fillb32((msg->data + msg->offset), payload_len);
1490                 msg->offset += 4;
1491         }
1492
1493         if (il_bit == TRUE)
1494                 msg->data[msg->offset++] = payload_id_len;
1495
1496         if (type_name != NULL) {
1497                 memcpy(msg->data + msg->offset, type_name, type_len);
1498                 msg->offset += type_len;
1499         }
1500
1501         if (il_bit == TRUE) {
1502                 memcpy(msg->data + msg->offset, payload_id, payload_id_len);
1503                 msg->offset += payload_id_len;
1504         }
1505
1506         return msg;
1507
1508 fail:
1509         near_error("ndef message struct allocation failed");
1510         g_free(msg->data);
1511         g_free(msg);
1512
1513         return NULL;
1514 }
1515
1516 /*
1517  *  @brief Allocates ndef message structure
1518  *
1519  *  This is a wrapper to ndef_message_alloc, as, in most cases,
1520  *  there's no payload id, and MB=TRUE and ME=TRUE. Default type name format
1521  *  is also set to RECORD_TNF_WELLKNOWN
1522  *
1523  */
1524 static struct near_ndef_message *ndef_message_alloc(char* type_name,
1525                                                         uint32_t payload_len)
1526 {
1527         return ndef_message_alloc_complete(type_name, payload_len,
1528                         NULL, 0,
1529                         RECORD_TNF_WELLKNOWN,
1530                         TRUE, TRUE);
1531 }
1532
1533 static struct near_ndef_ac_record *parse_ac_record(uint8_t *rec,
1534                                                 uint32_t length)
1535 {
1536         struct near_ndef_ac_record *ac_record = NULL;
1537         uint32_t offset;
1538
1539         DBG("");
1540
1541         if (rec == NULL)
1542                 return NULL;
1543
1544         offset = 0;
1545         ac_record = g_try_malloc0(sizeof(struct near_ndef_ac_record));
1546         if (ac_record == NULL)
1547                 goto fail;
1548
1549         /* Carrier flag */
1550         ac_record->cps = rec[offset];    /* TODO Check enum */
1551         offset++;
1552
1553         /* Carrier data reference length */
1554         ac_record->cdr_len = rec[offset];
1555         offset++;
1556
1557         /* Carrier data reference */
1558         ac_record->cdr = rec[offset];
1559         offset = offset + ac_record->cdr_len;
1560
1561         /* Auxiliary data reference count */
1562         ac_record->adata_refcount = rec[offset];
1563         offset++;
1564
1565         if (ac_record->adata_refcount == 0)
1566                 return ac_record;
1567
1568         /* save the auxiliary data reference */
1569         ac_record->adata = g_try_malloc0(
1570                         ac_record->adata_refcount * sizeof(uint16_t));
1571         if (ac_record->adata == NULL)
1572                 goto fail;
1573
1574         memcpy(ac_record->adata, rec + offset,
1575                         ac_record->adata_refcount * sizeof(uint16_t));
1576
1577         /* and leave */
1578         return ac_record;
1579
1580 fail:
1581         near_error("ac record parsing failed");
1582         free_ac_record(ac_record);
1583
1584         return NULL;
1585 }
1586
1587 /* carrier power state & carrier reference */
1588 static struct near_ndef_message *near_ndef_prepare_ac_message(uint8_t cps,
1589                                                                 char cdr)
1590 {
1591         struct near_ndef_message *ac_msg;
1592
1593         /* alloc "ac" message minus adata*/
1594         ac_msg = ndef_message_alloc_complete("ac", AC_RECORD_PAYLOAD_LEN,
1595                                         NULL, 0,
1596                                         RECORD_TNF_WELLKNOWN,
1597                                         TRUE, TRUE);
1598         if (ac_msg == NULL)
1599                 return NULL;
1600
1601         /* Prepare ac message */
1602         ac_msg->data[ac_msg->offset++] = cps;
1603         ac_msg->data[ac_msg->offset++] = 1;     /* cdr_len def size */
1604         ac_msg->data[ac_msg->offset++] = cdr;   /* cdr */
1605         ac_msg->data[ac_msg->offset] = 0;       /* adata ref count */
1606
1607         return ac_msg;
1608 }
1609
1610 /* Collision Record message */
1611 static struct near_ndef_message *near_ndef_prepare_cr_message(uint16_t cr_id)
1612 {
1613         struct near_ndef_message *cr_msg;
1614
1615         cr_msg = ndef_message_alloc_complete("cr", sizeof(uint16_t),
1616                                                 NULL, 0,
1617                                                 RECORD_TNF_WELLKNOWN,
1618                                                 TRUE, TRUE);
1619         if (cr_msg == NULL)
1620                 return NULL;
1621
1622         /* Prepare ac message */
1623         *(uint16_t *)(cr_msg->data + cr_msg->offset) = g_htons(cr_id);
1624
1625         return cr_msg;
1626 }
1627
1628 /* Prepare the bluetooth data record */
1629 static struct near_ndef_message *near_ndef_prepare_bt_message(uint8_t *bt_data,
1630                         int bt_data_len, char cdr, uint8_t cdr_len)
1631 {
1632         struct near_ndef_message *bt_msg = NULL;
1633
1634         if (bt_data == NULL)
1635                 goto fail;
1636
1637         bt_msg = ndef_message_alloc_complete(BT_MIME_STRING_2_1, bt_data_len,
1638                                         &cdr, cdr_len, RECORD_TNF_MIME,
1639                                         TRUE, TRUE);
1640         if (bt_msg == NULL)
1641                 goto fail;
1642
1643         /* store data */
1644         memcpy(bt_msg->data + bt_msg->offset, bt_data, bt_data_len);
1645
1646         return bt_msg;
1647
1648 fail:
1649         if (bt_msg != NULL)
1650                 g_free(bt_msg->data);
1651
1652         g_free(bt_msg);
1653
1654         return NULL;
1655 }
1656
1657 /*
1658  * @brief Prepare Handover select record with mandatory fields.
1659  *
1660  * TODO: only mime (BT) are supported now... Wifi will come soon...
1661  * Only 1 ac record + 1 collision record+ Hr header
1662  */
1663 struct near_ndef_message *near_ndef_prepare_handover_record(char* type_name,
1664                                         struct near_ndef_record *record,
1665                                         enum near_ndef_handover_carrier carrier)
1666 {
1667         uint8_t *oob_data = NULL;
1668         int oob_size;
1669         struct near_ndef_message *hs_msg = NULL;
1670         struct near_ndef_message *ac_msg = NULL;
1671         struct near_ndef_message *cr_msg = NULL;
1672         struct near_ndef_message *bt_msg = NULL;
1673         uint16_t collision;
1674         uint8_t hs_length;
1675         char cdr = '0';                 /* Carrier data reference */
1676
1677         if (record->ho == NULL)
1678                 goto fail;
1679
1680         collision = record->ho->collision_record;
1681
1682         /*
1683          * Prepare records to be added
1684          * now prepare the cr message: MB=1 ME=0
1685          */
1686         if (collision != 0) {
1687                 cr_msg = near_ndef_prepare_cr_message(collision);
1688                 if (cr_msg == NULL)
1689                         goto fail;
1690         }
1691
1692         /*
1693          * ac record: if only one: MB=0 ME=1
1694          * cps should be active
1695          */
1696         ac_msg = near_ndef_prepare_ac_message(CPS_ACTIVE, cdr);
1697         if (ac_msg == NULL)
1698                 goto fail;
1699
1700         switch (carrier) {
1701         case NEAR_CARRIER_BLUETOOTH:
1702                 /* Retrieve the bluetooth settings */
1703                 oob_data = __near_bluetooth_local_get_properties(&oob_size);
1704                 if (oob_data == NULL) {
1705                         near_error("Getting Bluetooth OOB data failed");
1706                         goto fail;
1707                 }
1708
1709                 bt_msg = near_ndef_prepare_bt_message(oob_data, oob_size,
1710                                                                 cdr, 1);
1711                 if (bt_msg == NULL)
1712                         goto fail;
1713
1714                 near_ndef_set_mb_me(bt_msg->data, FALSE, TRUE);
1715
1716                 break;
1717
1718         case NEAR_CARRIER_WIFI:
1719                 goto fail;
1720         }
1721
1722         /*
1723          * Build the complete handover frame
1724          * Prepare Hs or Hr message (1 for version)
1725          */
1726         hs_length = 1 + ac_msg->length;
1727         if (cr_msg != NULL)
1728                 hs_length += cr_msg->length;
1729
1730         if (bt_msg != NULL)
1731                 hs_msg = ndef_message_alloc(type_name, hs_length +
1732                                                                 bt_msg->length);
1733         else
1734                 hs_msg = ndef_message_alloc(type_name, hs_length);
1735         if (hs_msg == NULL)
1736                 goto fail;
1737
1738         /*
1739          * The handover payload length is not the *real* length.
1740          * The PL refers to the NDEF record, not the extra ones.
1741          * So, we have to fix the payload length in the header.
1742          */
1743         hs_msg->data[NDEF_PAYLOAD_LENGTH_OFFSET] = hs_length;
1744
1745         /* Fill the message .... */
1746         near_ndef_set_mb_me(hs_msg->data, TRUE, FALSE);
1747
1748         /* Add version */
1749         hs_msg->data[hs_msg->offset++] = HANDOVER_VERSION;
1750
1751         /* copy cr */
1752         if (cr_msg != NULL) {
1753                 near_ndef_set_mb_me(cr_msg->data, TRUE, FALSE);
1754                 memcpy(hs_msg->data + hs_msg->offset, cr_msg->data,
1755                                 cr_msg->length);
1756                 hs_msg->offset += cr_msg->length;
1757         }
1758
1759         /* copy ac */
1760         if (cr_msg != NULL)
1761                 near_ndef_set_mb_me(ac_msg->data, FALSE, TRUE);
1762         else
1763                 near_ndef_set_mb_me(ac_msg->data, TRUE, TRUE);
1764
1765         memcpy(hs_msg->data + hs_msg->offset, ac_msg->data, ac_msg->length);
1766         hs_msg->offset += ac_msg->length;
1767
1768         if (hs_msg->offset > hs_msg->length)
1769                 goto fail;
1770
1771         /*
1772          * Additional NDEF (associated to the ac records)
1773          * Add the BT record which is not part in hs initial size
1774          */
1775         if (bt_msg != NULL) {
1776                 near_ndef_set_mb_me(hs_msg->data, TRUE, FALSE);
1777
1778                 memcpy(hs_msg->data + hs_msg->offset, bt_msg->data,
1779                                                         bt_msg->length);
1780         }
1781
1782         if (ac_msg != NULL) {
1783                 g_free(ac_msg->data);
1784                 g_free(ac_msg);
1785         }
1786
1787         if (cr_msg != NULL) {
1788                 g_free(cr_msg->data);
1789                 g_free(cr_msg);
1790         }
1791
1792         if (bt_msg != NULL) {
1793                 g_free(bt_msg->data);
1794                 g_free(bt_msg);
1795         }
1796
1797         g_free(oob_data);
1798
1799         DBG("Hs NDEF done");
1800
1801         return hs_msg;
1802
1803 fail:
1804         near_error("handover select record preparation failed");
1805
1806         if (ac_msg != NULL) {
1807                 g_free(ac_msg->data);
1808                 g_free(ac_msg);
1809         }
1810
1811         if (cr_msg != NULL) {
1812                 g_free(cr_msg->data);
1813                 g_free(cr_msg);
1814         }
1815
1816         if (hs_msg != NULL) {
1817                 g_free(hs_msg->data);
1818                 g_free(hs_msg);
1819         }
1820
1821         if (bt_msg != NULL) {
1822                 g_free(bt_msg->data);
1823                 g_free(bt_msg);
1824         }
1825
1826         g_free(oob_data);
1827
1828         return NULL;
1829 }
1830
1831 /* Code to fill hr record structure from acs and mimes lists */
1832 static int near_fill_ho_record(struct near_ndef_ho_record *ho,
1833                                         GSList *acs, GSList *mimes)
1834 {
1835         int rec_count;
1836         int i;
1837         GSList *temp;
1838
1839         rec_count = g_slist_length(acs);
1840         ho->ac_records = g_try_malloc0(rec_count *
1841                         sizeof(struct near_ndef_ac_record *));
1842         if (ho->ac_records == NULL)
1843                 goto fail;
1844         temp = acs;
1845         for (i = 0; i < rec_count; i++) {
1846                 ho->ac_records[i] = temp->data;
1847                 temp = temp->next;
1848         }
1849         ho->number_of_ac_records = rec_count;
1850         g_slist_free(acs);
1851
1852         /* Same process for cfg mimes */
1853         rec_count = g_slist_length(mimes);
1854         ho->cfg_records = g_try_malloc0(rec_count *
1855                         sizeof(struct near_ndef_mime_record *));
1856         if (ho->cfg_records == NULL)
1857                 goto fail;
1858         temp = mimes;
1859         for (i = 0; i < rec_count; i++) {
1860                 ho->cfg_records[i] = temp->data;
1861                 temp = temp->next;
1862         }
1863
1864         ho->number_of_cfg_records = rec_count;
1865         g_slist_free(mimes);
1866
1867         return 0;
1868 fail:
1869         g_free(ho->ac_records);
1870         g_free(ho->cfg_records);
1871         ho->ac_records = NULL;
1872         ho->cfg_records = NULL;
1873         return -ENOMEM;
1874 }
1875
1876 /*
1877  * @brief Parse the Handover request record
1878  * This function will parse an Hr record, retrieving sub records
1879  * like (ac, cr, er) but it  will also get the associated
1880  * ndefs (eg: handover carrier record, mime type for BT)
1881  * In a handover frame, only the following types are expected:
1882  *     RECORD_TYPE_WKT_HANDOVER_CARRIER:
1883  *     RECORD_TYPE_WKT_COLLISION_RESOLUTION
1884  *     RECORD_TYPE_MIME_TYPE
1885  *     RECORD_TYPE_WKT_ALTERNATIVE_CARRIER
1886  */
1887 static struct near_ndef_ho_record *parse_ho_record(enum record_type rec_type,
1888                 uint8_t *rec, uint32_t ho_length, size_t frame_length,
1889                 uint8_t ho_mb, uint8_t ho_me)
1890 {
1891         struct near_ndef_ho_record *ho_record = NULL;
1892         struct near_ndef_ac_record *ac = NULL;
1893         struct near_ndef_mime_record *mime = NULL;
1894         struct near_ndef_record *trec = NULL;
1895         GSList *acs = NULL, *mimes = NULL;
1896         uint8_t mb = 0, me = 0;
1897         uint32_t offset;
1898         int16_t count_ac = 0;
1899         near_bool_t bt_pair;
1900
1901         DBG("");
1902
1903         if (rec == NULL)
1904                 return NULL;
1905         offset = 0;
1906
1907         /* Create the handover record */
1908         ho_record = g_try_malloc0(sizeof(struct near_ndef_ho_record));
1909         if (ho_record == NULL)
1910                 return NULL;
1911
1912         /* Version is the first mandatory field of hr record */
1913         ho_record->version = rec[offset];
1914         if (ho_record->version > HANDOVER_VERSION) {
1915                 near_error("Unsupported version (%d)", ho_record->version);
1916                 goto fail;
1917         }
1918
1919         offset = offset + 1;
1920         frame_length = frame_length - 1;        /* Remove Hr length size */
1921
1922         /* We should work on the whole frame */
1923         ho_length = frame_length;
1924
1925         while (offset < ho_length) {
1926                 /* Create local record for mime parsing */
1927                 trec = g_try_malloc0(sizeof(struct near_ndef_record));
1928                 if (trec == NULL)
1929                         return NULL;
1930
1931                 trec->header = parse_record_header(rec, offset, ho_length);
1932
1933                 if (trec->header == NULL)
1934                         goto fail;
1935
1936                 offset = trec->header->offset;
1937
1938                 switch (trec->header->rec_type) {
1939                 case RECORD_TYPE_WKT_SMART_POSTER:
1940                 case RECORD_TYPE_WKT_SIZE:
1941                 case RECORD_TYPE_WKT_TEXT:
1942                 case RECORD_TYPE_WKT_TYPE:
1943                 case RECORD_TYPE_WKT_ACTION:
1944                 case RECORD_TYPE_WKT_URI:
1945                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
1946                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
1947                 case RECORD_TYPE_WKT_ERROR:
1948                 case RECORD_TYPE_UNKNOWN:
1949                 case RECORD_TYPE_ERROR:
1950                         break;
1951
1952                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
1953                         DBG("HANDOVER_CARRIER");
1954                         /*
1955                          * TODO process Hc record too !!!
1956                          * Used for Wifi session
1957                          */
1958                         break;
1959
1960                 case RECORD_TYPE_MIME_TYPE:
1961                         DBG("TYPE_MIME_TYPE");
1962
1963                         /* check mb/me bits */
1964                         if (validate_record_begin_and_end_bits(&ho_mb, &ho_me,
1965                                 trec->header->mb, trec->header->me) != 0) {
1966                                 DBG("validate mb me failed");
1967                                 goto fail;
1968                         }
1969
1970                         /*
1971                          * In Handover, the mime type gives bluetooth handover
1972                          * configuration datas.
1973                          * If we initiated the session, the received Hs frame
1974                          * is the signal to launch the pairing.
1975                          */
1976                         if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT)
1977                                 bt_pair = TRUE;
1978                         else
1979                                 bt_pair = FALSE;
1980
1981                         mime = parse_mime_type(trec, rec, frame_length,
1982                                         offset, trec->header->payload_len,
1983                                         bt_pair);
1984                         if (mime == NULL)
1985                                 goto fail;
1986
1987                         /* add the mime to the list */
1988                         mimes = g_slist_append(mimes, mime);
1989                         count_ac--;
1990                         if (count_ac == 0)
1991                                 offset = ho_length;
1992                         break;
1993
1994                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
1995                         DBG("COLLISION_RESOLUTION");
1996
1997                         /* check nested mb/me bits */
1998                         if (validate_record_begin_and_end_bits(&mb, &me,
1999                                 trec->header->mb, trec->header->me) != 0) {
2000                                 DBG("validate mb me failed");
2001                                 goto fail;
2002                         }
2003
2004                         ho_record->collision_record =
2005                                         g_ntohs(*((uint16_t *)(rec + offset)));
2006                         break;
2007
2008                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2009                         DBG("ALTERNATIVE_CARRIER");
2010
2011                         /* check nested mb/me bits */
2012                         if (validate_record_begin_and_end_bits(&mb, &me,
2013                                 trec->header->mb, trec->header->me) != 0) {
2014                                 DBG("validate mb me failed");
2015                                 goto fail;
2016                         }
2017
2018                         ac = parse_ac_record(rec + offset,
2019                                         trec->header->payload_len);
2020                         if (ac == NULL)
2021                                 goto fail;
2022
2023                         acs = g_slist_append(acs, ac);
2024
2025                         /* TODO check if adata are present */
2026                         count_ac++;
2027                         break;
2028                 }
2029
2030                 offset += trec->header->payload_len;
2031                 g_free(trec->header->il_field);
2032                 g_free(trec->header->type_name);
2033                 g_free(trec->header);
2034                 trec->header = NULL;
2035
2036                 g_free(trec);
2037         }
2038
2039         if ((acs == NULL) || (mimes == NULL))
2040                 return ho_record;
2041
2042         /* Save the records */
2043         if (near_fill_ho_record(ho_record, acs, mimes) < 0)
2044                 goto fail;
2045
2046         DBG("handover record parsing complete");
2047
2048         return ho_record;
2049
2050 fail:
2051         near_error("handover record parsing failed");
2052
2053         if (trec != NULL) {
2054                 if (trec->header != NULL) {
2055                         g_free(trec->header->type_name);
2056                         g_free(trec->header->il_field);
2057                         g_free(trec->header);
2058                 }
2059                 g_free(trec);
2060         }
2061
2062         free_ho_record(ho_record);
2063
2064         return NULL;
2065 }
2066
2067 int __near_ndef_record_register(struct near_ndef_record *record, char *path)
2068 {
2069         record->path = path;
2070
2071         g_dbus_register_interface(connection, record->path,
2072                                                 NFC_RECORD_INTERFACE,
2073                                                 record_methods,
2074                                                 NULL, NULL,
2075                                                 record, NULL);
2076
2077         return 0;
2078 }
2079
2080 GList *near_ndef_parse(uint8_t *ndef_data, size_t ndef_length)
2081 {
2082         GList *records;
2083         uint8_t p_mb = 0, p_me = 0, *record_start;
2084         size_t offset = 0;
2085         struct near_ndef_record *record = NULL;
2086
2087         DBG("");
2088
2089         records = NULL;
2090
2091         if (ndef_data == NULL ||
2092                 ndef_length < NDEF_MSG_MIN_LENGTH)
2093                         goto fail;
2094
2095         while (offset < ndef_length) {
2096
2097                 DBG("Record Header : 0x%X", ndef_data[offset]);
2098
2099                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2100                 if (record == NULL)
2101                         goto fail;
2102
2103                 record->header = parse_record_header(ndef_data, offset,
2104                                                         ndef_length);
2105                 if (record->header == NULL)
2106                         goto fail;
2107
2108                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2109                                         record->header->mb,
2110                                         record->header->me) != 0) {
2111                         DBG("validate mb me failed");
2112                         goto fail;
2113                 }
2114
2115                 record_start = ndef_data + offset;
2116                 offset = record->header->offset;
2117
2118                 switch (record->header->rec_type) {
2119                 case RECORD_TYPE_WKT_SIZE:
2120                 case RECORD_TYPE_WKT_TYPE:
2121                 case RECORD_TYPE_WKT_ACTION:
2122                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2123                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2124                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2125                 case RECORD_TYPE_WKT_ERROR:
2126                 case RECORD_TYPE_UNKNOWN:
2127                 case RECORD_TYPE_ERROR:
2128                         break;
2129
2130                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2131                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2132                         /*
2133                          * Handover frame are a little bit special as the NDEF
2134                          * length (specified in the header) is not the real
2135                          * frame size. The complete frame includes extra NDEF
2136                          * following the initial handover NDEF
2137                          */
2138                         record->ho = parse_ho_record(record->header->rec_type,
2139                                         ndef_data + offset,
2140                                         record->header->payload_len,
2141                                         ndef_length,
2142                                         record->header->mb, record->header->me);
2143                         if (record->ho == NULL)
2144                                 goto fail;
2145
2146                         /* the complete frame is processed, break the loop */
2147                         record->header->payload_len = ndef_length;
2148                         break;
2149
2150                 case RECORD_TYPE_WKT_TEXT:
2151                         record->text = parse_text_record(ndef_data + offset,
2152                                                 record->header->payload_len);
2153
2154                         if (record->text == NULL)
2155                                 goto fail;
2156
2157                         break;
2158
2159                 case RECORD_TYPE_WKT_URI:
2160                         record->uri = parse_uri_record(ndef_data + offset,
2161                                                 record->header->payload_len);
2162
2163                         if (record->uri == NULL)
2164                                 goto fail;
2165
2166                         break;
2167
2168                 case RECORD_TYPE_WKT_SMART_POSTER:
2169                         record->sp = parse_smart_poster_record(
2170                                                 ndef_data + offset,
2171                                                 record->header->payload_len);
2172
2173                         if (record->sp == NULL)
2174                                 goto fail;
2175
2176                         break;
2177
2178                 case RECORD_TYPE_MIME_TYPE:
2179                         record->mime = parse_mime_type(record, ndef_data,
2180                                                 ndef_length, offset,
2181                                                 record->header->payload_len,
2182                                                 TRUE);
2183
2184
2185                         if (record->mime == NULL)
2186                                 goto fail;
2187
2188                         break;
2189                 }
2190
2191                 record->data_len = record->header->header_len +
2192                                         record->header->payload_len;
2193
2194                 record->data = g_try_malloc0(record->data_len);
2195                 if (record->data == NULL)
2196                         goto fail;
2197
2198                 memcpy(record->data, record_start, record->data_len);
2199
2200                 records = g_list_append(records, record);
2201
2202                 build_record_type_string(record);
2203
2204                 offset += record->header->payload_len;
2205         }
2206
2207         return records;
2208
2209 fail:
2210         near_error("ndef parsing failed");
2211         free_ndef_record(record);
2212
2213         return records;
2214 }
2215
2216 void near_ndef_records_free(GList *records)
2217 {
2218         GList *list;
2219
2220         for (list = records; list; list = list->next) {
2221                 struct near_ndef_record *record = list->data;
2222
2223                 __near_ndef_record_free(record);
2224         }
2225
2226         g_list_free(records);
2227 }
2228
2229 /*
2230  * @brief Compute an NDEF record length
2231  *
2232  * Would compute ndef records length, even though the submitted frame
2233  * is incomplete. This code is used in the handover read function, as
2234  * we have to "guess" the final frame size.
2235  *
2236  * Message size for SR=1 is:
2237  *  1 : ndef rec header (offset 0)
2238  *  x : record type length (offset 1)
2239  *  y : payload length (offset 2) 1 byte ONLY if SR=1
2240  *      if SR=0: (4bytes) 32 bits
2241  *  z : payload id length (offset 3) ONLY if il_length=1
2242  * */
2243 int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length)
2244 {
2245         int ndef_size;   /* default size for NDEF hdr + rec typ len + payl */
2246         size_t offset;
2247         uint8_t hdr;
2248
2249         DBG("");
2250
2251         if (ndef_in_length < 3)
2252                 return -EINVAL;
2253
2254         ndef_size = 3;
2255         offset = 0;
2256
2257         /* save header byte */
2258         hdr = ndef_in[offset];
2259         offset++;
2260
2261         /* header->type_len */
2262         ndef_size += ndef_in[offset++];
2263
2264         /* header->payload_len */
2265         if (RECORD_SR_BIT(hdr) == 1) {
2266                 ndef_size += ndef_in[offset++];
2267         } else {
2268                 ndef_size += g_ntohl(*((uint32_t *)(ndef_in + offset)));
2269                 offset += 4;
2270
2271                 if (offset >= ndef_in_length)
2272                         return -ERANGE;
2273         }
2274
2275         /* header->il */
2276         ndef_size += RECORD_IL_BIT(hdr);
2277
2278         /* header->il_length */
2279         if (RECORD_IL_BIT(hdr) == 1)
2280                 ndef_size += ndef_in[offset++];
2281
2282         DBG("near_ndef_message_length is %d", ndef_size);
2283
2284         return ndef_size;
2285 }
2286
2287 int near_ndef_count_records(uint8_t *ndef_in, size_t ndef_in_length,
2288                         uint8_t record_type)
2289 {
2290         uint8_t p_mb = 0, p_me = 0;
2291         int err;
2292         size_t offset;
2293         struct near_ndef_record *record = NULL;
2294         int counted_records = 0 ;
2295
2296         DBG("");
2297
2298         offset = 0;
2299
2300         if (ndef_in == NULL ||  ndef_in_length < NDEF_MSG_MIN_LENGTH) {
2301                 err = -EINVAL;
2302                 goto fail;
2303         }
2304
2305         while (offset < ndef_in_length) {
2306                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2307                 if (record == NULL) {
2308                         err = -ENOMEM;
2309                         goto fail;
2310                 }
2311
2312                 /* Create a record */
2313                 record->header = parse_record_header(ndef_in, offset,
2314                                                         ndef_in_length);
2315                 if (record->header == NULL) {
2316                         err = -EINVAL;
2317                         goto fail;
2318                 }
2319
2320                 /* Validate MB ME */
2321                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2322                                         record->header->mb,
2323                                         record->header->me) != 0) {
2324                         DBG("validate mb me failed");
2325                         err = -EINVAL;
2326                         goto fail;
2327                 }
2328
2329                 /* Is this what we want ? */
2330                 if (record->header->rec_type == record_type)
2331                         counted_records++;
2332
2333                 /* Jump to the next record */
2334                 offset = record->header->offset + record->header->payload_len;
2335
2336                 free_ndef_record(record);
2337         }
2338
2339         DBG("Type %d Records found: %d", record_type, counted_records);
2340
2341         return counted_records;
2342
2343 fail:
2344         near_error("ndef counting failed");
2345         free_ndef_record(record);
2346         return err;
2347 }
2348
2349 /**
2350  * @brief Prepare Text ndef record
2351  *
2352  * Prepare text ndef record with provided input data and return
2353  * ndef message structure (length and byte stream) in success or
2354  * NULL in failure case.
2355  *
2356  * @note : caller responsibility to free the input and output
2357  *         parameters memory.
2358  *
2359  * @param[in] encoding      Encoding (UTF-8 | UTF-16)
2360  * @param[in] language_code Language Code
2361  * @param[in] text          Actual text
2362  *
2363  * @return struct near_ndef_message * - Success
2364  *         NULL - Failure
2365  */
2366 struct near_ndef_message *near_ndef_prepare_text_record(char *encoding,
2367                                                 char *language_code, char *text)
2368 {
2369         struct near_ndef_message *msg;
2370         uint32_t text_len, payload_length;
2371         uint8_t  code_len, status = 0;
2372
2373         DBG("");
2374
2375         /* Validate input parameters*/
2376         if (((g_strcmp0(encoding, "UTF-8") != 0) &&
2377                  (g_strcmp0(encoding, "UTF-16") != 0)) ||
2378                  (language_code == NULL) ||
2379                  (text == NULL)) {
2380                 return NULL;
2381         }
2382
2383         code_len = strlen(language_code);
2384         text_len = strlen(text);
2385         payload_length = 1 + code_len + text_len;
2386
2387         msg = ndef_message_alloc("T", payload_length);
2388         if (msg == NULL)
2389                 return NULL;
2390
2391         if (g_strcmp0(encoding, "UTF-16") == 0)
2392                 status |= NDEF_TEXT_RECORD_UTF16_STATUS;
2393
2394         status = status | code_len;
2395         msg->data[msg->offset++] = status;
2396
2397         if (code_len > 0)
2398                 memcpy(msg->data + msg->offset, language_code, code_len);
2399
2400         msg->offset += code_len;
2401
2402         if (text_len > 0)
2403                 memcpy(msg->data + msg->offset, text, text_len);
2404
2405         msg->offset += text_len;
2406
2407         if (msg->offset > msg->length)
2408                 goto fail;
2409
2410         return msg;
2411
2412 fail:
2413         near_error("text record preparation failed");
2414         g_free(msg->data);
2415         g_free(msg);
2416
2417         return NULL;
2418 }
2419
2420 /**
2421  * @brief Prepare URI ndef record
2422  *
2423  * Prepare uri ndef record with provided input data and return
2424  * ndef message structure (length and byte stream) in success or
2425  * NULL in failure case.
2426  *
2427  * @note : caller responsibility to free the input and output
2428  *         parameters memory.
2429  *
2430  * @param[in] identifier    URI Identifier
2431  * @param[in] field_length  URI field length
2432  * @param[in] field         URI field
2433  *
2434  * @return struct near_ndef_message * - Success
2435  *         NULL - Failure
2436  */
2437 struct near_ndef_message *near_ndef_prepare_uri_record(uint8_t identifier,
2438                                         uint32_t field_length, uint8_t *field)
2439 {
2440         struct near_ndef_message *msg = NULL;
2441         uint32_t payload_length;
2442
2443         DBG("");
2444
2445         /* Validate input parameters*/
2446         if ((field_length == 0 && field != NULL) ||
2447                 (field_length != 0 && field == NULL)) {
2448                 return NULL;
2449         }
2450
2451         payload_length = field_length + 1;
2452
2453         msg = ndef_message_alloc("U", payload_length);
2454         if (msg == NULL)
2455                 return NULL;
2456
2457         msg->data[msg->offset++] = identifier;
2458
2459         if (field_length > 0) {
2460                 memcpy(msg->data + msg->offset, field, field_length);
2461                 msg->offset += field_length;
2462         }
2463
2464         if (msg->offset > msg->length)
2465                 goto fail;
2466
2467         return msg;
2468
2469 fail:
2470         near_error("uri record preparation failed");
2471         g_free(msg->data);
2472         g_free(msg);
2473
2474         return NULL;
2475 }
2476
2477 /**
2478  * @brief Prepare Smartposter ndef record with mandatory URI fields.
2479  *
2480  * Prepare smartposter ndef record with provided input data and
2481  * return ndef message structure (length and byte stream) in success or
2482  * NULL in failure case.
2483  *
2484  * @note : caller responsibility to free the input and output
2485  *         parameters memory.
2486  *
2487  * @param[in] uri_identfier
2488  * @param[in] uri_field_length
2489  * @param[in] uri_field
2490  *
2491  * @return struct near_ndef_message * - Success
2492  *         NULL - Failure
2493  */
2494 struct near_ndef_message *
2495 near_ndef_prepare_smartposter_record(uint8_t uri_identifier,
2496                                         uint32_t uri_field_length,
2497                                         uint8_t *uri_field)
2498 {
2499         struct near_ndef_message *msg = NULL, *uri = NULL;
2500
2501         /* URI is mandatory in Smartposter */
2502         uri = near_ndef_prepare_uri_record(uri_identifier, uri_field_length,
2503                                                                 uri_field);
2504         if (uri == NULL)
2505                 goto fail;
2506
2507         /* URI record length is equal to payload length of Sp record */
2508         msg = ndef_message_alloc("Sp", uri->length);
2509         if (msg == NULL)
2510                 goto fail;
2511
2512         memcpy(msg->data + msg->offset, uri->data, uri->length);
2513         msg->offset += uri->length;
2514
2515         if (msg->offset > msg->length)
2516                 goto fail;
2517
2518         if (uri != NULL) {
2519                 g_free(uri->data);
2520                 g_free(uri);
2521         }
2522
2523         return msg;
2524
2525 fail:
2526         near_error("smartposter record preparation failed");
2527
2528         if (uri != NULL) {
2529                 g_free(uri->data);
2530                 g_free(uri);
2531         }
2532
2533         if (msg != NULL) {
2534                 g_free(msg->data);
2535                 g_free(msg);
2536         }
2537
2538         return NULL;
2539 }
2540
2541 static char *get_text_field(DBusMessage *msg, char *text)
2542 {
2543         DBusMessageIter iter, arr_iter;
2544         char *uri = NULL;
2545
2546         DBG("");
2547
2548         if (text == NULL)
2549                 return NULL;
2550
2551         dbus_message_iter_init(msg, &iter);
2552         dbus_message_iter_recurse(&iter, &arr_iter);
2553
2554         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2555                                         DBUS_TYPE_INVALID) {
2556                 const char *key;
2557                 DBusMessageIter ent_iter;
2558                 DBusMessageIter var_iter;
2559
2560                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2561                 dbus_message_iter_get_basic(&ent_iter, &key);
2562                 dbus_message_iter_next(&ent_iter);
2563                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2564
2565                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2566                 case DBUS_TYPE_STRING:
2567                         if (g_strcmp0(key, text) == 0)
2568                                 dbus_message_iter_get_basic(&var_iter, &uri);
2569
2570                         break;
2571                 }
2572
2573                 dbus_message_iter_next(&arr_iter);
2574         }
2575
2576         return uri;
2577 }
2578
2579 static inline char *get_uri_field(DBusMessage *msg)
2580 {
2581         return get_text_field(msg, "URI");
2582 }
2583
2584 static inline char *get_carrier_field(DBusMessage *msg)
2585 {
2586         return get_text_field(msg, "Carrier");
2587 }
2588
2589 static struct near_ndef_message *build_text_record(DBusMessage *msg)
2590 {
2591         DBusMessageIter iter, arr_iter;
2592         char *cod = NULL, *lang = NULL, *rep = NULL;
2593
2594         DBG("");
2595
2596         dbus_message_iter_init(msg, &iter);
2597         dbus_message_iter_recurse(&iter, &arr_iter);
2598
2599         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2600                                         DBUS_TYPE_INVALID) {
2601                 const char *key;
2602                 DBusMessageIter ent_iter;
2603                 DBusMessageIter var_iter;
2604
2605                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2606                 dbus_message_iter_get_basic(&ent_iter, &key);
2607                 dbus_message_iter_next(&ent_iter);
2608                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2609
2610                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2611                 case DBUS_TYPE_STRING:
2612                         if (g_strcmp0(key, "Encoding") == 0)
2613                                 dbus_message_iter_get_basic(&var_iter, &cod);
2614                         else if (g_strcmp0(key, "Language") == 0)
2615                                 dbus_message_iter_get_basic(&var_iter, &lang);
2616                         else if (g_strcmp0(key, "Representation") == 0)
2617                                 dbus_message_iter_get_basic(&var_iter, &rep);
2618
2619                         break;
2620                 }
2621
2622                 dbus_message_iter_next(&arr_iter);
2623         }
2624
2625         return near_ndef_prepare_text_record(cod, lang, rep);
2626 }
2627
2628 static struct near_ndef_message *build_uri_record(DBusMessage *msg)
2629 {
2630         char *uri = NULL;
2631         const char *uri_prefix = NULL;
2632         uint8_t id_len, i, id;
2633         uint32_t uri_len;
2634
2635         DBG("");
2636
2637         uri = get_uri_field(msg);
2638         if (uri == NULL)
2639                 return NULL;
2640
2641         id = 0;
2642         id_len = 0;
2643
2644         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
2645                 uri_prefix = __near_ndef_get_uri_prefix(i);
2646
2647                 if (uri_prefix != NULL &&
2648                     g_str_has_prefix(uri, uri_prefix) == TRUE) {
2649                         id = i;
2650                         id_len = strlen(uri_prefix);
2651                         break;
2652                 }
2653         }
2654
2655         DBG("%d %d\n", i, id_len);
2656
2657         uri_len = strlen(uri) - id_len;
2658         return near_ndef_prepare_uri_record(id, uri_len,
2659                                                 (uint8_t *)(uri + id_len));
2660 }
2661
2662 static struct near_ndef_message *build_sp_record(DBusMessage *msg)
2663 {
2664         char *uri = NULL;
2665         const char *uri_prefix;
2666         uint8_t id_len, i;
2667         uint32_t uri_len;
2668
2669         DBG("");
2670
2671         /*
2672          * Currently this function supports only mandatory URI record,
2673          * TODO: Other records support.
2674          */
2675         uri = get_uri_field(msg);
2676         if (uri == NULL)
2677                 return NULL;
2678
2679         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
2680                 uri_prefix = __near_ndef_get_uri_prefix(i);
2681
2682                 if (uri_prefix != NULL &&
2683                                 g_str_has_prefix(uri, uri_prefix) == TRUE)
2684                         break;
2685         }
2686
2687         if (uri_prefix == NULL) {
2688                 i = 0;
2689                 id_len = 0;
2690         } else
2691                 id_len = strlen(uri_prefix);
2692
2693         uri_len = strlen(uri) - id_len;
2694         return near_ndef_prepare_smartposter_record(i, uri_len,
2695                                                 (uint8_t *)(uri + id_len));
2696 }
2697
2698 static struct near_ndef_ac_record *build_ho_local_ac_record(void)
2699 {
2700         struct near_ndef_ac_record *ac_record = NULL;
2701
2702         DBG("");
2703
2704         /* Allocate ac record */
2705         ac_record = g_try_malloc0(sizeof(struct near_ndef_ac_record));
2706         if (ac_record == NULL)
2707                 return NULL;
2708
2709         /* Carrier flag */
2710         ac_record->cps = CPS_ACTIVE;    /* TODO Should reflect BT state */
2711
2712         /* Carrier data reference length */
2713         ac_record->cdr_len = 1;
2714
2715         /* Carrier data reference */
2716         ac_record->cdr = '0';
2717
2718         /* Auxiliary data reference count */
2719         ac_record->adata_refcount = 0;
2720
2721         return ac_record;
2722 }
2723
2724 static struct near_ndef_message *build_ho_record(DBusMessage *msg)
2725 {
2726         char *carrier_type = NULL;
2727         enum near_ndef_handover_carrier carrier;
2728         struct near_ndef_record *record = NULL;
2729
2730         DBG("");
2731
2732         carrier_type = get_carrier_field(msg);
2733         if (carrier_type == NULL) {
2734                 DBG("Empty carrier name");
2735                 return NULL;
2736         }
2737
2738         if (g_strcmp0(carrier_type, "bluetooth") == 0)
2739                 carrier = NEAR_CARRIER_BLUETOOTH;
2740         else if (g_strcmp0(carrier_type, "wifi") == 0)
2741                 carrier = NEAR_CARRIER_WIFI;
2742         else {
2743                 DBG("Invalid carrier name");
2744                 return NULL;
2745         }
2746
2747         /* Build local record */
2748         record = g_try_malloc0(sizeof(struct near_ndef_record));
2749         if (record == NULL)
2750                 return NULL;
2751
2752         /* Do a Ho */
2753         record->ho = g_try_malloc0(sizeof(struct near_ndef_ho_record));
2754         if (record->ho == NULL)
2755                 goto fail;
2756
2757         /* fill the Ho */
2758         record->ho->version = HANDOVER_VERSION;
2759
2760         record->ho->collision_record = 0x1664; /* TODO randomize it */
2761         record->ho->err_record = NULL;
2762
2763         record->ho->number_of_ac_records = 1;
2764         record->ho->ac_records = g_try_malloc0(
2765                                         sizeof(struct near_ndef_ac_record *));
2766         if (record->ho->ac_records == NULL)
2767                 goto fail;
2768         record->ho->ac_records[0] = build_ho_local_ac_record();
2769
2770         return near_ndef_prepare_handover_record("Hr", record, carrier);
2771
2772 fail:
2773         free_ho_record(record->ho);
2774         g_free(record);
2775
2776         return NULL;
2777 }
2778
2779 struct near_ndef_message *__ndef_build_from_message(DBusMessage *msg)
2780 {
2781         DBusMessageIter iter;
2782         DBusMessageIter arr_iter;
2783         struct near_ndef_message *ndef;
2784
2785         DBG("");
2786
2787         dbus_message_iter_init(msg, &iter);
2788         dbus_message_iter_recurse(&iter, &arr_iter);
2789
2790         ndef = NULL;
2791
2792         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2793                                                 DBUS_TYPE_INVALID) {
2794                 const char *key, *value;
2795                 DBusMessageIter ent_iter;
2796                 DBusMessageIter var_iter;
2797
2798                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2799                 dbus_message_iter_get_basic(&ent_iter, &key);
2800
2801                 if (g_strcmp0(key, "Type") != 0) {
2802                         dbus_message_iter_next(&arr_iter);
2803                         continue;
2804                 }
2805
2806                 dbus_message_iter_next(&ent_iter);
2807                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2808
2809                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2810                 case DBUS_TYPE_STRING:
2811                         dbus_message_iter_get_basic(&var_iter, &value);
2812
2813                         if (g_strcmp0(value, "Text") == 0) {
2814                                 ndef = build_text_record(msg);
2815                                 break;
2816                         } else if (g_strcmp0(value, "URI") == 0) {
2817                                 ndef = build_uri_record(msg);
2818                                 break;
2819                         } else if (g_strcmp0(value, "SmartPoster") == 0) {
2820                                 ndef = build_sp_record(msg);
2821                                 break;
2822                         } else if (g_strcmp0(value, "Handover") == 0) {
2823                                 ndef = build_ho_record(msg);
2824                                 break;
2825                         } else {
2826                                 near_error("%s not supported", value);
2827                                 ndef = NULL;
2828                                 break;
2829                         }
2830
2831                         break;
2832                 }
2833
2834                 dbus_message_iter_next(&arr_iter);
2835         }
2836
2837         return ndef;
2838 }
2839
2840 int __near_ndef_init(void)
2841 {
2842         DBG("");
2843
2844         connection = near_dbus_get_connection();
2845
2846         return 0;
2847 }
2848
2849 void __near_ndef_cleanup(void)
2850 {
2851 }