mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 11:28:36 -07:00
NFC: Improve URI decoding in NDEF parser (#267)
* add decode_char * Skip double malloc(), can just tell printf() how long the string is * Decode URI within the same buffer * Only decode if next 2 chars are valid hex * Update changelog * Clearer code for hex decode Co-authored-by: jaylikesbunda <jaylikesbunda@users.noreply.github.com> --------- Co-authored-by: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Co-authored-by: jaylikesbunda <jaylikesbunda@users.noreply.github.com>
This commit is contained in:
@@ -112,6 +112,7 @@
|
|||||||
- NFC:
|
- NFC:
|
||||||
- Added 6 new Mifare Classic keys from Bulgaria Hotel (#216 by @z3r0l1nk)
|
- Added 6 new Mifare Classic keys from Bulgaria Hotel (#216 by @z3r0l1nk)
|
||||||
- NDEF parser supports NTAG I2C Plus 1k and 2k chips too (by @RocketGod-git)
|
- NDEF parser supports NTAG I2C Plus 1k and 2k chips too (by @RocketGod-git)
|
||||||
|
- NDEF parser decodes URL-encoded URI characters (#267 by @jaylikesbunda)
|
||||||
- UL: Add iq aparts hotel key (by @xMasterX)
|
- UL: Add iq aparts hotel key (by @xMasterX)
|
||||||
- OFW/UL: Rename 'Detect Reader' to 'Extract MFC Keys' (by @bettse & @xMasterX)
|
- OFW/UL: Rename 'Detect Reader' to 'Extract MFC Keys' (by @bettse & @xMasterX)
|
||||||
- OFW: Plantain parser improvements (by @assasinfil)
|
- OFW: Plantain parser improvements (by @assasinfil)
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user