// Header #include "ui.h" // Constants #define MAX_OPTIONS 4 // Structures /* Scenes */ typedef enum { FP_Scene_MainMenu, FP_Scene_Overview, FP_Scene_View, FP_Scene_Cred, FP_Scene_Send, FP_Scene_Create, FP_Scene_Type, FP_Scene_Archive, FP_Scene_About, FP_Scene_Count // Last Index, says how many scenes there are } FP_Scene; /* Types of Views */ typedef enum { FP_View_VariableItemList, FP_View_Submenu, FP_View_TextBox, FP_View_TextInput, FP_View_Dialog, FP_View_Popup } FP_View; /* Scene events */ typedef enum { FP_Scene_MainMenu_Event_View, FP_Scene_MainMenu_Event_Create, FP_Scene_MainMenu_Event_Archive, FP_Scene_MainMenu_Event_About } FP_Scene_MainMenu_Event; typedef enum { FP_Scene_View_Event_Username, FP_Scene_View_Event_Password, FP_Scene_View_Event_BadUSB } FP_Scene_View_Event; typedef enum { FP_Scene_Create_Event_Name, FP_Scene_Create_Event_Username, FP_Scene_Create_Event_Password, FP_Scene_Create_Event_Done } FP_Scene_Create_Event; // Page functions void FP_Scene_Callback_Default(void* context, uint32_t index) { // Setting context FP_App* app = context; // Sending it to the scene manager scene_manager_handle_custom_event(app->scene_manager, index); } void FP_Scene_Callback_Dialog(DialogExResult result, void* context) { // Setting context FP_App* app = context; // Sending it to the scene manager scene_manager_handle_custom_event(app->scene_manager, result); } void FP_Scene_Callback_Type(void* context) { // Setting context FP_App* app = context; // DEBUG FURI_LOG_D(TAG, "Typed: %s", app->temp); // Going back a page scene_manager_previous_scene(app->scene_manager); } void FP_Scene_Enter_MainMenu(void* context) { // Setting context FP_App* app = context; // Reset menu for next draw submenu_reset(app->submenu); // Adding items to menu submenu_add_item( app->submenu, "View Passwords", FP_Scene_MainMenu_Event_View, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "Create Password", FP_Scene_MainMenu_Event_Create, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "Archive Actions", FP_Scene_MainMenu_Event_Archive, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "About", FP_Scene_MainMenu_Event_About, FP_Scene_Callback_Default, app ); // Switching to current view view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_Submenu); } void FP_Scene_Enter_Overview(void* context) { // Setting context FP_App* app = context; // Reset menu submenu_reset(app->submenu); // Adding menu items for (int i = 0; i < app->manager->count; i++) { submenu_add_item( app->submenu, app->manager->names[i], i, FP_Scene_Callback_Default, app ); } // Sending view to Flipper view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_Submenu); } void FP_Scene_Enter_View(void* context) { // Setting context FP_App* app = context; // Freeing Dialog submenu_reset(app->submenu); // Adding some content submenu_add_item( app->submenu, "View Username", FP_Scene_View_Event_Username, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "View Password", FP_Scene_View_Event_Password, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "BadUSB", FP_Scene_View_Event_BadUSB, FP_Scene_Callback_Default, app ); // Sending view to Flipper view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_Submenu); } void FP_Scene_Enter_Cred(void* context) { // Set context FP_App* app = context; // Reset view text_box_reset(app->textbox); // Setting text if (!strcmp(app->temp, "Username")) { text_box_set_text( app->textbox, app->manager->current->user ); } else { text_box_set_text( app->textbox, app->manager->current->phrase ); } // Send view to Flipper view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_TextBox); } void FP_Scene_Enter_Send(void* context) { // Setting context FP_App* app = context; // Reset view dialog_ex_reset(app->dialog); // Adding dialog content dialog_ex_set_header( app->dialog, "Send via BadUSB", 0,0, AlignLeft, AlignTop ); dialog_ex_set_text( app->dialog, "This will type out either the Username or Password using BadUSB", 5,15, AlignLeft, AlignTop ); dialog_ex_set_left_button_text( app->dialog, "Username" ); dialog_ex_set_right_button_text( app->dialog, "Password" ); // Setting context and callback dialog_ex_set_result_callback(app->dialog, FP_Scene_Callback_Dialog); dialog_ex_set_context(app->dialog, app); // Send view to Flipper view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_Dialog); } void FP_Scene_Enter_Create(void* context) { // Setting context FP_App* app = context; // Reset page submenu_reset(app->submenu); // Checking if we typed something before if (app->temp) { // Boolean bool is_field = true; // Checking if it's any of the following: if (!strcmp(app->temp, "Username")) {is_field = false;} if (!strcmp(app->temp, "Password")) {is_field = false;} // We're good! if(is_field) { // Did we already start a password? if (!app->manager->new) { app->manager->new = malloc(sizeof(Password)); } // Checking what we selected switch (app->selection) { case 0: // Name // Does name already exist? if (app->manager->new->name) { free(app->manager->new->name); } // Copying it app->manager->new->name = malloc(sizeof(char*)); strcpy(app->manager->new->name, app->temp); break; case 1: // Username // Does user already exist? if (app->manager->new->user) { free(app->manager->new->user); } // Copying it app->manager->new->user = malloc(sizeof(char*)); strcpy(app->manager->new->user, app->temp); break; case 2: // Password // Does phrase already exist? if (app->manager->new->phrase) { free(app->manager->new->phrase); } // Copying it app->manager->new->phrase = malloc(sizeof(char*)); strcpy(app->manager->new->phrase, app->temp); break; } } // Freeing temp free(app->temp); } // Options submenu_add_item( app->submenu, "Set Name", FP_Scene_Create_Event_Name, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "Set Username", FP_Scene_Create_Event_Username, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "Set Password", FP_Scene_Create_Event_Password, FP_Scene_Callback_Default, app ); submenu_add_item( app->submenu, "Finish", FP_Scene_Create_Event_Done, FP_Scene_Callback_Default, app ); // Send view to Flipper view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_Submenu); } void FP_Scene_Enter_Type(void* context) { // Set Context FP_App* app = context; // Reset view text_input_reset(app->textinput); // Creating temp string app->temp = malloc(sizeof(char*)); // Setting stuff text_input_set_result_callback( app->textinput, FP_Scene_Callback_Type, app, app->temp, 255, true ); // Send view to Flipper view_dispatcher_switch_to_view(app->view_dispatcher, FP_View_TextInput); } void FP_Scene_Exit_Default(void* context) { // Setting context FP_App* app = context; // Reset menu submenu_reset(app->submenu); } void FP_Scene_Exit_Cred(void* context) { // Setting context FP_App* app = context; // Free the temp string free(app->temp); // Reset menu dialog_ex_reset(app->dialog); } bool FP_Scene_Event_MainMenu(void* context, SceneManagerEvent event) { // Setting context FP_App* app = context; bool consumed = false; // Switching based on event if (event.type == SceneManagerEventTypeCustom) { // We consumed it consumed = true; // What to do? switch (event.event) { case FP_Scene_MainMenu_Event_About: scene_manager_next_scene(app->scene_manager, FP_Scene_About); break; case FP_Scene_MainMenu_Event_View: scene_manager_next_scene(app->scene_manager, FP_Scene_Overview); break; case FP_Scene_MainMenu_Event_Create: scene_manager_next_scene(app->scene_manager, FP_Scene_Create); break; default: break; } } else { consumed = false; } // Return result return consumed; } bool FP_Scene_Event_Overview(void* context, SceneManagerEvent event) { // Setting context FP_App* app = context; bool consumed = false; // Switching based on event if (event.type == SceneManagerEventTypeCustom) { // We consumed it consumed = true; // Loading password manager_loadpass(app->manager, app->manager->names[event.event]); // Is the current password a fake? if (!app->manager->current) { FURI_LOG_E(TAG, "Password is NULL!"); furi_crash(); } // Switch to password view screen scene_manager_next_scene(app->scene_manager, FP_Scene_View); } else { consumed = false; } // Return result return consumed; } bool FP_Scene_Event_View(void* context, SceneManagerEvent event) { // Setting context FP_App* app = context; bool consumed = false; // Switching based on event if (event.type == SceneManagerEventTypeCustom) { // We consumed it consumed = true; // What did we press? switch (event.event) { case FP_Scene_View_Event_Username: app->temp = malloc(sizeof(char*)); app->temp = "Username"; scene_manager_next_scene(app->scene_manager, FP_Scene_Cred); break; case FP_Scene_View_Event_Password: app->temp = malloc(sizeof(char*)); app->temp = "Password"; scene_manager_next_scene(app->scene_manager, FP_Scene_Cred); break; case FP_Scene_View_Event_BadUSB: scene_manager_next_scene(app->scene_manager, FP_Scene_Send); break; default: break; } } else { consumed = false; } // Return result return consumed; } bool FP_Scene_Event_Cred(void* context, SceneManagerEvent event) { // Setting context FP_App* app = context; bool consumed = false; // Switching based on event if (event.type == SceneManagerEventTypeCustom) { // We consumed it consumed = true; // Debug log about what we pressed FURI_LOG_D(TAG, "Pressed %li", event.event); UNUSED(app); // What to do? switch (event.event) { default: break; } } else { consumed = false; } // Return result return consumed; } bool FP_Scene_Event_Send(void* context, SceneManagerEvent event) { // Setting context FP_App* app = context; bool consumed = false; // Switching based on event if (event.type == SceneManagerEventTypeCustom) { // We consumed it consumed = true; UNUSED(app); // What to do? switch (event.event) { default: break; } } else { consumed = false; } // Return result return consumed; } bool FP_Scene_Event_Create(void* context, SceneManagerEvent event) { // Setting context FP_App* app = context; bool consumed = false; // Switching based on event if (event.type == SceneManagerEventTypeCustom) { // We consumed it consumed = true; // What to do? switch (event.event) { case FP_Scene_Create_Event_Name: case FP_Scene_Create_Event_Username: case FP_Scene_Create_Event_Password: // Set selection app->selection = event.event; // Switch to keyboard scene scene_manager_next_scene(app->scene_manager, FP_Scene_Type); break; case FP_Scene_Create_Event_Done: // Save the password manager_savepass(app->manager->new); // Reload manager manager_free(app->manager); app->manager = manager_init(); // Switching scenes scene_manager_previous_scene(app->scene_manager); break; default: break; } } else { consumed = false; } // Return result return consumed; } bool FP_Scene_Event_Type(void* context, SceneManagerEvent event) { // Return result UNUSED(context); return event.type == SceneManagerEventTypeCustom; } /* Handlers */ void (*const FP_Scene_Enter_Handlers[])(void*) = { FP_Scene_Enter_MainMenu, FP_Scene_Enter_Overview, FP_Scene_Enter_View, FP_Scene_Enter_Cred, FP_Scene_Enter_Send, FP_Scene_Enter_Create, FP_Scene_Enter_Type }; bool (*const FP_Scene_Event_Handlers[])(void*, SceneManagerEvent) = { FP_Scene_Event_MainMenu, FP_Scene_Event_Overview, FP_Scene_Event_View, FP_Scene_Event_Cred, FP_Scene_Event_Send, FP_Scene_Event_Create, FP_Scene_Event_Type }; void (*const FP_Scene_Exit_Handlers[])(void*) = { FP_Scene_Exit_Default, FP_Scene_Exit_Default, FP_Scene_Exit_Default, FP_Scene_Exit_Cred, FP_Scene_Exit_Default, FP_Scene_Exit_Default, FP_Scene_Exit_Default }; /* Event Handlers */ const SceneManagerHandlers FP_SceneEventHandlers = { .on_enter_handlers = FP_Scene_Enter_Handlers, .on_event_handlers = FP_Scene_Event_Handlers, .on_exit_handlers = FP_Scene_Exit_Handlers, .scene_num = FP_Scene_Count}; // Functions - Private bool FP_SceneManager_Callback_CustomEvent(void* context, uint32_t custom_event) { // Is our context okay? furi_assert(context); // Setting context FP_App* app = context; // Return event return scene_manager_handle_custom_event(app->scene_manager, custom_event); } bool FP_SceneManager_Callback_Navigation(void* context) { // Is our context okay? furi_assert(context); // Setting context FP_App* app = context; // Return navigation return scene_manager_handle_back_event(app->scene_manager); } // Constructors FP_App* fp_app_init() { // Allocate memory for new app variable FP_App* result = malloc(sizeof(FP_App)); // Initilize the manager result->manager = manager_init(); // Init Scene Manager result->scene_manager = scene_manager_alloc(&FP_SceneEventHandlers, result); // Init View Dispatcher result->view_dispatcher = view_dispatcher_alloc(); view_dispatcher_enable_queue(result->view_dispatcher); // Allocating all types of views result->varitemlist = variable_item_list_alloc(); result->textinput = text_input_alloc(); result->dialog = dialog_ex_alloc(); result->submenu = submenu_alloc(); result->textbox = text_box_alloc(); result->popup = popup_alloc(); // Event handling view_dispatcher_set_event_callback_context(result->view_dispatcher, result); view_dispatcher_set_custom_event_callback(result->view_dispatcher, FP_SceneManager_Callback_CustomEvent); view_dispatcher_set_navigation_event_callback(result->view_dispatcher, FP_SceneManager_Callback_Navigation); // Adding views to dispatcher view_dispatcher_add_view(result->view_dispatcher, FP_View_VariableItemList, variable_item_list_get_view(result->varitemlist)); view_dispatcher_add_view(result->view_dispatcher, FP_View_TextInput, text_input_get_view(result->textinput)); view_dispatcher_add_view(result->view_dispatcher, FP_View_TextBox, text_box_get_view(result->textbox)); view_dispatcher_add_view(result->view_dispatcher, FP_View_Dialog, dialog_ex_get_view(result->dialog)); view_dispatcher_add_view(result->view_dispatcher, FP_View_Submenu, submenu_get_view(result->submenu)); view_dispatcher_add_view(result->view_dispatcher, FP_View_Popup, popup_get_view(result->popup)); // Return app return result; } // Functions void fp_app_run(FP_App* app) { // Creating GUI Gui* gui = furi_record_open(RECORD_GUI); // Attaching view dispatcher to GUI view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen); // Starting scene scene_manager_next_scene(app->scene_manager, FP_Scene_MainMenu); // Start view dispatcher view_dispatcher_run(app->view_dispatcher); /* Post Application */ furi_record_close(RECORD_GUI); } void fp_app_free(FP_App* app) { // Freeing stuff from memory manager_free(app->manager); scene_manager_free(app->scene_manager); view_dispatcher_remove_view(app->view_dispatcher, FP_View_VariableItemList); view_dispatcher_remove_view(app->view_dispatcher, FP_View_TextInput); view_dispatcher_remove_view(app->view_dispatcher, FP_View_Submenu); view_dispatcher_remove_view(app->view_dispatcher, FP_View_TextBox); view_dispatcher_remove_view(app->view_dispatcher, FP_View_Dialog); view_dispatcher_remove_view(app->view_dispatcher, FP_View_Popup); view_dispatcher_free(app->view_dispatcher); variable_item_list_free(app->varitemlist); text_input_free(app->textinput); dialog_ex_free(app->dialog); text_box_free(app->textbox); submenu_free(app->submenu); popup_free(app->popup); free(app->temp); free(app); }