upd ndef parser

by jaylikesbunda and Willy-JL
This commit is contained in:
MX 2024-10-22 02:37:04 +03:00
parent fc16978be5
commit b0e591601c
No known key found for this signature in database
GPG Key ID: 7CCC66B7DBDD1C83

View File

@ -27,11 +27,7 @@ static void
print_data(FuriString* str, const char* prefix, const uint8_t* buf, size_t len, bool force_hex) { print_data(FuriString* str, const char* prefix, const uint8_t* buf, size_t len, bool force_hex) {
if(prefix) furi_string_cat_printf(str, "%s: ", prefix); if(prefix) furi_string_cat_printf(str, "%s: ", prefix);
if(!force_hex && is_text(buf, len)) { if(!force_hex && is_text(buf, len)) {
char* tmp = malloc(len + 1); furi_string_cat_printf(str, "%.*s", len, buf);
memcpy(tmp, buf, len);
tmp[len] = '\0';
furi_string_cat_printf(str, "%s", tmp);
free(tmp);
} else { } else {
for(uint8_t i = 0; i < len; i++) { for(uint8_t i = 0; i < len; i++) {
furi_string_cat_printf(str, "%02X ", buf[i]); furi_string_cat_printf(str, "%02X ", buf[i]);
@ -40,6 +36,17 @@ static void
furi_string_cat(str, "\n"); furi_string_cat(str, "\n");
} }
static inline uint8_t hex_to_int(char c) {
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'A' && c <= 'F') return c - 'A' + 10;
if(c >= 'a' && c <= 'f') return c - 'a' + 10;
return 0;
}
static char decode_char(const char* str) {
return (hex_to_int(str[1]) << 4) | hex_to_int(str[2]);
}
static void parse_ndef_uri(FuriString* str, const uint8_t* payload, uint32_t payload_len) { static void parse_ndef_uri(FuriString* str, const uint8_t* payload, uint32_t payload_len) {
// https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef#uri-records-0x55-slash-u-607763 // https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef#uri-records-0x55-slash-u-607763
const char* prepends[] = { const char* prepends[] = {
@ -88,26 +95,44 @@ static void parse_ndef_uri(FuriString* str, const uint8_t* payload, uint32_t pay
size_t prepend_len = strlen(prepend); size_t prepend_len = strlen(prepend);
size_t uri_len = prepend_len + (payload_len - 1); size_t uri_len = prepend_len + (payload_len - 1);
char* const uri_buf = malloc(uri_len); char* const uri_buf = malloc(uri_len); // const to keep the original pointer to free later
memcpy(uri_buf, prepend, prepend_len); memcpy(uri_buf, prepend, prepend_len);
memcpy(uri_buf + prepend_len, payload + 1, payload_len - 1); memcpy(uri_buf + prepend_len, payload + 1, payload_len - 1);
char* uri = uri_buf; char* uri = uri_buf; // cursor we can iterate and shift freely
// Encoded chars take 3 bytes (%AB), decoded chars take 1 byte
// We can decode by iterating and overwriting the same buffer
size_t decoded_len = 0;
for(size_t encoded_idx = 0; encoded_idx < uri_len; encoded_idx++) {
if(uri[encoded_idx] == '%' && encoded_idx + 2 < uri_len) {
char hi = toupper(uri[encoded_idx + 1]);
char lo = toupper(uri[encoded_idx + 2]);
if(((hi >= 'A' && hi <= 'F') || (hi >= '0' && hi <= '9')) &&
((lo >= 'A' && lo <= 'F') || (lo >= '0' && lo <= '9'))) {
uri[decoded_len++] = decode_char(&uri[encoded_idx]);
encoded_idx += 2;
continue;
}
}
uri[decoded_len++] = uri[encoded_idx];
}
const char* type = "URI"; const char* type = "URI";
if(strncmp(uri, "http", strlen("http")) == 0) { if(strncmp(uri, "http", 4) == 0) {
type = "URL"; type = "URL";
} else if(strncmp(uri, "tel:", strlen("tel:")) == 0) { } else if(strncmp(uri, "tel:", 4) == 0) {
type = "Phone"; type = "Phone";
uri += strlen("tel:"); uri += 4;
uri_len -= strlen("tel:"); decoded_len -= 4;
} else if(strncmp(uri, "mailto:", strlen("mailto:")) == 0) { } else if(strncmp(uri, "mailto:", 7) == 0) {
type = "Mail"; type = "Mail";
uri += strlen("mailto:"); uri += 7;
uri_len -= strlen("mailto:"); decoded_len -= 7;
} }
furi_string_cat_printf(str, "%s\n", type); furi_string_cat_printf(str, "%s\n", type);
print_data(str, NULL, (uint8_t*)uri, uri_len, false); print_data(str, NULL, (uint8_t*)uri, decoded_len, false);
free(uri_buf); free(uri_buf);
} }
@ -477,6 +502,6 @@ static const FlipperAppPluginDescriptor ndef_plugin_descriptor = {
}; };
/* Plugin entry point - must return a pointer to const descriptor */ /* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* ndef_plugin_ep() { const FlipperAppPluginDescriptor* ndef_plugin_ep(void) {
return &ndef_plugin_descriptor; return &ndef_plugin_descriptor;
} }