@@ -27,11 +27,7 @@ static void
27
27
print_data (FuriString * str , const char * prefix , const uint8_t * buf , size_t len , bool force_hex ) {
28
28
if (prefix ) furi_string_cat_printf (str , "%s: " , prefix );
29
29
if (!force_hex && is_text (buf , len )) {
30
- char * tmp = malloc (len + 1 );
31
- memcpy (tmp , buf , len );
32
- tmp [len ] = '\0' ;
33
- furi_string_cat_printf (str , "%s" , tmp );
34
- free (tmp );
30
+ furi_string_cat_printf (str , "%.*s" , len , buf );
35
31
} else {
36
32
for (uint8_t i = 0 ; i < len ; i ++ ) {
37
33
furi_string_cat_printf (str , "%02X " , buf [i ]);
@@ -40,6 +36,17 @@ static void
40
36
furi_string_cat (str , "\n" );
41
37
}
42
38
39
+ static inline uint8_t hex_to_int (char c ) {
40
+ if (c >= '0' && c <= '9' ) return c - '0' ;
41
+ if (c >= 'A' && c <= 'F' ) return c - 'A' + 10 ;
42
+ if (c >= 'a' && c <= 'f' ) return c - 'a' + 10 ;
43
+ return 0 ;
44
+ }
45
+
46
+ static char decode_char (const char * str ) {
47
+ return (hex_to_int (str [1 ]) << 4 ) | hex_to_int (str [2 ]);
48
+ }
49
+
43
50
static void parse_ndef_uri (FuriString * str , const uint8_t * payload , uint32_t payload_len ) {
44
51
// https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef#uri-records-0x55-slash-u-607763
45
52
const char * prepends [] = {
@@ -88,26 +95,44 @@ static void parse_ndef_uri(FuriString* str, const uint8_t* payload, uint32_t pay
88
95
size_t prepend_len = strlen (prepend );
89
96
90
97
size_t uri_len = prepend_len + (payload_len - 1 );
91
- char * const uri_buf = malloc (uri_len );
98
+ char * const uri_buf = malloc (uri_len ); // const to keep the original pointer to free later
92
99
memcpy (uri_buf , prepend , prepend_len );
93
100
memcpy (uri_buf + prepend_len , payload + 1 , payload_len - 1 );
94
- char * uri = uri_buf ;
101
+ char * uri = uri_buf ; // cursor we can iterate and shift freely
102
+
103
+ // Encoded chars take 3 bytes (%AB), decoded chars take 1 byte
104
+ // We can decode by iterating and overwriting the same buffer
105
+ size_t decoded_len = 0 ;
106
+ for (size_t encoded_idx = 0 ; encoded_idx < uri_len ; encoded_idx ++ ) {
107
+ if (uri [encoded_idx ] == '%' && encoded_idx + 2 < uri_len ) {
108
+ char hi = toupper (uri [encoded_idx + 1 ]);
109
+ char lo = toupper (uri [encoded_idx + 2 ]);
110
+ if (((hi >= 'A' && hi <= 'F' ) || (hi >= '0' && hi <= '9' )) &&
111
+ ((lo >= 'A' && lo <= 'F' ) || (lo >= '0' && lo <= '9' ))) {
112
+ uri [decoded_len ++ ] = decode_char (& uri [encoded_idx ]);
113
+ encoded_idx += 2 ;
114
+ continue ;
115
+ }
116
+ }
117
+ uri [decoded_len ++ ] = uri [encoded_idx ];
118
+ }
95
119
96
120
const char * type = "URI" ;
97
- if (strncmp (uri , "http" , strlen ( "http" ) ) == 0 ) {
121
+ if (strncmp (uri , "http" , 4 ) == 0 ) {
98
122
type = "URL" ;
99
- } else if (strncmp (uri , "tel:" , strlen ( "tel:" ) ) == 0 ) {
123
+ } else if (strncmp (uri , "tel:" , 4 ) == 0 ) {
100
124
type = "Phone" ;
101
- uri += strlen ( "tel:" ) ;
102
- uri_len -= strlen ( "tel:" ) ;
103
- } else if (strncmp (uri , "mailto:" , strlen ( "mailto:" ) ) == 0 ) {
125
+ uri += 4 ;
126
+ decoded_len -= 4 ;
127
+ } else if (strncmp (uri , "mailto:" , 7 ) == 0 ) {
104
128
type = "Mail" ;
105
- uri += strlen ( "mailto:" ) ;
106
- uri_len -= strlen ( "mailto:" ) ;
129
+ uri += 7 ;
130
+ decoded_len -= 7 ;
107
131
}
108
132
109
133
furi_string_cat_printf (str , "%s\n" , type );
110
- print_data (str , NULL , (uint8_t * )uri , uri_len , false);
134
+ print_data (str , NULL , (uint8_t * )uri , decoded_len , false);
135
+
111
136
free (uri_buf );
112
137
}
113
138
@@ -477,6 +502,6 @@ static const FlipperAppPluginDescriptor ndef_plugin_descriptor = {
477
502
};
478
503
479
504
/* Plugin entry point - must return a pointer to const descriptor */
480
- const FlipperAppPluginDescriptor * ndef_plugin_ep () {
505
+ const FlipperAppPluginDescriptor * ndef_plugin_ep (void ) {
481
506
return & ndef_plugin_descriptor ;
482
507
}
0 commit comments