subbrute_scene_save_name.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "../subbrute.h"
  2. #include "m-string.h"
  3. #include "subghz/types.h"
  4. #include <lib/toolbox/random_name.h>
  5. #include <gui/modules/validators.h>
  6. #include <lib/toolbox/path.h>
  7. #define MAX_TEXT_INPUT_LEN 22
  8. bool backpressed = false;
  9. bool subbrute_path_is_file(string_t path) {
  10. return string_end_with_str_p(path, ".sub");
  11. }
  12. // method modified from subghz_i.c
  13. // https://github.com/flipperdevices/flipperzero-firmware/blob/b0daa601ad5b87427a45f9089c8b403a01f72c2a/applications/subghz/subghz_i.c#L417-L456
  14. bool subbrute_save_protocol_to_file(Stream* flipper_format_stream, const char* dev_file_name) {
  15. furi_assert(dev_file_name);
  16. Storage* storage = furi_record_open(RECORD_STORAGE);
  17. bool saved = false;
  18. string_t file_dir;
  19. string_init(file_dir);
  20. path_extract_dirname(dev_file_name, file_dir);
  21. do {
  22. if(!storage_simply_mkdir(storage, string_get_cstr(file_dir))) {
  23. FURI_LOG_E(TAG, "(save) Cannot mkdir");
  24. break;
  25. }
  26. if(!storage_simply_remove(storage, dev_file_name)) {
  27. FURI_LOG_E(TAG, "(save) Cannot remove");
  28. break;
  29. }
  30. stream_seek(flipper_format_stream, 0, StreamOffsetFromStart);
  31. stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS);
  32. saved = true;
  33. FURI_LOG_D(TAG, "(save) OK Save");
  34. } while(0);
  35. string_clear(file_dir);
  36. furi_record_close(RECORD_STORAGE);
  37. return saved;
  38. }
  39. void custom_callback(SubBruteState* context) {
  40. if(strcmp(context->file_name_tmp, "")) {
  41. string_cat_printf(context->file_path, "/%s%s", context->file_name_tmp, ".sub");
  42. if(subbrute_path_is_file(context->file_path_tmp)) {
  43. context->current_scene = SceneAttack;
  44. return; //false;
  45. } else {
  46. subbrute_save_protocol_to_file(context->stream, string_get_cstr(context->file_path));
  47. }
  48. string_set_str(context->file_path, EXT_PATH("subghz"));
  49. string_reset(context->file_path_tmp);
  50. //scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
  51. context->current_scene = SceneAttack;
  52. return; //true;
  53. } else {
  54. //error no file name
  55. context->current_scene = SceneAttack;
  56. return; //true;
  57. }
  58. }
  59. void subbrute_scene_save_name_text_input_callback(void* context) {
  60. furi_assert(context);
  61. SubBruteState* statee = context;
  62. custom_callback(statee);
  63. }
  64. void subbrute_scene_save_name_on_tick(SubBruteState* context) {
  65. if(backpressed) {
  66. void* validator_context = text_input_get_validator_callback_context(context->text_input);
  67. text_input_set_validator(context->text_input, NULL, NULL);
  68. validator_is_file_free(validator_context);
  69. // Clear view
  70. text_input_reset(context->text_input);
  71. // TextInput
  72. view_dispatcher_remove_view(context->view_dispatcher, 0);
  73. text_input_free(context->text_input);
  74. // Popup
  75. view_dispatcher_remove_view(context->view_dispatcher, 1);
  76. popup_free(context->popup);
  77. context->current_scene = SceneAttack;
  78. }
  79. }
  80. bool subbrute_back_event_callback(void* context) {
  81. UNUSED(context);
  82. backpressed = true;
  83. return true;
  84. }
  85. void subbrute_scene_save_name_on_enter(SubBruteState* context) {
  86. // Text Input
  87. context->text_input = text_input_alloc();
  88. view_dispatcher_add_view(
  89. context->view_dispatcher, 0, text_input_get_view(context->text_input));
  90. // Popup
  91. context->popup = popup_alloc();
  92. view_dispatcher_add_view(context->view_dispatcher, 1, popup_get_view(context->popup));
  93. // Setup view
  94. TextInput* text_input = context->text_input;
  95. bool dev_name_empty = false;
  96. string_t file_name;
  97. string_t dir_name;
  98. string_init(file_name);
  99. string_init(dir_name);
  100. if(!subbrute_path_is_file(context->file_path)) {
  101. char file_name_buf[64] = {0};
  102. set_random_name(file_name_buf, 64);
  103. string_set_str(file_name, file_name_buf);
  104. string_set_str(context->file_path, EXT_PATH("subghz"));
  105. //highlighting the entire filename by default
  106. dev_name_empty = true;
  107. } else {
  108. string_set(context->file_path_tmp, context->file_path);
  109. path_extract_dirname(string_get_cstr(context->file_path), dir_name);
  110. path_extract_filename(context->file_path, file_name, true);
  111. string_set(context->file_path, dir_name);
  112. }
  113. strncpy(context->file_name_tmp, string_get_cstr(file_name), 64);
  114. text_input_set_header_text(text_input, "Name signal");
  115. text_input_set_result_callback(
  116. text_input,
  117. subbrute_scene_save_name_text_input_callback,
  118. context,
  119. context->file_name_tmp,
  120. MAX_TEXT_INPUT_LEN, // buffer size
  121. dev_name_empty);
  122. ValidatorIsFile* validator_is_file =
  123. validator_is_file_alloc_init(string_get_cstr(context->file_path), ".sub", "");
  124. text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
  125. string_clear(file_name);
  126. string_clear(dir_name);
  127. view_dispatcher_set_navigation_event_callback(
  128. context->view_dispatcher, subbrute_back_event_callback);
  129. view_dispatcher_switch_to_view(context->view_dispatcher, 0);
  130. }
  131. void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context) {
  132. UNUSED(context);
  133. if(event.evt_type == EventTypeKey) {
  134. if(event.input_type == InputTypeShort) {
  135. switch(event.key) {
  136. case InputKeyDown:
  137. case InputKeyUp:
  138. case InputKeyLeft:
  139. case InputKeyRight:
  140. case InputKeyOk:
  141. break;
  142. case InputKeyBack:
  143. //context->current_scene = SceneAttack;
  144. break;
  145. }
  146. }
  147. }
  148. }
  149. void subbrute_scene_save_name_on_exit(SubBruteState* context) {
  150. if(!backpressed) {
  151. // Clear validator
  152. void* validator_context = text_input_get_validator_callback_context(context->text_input);
  153. text_input_set_validator(context->text_input, NULL, NULL);
  154. validator_is_file_free(validator_context);
  155. // Clear view
  156. text_input_reset(context->text_input);
  157. // Setup view
  158. Popup* popup = context->popup;
  159. popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
  160. popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom);
  161. popup_set_timeout(popup, 1500);
  162. popup_set_context(popup, context);
  163. popup_set_callback(popup, NULL);
  164. popup_enable_timeout(popup);
  165. view_dispatcher_switch_to_view(context->view_dispatcher, 1);
  166. furi_delay_ms(1050);
  167. // Clear view
  168. //Popup* popup = subghz->popup;
  169. popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
  170. popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
  171. popup_set_icon(popup, 0, 0, NULL);
  172. popup_set_callback(popup, NULL);
  173. popup_set_context(popup, NULL);
  174. popup_set_timeout(popup, 0);
  175. popup_disable_timeout(popup);
  176. // TextInput
  177. view_dispatcher_remove_view(context->view_dispatcher, 0);
  178. text_input_free(context->text_input);
  179. // Popup
  180. view_dispatcher_remove_view(context->view_dispatcher, 1);
  181. popup_free(context->popup);
  182. } else {
  183. backpressed = false;
  184. }
  185. }