2dd51e87bbf07817551549b702b825bd67ed71aa
[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         near_info("handover select record preparation OK");
1800         return hs_msg;
1801
1802 fail:
1803         near_error("handover select record preparation failed");
1804
1805         if (ac_msg != NULL) {
1806                 g_free(ac_msg->data);
1807                 g_free(ac_msg);
1808         }
1809
1810         if (cr_msg != NULL) {
1811                 g_free(cr_msg->data);
1812                 g_free(cr_msg);
1813         }
1814
1815         if (hs_msg != NULL) {
1816                 g_free(hs_msg->data);
1817                 g_free(hs_msg);
1818         }
1819
1820         if (bt_msg != NULL) {
1821                 g_free(bt_msg->data);
1822                 g_free(bt_msg);
1823         }
1824
1825         g_free(oob_data);
1826
1827         return NULL;
1828 }
1829
1830 /* Code to fill hr record structure from acs and mimes lists */
1831 static int near_fill_ho_record(struct near_ndef_ho_record *ho,
1832                                         GSList *acs, GSList *mimes)
1833 {
1834         int rec_count;
1835         int i;
1836         GSList *temp;
1837
1838         rec_count = g_slist_length(acs);
1839         ho->ac_records = g_try_malloc0(rec_count *
1840                         sizeof(struct near_ndef_ac_record *));
1841         if (ho->ac_records == NULL)
1842                 goto fail;
1843         temp = acs;
1844         for (i = 0; i < rec_count; i++) {
1845                 ho->ac_records[i] = temp->data;
1846                 temp = temp->next;
1847         }
1848         ho->number_of_ac_records = rec_count;
1849         g_slist_free(acs);
1850
1851         /* Same process for cfg mimes */
1852         rec_count = g_slist_length(mimes);
1853         ho->cfg_records = g_try_malloc0(rec_count *
1854                         sizeof(struct near_ndef_mime_record *));
1855         if (ho->cfg_records == NULL)
1856                 goto fail;
1857         temp = mimes;
1858         for (i = 0; i < rec_count; i++) {
1859                 ho->cfg_records[i] = temp->data;
1860                 temp = temp->next;
1861         }
1862
1863         ho->number_of_cfg_records = rec_count;
1864         g_slist_free(mimes);
1865
1866         return 0;
1867 fail:
1868         g_free(ho->ac_records);
1869         g_free(ho->cfg_records);
1870         ho->ac_records = NULL;
1871         ho->cfg_records = NULL;
1872         return -ENOMEM;
1873 }
1874
1875 /*
1876  * @brief Parse the Handover request record
1877  * This function will parse an Hr record, retrieving sub records
1878  * like (ac, cr, er) but it  will also get the associated
1879  * ndefs (eg: handover carrier record, mime type for BT)
1880  * In a handover frame, only the following types are expected:
1881  *     RECORD_TYPE_WKT_HANDOVER_CARRIER:
1882  *     RECORD_TYPE_WKT_COLLISION_RESOLUTION
1883  *     RECORD_TYPE_MIME_TYPE
1884  *     RECORD_TYPE_WKT_ALTERNATIVE_CARRIER
1885  */
1886 static struct near_ndef_ho_record *parse_ho_record(enum record_type rec_type,
1887                 uint8_t *rec, uint32_t ho_length, size_t frame_length,
1888                 uint8_t ho_mb, uint8_t ho_me)
1889 {
1890         struct near_ndef_ho_record *ho_record = NULL;
1891         struct near_ndef_ac_record *ac = NULL;
1892         struct near_ndef_mime_record *mime = NULL;
1893         struct near_ndef_record *trec = NULL;
1894         GSList *acs = NULL, *mimes = NULL;
1895         uint8_t mb = 0, me = 0;
1896         uint32_t offset;
1897         int16_t count_ac = 0;
1898         near_bool_t bt_pair;
1899
1900         DBG("");
1901
1902         if (rec == NULL)
1903                 return NULL;
1904         offset = 0;
1905
1906         /* Create the handover record */
1907         ho_record = g_try_malloc0(sizeof(struct near_ndef_ho_record));
1908         if (ho_record == NULL)
1909                 return NULL;
1910
1911         /* Version is the first mandatory field of hr record */
1912         ho_record->version = rec[offset];
1913         if (ho_record->version > HANDOVER_VERSION) {
1914                 near_error("Unsupported version (%d)", ho_record->version);
1915                 goto fail;
1916         }
1917
1918         offset = offset + 1;
1919         frame_length = frame_length - 1;        /* Remove Hr length size */
1920
1921         /* We should work on the whole frame */
1922         ho_length = frame_length;
1923
1924         while (offset < ho_length) {
1925                 /* Create local record for mime parsing */
1926                 trec = g_try_malloc0(sizeof(struct near_ndef_record));
1927                 if (trec == NULL)
1928                         return NULL;
1929
1930                 trec->header = parse_record_header(rec, offset, ho_length);
1931
1932                 if (trec->header == NULL)
1933                         goto fail;
1934
1935                 offset = trec->header->offset;
1936
1937                 switch (trec->header->rec_type) {
1938                 case RECORD_TYPE_WKT_SMART_POSTER:
1939                 case RECORD_TYPE_WKT_SIZE:
1940                 case RECORD_TYPE_WKT_TEXT:
1941                 case RECORD_TYPE_WKT_TYPE:
1942                 case RECORD_TYPE_WKT_ACTION:
1943                 case RECORD_TYPE_WKT_URI:
1944                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
1945                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
1946                 case RECORD_TYPE_WKT_ERROR:
1947                 case RECORD_TYPE_UNKNOWN:
1948                 case RECORD_TYPE_ERROR:
1949                         break;
1950
1951                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
1952                         DBG("HANDOVER_CARRIER");
1953                         /*
1954                          * TODO process Hc record too !!!
1955                          * Used for Wifi session
1956                          */
1957                         break;
1958
1959                 case RECORD_TYPE_MIME_TYPE:
1960                         DBG("TYPE_MIME_TYPE");
1961
1962                         /* check mb/me bits */
1963                         if (validate_record_begin_and_end_bits(&ho_mb, &ho_me,
1964                                 trec->header->mb, trec->header->me) != 0) {
1965                                 DBG("validate mb me failed");
1966                                 goto fail;
1967                         }
1968
1969                         /*
1970                          * In Handover, the mime type gives bluetooth handover
1971                          * configuration datas.
1972                          * If we initiated the session, the received Hs frame
1973                          * is the signal to launch the pairing.
1974                          */
1975                         if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT)
1976                                 bt_pair = TRUE;
1977                         else
1978                                 bt_pair = FALSE;
1979
1980                         mime = parse_mime_type(trec, rec, frame_length,
1981                                         offset, trec->header->payload_len,
1982                                         bt_pair);
1983                         if (mime == NULL)
1984                                 goto fail;
1985
1986                         /* add the mime to the list */
1987                         mimes = g_slist_append(mimes, mime);
1988                         count_ac--;
1989                         if (count_ac == 0)
1990                                 offset = ho_length;
1991                         break;
1992
1993                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
1994                         DBG("COLLISION_RESOLUTION");
1995
1996                         /* check nested mb/me bits */
1997                         if (validate_record_begin_and_end_bits(&mb, &me,
1998                                 trec->header->mb, trec->header->me) != 0) {
1999                                 DBG("validate mb me failed");
2000                                 goto fail;
2001                         }
2002
2003                         ho_record->collision_record =
2004                                         g_ntohs(*((uint16_t *)(rec + offset)));
2005                         break;
2006
2007                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2008                         DBG("ALTERNATIVE_CARRIER");
2009
2010                         /* check nested mb/me bits */
2011                         if (validate_record_begin_and_end_bits(&mb, &me,
2012                                 trec->header->mb, trec->header->me) != 0) {
2013                                 DBG("validate mb me failed");
2014                                 goto fail;
2015                         }
2016
2017                         ac = parse_ac_record(rec + offset,
2018                                         trec->header->payload_len);
2019                         if (ac == NULL)
2020                                 goto fail;
2021
2022                         acs = g_slist_append(acs, ac);
2023
2024                         /* TODO check if adata are present */
2025                         count_ac++;
2026                         break;
2027                 }
2028
2029                 offset += trec->header->payload_len;
2030                 g_free(trec->header->il_field);
2031                 g_free(trec->header->type_name);
2032                 g_free(trec->header);
2033                 trec->header = NULL;
2034
2035                 g_free(trec);
2036         }
2037
2038         if ((acs == NULL) || (mimes == NULL))
2039                 return ho_record;
2040
2041         /* Save the records */
2042         if (near_fill_ho_record(ho_record, acs, mimes) < 0)
2043                 goto fail;
2044
2045         near_error("handover record parsing complete");
2046         return ho_record;
2047
2048 fail:
2049         near_error("handover record parsing failed");
2050
2051         if (trec != NULL) {
2052                 if (trec->header != NULL) {
2053                         g_free(trec->header->type_name);
2054                         g_free(trec->header->il_field);
2055                         g_free(trec->header);
2056                 }
2057                 g_free(trec);
2058         }
2059
2060         free_ho_record(ho_record);
2061
2062         return NULL;
2063 }
2064
2065 int __near_ndef_record_register(struct near_ndef_record *record, char *path)
2066 {
2067         record->path = path;
2068
2069         g_dbus_register_interface(connection, record->path,
2070                                                 NFC_RECORD_INTERFACE,
2071                                                 record_methods,
2072                                                 NULL, NULL,
2073                                                 record, NULL);
2074
2075         return 0;
2076 }
2077
2078 GList *near_ndef_parse(uint8_t *ndef_data, size_t ndef_length)
2079 {
2080         GList *records;
2081         uint8_t p_mb = 0, p_me = 0, *record_start;
2082         size_t offset = 0;
2083         struct near_ndef_record *record = NULL;
2084
2085         DBG("");
2086
2087         records = NULL;
2088
2089         if (ndef_data == NULL ||
2090                 ndef_length < NDEF_MSG_MIN_LENGTH)
2091                         goto fail;
2092
2093         while (offset < ndef_length) {
2094
2095                 DBG("Record Header : 0x%X", ndef_data[offset]);
2096
2097                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2098                 if (record == NULL)
2099                         goto fail;
2100
2101                 record->header = parse_record_header(ndef_data, offset,
2102                                                         ndef_length);
2103                 if (record->header == NULL)
2104                         goto fail;
2105
2106                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2107                                         record->header->mb,
2108                                         record->header->me) != 0) {
2109                         DBG("validate mb me failed");
2110                         goto fail;
2111                 }
2112
2113                 record_start = ndef_data + offset;
2114                 offset = record->header->offset;
2115
2116                 switch (record->header->rec_type) {
2117                 case RECORD_TYPE_WKT_SIZE:
2118                 case RECORD_TYPE_WKT_TYPE:
2119                 case RECORD_TYPE_WKT_ACTION:
2120                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2121                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2122                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2123                 case RECORD_TYPE_WKT_ERROR:
2124                 case RECORD_TYPE_UNKNOWN:
2125                 case RECORD_TYPE_ERROR:
2126                         break;
2127
2128                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2129                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2130                         /*
2131                          * Handover frame are a little bit special as the NDEF
2132                          * length (specified in the header) is not the real
2133                          * frame size. The complete frame includes extra NDEF
2134                          * following the initial handover NDEF
2135                          */
2136                         record->ho = parse_ho_record(record->header->rec_type,
2137                                         ndef_data + offset,
2138                                         record->header->payload_len,
2139                                         ndef_length,
2140                                         record->header->mb, record->header->me);
2141                         if (record->ho == NULL)
2142                                 goto fail;
2143
2144                         /* the complete frame is processed, break the loop */
2145                         record->header->payload_len = ndef_length;
2146                         break;
2147
2148                 case RECORD_TYPE_WKT_TEXT:
2149                         record->text = parse_text_record(ndef_data + offset,
2150                                                 record->header->payload_len);
2151
2152                         if (record->text == NULL)
2153                                 goto fail;
2154
2155                         break;
2156
2157                 case RECORD_TYPE_WKT_URI:
2158                         record->uri = parse_uri_record(ndef_data + offset,
2159                                                 record->header->payload_len);
2160
2161                         if (record->uri == NULL)
2162                                 goto fail;
2163
2164                         break;
2165
2166                 case RECORD_TYPE_WKT_SMART_POSTER:
2167                         record->sp = parse_smart_poster_record(
2168                                                 ndef_data + offset,
2169                                                 record->header->payload_len);
2170
2171                         if (record->sp == NULL)
2172                                 goto fail;
2173
2174                         break;
2175
2176                 case RECORD_TYPE_MIME_TYPE:
2177                         record->mime = parse_mime_type(record, ndef_data,
2178                                                 ndef_length, offset,
2179                                                 record->header->payload_len,
2180                                                 TRUE);
2181
2182
2183                         if (record->mime == NULL)
2184                                 goto fail;
2185
2186                         break;
2187                 }
2188
2189                 record->data_len = record->header->header_len +
2190                                         record->header->payload_len;
2191
2192                 record->data = g_try_malloc0(record->data_len);
2193                 if (record->data == NULL)
2194                         goto fail;
2195
2196                 memcpy(record->data, record_start, record->data_len);
2197
2198                 records = g_list_append(records, record);
2199
2200                 build_record_type_string(record);
2201
2202                 offset += record->header->payload_len;
2203         }
2204
2205         return records;
2206
2207 fail:
2208         near_error("ndef parsing failed");
2209         free_ndef_record(record);
2210
2211         return records;
2212 }
2213
2214 void near_ndef_records_free(GList *records)
2215 {
2216         GList *list;
2217
2218         for (list = records; list; list = list->next) {
2219                 struct near_ndef_record *record = list->data;
2220
2221                 __near_ndef_record_free(record);
2222         }
2223
2224         g_list_free(records);
2225 }
2226
2227 /*
2228  * @brief Compute an NDEF record length
2229  *
2230  * Would compute ndef records length, even though the submitted frame
2231  * is incomplete. This code is used in the handover read function, as
2232  * we have to "guess" the final frame size.
2233  *
2234  * Message size for SR=1 is:
2235  *  1 : ndef rec header (offset 0)
2236  *  x : record type length (offset 1)
2237  *  y : payload length (offset 2) 1 byte ONLY if SR=1
2238  *      if SR=0: (4bytes) 32 bits
2239  *  z : payload id length (offset 3) ONLY if il_length=1
2240  * */
2241 int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length)
2242 {
2243         int ndef_size;   /* default size for NDEF hdr + rec typ len + payl */
2244         size_t offset;
2245         uint8_t hdr;
2246
2247         DBG("");
2248
2249         if (ndef_in_length < 3)
2250                 return -EINVAL;
2251
2252         ndef_size = 3;
2253         offset = 0;
2254
2255         /* save header byte */
2256         hdr = ndef_in[offset];
2257         offset++;
2258
2259         /* header->type_len */
2260         ndef_size += ndef_in[offset++];
2261
2262         /* header->payload_len */
2263         if (RECORD_SR_BIT(hdr) == 1) {
2264                 ndef_size += ndef_in[offset++];
2265         } else {
2266                 ndef_size += g_ntohl(*((uint32_t *)(ndef_in + offset)));
2267                 offset += 4;
2268
2269                 if (offset >= ndef_in_length)
2270                         return -ERANGE;
2271         }
2272
2273         /* header->il */
2274         ndef_size += RECORD_IL_BIT(hdr);
2275
2276         /* header->il_length */
2277         if (RECORD_IL_BIT(hdr) == 1)
2278                 ndef_size += ndef_in[offset++];
2279
2280         DBG("near_ndef_message_length is %d", ndef_size);
2281
2282         return ndef_size;
2283 }
2284
2285 int near_ndef_count_records(uint8_t *ndef_in, size_t ndef_in_length,
2286                         uint8_t record_type)
2287 {
2288         uint8_t p_mb = 0, p_me = 0;
2289         int err;
2290         size_t offset;
2291         struct near_ndef_record *record = NULL;
2292         int counted_records = 0 ;
2293
2294         DBG("");
2295
2296         offset = 0;
2297
2298         if (ndef_in == NULL ||  ndef_in_length < NDEF_MSG_MIN_LENGTH) {
2299                 err = -EINVAL;
2300                 goto fail;
2301         }
2302
2303         while (offset < ndef_in_length) {
2304                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2305                 if (record == NULL) {
2306                         err = -ENOMEM;
2307                         goto fail;
2308                 }
2309
2310                 /* Create a record */
2311                 record->header = parse_record_header(ndef_in, offset,
2312                                                         ndef_in_length);
2313                 if (record->header == NULL) {
2314                         err = -EINVAL;
2315                         goto fail;
2316                 }
2317
2318                 /* Validate MB ME */
2319                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2320                                         record->header->mb,
2321                                         record->header->me) != 0) {
2322                         DBG("validate mb me failed");
2323                         err = -EINVAL;
2324                         goto fail;
2325                 }
2326
2327                 /* Is this what we want ? */
2328                 if (record->header->rec_type == record_type)
2329                         counted_records++;
2330
2331                 /* Jump to the next record */
2332                 offset = record->header->offset + record->header->payload_len;
2333
2334                 free_ndef_record(record);
2335         }
2336
2337         DBG("Type %d Records found: %d", record_type, counted_records);
2338
2339         return counted_records;
2340
2341 fail:
2342         near_error("ndef counting failed");
2343         free_ndef_record(record);
2344         return err;
2345 }
2346
2347 /**
2348  * @brief Prepare Text ndef record
2349  *
2350  * Prepare text ndef record with provided input data and return
2351  * ndef message structure (length and byte stream) in success or
2352  * NULL in failure case.
2353  *
2354  * @note : caller responsibility to free the input and output
2355  *         parameters memory.
2356  *
2357  * @param[in] encoding      Encoding (UTF-8 | UTF-16)
2358  * @param[in] language_code Language Code
2359  * @param[in] text          Actual text
2360  *
2361  * @return struct near_ndef_message * - Success
2362  *         NULL - Failure
2363  */
2364 struct near_ndef_message *near_ndef_prepare_text_record(char *encoding,
2365                                                 char *language_code, char *text)
2366 {
2367         struct near_ndef_message *msg;
2368         uint32_t text_len, payload_length;
2369         uint8_t  code_len, status = 0;
2370
2371         DBG("");
2372
2373         /* Validate input parameters*/
2374         if (((g_strcmp0(encoding, "UTF-8") != 0) &&
2375                  (g_strcmp0(encoding, "UTF-16") != 0)) ||
2376                  (language_code == NULL) ||
2377                  (text == NULL)) {
2378                 return NULL;
2379         }
2380
2381         code_len = strlen(language_code);
2382         text_len = strlen(text);
2383         payload_length = 1 + code_len + text_len;
2384
2385         msg = ndef_message_alloc("T", payload_length);
2386         if (msg == NULL)
2387                 return NULL;
2388
2389         if (g_strcmp0(encoding, "UTF-16") == 0)
2390                 status |= NDEF_TEXT_RECORD_UTF16_STATUS;
2391
2392         status = status | code_len;
2393         msg->data[msg->offset++] = status;
2394
2395         if (code_len > 0)
2396                 memcpy(msg->data + msg->offset, language_code, code_len);
2397
2398         msg->offset += code_len;
2399
2400         if (text_len > 0)
2401                 memcpy(msg->data + msg->offset, text, text_len);
2402
2403         msg->offset += text_len;
2404
2405         if (msg->offset > msg->length)
2406                 goto fail;
2407
2408         return msg;
2409
2410 fail:
2411         near_error("text record preparation failed");
2412         g_free(msg->data);
2413         g_free(msg);
2414
2415         return NULL;
2416 }
2417
2418 /**
2419  * @brief Prepare URI ndef record
2420  *
2421  * Prepare uri ndef record with provided input data and return
2422  * ndef message structure (length and byte stream) in success or
2423  * NULL in failure case.
2424  *
2425  * @note : caller responsibility to free the input and output
2426  *         parameters memory.
2427  *
2428  * @param[in] identifier    URI Identifier
2429  * @param[in] field_length  URI field length
2430  * @param[in] field         URI field
2431  *
2432  * @return struct near_ndef_message * - Success
2433  *         NULL - Failure
2434  */
2435 struct near_ndef_message *near_ndef_prepare_uri_record(uint8_t identifier,
2436                                         uint32_t field_length, uint8_t *field)
2437 {
2438         struct near_ndef_message *msg = NULL;
2439         uint32_t payload_length;
2440
2441         DBG("");
2442
2443         /* Validate input parameters*/
2444         if ((field_length == 0 && field != NULL) ||
2445                 (field_length != 0 && field == NULL)) {
2446                 return NULL;
2447         }
2448
2449         payload_length = field_length + 1;
2450
2451         msg = ndef_message_alloc("U", payload_length);
2452         if (msg == NULL)
2453                 return NULL;
2454
2455         msg->data[msg->offset++] = identifier;
2456
2457         if (field_length > 0) {
2458                 memcpy(msg->data + msg->offset, field, field_length);
2459                 msg->offset += field_length;
2460         }
2461
2462         if (msg->offset > msg->length)
2463                 goto fail;
2464
2465         return msg;
2466
2467 fail:
2468         near_error("uri record preparation failed");
2469         g_free(msg->data);
2470         g_free(msg);
2471
2472         return NULL;
2473 }
2474
2475 /**
2476  * @brief Prepare Smartposter ndef record with mandatory URI fields.
2477  *
2478  * Prepare smartposter ndef record with provided input data and
2479  * return ndef message structure (length and byte stream) in success or
2480  * NULL in failure case.
2481  *
2482  * @note : caller responsibility to free the input and output
2483  *         parameters memory.
2484  *
2485  * @param[in] uri_identfier
2486  * @param[in] uri_field_length
2487  * @param[in] uri_field
2488  *
2489  * @return struct near_ndef_message * - Success
2490  *         NULL - Failure
2491  */
2492 struct near_ndef_message *
2493 near_ndef_prepare_smartposter_record(uint8_t uri_identifier,
2494                                         uint32_t uri_field_length,
2495                                         uint8_t *uri_field)
2496 {
2497         struct near_ndef_message *msg = NULL, *uri = NULL;
2498
2499         /* URI is mandatory in Smartposter */
2500         uri = near_ndef_prepare_uri_record(uri_identifier, uri_field_length,
2501                                                                 uri_field);
2502         if (uri == NULL)
2503                 goto fail;
2504
2505         /* URI record length is equal to payload length of Sp record */
2506         msg = ndef_message_alloc("Sp", uri->length);
2507         if (msg == NULL)
2508                 goto fail;
2509
2510         memcpy(msg->data + msg->offset, uri->data, uri->length);
2511         msg->offset += uri->length;
2512
2513         if (msg->offset > msg->length)
2514                 goto fail;
2515
2516         if (uri != NULL) {
2517                 g_free(uri->data);
2518                 g_free(uri);
2519         }
2520
2521         return msg;
2522
2523 fail:
2524         near_error("smartposter record preparation failed");
2525
2526         if (uri != NULL) {
2527                 g_free(uri->data);
2528                 g_free(uri);
2529         }
2530
2531         if (msg != NULL) {
2532                 g_free(msg->data);
2533                 g_free(msg);
2534         }
2535
2536         return NULL;
2537 }
2538
2539 static char *get_text_field(DBusMessage *msg, char *text)
2540 {
2541         DBusMessageIter iter, arr_iter;
2542         char *uri = NULL;
2543
2544         DBG("");
2545
2546         if (text == NULL)
2547                 return NULL;
2548
2549         dbus_message_iter_init(msg, &iter);
2550         dbus_message_iter_recurse(&iter, &arr_iter);
2551
2552         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2553                                         DBUS_TYPE_INVALID) {
2554                 const char *key;
2555                 DBusMessageIter ent_iter;
2556                 DBusMessageIter var_iter;
2557
2558                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2559                 dbus_message_iter_get_basic(&ent_iter, &key);
2560                 dbus_message_iter_next(&ent_iter);
2561                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2562
2563                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2564                 case DBUS_TYPE_STRING:
2565                         if (g_strcmp0(key, text) == 0)
2566                                 dbus_message_iter_get_basic(&var_iter, &uri);
2567
2568                         break;
2569                 }
2570
2571                 dbus_message_iter_next(&arr_iter);
2572         }
2573
2574         return uri;
2575 }
2576
2577 static inline char *get_uri_field(DBusMessage *msg)
2578 {
2579         return get_text_field(msg, "URI");
2580 }
2581
2582 static inline char *get_carrier_field(DBusMessage *msg)
2583 {
2584         return get_text_field(msg, "Carrier");
2585 }
2586
2587 static struct near_ndef_message *build_text_record(DBusMessage *msg)
2588 {
2589         DBusMessageIter iter, arr_iter;
2590         char *cod = NULL, *lang = NULL, *rep = NULL;
2591
2592         DBG("");
2593
2594         dbus_message_iter_init(msg, &iter);
2595         dbus_message_iter_recurse(&iter, &arr_iter);
2596
2597         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2598                                         DBUS_TYPE_INVALID) {
2599                 const char *key;
2600                 DBusMessageIter ent_iter;
2601                 DBusMessageIter var_iter;
2602
2603                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2604                 dbus_message_iter_get_basic(&ent_iter, &key);
2605                 dbus_message_iter_next(&ent_iter);
2606                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2607
2608                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2609                 case DBUS_TYPE_STRING:
2610                         if (g_strcmp0(key, "Encoding") == 0)
2611                                 dbus_message_iter_get_basic(&var_iter, &cod);
2612                         else if (g_strcmp0(key, "Language") == 0)
2613                                 dbus_message_iter_get_basic(&var_iter, &lang);
2614                         else if (g_strcmp0(key, "Representation") == 0)
2615                                 dbus_message_iter_get_basic(&var_iter, &rep);
2616
2617                         break;
2618                 }
2619
2620                 dbus_message_iter_next(&arr_iter);
2621         }
2622
2623         return near_ndef_prepare_text_record(cod, lang, rep);
2624 }
2625
2626 static struct near_ndef_message *build_uri_record(DBusMessage *msg)
2627 {
2628         char *uri = NULL;
2629         const char *uri_prefix = NULL;
2630         uint8_t id_len, i;
2631         uint32_t uri_len;
2632
2633         DBG("");
2634
2635         uri = get_uri_field(msg);
2636         if (uri == NULL)
2637                 return NULL;
2638
2639         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
2640                 uri_prefix = __near_ndef_get_uri_prefix(i);
2641
2642                 if (uri_prefix != NULL &&
2643                                 g_str_has_prefix(uri, uri_prefix) == TRUE)
2644                         break;
2645         }
2646
2647         /* If uri_prefix is NULL then ID will be zero */
2648         if (uri_prefix == NULL) {
2649                 i = 0;
2650                 id_len = 0;
2651         } else
2652                 id_len = strlen(uri_prefix);
2653
2654         uri_len = strlen(uri) - id_len;
2655         return near_ndef_prepare_uri_record(i, uri_len,
2656                                                 (uint8_t *)(uri + id_len));
2657 }
2658
2659 static struct near_ndef_message *build_sp_record(DBusMessage *msg)
2660 {
2661         char *uri = NULL;
2662         const char *uri_prefix;
2663         uint8_t id_len, i;
2664         uint32_t uri_len;
2665
2666         DBG("");
2667
2668         /*
2669          * Currently this function supports only mandatory URI record,
2670          * TODO: Other records support.
2671          */
2672         uri = get_uri_field(msg);
2673         if (uri == NULL)
2674                 return NULL;
2675
2676         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
2677                 uri_prefix = __near_ndef_get_uri_prefix(i);
2678
2679                 if (uri_prefix != NULL &&
2680                                 g_str_has_prefix(uri, uri_prefix) == TRUE)
2681                         break;
2682         }
2683
2684         if (uri_prefix == NULL) {
2685                 i = 0;
2686                 id_len = 0;
2687         } else
2688                 id_len = strlen(uri_prefix);
2689
2690         uri_len = strlen(uri) - id_len;
2691         return near_ndef_prepare_smartposter_record(i, uri_len,
2692                                                 (uint8_t *)(uri + id_len));
2693 }
2694
2695 static struct near_ndef_ac_record *build_ho_local_ac_record(void)
2696 {
2697         struct near_ndef_ac_record *ac_record = NULL;
2698
2699         DBG("");
2700
2701         /* Allocate ac record */
2702         ac_record = g_try_malloc0(sizeof(struct near_ndef_ac_record));
2703         if (ac_record == NULL)
2704                 return NULL;
2705
2706         /* Carrier flag */
2707         ac_record->cps = CPS_ACTIVE;    /* TODO Should reflect BT state */
2708
2709         /* Carrier data reference length */
2710         ac_record->cdr_len = 1;
2711
2712         /* Carrier data reference */
2713         ac_record->cdr = '0';
2714
2715         /* Auxiliary data reference count */
2716         ac_record->adata_refcount = 0;
2717
2718         return ac_record;
2719 }
2720
2721 static struct near_ndef_message *build_ho_record(DBusMessage *msg)
2722 {
2723         char *carrier_type = NULL;
2724         enum near_ndef_handover_carrier carrier;
2725         struct near_ndef_record *record = NULL;
2726
2727         DBG("");
2728
2729         carrier_type = get_carrier_field(msg);
2730         if (carrier_type == NULL) {
2731                 DBG("Empty carrier name");
2732                 return NULL;
2733         }
2734
2735         if (g_strcmp0(carrier_type, "bluetooth") == 0)
2736                 carrier = NEAR_CARRIER_BLUETOOTH;
2737         else if (g_strcmp0(carrier_type, "wifi") == 0)
2738                 carrier = NEAR_CARRIER_WIFI;
2739         else {
2740                 DBG("Invalid carrier name");
2741                 return NULL;
2742         }
2743
2744         /* Build local record */
2745         record = g_try_malloc0(sizeof(struct near_ndef_record));
2746         if (record == NULL)
2747                 return NULL;
2748
2749         /* Do a Ho */
2750         record->ho = g_try_malloc0(sizeof(struct near_ndef_ho_record));
2751         if (record->ho == NULL)
2752                 goto fail;
2753
2754         /* fill the Ho */
2755         record->ho->version = HANDOVER_VERSION;
2756
2757         record->ho->collision_record = 0x1664; /* TODO randomize it */
2758         record->ho->err_record = NULL;
2759
2760         record->ho->number_of_ac_records = 1;
2761         record->ho->ac_records = g_try_malloc0(
2762                                         sizeof(struct near_ndef_ac_record *));
2763         if (record->ho->ac_records == NULL)
2764                 goto fail;
2765         record->ho->ac_records[0] = build_ho_local_ac_record();
2766
2767         return near_ndef_prepare_handover_record("Hr", record, carrier);
2768
2769 fail:
2770         free_ho_record(record->ho);
2771         g_free(record);
2772
2773         return NULL;
2774 }
2775
2776 struct near_ndef_message *__ndef_build_from_message(DBusMessage *msg)
2777 {
2778         DBusMessageIter iter;
2779         DBusMessageIter arr_iter;
2780         struct near_ndef_message *ndef;
2781
2782         DBG("");
2783
2784         dbus_message_iter_init(msg, &iter);
2785         dbus_message_iter_recurse(&iter, &arr_iter);
2786
2787         ndef = NULL;
2788
2789         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2790                                                 DBUS_TYPE_INVALID) {
2791                 const char *key, *value;
2792                 DBusMessageIter ent_iter;
2793                 DBusMessageIter var_iter;
2794
2795                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2796                 dbus_message_iter_get_basic(&ent_iter, &key);
2797
2798                 if (g_strcmp0(key, "Type") != 0) {
2799                         dbus_message_iter_next(&arr_iter);
2800                         continue;
2801                 }
2802
2803                 dbus_message_iter_next(&ent_iter);
2804                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2805
2806                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2807                 case DBUS_TYPE_STRING:
2808                         dbus_message_iter_get_basic(&var_iter, &value);
2809
2810                         if (g_strcmp0(value, "Text") == 0) {
2811                                 ndef = build_text_record(msg);
2812                                 break;
2813                         } else if (g_strcmp0(value, "URI") == 0) {
2814                                 ndef = build_uri_record(msg);
2815                                 break;
2816                         } else if (g_strcmp0(value, "SmartPoster") == 0) {
2817                                 ndef = build_sp_record(msg);
2818                                 break;
2819                         } else if (g_strcmp0(value, "Handover") == 0) {
2820                                 ndef = build_ho_record(msg);
2821                                 break;
2822                         } else {
2823                                 near_error("%s not supported", value);
2824                                 ndef = NULL;
2825                                 break;
2826                         }
2827
2828                         break;
2829                 }
2830
2831                 dbus_message_iter_next(&arr_iter);
2832         }
2833
2834         return ndef;
2835 }
2836
2837 int __near_ndef_init(void)
2838 {
2839         DBG("");
2840
2841         connection = near_dbus_get_connection();
2842
2843         return 0;
2844 }
2845
2846 void __near_ndef_cleanup(void)
2847 {
2848 }