From e70121e20f00082887ec7118a58b246752976794 Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 21 Sep 2022 18:53:25 +0300 Subject: [PATCH] [FL-2843] NFC fixes (#1764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: fix empty desfire card message * nfc: limit total user keys to list * nfc: increase popup timeout Co-authored-by: あく --- .../scenes/nfc_scene_mf_classic_keys_list.c | 92 +++++++++++---- .../nfc/scenes/nfc_scene_mf_desfire_app.c | 111 ++++++++++-------- 2 files changed, 127 insertions(+), 76 deletions(-) diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c index 36f01897..6670ae13 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c @@ -1,48 +1,87 @@ #include "../nfc_i.h" -void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; +#define NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX (100) +void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } +void nfc_scene_mf_classic_keys_list_popup_callback(void* context) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) { + Submenu* submenu = nfc->submenu; + uint32_t index = 0; + string_t temp_key; + string_init(temp_key); + + submenu_set_header(submenu, "Select key to delete:"); + while(mf_classic_dict_get_next_key_str(dict, temp_key)) { + char* current_key = (char*)malloc(sizeof(char) * 13); + strncpy(current_key, string_get_cstr(temp_key), 12); + MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); + FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key); + submenu_add_item( + submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc); + } + string_clear(temp_key); +} + void nfc_scene_mf_classic_keys_list_on_enter(void* context) { Nfc* nfc = context; - Submenu* submenu = nfc->submenu; MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); - uint32_t index = 0; - string_t temp_key; MfClassicUserKeys_init(nfc->mfc_key_strs); - string_init(temp_key); if(dict) { - mf_classic_dict_rewind(dict); - while(mf_classic_dict_get_next_key_str(dict, temp_key)) { - char* current_key = (char*)malloc(sizeof(char) * 13); - strncpy(current_key, string_get_cstr(temp_key), 12); - MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); - FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key); - submenu_add_item( - submenu, - current_key, - index++, - nfc_scene_mf_classic_keys_list_submenu_callback, - nfc); + uint32_t total_user_keys = mf_classic_dict_get_total_keys(dict); + if(total_user_keys < NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX) { + nfc_scene_mf_classic_keys_list_prepare(nfc, dict); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + } else { + popup_set_header(nfc->popup, "Too many keys!", 64, 0, AlignCenter, AlignTop); + popup_set_text( + nfc->popup, + "Edit user dictionary\nwith file browser", + 64, + 12, + AlignCenter, + AlignTop); + popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); } + mf_classic_dict_free(dict); + } else { + popup_set_header( + nfc->popup, "Failed to load dictionary", 64, 32, AlignCenter, AlignCenter); + popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); } - submenu_set_header(submenu, "Select key to delete:"); - mf_classic_dict_free(dict); - string_clear(temp_key); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event); - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete); - consumed = true; + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } else { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete); + consumed = true; + } } return consumed; } @@ -57,4 +96,5 @@ void nfc_scene_mf_classic_keys_list_on_exit(void* context) { } MfClassicUserKeys_clear(nfc->mfc_key_strs); submenu_reset(nfc->submenu); + popup_reset(nfc->popup); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c index 7faafdcf..dd842464 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -7,6 +7,13 @@ enum SubmenuIndex { SubmenuIndexDynamic, // dynamic indexes start here }; +void nfc_scene_mf_desfire_popup_callback(void* context) { + furi_assert(context); + + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) { uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >> 1; @@ -25,46 +32,45 @@ void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) { void nfc_scene_mf_desfire_app_on_enter(void* context) { Nfc* nfc = context; - Submenu* submenu = nfc->submenu; MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); if(!app) { popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42); - popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom); - popup_set_text( - nfc->popup, - "No app selected.\nThis should\nnever happen,\nplease file a bug.", - 55, - 15, - AlignLeft, - AlignTop); + popup_set_header(nfc->popup, "Empty card!", 55, 12, AlignLeft, AlignBottom); + popup_set_callback(nfc->popup, nfc_scene_mf_desfire_popup_callback); + popup_set_context(nfc->popup, nfc); + popup_set_timeout(nfc->popup, 3000); + popup_enable_timeout(nfc->popup); + popup_set_text(nfc->popup, "No application\nfound.", 55, 15, AlignLeft, AlignTop); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - FURI_LOG_E(TAG, "Bad state. No app selected?"); - return; - } + } else { + text_box_set_font(nfc->text_box, TextBoxFontHex); + submenu_add_item( + nfc->submenu, + "App info", + SubmenuIndexAppInfo, + nfc_scene_mf_desfire_app_submenu_callback, + nfc); - text_box_set_font(nfc->text_box, TextBoxFontHex); - - submenu_add_item( - submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc); - - uint16_t cap = NFC_TEXT_STORE_SIZE; - char* buf = nfc->text_store; - int idx = SubmenuIndexDynamic; - for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - int size = snprintf(buf, cap, "File %d", file->id); - if(size < 0 || size >= cap) { - FURI_LOG_W( - TAG, - "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); - break; + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; + int idx = SubmenuIndexDynamic; + for(MifareDesfireFile* file = app->file_head; file; file = file->next) { + int size = snprintf(buf, cap, "File %d", file->id); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, + "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; + submenu_add_item( + nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); } - char* label = buf; - cap -= size + 1; - buf += size + 1; - submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); - } - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); + } } bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { @@ -73,26 +79,30 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp); if(event.type == SceneManagerEventTypeCustom) { - MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); - TextBox* text_box = nfc->text_box; - string_reset(nfc->text_box_store); - if(event.event == SubmenuIndexAppInfo) { - mf_df_cat_application_info(app, nfc->text_box_store); + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_previous_scene(nfc->scene_manager); } else { - uint16_t index = event.event - SubmenuIndexDynamic; - MifareDesfireFile* file = app->file_head; - for(int i = 0; file && i < index; i++) { - file = file->next; + MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); + TextBox* text_box = nfc->text_box; + string_reset(nfc->text_box_store); + if(event.event == SubmenuIndexAppInfo) { + mf_df_cat_application_info(app, nfc->text_box_store); + } else { + uint16_t index = event.event - SubmenuIndexDynamic; + MifareDesfireFile* file = app->file_head; + for(int i = 0; file && i < index; i++) { + file = file->next; + } + if(!file) { + return false; + } + mf_df_cat_file(file, nfc->text_box_store); } - if(!file) { - return false; - } - mf_df_cat_file(file, nfc->text_box_store); + text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); + consumed = true; } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - consumed = true; } else if(event.type == SceneManagerEventTypeBack) { if(state & 1) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); @@ -108,6 +118,7 @@ void nfc_scene_mf_desfire_app_on_exit(void* context) { Nfc* nfc = context; // Clear views + popup_reset(nfc->popup); text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); submenu_reset(nfc->submenu);