pof_token.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <toolbox/path.h>
  2. #include <flipper_format/flipper_format.h>
  3. #include <portal_of_flipper_icons.h>
  4. #include "pof_token.h"
  5. #define TAG "PoFToken"
  6. static uint8_t pof_token_sector_0_key[] = {0x4b, 0x0b, 0x20, 0x10, 0x7c, 0xcb};
  7. PoFToken* pof_token_alloc() {
  8. PoFToken* pof_token = malloc(sizeof(PoFToken));
  9. memset(pof_token, 0, sizeof(PoFToken));
  10. pof_token->storage = furi_record_open(RECORD_STORAGE);
  11. pof_token->dialogs = furi_record_open(RECORD_DIALOGS);
  12. pof_token->load_path = furi_string_alloc();
  13. pof_token->loaded = false;
  14. pof_token->change = false;
  15. pof_token->nfc_device = nfc_device_alloc();
  16. return pof_token;
  17. }
  18. void pof_token_set_name(PoFToken* pof_token, const char* name) {
  19. furi_assert(pof_token);
  20. strlcpy(pof_token->dev_name, name, sizeof(pof_token->dev_name));
  21. }
  22. static bool pof_token_load_data(PoFToken* pof_token, FuriString* path, bool show_dialog) {
  23. FuriString* reason = furi_string_alloc_set("Couldn't load file");
  24. if(pof_token->loading_cb) {
  25. pof_token->loading_cb(pof_token->loading_cb_ctx, true);
  26. }
  27. do {
  28. NfcDevice* nfc_device = pof_token->nfc_device;
  29. if(!nfc_device_load(nfc_device, furi_string_get_cstr(path))) break;
  30. NfcProtocol protocol = nfc_device_get_protocol(nfc_device);
  31. if(protocol != NfcProtocolMfClassic) {
  32. furi_string_printf(reason, "Not Mifare Classic");
  33. break;
  34. }
  35. const MfClassicData* data = nfc_device_get_data(nfc_device, NfcProtocolMfClassic);
  36. if(!mf_classic_is_card_read(data)) {
  37. furi_string_printf(reason, "Incomplete data");
  38. break;
  39. }
  40. MfClassicKey key = mf_classic_get_key(data, 0, MfClassicKeyTypeA);
  41. if(memcmp(key.data, pof_token_sector_0_key, MF_CLASSIC_KEY_SIZE) != 0) {
  42. furi_string_printf(reason, "Wrong key");
  43. break;
  44. }
  45. pof_token->loaded = true;
  46. pof_token->change = true;
  47. } while(false);
  48. if(pof_token->loading_cb) {
  49. pof_token->loading_cb(pof_token->loading_cb_ctx, false);
  50. }
  51. if((!pof_token->loaded) && (show_dialog)) {
  52. dialog_message_show_storage_error(pof_token->dialogs, furi_string_get_cstr(reason));
  53. }
  54. furi_string_free(reason);
  55. return pof_token->loaded;
  56. }
  57. void pof_token_clear(PoFToken* pof_token, bool save) {
  58. furi_assert(pof_token);
  59. if(save) {
  60. // Saving during app clean up causes a crash
  61. nfc_device_save(pof_token->nfc_device, furi_string_get_cstr(pof_token->load_path));
  62. }
  63. nfc_device_clear(pof_token->nfc_device);
  64. furi_string_reset(pof_token->load_path);
  65. memset(pof_token->dev_name, 0, sizeof(pof_token->dev_name));
  66. pof_token->loaded = false;
  67. pof_token->change = true;
  68. }
  69. void pof_token_free(PoFToken* pof_token) {
  70. furi_assert(pof_token);
  71. pof_token_clear(pof_token, false);
  72. furi_record_close(RECORD_STORAGE);
  73. furi_record_close(RECORD_DIALOGS);
  74. furi_string_free(pof_token->load_path);
  75. nfc_device_free(pof_token->nfc_device);
  76. free(pof_token);
  77. }
  78. bool pof_file_select(PoFToken* pof_token) {
  79. furi_assert(pof_token);
  80. FuriString* pof_app_folder;
  81. pof_app_folder = furi_string_alloc_set("/ext/nfc");
  82. DialogsFileBrowserOptions browser_options;
  83. dialog_file_browser_set_basic_options(&browser_options, ".nfc", &I_Nfc_10px);
  84. browser_options.base_path = "/ext/nfc";
  85. bool res = dialog_file_browser_show(
  86. pof_token->dialogs, pof_token->load_path, pof_app_folder, &browser_options);
  87. furi_string_free(pof_app_folder);
  88. if(res) {
  89. FuriString* filename;
  90. filename = furi_string_alloc();
  91. path_extract_filename(pof_token->load_path, filename, true);
  92. strlcpy(pof_token->dev_name, furi_string_get_cstr(filename), sizeof(pof_token->dev_name));
  93. res = pof_token_load_data(pof_token, pof_token->load_path, true);
  94. if(res) {
  95. pof_token_set_name(pof_token, pof_token->dev_name);
  96. }
  97. furi_string_free(filename);
  98. }
  99. return res;
  100. }
  101. void pof_token_set_loading_callback(
  102. PoFToken* pof_token,
  103. PoFLoadingCallback callback,
  104. void* context) {
  105. furi_assert(pof_token);
  106. pof_token->loading_cb = callback;
  107. pof_token->loading_cb_ctx = context;
  108. }