NFC user dict list, delete, and de-duplication. (#1533)

* Add MFC user keys list
* Leakey submenu fix
* Set next target for Save/Delete success scenes
* Delete individual user keys
* Update count of total keys
* Fix memory leak
* Check for duplicate keys
* Remove a submodule that I never added?
* Swap and position icons
* Revamp according to design doc
* Rename icons to include size and replace keychain icon with smaller variant
* Fix typos
* Final fixes
* Fufill requested changes
* Cleanup comments
* Merge dev after SD app loading
* Fixing icon names
* Revert merge mistakes and API version
* Scene switching adjustments
* F7: add/change/remove some nfc icons in api_symbols.csv

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
David 2022-09-19 11:43:53 -05:00 committed by GitHub
parent 9f3b80e606
commit f5ff6438d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 465 additions and 64 deletions

View file

@ -22,4 +22,4 @@
"SConstruct": "python",
"*.fam": "python",
}
}
}

View file

@ -16,7 +16,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
LfRfidReadViewModel* model = _model;
canvas_set_color(canvas, ColorBlack);
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual);
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual_60x50);
canvas_set_font(canvas, FontPrimary);

View file

@ -37,6 +37,10 @@
#include "rpc/rpc_app.h"
#include <m-array.h>
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
#define NFC_TEXT_STORE_SIZE 128
typedef enum {
@ -60,6 +64,7 @@ struct Nfc {
char text_store[NFC_TEXT_STORE_SIZE + 1];
string_t text_box_store;
uint8_t byte_input_store[6];
MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing
void* rpc_ctx;
NfcRpcState rpc_state;

View file

@ -32,6 +32,9 @@ ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList)
ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete)
ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
ADD_SCENE(nfc, emv_menu, EmvMenu)

View file

@ -25,8 +25,13 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
}
}
}
return consumed;

View file

@ -31,7 +31,10 @@ bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneExtraActions);
} else {

View file

@ -17,7 +17,7 @@ void nfc_scene_extra_actions_on_enter(void* context) {
submenu_add_item(
submenu,
"Mf Classic Keys",
"Mifare Classic Keys",
SubmenuIndexMfClassicKeys,
nfc_scene_extra_actions_submenu_callback,
nfc);

View file

@ -26,15 +26,25 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
}
widget_add_string_element(
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MF Classic Keys");
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys");
char temp_str[32];
snprintf(temp_str, sizeof(temp_str), "Flipper dict: %ld", flipper_dict_keys_total);
snprintf(temp_str, sizeof(temp_str), "Flipper list: %ld", flipper_dict_keys_total);
widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str);
snprintf(temp_str, sizeof(temp_str), "User dict: %ld", user_dict_keys_total);
snprintf(temp_str, sizeof(temp_str), "User list: %ld", user_dict_keys_total);
widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
widget_add_button_element(
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain);
widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_mf_classic_keys_widget_callback, nfc);
widget_add_icon_element(nfc->widget, 87, 13, &I_Keychain_39x36);
if(user_dict_keys_total > 0) {
widget_add_button_element(
nfc->widget,
GuiButtonTypeRight,
"List",
nfc_scene_mf_classic_keys_widget_callback,
nfc);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
@ -47,6 +57,12 @@ bool nfc_scene_mf_classic_keys_on_event(void* context, SceneManagerEvent event)
if(event.event == GuiButtonTypeCenter) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd);
consumed = true;
} else if(event.event == GuiButtonTypeLeft) {
scene_manager_previous_scene(nfc->scene_manager);
consumed = true;
} else if(event.event == GuiButtonTypeRight) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysList);
consumed = true;
}
}

View file

@ -29,15 +29,16 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
// Add key to dict
bool key_added = false;
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
if(dict) {
if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
key_added = true;
if(mf_classic_dict_is_key_present(dict, nfc->byte_input_store)) {
scene_manager_next_scene(
nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
} else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
}
}
if(key_added) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
}

View file

@ -0,0 +1,77 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_keys_delete_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
Nfc* nfc = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
}
void nfc_scene_mf_classic_keys_delete_on_enter(void* context) {
Nfc* nfc = context;
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
uint32_t key_index =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
// Setup Custom Widget view
string_t key_str;
string_init(key_str);
widget_add_string_element(
nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Delete this key?");
widget_add_button_element(
nfc->widget,
GuiButtonTypeLeft,
"Cancel",
nfc_scene_mf_classic_keys_delete_widget_callback,
nfc);
widget_add_button_element(
nfc->widget,
GuiButtonTypeRight,
"Delete",
nfc_scene_mf_classic_keys_delete_widget_callback,
nfc);
mf_classic_dict_get_key_at_index_str(dict, key_str, key_index);
widget_add_string_element(
nfc->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(key_str));
string_clear(key_str);
mf_classic_dict_free(dict);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
bool nfc_scene_mf_classic_keys_delete_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
uint32_t key_index =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else if(event.event == GuiButtonTypeRight) {
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
if(mf_classic_dict_delete_index(dict, key_index)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
} else {
scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
}
mf_classic_dict_free(dict);
consumed = true;
}
}
return consumed;
}
void nfc_scene_mf_classic_keys_delete_on_exit(void* context) {
Nfc* nfc = context;
widget_reset(nfc->widget);
}

View file

@ -0,0 +1,60 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
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);
}
}
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;
}
return consumed;
}
void nfc_scene_mf_classic_keys_list_on_exit(void* context) {
Nfc* nfc = context;
MfClassicUserKeys_it_t it;
for(MfClassicUserKeys_it(it, nfc->mfc_key_strs); !MfClassicUserKeys_end_p(it);
MfClassicUserKeys_next(it)) {
free(*MfClassicUserKeys_ref(it));
}
MfClassicUserKeys_clear(nfc->mfc_key_strs);
submenu_reset(nfc->submenu);
}

View file

@ -0,0 +1,47 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_keys_warn_duplicate_popup_callback(void* context) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
void nfc_scene_mf_classic_keys_warn_duplicate_on_enter(void* context) {
Nfc* nfc = context;
// Setup view
Popup* popup = nfc->popup;
popup_set_icon(popup, 72, 16, &I_DolphinCommon_56x48);
popup_set_header(popup, "Key already exists!", 64, 3, AlignCenter, AlignTop);
popup_set_text(
popup,
"Please enter a\n"
"different key.",
4,
24,
AlignLeft,
AlignTop);
popup_set_timeout(popup, 5000);
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_mf_classic_keys_warn_duplicate_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
bool nfc_scene_mf_classic_keys_warn_duplicate_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeysAdd);
}
}
return consumed;
}
void nfc_scene_mf_classic_keys_warn_duplicate_on_exit(void* context) {
Nfc* nfc = context;
popup_reset(nfc->popup);
}

View file

@ -27,7 +27,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState
popup_reset(nfc->popup);
popup_set_text(
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
} else if(state == NfcSceneMfUlReadStateReading) {
popup_reset(nfc->popup);
popup_set_header(

View file

@ -26,7 +26,7 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
popup_reset(nfc->popup);
popup_set_text(
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
} else if(state == NfcSceneReadStateReading) {
popup_reset(nfc->popup);
popup_set_header(

View file

@ -11,7 +11,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring);
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring_38x32);
dialog_ex_set_text(
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
dialog_ex_set_left_button_text(dialog_ex, "Cancel");

View file

@ -27,7 +27,10 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneSavedMenu);
} else {

View file

@ -109,7 +109,7 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = {
{.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS},
},
{
{.width = 1, .icon = &I_Pin_arrow_up7x9, .value = HID_KEYBOARD_L_SHIFT},
{.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT},
{.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA},
{.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT},
{.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR},

View file

@ -53,7 +53,7 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) {
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up7x9);
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up_7x9);
canvas_set_color(canvas, ColorBlack);
// Down

View file

@ -117,7 +117,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9);
break;
case InputKeyUp:
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up7x9);
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9);
break;
case InputKeyLeft:
canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,1.5,,
Version,+,1.6,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -2612,7 +2612,7 @@ Variable,+,I_KeyBackspaceSelected_16x9,const Icon,
Variable,+,I_KeyBackspace_16x9,const Icon,
Variable,+,I_KeySaveSelected_24x11,const Icon,
Variable,+,I_KeySave_24x11,const Icon,
Variable,+,I_Keychain,const Icon,
Variable,+,I_Keychain_39x36,const Icon,
Variable,+,I_Left_mouse_icon_9x9,const Icon,
Variable,+,I_Lock_7x8,const Icon,
Variable,+,I_Lock_8x8,const Icon,
@ -2620,7 +2620,7 @@ Variable,+,I_MHz_25x11,const Icon,
Variable,+,I_Medium_chip_22x21,const Icon,
Variable,+,I_Mute_25x27,const Icon,
Variable,+,I_Mute_hvr_25x27,const Icon,
Variable,+,I_NFC_manual,const Icon,
Variable,+,I_NFC_manual_60x50,const Icon,
Variable,+,I_Nfc_10px,const Icon,
Variable,+,I_Ok_btn_9x9,const Icon,
Variable,+,I_Ok_btn_pressed_13x13,const Icon,
@ -2628,7 +2628,7 @@ Variable,+,I_Percent_10x14,const Icon,
Variable,+,I_Pin_arrow_down_7x9,const Icon,
Variable,+,I_Pin_arrow_left_9x7,const Icon,
Variable,+,I_Pin_arrow_right_9x7,const Icon,
Variable,+,I_Pin_arrow_up7x9,const Icon,
Variable,+,I_Pin_arrow_up_7x9,const Icon,
Variable,+,I_Pin_attention_dpad_29x29,const Icon,
Variable,+,I_Pin_back_arrow_10x8,const Icon,
Variable,+,I_Pin_back_full_40x8,const Icon,
@ -2642,7 +2642,8 @@ Variable,+,I_RFIDBigChip_37x36,const Icon,
Variable,+,I_RFIDDolphinReceive_97x61,const Icon,
Variable,+,I_RFIDDolphinSend_97x61,const Icon,
Variable,+,I_RFIDDolphinSuccess_108x57,const Icon,
Variable,+,I_Restoring,const Icon,
Variable,+,I_Reader_detect_43x40,const Icon,
Variable,+,I_Restoring_38x32,const Icon,
Variable,+,I_Right_mouse_icon_9x9,const Icon,
Variable,+,I_SDQuestion_35x43,const Icon,
Variable,+,I_SDcardFail_11x8,const Icon,

1 entry status name type params
2 Version + 1.5 1.6
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
2612 Variable + I_KeyBackspace_16x9 const Icon
2613 Variable + I_KeySaveSelected_24x11 const Icon
2614 Variable + I_KeySave_24x11 const Icon
2615 Variable + I_Keychain I_Keychain_39x36 const Icon
2616 Variable + I_Left_mouse_icon_9x9 const Icon
2617 Variable + I_Lock_7x8 const Icon
2618 Variable + I_Lock_8x8 const Icon
2620 Variable + I_Medium_chip_22x21 const Icon
2621 Variable + I_Mute_25x27 const Icon
2622 Variable + I_Mute_hvr_25x27 const Icon
2623 Variable + I_NFC_manual I_NFC_manual_60x50 const Icon
2624 Variable + I_Nfc_10px const Icon
2625 Variable + I_Ok_btn_9x9 const Icon
2626 Variable + I_Ok_btn_pressed_13x13 const Icon
2628 Variable + I_Pin_arrow_down_7x9 const Icon
2629 Variable + I_Pin_arrow_left_9x7 const Icon
2630 Variable + I_Pin_arrow_right_9x7 const Icon
2631 Variable + I_Pin_arrow_up7x9 I_Pin_arrow_up_7x9 const Icon
2632 Variable + I_Pin_attention_dpad_29x29 const Icon
2633 Variable + I_Pin_back_arrow_10x8 const Icon
2634 Variable + I_Pin_back_full_40x8 const Icon
2642 Variable + I_RFIDDolphinReceive_97x61 const Icon
2643 Variable + I_RFIDDolphinSend_97x61 const Icon
2644 Variable + I_RFIDDolphinSuccess_108x57 const Icon
2645 Variable + I_Restoring I_Reader_detect_43x40 const Icon
2646 Variable + I_Restoring_38x32 const Icon
2647 Variable + I_Right_mouse_icon_9x9 const Icon
2648 Variable + I_SDQuestion_35x43 const Icon
2649 Variable + I_SDcardFail_11x8 const Icon

View file

@ -86,38 +86,30 @@ void mf_classic_dict_free(MfClassicDict* dict) {
free(dict);
}
static void mf_classic_dict_int_to_str(uint8_t* key_int, string_t key_str) {
string_reset(key_str);
for(size_t i = 0; i < 6; i++) {
string_cat_printf(key_str, "%02X", key_int[i]);
}
}
static void mf_classic_dict_str_to_int(string_t key_str, uint64_t* key_int) {
uint8_t key_byte_tmp;
*key_int = 0ULL;
for(uint8_t i = 0; i < 12; i += 2) {
args_char_to_hex(
string_get_char(key_str, i), string_get_char(key_str, i + 1), &key_byte_tmp);
*key_int |= (uint8_t)key_byte_tmp << 8 * (5 - i / 2);
}
}
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict) {
furi_assert(dict);
return dict->total_keys;
}
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) {
furi_assert(dict);
furi_assert(dict->stream);
uint8_t key_byte_tmp = 0;
string_t next_line;
string_init(next_line);
bool key_read = false;
*key = 0ULL;
while(!key_read) {
if(!stream_read_line(dict->stream, next_line)) break;
if(string_get_char(next_line, 0) == '#') continue;
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
for(uint8_t i = 0; i < 12; i += 2) {
args_char_to_hex(
string_get_char(next_line, i), string_get_char(next_line, i + 1), &key_byte_tmp);
*key |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2);
}
key_read = true;
}
string_clear(next_line);
return key_read;
}
bool mf_classic_dict_rewind(MfClassicDict* dict) {
furi_assert(dict);
furi_assert(dict->stream);
@ -125,24 +117,194 @@ bool mf_classic_dict_rewind(MfClassicDict* dict) {
return stream_rewind(dict->stream);
}
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) {
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key) {
furi_assert(dict);
furi_assert(dict->stream);
string_t key_str;
string_init(key_str);
for(size_t i = 0; i < 6; i++) {
string_cat_printf(key_str, "%02X", key[i]);
bool key_read = false;
string_reset(key);
while(!key_read) {
if(!stream_read_line(dict->stream, key)) break;
if(string_get_char(key, 0) == '#') continue;
if(string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue;
string_left(key, 12);
key_read = true;
}
string_cat_printf(key_str, "\n");
return key_read;
}
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) {
furi_assert(dict);
furi_assert(dict->stream);
string_t temp_key;
string_init(temp_key);
bool key_read = mf_classic_dict_get_next_key_str(dict, temp_key);
if(key_read) {
mf_classic_dict_str_to_int(temp_key, key);
}
string_clear(temp_key);
return key_read;
}
bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key) {
furi_assert(dict);
furi_assert(dict->stream);
string_t next_line;
string_init(next_line);
bool key_found = false;
stream_rewind(dict->stream);
while(!key_found) {
if(!stream_read_line(dict->stream, next_line)) break;
if(string_get_char(next_line, 0) == '#') continue;
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
string_left(next_line, 12);
if(!string_equal_p(key, next_line)) continue;
key_found = true;
}
string_clear(next_line);
return key_found;
}
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) {
string_t temp_key;
string_init(temp_key);
mf_classic_dict_int_to_str(key, temp_key);
bool key_found = mf_classic_dict_is_key_present_str(dict, temp_key);
string_clear(temp_key);
return key_found;
}
bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key) {
furi_assert(dict);
furi_assert(dict->stream);
string_cat_printf(key, "\n");
bool key_added = false;
do {
if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break;
if(!stream_insert_string(dict->stream, key_str)) break;
if(!stream_insert_string(dict->stream, key)) break;
dict->total_keys++;
key_added = true;
} while(false);
string_clear(key_str);
string_left(key, 12);
return key_added;
}
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) {
furi_assert(dict);
furi_assert(dict->stream);
string_t temp_key;
string_init(temp_key);
mf_classic_dict_int_to_str(key, temp_key);
bool key_added = mf_classic_dict_add_key_str(dict, temp_key);
string_clear(temp_key);
return key_added;
}
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target) {
furi_assert(dict);
furi_assert(dict->stream);
string_t next_line;
uint32_t index = 0;
string_init(next_line);
string_reset(key);
bool key_found = false;
while(!key_found) {
if(!stream_read_line(dict->stream, next_line)) break;
if(string_get_char(next_line, 0) == '#') continue;
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
if(index++ != target) continue;
string_set_n(key, next_line, 0, 12);
key_found = true;
}
string_clear(next_line);
return key_found;
}
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target) {
furi_assert(dict);
furi_assert(dict->stream);
string_t temp_key;
string_init(temp_key);
bool key_found = mf_classic_dict_get_key_at_index_str(dict, temp_key, target);
if(key_found) {
mf_classic_dict_str_to_int(temp_key, key);
}
string_clear(temp_key);
return key_found;
}
bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target) {
furi_assert(dict);
furi_assert(dict->stream);
string_t next_line;
string_init(next_line);
bool key_found = false;
uint32_t index = 0;
stream_rewind(dict->stream);
while(!key_found) {
if(!stream_read_line(dict->stream, next_line)) break;
if(string_get_char(next_line, 0) == '#') continue;
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
string_left(next_line, 12);
if(!string_equal_p(key, next_line)) continue;
key_found = true;
*target = index;
}
string_clear(next_line);
return key_found;
}
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target) {
furi_assert(dict);
furi_assert(dict->stream);
string_t temp_key;
string_init(temp_key);
mf_classic_dict_int_to_str(key, temp_key);
bool key_found = mf_classic_dict_find_index_str(dict, temp_key, target);
string_clear(temp_key);
return key_found;
}
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) {
furi_assert(dict);
furi_assert(dict->stream);
string_t next_line;
string_init(next_line);
uint32_t index = 0;
bool key_removed = false;
while(!key_removed) {
if(!stream_read_line(dict->stream, next_line)) break;
if(string_get_char(next_line, 0) == '#') continue;
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
if(index++ != target) continue;
stream_seek(dict->stream, -NFC_MF_CLASSIC_KEY_LEN, StreamOffsetFromCurrent);
if(!stream_delete(dict->stream, NFC_MF_CLASSIC_KEY_LEN)) break;
dict->total_keys--;
key_removed = true;
}
string_clear(next_line);
return key_removed;
}

View file

@ -21,8 +21,26 @@ void mf_classic_dict_free(MfClassicDict* dict);
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict);
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key);
bool mf_classic_dict_rewind(MfClassicDict* dict);
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key);
bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key);
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key);
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key);
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target);
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target);
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key);
bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key);
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target);
bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target);
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target);