diff --git a/applications/plugins/totp/cli/cli.c b/applications/plugins/totp/cli/cli.c index 829860174..e61c67206 100644 --- a/applications/plugins/totp/cli/cli.c +++ b/applications/plugins/totp/cli/cli.c @@ -10,6 +10,7 @@ #include "commands/help/help.h" #include "commands/move/move.h" #include "commands/pin/pin.h" +#include "commands/notification/notification.h" static void totp_cli_print_unknown_command(const FuriString* unknown_command) { TOTP_CLI_PRINTF( @@ -52,6 +53,8 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { totp_cli_command_move_handle(plugin_state, args, cli); } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_PIN) == 0) { totp_cli_command_pin_handle(plugin_state, args, cli); + } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_NOTIFICATION) == 0) { + totp_cli_command_notification_handle(plugin_state, args, cli); } else { totp_cli_print_unknown_command(cmd); } diff --git a/applications/plugins/totp/cli/cli_helpers.h b/applications/plugins/totp/cli/cli_helpers.h index 0b375ec08..075822cd6 100644 --- a/applications/plugins/totp/cli/cli_helpers.h +++ b/applications/plugins/totp/cli/cli_helpers.h @@ -6,6 +6,7 @@ #define TOTP_CLI_COMMAND_NAME "totp" #define DOCOPT_ARGUMENT(arg) "<" arg ">" +#define DOCOPT_MULTIPLE(arg) arg "..." #define DOCOPT_OPTIONAL(param) "[" param "]" #define DOCOPT_REQUIRED(param) "(" param ")" #define DOCOPT_OPTION(option, value) option " " value diff --git a/applications/plugins/totp/cli/commands/add/add.c b/applications/plugins/totp/cli/commands/add/add.c index 26131d894..90cc0f420 100644 --- a/applications/plugins/totp/cli/commands/add/add.c +++ b/applications/plugins/totp/cli/commands/add/add.c @@ -4,6 +4,7 @@ #include "../../../lib/list/list.h" #include "../../../types/token_info.h" #include "../../../services/config/config.h" +#include "../../../services/convert/convert.h" #include "../../cli_helpers.h" #include "../../../ui/scene_director.h" @@ -14,21 +15,6 @@ #define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d" #define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u" -static bool token_info_set_digits_from_str(TokenInfo* token_info, const FuriString* str) { - switch(furi_string_get_char(str, 0)) { - case '6': - token_info->digits = TOTP_6_DIGITS; - return true; - case '8': - token_info->digits = TOTP_8_DIGITS; - return true; - default: - break; - } - - return false; -} - static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { token_info->algo = SHA1; @@ -73,6 +59,7 @@ void totp_cli_command_add_docopt_options() { DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_ALGO)) " Token hashing algorithm.\r\n"); TOTP_CLI_PRINTF( " Could be one of: sha1, sha256, sha512 " DOCOPT_DEFAULT("sha1") "\r\n"); + cli_nl(); TOTP_CLI_PRINTF(" " DOCOPT_OPTION( TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX, DOCOPT_ARGUMENT( @@ -164,7 +151,8 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl TOTP_CLI_PRINTF( "Missed value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "\"\r\n"); - } else if(!token_info_set_digits_from_str(token_info, temp_str)) { + } else if(!token_info_set_digits_from_int( + token_info, CONVERT_CHAR_TO_DIGIT(furi_string_get_char(temp_str, 0)))) { TOTP_CLI_PRINTF( "\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "\"\r\n", diff --git a/applications/plugins/totp/cli/commands/help/help.c b/applications/plugins/totp/cli/commands/help/help.c index 7da5a2308..419964880 100644 --- a/applications/plugins/totp/cli/commands/help/help.c +++ b/applications/plugins/totp/cli/commands/help/help.c @@ -6,6 +6,7 @@ #include "../timezone/timezone.h" #include "../move/move.h" #include "../pin/pin.h" +#include "../notification/notification.h" void totp_cli_command_help_docopt_commands() { TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT @@ -27,6 +28,7 @@ void totp_cli_command_help_handle() { totp_cli_command_timezone_docopt_usage(); totp_cli_command_move_docopt_usage(); totp_cli_command_pin_docopt_usage(); + totp_cli_command_notification_docopt_usage(); cli_nl(); TOTP_CLI_PRINTF("Commands:\r\n"); totp_cli_command_help_docopt_commands(); @@ -36,11 +38,13 @@ void totp_cli_command_help_handle() { totp_cli_command_timezone_docopt_commands(); totp_cli_command_move_docopt_commands(); totp_cli_command_pin_docopt_commands(); + totp_cli_command_notification_docopt_commands(); cli_nl(); TOTP_CLI_PRINTF("Arguments:\r\n"); totp_cli_command_add_docopt_arguments(); totp_cli_command_delete_docopt_arguments(); totp_cli_command_timezone_docopt_arguments(); + totp_cli_command_notification_docopt_arguments(); cli_nl(); TOTP_CLI_PRINTF("Options:\r\n"); totp_cli_command_add_docopt_options(); diff --git a/applications/plugins/totp/cli/commands/list/list.c b/applications/plugins/totp/cli/commands/list/list.c index c9f57e57f..739a0de40 100644 --- a/applications/plugins/totp/cli/commands/list/list.c +++ b/applications/plugins/totp/cli/commands/list/list.c @@ -20,19 +20,6 @@ static char* get_algo_as_cstr(TokenHashAlgo algo) { return "UNKNOWN"; } -static uint8_t get_digits_as_int(TokenDigitsCount digits) { - switch(digits) { - case TOTP_6_DIGITS: - return 6; - case TOTP_8_DIGITS: - return 8; - default: - break; - } - - return 6; -} - void totp_cli_command_list_docopt_commands() { TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_LIST ", " TOTP_CLI_COMMAND_LIST_ALT " List all available tokens\r\n"); @@ -59,13 +46,12 @@ void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) { uint16_t index = 1; TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { TokenInfo* token_info = (TokenInfo*)node->data; - token_info_get_digits_count(token_info); TOTP_CLI_PRINTF( "| %-3" PRIu16 " | %-27.27s | %-6s | %-6" PRIu8 " |\r\n", index, token_info->name, get_algo_as_cstr(token_info->algo), - get_digits_as_int(token_info->digits)); + token_info->digits); index++; }); TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n"); diff --git a/applications/plugins/totp/cli/commands/timezone/timezone.c b/applications/plugins/totp/cli/commands/timezone/timezone.c index 8aed95722..7a17c1ae2 100644 --- a/applications/plugins/totp/cli/commands/timezone/timezone.c +++ b/applications/plugins/totp/cli/commands/timezone/timezone.c @@ -21,8 +21,6 @@ void totp_cli_command_timezone_docopt_usage() { void totp_cli_command_timezone_docopt_arguments() { TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE " Timezone offset in hours to be set.\r\n"); - TOTP_CLI_PRINTF( - " If not provided then current timezone offset will be printed\r\n"); } void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { diff --git a/applications/plugins/totp/lib/roll_value/roll_value.h b/applications/plugins/totp/lib/roll_value/roll_value.h index bb8360c96..3c270be9a 100644 --- a/applications/plugins/totp/lib/roll_value/roll_value.h +++ b/applications/plugins/totp/lib/roll_value/roll_value.h @@ -2,7 +2,9 @@ #include -typedef enum { +typedef uint8_t TotpRollValueOverflowBehavior; + +enum TotpRollValueOverflowBehaviors { /** * @brief Do not change value if it reached constraint */ @@ -12,7 +14,7 @@ typedef enum { * @brief Set value to opposite constraint value if it reached constraint */ RollOverflowBehaviorRoll -} TotpRollValueOverflowBehavior; +}; #define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \ void totp_roll_value_##type( \ diff --git a/applications/plugins/totp/scenes/scene_director.h b/applications/plugins/totp/scenes/scene_director.h deleted file mode 100644 index 541a63f1c..000000000 --- a/applications/plugins/totp/scenes/scene_director.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include "../types/plugin_state.h" -#include "../types/plugin_event.h" -#include "totp_scenes_enum.h" - -/** - * @brief Activates scene - * @param plugin_state application state - * @param scene scene to be activated - * @param context scene context to be passed to the scene activation method - */ -void totp_scene_director_activate_scene( - PluginState* const plugin_state, - Scene scene, - const void* context); - -/** - * @brief Deactivate current scene - * @param plugin_state application state - */ -void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state); - -/** - * @brief Initializes all the available scenes - * @param plugin_state application state - */ -void totp_scene_director_init_scenes(PluginState* const plugin_state); - -/** - * @brief Renders current scene - * @param canvas canvas to render at - * @param plugin_state application state - */ -void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state); - -/** - * @brief Disposes all the available scenes - * @param plugin_state application state - */ -void totp_scene_director_dispose(const PluginState* const plugin_state); - -/** - * @brief Handles application event for the current scene - * @param event event to be handled - * @param plugin_state application state - * @return \c true if event handled and applilcation should continue; \c false if application should be closed - */ -bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state); diff --git a/applications/plugins/totp/scenes/totp_scenes_enum.h b/applications/plugins/totp/scenes/totp_scenes_enum.h deleted file mode 100644 index c90f76bab..000000000 --- a/applications/plugins/totp/scenes/totp_scenes_enum.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -/** - * @brief TOTP application scenes - */ -typedef enum { - /** - * @brief Empty scene which does nothing - */ - TotpSceneNone, - - /** - * @brief Scene where user have to enter PIN to authenticate - */ - TotpSceneAuthentication, - - /** - * @brief Scene where actual TOTP token is getting generated and displayed to the user - */ - TotpSceneGenerateToken, - - /** - * @brief Scene where user can add new token - */ - TotpSceneAddNewToken, - - /** - * @brief Scene with a menu for given token, allowing user to do multiple actions - */ - TotpSceneTokenMenu, - - /** - * @brief Scene where user can change application settings - */ - TotpSceneAppSettings -} Scene; diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index e43f6c35b..ff7e4eb2d 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -10,32 +10,6 @@ #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" -static uint8_t token_info_get_digits_as_int(const TokenInfo* token_info) { - switch(token_info->digits) { - case TOTP_6_DIGITS: - return 6; - case TOTP_8_DIGITS: - return 8; - default: - break; - } - - return 6; -} - -static void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { - switch(digits) { - case 6: - token_info->digits = TOTP_6_DIGITS; - break; - case 8: - token_info->digits = TOTP_8_DIGITS; - break; - default: - break; - } -} - static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { switch(token_info->algo) { case SHA1: @@ -106,6 +80,15 @@ FlipperFormat* totp_open_config_file(Storage* storage) { fff_data_file, "Timezone offset in hours. Important note: do not put '+' sign for positive values"); flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &tmp_tz, 1); + + uint32_t tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; + flipper_format_write_comment_cstr(fff_data_file, " "); + flipper_format_write_comment_cstr( + fff_data_file, + "How to notify user when new token is generated or badusb mode is activated (possible values: 0 - do not notify, 1 - sound, 2 - vibro, 3 sound and vibro)"); + flipper_format_write_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + FuriString* temp_str = furi_string_alloc(); flipper_format_write_comment_cstr(fff_data_file, " "); @@ -172,8 +155,8 @@ void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* tok } flipper_format_write_string_cstr( file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info)); - uint32_t digits_count_as_uint32 = token_info_get_digits_as_int(token_info); - flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &digits_count_as_uint32, 1); + uint32_t tmp_uint32 = token_info->digits; + flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1); } void totp_config_file_save_new_token(const TokenInfo* token_info) { @@ -196,6 +179,32 @@ void totp_config_file_update_timezone_offset(float new_timezone_offset) { totp_close_storage(); } +void totp_config_file_update_notification_method(NotificationMethod new_notification_method) { + Storage* cfg_storage = totp_open_storage(); + FlipperFormat* file = totp_open_config_file(cfg_storage); + + uint32_t tmp_uint32 = new_notification_method; + flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + + totp_close_config_file(file); + totp_close_storage(); +} + +void totp_config_file_update_user_settings(const PluginState* plugin_state) { + Storage* cfg_storage = totp_open_storage(); + FlipperFormat* file = totp_open_config_file(cfg_storage); + + flipper_format_insert_or_update_float( + file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1); + uint32_t tmp_uint32 = plugin_state->notification_method; + flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + + totp_close_config_file(file); + totp_close_storage(); +} + void totp_full_save_config_file(const PluginState* const plugin_state) { Storage* storage = totp_open_storage(); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); @@ -213,6 +222,9 @@ void totp_full_save_config_file(const PluginState* const plugin_state) { flipper_format_write_float( fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1); flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); + uint32_t tmp_uint32 = plugin_state->notification_method; + flipper_format_write_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { const TokenInfo* token_info = node->data; @@ -320,6 +332,16 @@ void totp_config_file_load_base(PluginState* const plugin_state) { plugin_state->pin_set = true; } + flipper_format_rewind(fff_data_file); + + uint32_t tmp_uint32; + if(!flipper_format_read_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; + } + + plugin_state->notification_method = tmp_uint32; + furi_string_free(temp_str); totp_close_config_file(fff_data_file); totp_close_storage(); @@ -408,10 +430,9 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) tokenInfo->algo = SHA1; } - if(flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1)) { - token_info_set_digits_from_int(tokenInfo, temp_data32); - } else { + if(!flipper_format_read_uint32( + fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1) || + !token_info_set_digits_from_int(tokenInfo, temp_data32)) { tokenInfo->digits = TOTP_6_DIGITS; } diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index cf433f9e5..1eabe3365 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -6,10 +6,12 @@ #include "../../types/token_info.h" #include "constants.h" +typedef uint8_t TokenLoadingResult; + /** * @brief Token loading results */ -typedef enum { +enum TokenLoadingResults { /** * @brief All the tokens loaded successfully */ @@ -24,7 +26,7 @@ typedef enum { * @brief Tokens not loaded because of error(s) */ TokenLoadingResultError -} TokenLoadingResult; +}; /** * @brief Opens storage record @@ -80,3 +82,15 @@ void totp_config_file_save_new_token(const TokenInfo* token_info); * @param new_timezone_offset new timezone offset to be set */ void totp_config_file_update_timezone_offset(float new_timezone_offset); + +/** + * @brief Updates notification method in an application config file + * @param new_notification_method new notification method to be set + */ +void totp_config_file_update_notification_method(NotificationMethod new_notification_method); + +/** + * @brief Updates application user settings + * @param plugin_state application state + */ +void totp_config_file_update_user_settings(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/services/config/constants.h b/applications/plugins/totp/services/config/constants.h index b094f653f..696ea1593 100644 --- a/applications/plugins/totp/services/config/constants.h +++ b/applications/plugins/totp/services/config/constants.h @@ -11,6 +11,7 @@ #define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto" #define TOTP_CONFIG_KEY_BASE_IV "BaseIV" #define TOTP_CONFIG_KEY_PINSET "PinIsSet" +#define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod" #define TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME "sha1" #define TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME "sha256" diff --git a/applications/plugins/totp/services/crypto/memset_s.h b/applications/plugins/totp/services/crypto/memset_s.h deleted file mode 100644 index 54628860d..000000000 --- a/applications/plugins/totp/services/crypto/memset_s.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -#ifndef _RSIZE_T_DECLARED -typedef uint64_t rsize_t; -#define _RSIZE_T_DECLARED -#endif -#ifndef _ERRNOT_DECLARED -typedef int16_t errno_t; //-V677 -#define _ERRNOT_DECLARED -#endif - -/** - * @brief Copies the value \p c into each of the first \p n characters of the object pointed to by \p s. - * @param s pointer to the object to fill - * @param smax size of the destination object - * @param c fill byte - * @param n number of bytes to fill - * @return \c 0 on success; non-zero otherwise - */ -errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n); \ No newline at end of file diff --git a/applications/plugins/totp/services/list/list.h b/applications/plugins/totp/services/list/list.h deleted file mode 100644 index 715c74901..000000000 --- a/applications/plugins/totp/services/list/list.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include -#include - -/** - * @brief Single linked list node - */ -typedef struct ListNode { - /** - * @brief Pointer to the data assigned to the current list node - */ - void* data; - - /** - * @brief Pointer to the next list node - */ - struct ListNode* next; -} ListNode; - -/** - * @brief Initializes a new list node head - * @param data data to be assigned to the head list node - * @return Head list node - */ -ListNode* list_init_head(void* data); - -/** - * @brief Adds new list node to the end of the list - * @param head head list node - * @param data data to be assigned to the newly added list node - * @return Head list node - */ -ListNode* list_add( - ListNode* head, - void* data); /* adds element with specified data to the end of the list and returns new head node. */ - -/** - * @brief Searches list node with the given assigned \p data in the list - * @param head head list node - * @param data data to be searched - * @return List node containing \p data if there is such a node in the list; \c NULL otherwise - */ -ListNode* list_find(ListNode* head, const void* data); - -/** - * @brief Searches list node with the given \p index in the list - * @param head head list node - * @param index desired list node index - * @return List node with the given \p index in the list if there is such a list node; \c NULL otherwise - */ -ListNode* list_element_at(ListNode* head, uint16_t index); - -/** - * @brief Removes list node from the list - * @param head head list node - * @param ep list node to be removed - * @return Head list node - */ -ListNode* list_remove(ListNode* head, ListNode* ep); - -/** - * @brief Removes list node with the given \p index in the list from the list - * @param head head list node - * @param index index of the node to be removed - * @param[out] removed_node_data data which was assigned to the removed list node - * @return Head list node - */ -ListNode* list_remove_at(ListNode* head, uint16_t index, void** removed_node_data); - -/** - * @brief Inserts new list node at the given index - * @param head head list node - * @param index index in the list where the new list node should be inserted - * @param data data to be assgned to the new list node - * @return Head list node - */ -ListNode* list_insert_at(ListNode* head, uint16_t index, void* data); - -/** - * @brief Disposes all the list nodes in the list - * @param head head list node - */ -void list_free(ListNode* head); - -#define TOTP_LIST_INIT_OR_ADD(head, item, assert) \ - do { \ - if(head == NULL) { \ - head = list_init_head(item); \ - assert(head != NULL); \ - } else { \ - assert(list_add(head, item) != NULL); \ - } \ - } while(false) diff --git a/applications/plugins/totp/services/roll_value/roll_value.h b/applications/plugins/totp/services/roll_value/roll_value.h deleted file mode 100644 index bb8360c96..000000000 --- a/applications/plugins/totp/services/roll_value/roll_value.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include - -typedef enum { - /** - * @brief Do not change value if it reached constraint - */ - RollOverflowBehaviorStop, - - /** - * @brief Set value to opposite constraint value if it reached constraint - */ - RollOverflowBehaviorRoll -} TotpRollValueOverflowBehavior; - -#define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \ - void totp_roll_value_##type( \ - type* value, \ - step_type step, \ - type min, \ - type max, \ - TotpRollValueOverflowBehavior overflow_behavior) - -/** - * @brief Rolls \c int8_t \p value using \p min and \p max as an value constraints with \p step step. - * When value reaches constraint value \p overflow_behavior defines what to do next. - * @param[in,out] value value to roll - * @param step step to be used to change value - * @param min minimal possible value - * @param max maximum possible value - * @param overflow_behavior defines what to do when value reaches constraint value - */ -TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t); - -/** - * @brief Rolls \c uint8_t \p value using \p min and \p max as an value constraints with \p step step. - * When value reaches constraint value \p overflow_behavior defines what to do next. - * @param[in,out] value value to roll - * @param step step to be used to change value - * @param min minimal possible value - * @param max maximum possible value - * @param overflow_behavior defines what to do when value reaches constraint value - */ -TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t); - -/** - * @brief Rolls \c uint16_t \p value using \p min and \p max as an value constraints with \p step step. - * When value reaches constraint value \p overflow_behavior defines what to do next. - * @param[in,out] value value to roll - * @param step step to be used to change value - * @param min minimal possible value - * @param max maximum possible value - * @param overflow_behavior defines what to do when value reaches constraint value - */ -TOTP_ROLL_VALUE_FN_HEADER(uint16_t, int16_t); \ No newline at end of file diff --git a/applications/plugins/totp/services/timezone_utils/timezone_utils.h b/applications/plugins/totp/services/timezone_utils/timezone_utils.h deleted file mode 100644 index 5bb3b8ead..000000000 --- a/applications/plugins/totp/services/timezone_utils/timezone_utils.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -/** - * @brief Calculates timezone offset in seconds given timezone offset in hours. - * @param hours timezone offset in hours - * @return Timezone offset in seconds. - */ -int32_t timezone_offset_from_hours(float hours); - -/** - * @brief Applies timezone offset to a given time. - * @param time time to apply offset to. - * @param offset timezone offset in seconds. - * @return Time with timezone offset applied. - */ -uint64_t timezone_offset_apply(uint64_t time, int32_t offset); diff --git a/applications/plugins/totp/services/ui/ui_controls.h b/applications/plugins/totp/services/ui/ui_controls.h deleted file mode 100644 index b97006a03..000000000 --- a/applications/plugins/totp/services/ui/ui_controls.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include - -/** - * @brief Renders TextBox control - * @param canvas canvas to render control at - * @param y vertical position of a control to be rendered at - * @param text text to be rendered inside control - * @param is_selected whether control should be rendered as focused or not - */ -void ui_control_text_box_render( - Canvas* const canvas, - int16_t y, - const char* text, - bool is_selected); - -/** - * @brief Renders Button control - * @param canvas canvas to render control at - * @param x horizontal position of a control to be rendered at - * @param y vertical position of a control to be rendered at - * @param width control width - * @param height control height - * @param text text to be rendered inside control - * @param is_selected whether control should be rendered as focused or not - */ -void ui_control_button_render( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t width, - uint8_t height, - const char* text, - bool is_selected); - -/** - * @brief Renders Select control - * @param canvas canvas to render control at - * @param x horizontal position of a control to be rendered at - * @param y vertical position of a control to be rendered at - * @param width control width - * @param text text to be rendered inside control - * @param is_selected whether control should be rendered as focused or not - */ -void ui_control_select_render( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t width, - const char* text, - bool is_selected); diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index b3b1af504..5a551c4f1 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -22,7 +22,7 @@ static void render_callback(Canvas* const canvas, void* ctx) { PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); - if(plugin_state != NULL && !plugin_state->changing_scene) { + if(plugin_state != NULL) { totp_scene_director_render(canvas, plugin_state); } @@ -38,8 +38,8 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu static bool totp_plugin_state_init(PluginState* const plugin_state) { plugin_state->gui = furi_record_open(RECORD_GUI); - plugin_state->notification = furi_record_open(RECORD_NOTIFICATION); - plugin_state->dialogs = furi_record_open(RECORD_DIALOGS); + plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); + plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); totp_config_file_load_base(plugin_state); @@ -57,7 +57,8 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); - DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs, message); + DialogMessageButton dialog_result = + dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); if(dialog_result == DialogMessageButtonRight) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); @@ -84,7 +85,7 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); - dialog_message_show(plugin_state->dialogs, message); + dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); return false; } @@ -150,7 +151,6 @@ int32_t totp_app() { bool processing = true; uint32_t last_user_interaction_time = furi_get_tick(); while(processing) { - if(plugin_state->changing_scene) continue; FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); PluginState* plugin_state_m = acquire_mutex_block(&state_mutex); diff --git a/applications/plugins/totp/types/event_type.h b/applications/plugins/totp/types/event_type.h index ed890caf1..4fe916872 100644 --- a/applications/plugins/totp/types/event_type.h +++ b/applications/plugins/totp/types/event_type.h @@ -1,7 +1,9 @@ #pragma once #include -typedef enum { +typedef uint8_t EventType; + +enum EventTypes { EventTypeTick, EventTypeKey, -} EventType; +}; diff --git a/applications/plugins/totp/types/plugin_state.h b/applications/plugins/totp/types/plugin_state.h index 3d554adc6..0aad2e125 100644 --- a/applications/plugins/totp/types/plugin_state.h +++ b/applications/plugins/totp/types/plugin_state.h @@ -5,6 +5,7 @@ #include #include "../lib/list/list.h" #include "../ui/totp_scenes_enum.h" +#include "notification_method.h" #define TOTP_IV_SIZE 16 @@ -22,20 +23,15 @@ typedef struct { */ void* current_scene_state; - /** - * @brief Whether scene is changing now - */ - bool changing_scene; - /** * @brief Reference to the firmware notification subsystem */ - NotificationApp* notification; + NotificationApp* notification_app; /** * @brief Reference to the firmware dialogs subsystem */ - DialogsApp* dialogs; + DialogsApp* dialogs_app; /** * @brief Reference to the firmware GUI subsystem @@ -86,4 +82,9 @@ typedef struct { * @brief Basic randomly-generated initialization vector (IV) */ uint8_t base_iv[TOTP_IV_SIZE]; + + /** + * @brief Notification method + */ + NotificationMethod notification_method; } PluginState; diff --git a/applications/plugins/totp/types/token_info.c b/applications/plugins/totp/types/token_info.c index 26329c776..c032c6d3f 100644 --- a/applications/plugins/totp/types/token_info.c +++ b/applications/plugins/totp/types/token_info.c @@ -45,15 +45,17 @@ bool token_info_set_secret( return result; } -uint8_t token_info_get_digits_count(const TokenInfo* token_info) { - switch(token_info->digits) { - case TOTP_6_DIGITS: - return 6; - case TOTP_8_DIGITS: - return 8; +bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { + switch(digits) { + case 6: + token_info->digits = TOTP_6_DIGITS; + return true; + case 8: + token_info->digits = TOTP_8_DIGITS; + return true; default: break; } - return 6; + return false; } diff --git a/applications/plugins/totp/types/token_info.h b/applications/plugins/totp/types/token_info.h index cbcf0ddef..04caa68a8 100644 --- a/applications/plugins/totp/types/token_info.h +++ b/applications/plugins/totp/types/token_info.h @@ -2,10 +2,13 @@ #include +typedef uint8_t TokenHashAlgo; +typedef uint8_t TokenDigitsCount; + /** * @brief Hashing algorithm to be used to generate token */ -typedef enum { +enum TokenHashAlgos { /** * @brief SHA1 hashing algorithm */ @@ -20,22 +23,22 @@ typedef enum { * @brief SHA512 hashing algorithm */ SHA512 -} TokenHashAlgo; +}; /** * @brief Token digits count to be generated. */ -typedef enum { +enum TokenDigitsCounts { /** * @brief 6 digits */ - TOTP_6_DIGITS, + TOTP_6_DIGITS = 6, /** * @brief 8 digits */ - TOTP_8_DIGITS -} TokenDigitsCount; + TOTP_8_DIGITS = 8 +}; #define TOTP_TOKEN_DIGITS_MAX_COUNT 8 @@ -96,8 +99,9 @@ bool token_info_set_secret( const uint8_t* iv); /** - * @brief Gets token digits count as \c uint8_t type - * @param token_info instance which's desired digits count should be returned - * @return Token digits length as \c uint8_t type + * @brief Sets token digits count from \c uint8_t value + * @param token_info instance whichs token digits count length should be updated + * @param digits desired token digits count length + * @return \c true if token digits count length has been updated; \c false p */ -uint8_t token_info_get_digits_count(const TokenInfo* token_info); +bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits); diff --git a/applications/plugins/totp/types/user_pin_codes.h b/applications/plugins/totp/types/user_pin_codes.h index 7cf5756ca..b5d72d398 100644 --- a/applications/plugins/totp/types/user_pin_codes.h +++ b/applications/plugins/totp/types/user_pin_codes.h @@ -1,8 +1,10 @@ #pragma once -typedef enum uint8_t { +typedef uint8_t TotpUserPinCode; + +enum TotpUserPinCodes { PinCodeArrowUp = 2, PinCodeArrowRight = 8, PinCodeArrowDown = 11, PinCodeArrowLeft = 5 -} TotpUserPinCode; \ No newline at end of file +}; \ No newline at end of file diff --git a/applications/plugins/totp/ui/scene_director.c b/applications/plugins/totp/ui/scene_director.c index e02e7790c..fcc9f37d8 100644 --- a/applications/plugins/totp/ui/scene_director.c +++ b/applications/plugins/totp/ui/scene_director.c @@ -10,7 +10,6 @@ void totp_scene_director_activate_scene( PluginState* const plugin_state, Scene scene, const void* context) { - plugin_state->changing_scene = true; totp_scene_director_deactivate_active_scene(plugin_state); switch(scene) { case TotpSceneGenerateToken: @@ -35,7 +34,6 @@ void totp_scene_director_activate_scene( } plugin_state->current_scene = scene; - plugin_state->changing_scene = false; } void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state) { diff --git a/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index e6693b8b8..e6351010e 100644 --- a/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -11,10 +11,9 @@ #include "../../../types/nullable.h" #include "../generate_token/totp_scene_generate_token.h" -#define TOKEN_ALGO_LIST_LENGTH 3 char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512"}; -#define TOKEN_DIGITS_LIST_LENGTH 2 -char* TOKEN_DIGITS_LIST[] = {"6 digits", "8 digits"}; +char* TOKEN_DIGITS_TEXT_LIST[] = {"6 digits", "8 digits"}; +TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = {TOTP_6_DIGITS, TOTP_8_DIGITS}; typedef enum { TokenNameTextBox, @@ -38,7 +37,7 @@ typedef struct { TotpNullable_uint16_t current_token_index; int16_t screen_y_offset; TokenHashAlgo algo; - TokenDigitsCount digits_count; + uint8_t digits_count_index; } SceneState; void totp_scene_add_new_token_init(const PluginState* plugin_state) { @@ -126,7 +125,7 @@ void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_s 0, 63 - scene_state->screen_y_offset, SCREEN_WIDTH, - TOKEN_DIGITS_LIST[scene_state->digits_count], + TOKEN_DIGITS_TEXT_LIST[scene_state->digits_count_index], scene_state->selected_control == TokenLengthSelect); ui_control_button_render( canvas, @@ -196,11 +195,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState totp_roll_value_uint8_t(&scene_state->algo, 1, SHA1, SHA512, RollOverflowBehaviorRoll); } else if(scene_state->selected_control == TokenLengthSelect) { totp_roll_value_uint8_t( - &scene_state->digits_count, - 1, - TOTP_6_DIGITS, - TOTP_8_DIGITS, - RollOverflowBehaviorRoll); + &scene_state->digits_count_index, 1, 0, 1, RollOverflowBehaviorRoll); } break; case InputKeyLeft: @@ -209,11 +204,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState &scene_state->algo, -1, SHA1, SHA512, RollOverflowBehaviorRoll); } else if(scene_state->selected_control == TokenLengthSelect) { totp_roll_value_uint8_t( - &scene_state->digits_count, - -1, - TOTP_6_DIGITS, - TOTP_8_DIGITS, - RollOverflowBehaviorRoll); + &scene_state->digits_count_index, -1, 0, 1, RollOverflowBehaviorRoll); } break; case InputKeyOk: @@ -252,7 +243,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState strlcpy( tokenInfo->name, scene_state->token_name, scene_state->token_name_length + 1); tokenInfo->algo = scene_state->algo; - tokenInfo->digits = scene_state->digits_count; + tokenInfo->digits = TOKEN_DIGITS_VALUE_LIST[scene_state->digits_count_index]; TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check); plugin_state->tokens_count++; @@ -274,7 +265,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); - dialog_message_show(plugin_state->dialogs, message); + dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); scene_state->selected_control = TokenSecretTextBox; update_screen_y_offset(scene_state); diff --git a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c index f87ada3dd..5f68c6772 100644 --- a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c @@ -1,20 +1,25 @@ #include "totp_app_settings.h" #include +#include #include "../../ui_controls.h" #include "../../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" #include "../../constants.h" #include "../../../services/config/config.h" +#include "../../../services/convert/convert.h" #include "../../../lib/roll_value/roll_value.h" #include "../../../types/nullable.h" -#define DIGIT_TO_CHAR(digit) ((digit) + '0') +char* YES_NO_LIST[] = {"NO", "YES"}; -typedef enum { HoursInput, MinutesInput, ConfirmButton } Control; +typedef enum { HoursInput, MinutesInput, Sound, Vibro, ConfirmButton } Control; typedef struct { int8_t tz_offset_hours; uint8_t tz_offset_minutes; + bool notification_sound; + bool notification_vibro; + uint8_t y_offset; TotpNullable_uint16_t current_token_index; Control selected_control; } SceneState; @@ -39,55 +44,87 @@ void totp_scene_app_settings_activate( float off_dec = modff(plugin_state->timezone_offset, &off_int); scene_state->tz_offset_hours = off_int; scene_state->tz_offset_minutes = 60.0f * off_dec; + scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound; + scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro; } static void two_digit_to_str(int8_t num, char* str) { uint8_t index = 0; if(num < 0) { - str[0] = '-'; - index++; + str[index++] = '-'; num = -num; } uint8_t d1 = (num / 10) % 10; uint8_t d2 = num % 10; - str[index] = DIGIT_TO_CHAR(d1); - str[index + 1] = DIGIT_TO_CHAR(d2); - str[index + 2] = '\0'; + str[index++] = CONVERT_DIGIT_TO_CHAR(d1); + str[index++] = CONVERT_DIGIT_TO_CHAR(d2); + str[index++] = '\0'; } -void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state) { - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; +void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state) { + const SceneState* scene_state = plugin_state->current_scene_state; canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Timezone offset"); + canvas_draw_str_aligned( + canvas, 0, 0 - scene_state->y_offset, AlignLeft, AlignTop, "Timezone offset"); canvas_set_font(canvas, FontSecondary); char tmp_str[4]; two_digit_to_str(scene_state->tz_offset_hours, &tmp_str[0]); - canvas_draw_str_aligned(canvas, 0, 16, AlignLeft, AlignTop, "Hours:"); + canvas_draw_str_aligned(canvas, 0, 16 - scene_state->y_offset, AlignLeft, AlignTop, "Hours:"); ui_control_select_render( canvas, 36, - 10, + 10 - scene_state->y_offset, SCREEN_WIDTH - 36, &tmp_str[0], scene_state->selected_control == HoursInput); two_digit_to_str(scene_state->tz_offset_minutes, &tmp_str[0]); - canvas_draw_str_aligned(canvas, 0, 34, AlignLeft, AlignTop, "Minutes:"); + canvas_draw_str_aligned( + canvas, 0, 34 - scene_state->y_offset, AlignLeft, AlignTop, "Minutes:"); ui_control_select_render( canvas, 36, - 28, + 28 - scene_state->y_offset, SCREEN_WIDTH - 36, &tmp_str[0], scene_state->selected_control == MinutesInput); + canvas_draw_icon( + canvas, + SCREEN_WIDTH_CENTER - 5, + SCREEN_HEIGHT - 5 - scene_state->y_offset, + &I_totp_arrow_bottom_10x5); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned( + canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications"); + canvas_set_font(canvas, FontSecondary); + + canvas_draw_str_aligned(canvas, 0, 80 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); + ui_control_select_render( + canvas, + 36, + 74 - scene_state->y_offset, + SCREEN_WIDTH - 36, + YES_NO_LIST[scene_state->notification_sound], + scene_state->selected_control == Sound); + + canvas_draw_str_aligned(canvas, 0, 98 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); + ui_control_select_render( + canvas, + 36, + 92 - scene_state->y_offset, + SCREEN_WIDTH - 36, + YES_NO_LIST[scene_state->notification_vibro], + scene_state->selected_control == Vibro); + ui_control_button_render( canvas, SCREEN_WIDTH_CENTER - 24, - 50, + 115 - scene_state->y_offset, 48, 13, "Confirm", @@ -114,10 +151,20 @@ bool totp_scene_app_settings_handle_event( HoursInput, ConfirmButton, RollOverflowBehaviorStop); + if(scene_state->selected_control > MinutesInput) { + scene_state->y_offset = 64; + } else { + scene_state->y_offset = 0; + } break; case InputKeyDown: totp_roll_value_uint8_t( &scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop); + if(scene_state->selected_control > MinutesInput) { + scene_state->y_offset = 64; + } else { + scene_state->y_offset = 0; + } break; case InputKeyRight: if(scene_state->selected_control == HoursInput) { @@ -126,6 +173,10 @@ bool totp_scene_app_settings_handle_event( } else if(scene_state->selected_control == MinutesInput) { totp_roll_value_uint8_t( &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == Sound) { + scene_state->notification_sound = !scene_state->notification_sound; + } else if(scene_state->selected_control == Vibro) { + scene_state->notification_vibro = !scene_state->notification_vibro; } break; case InputKeyLeft: @@ -135,13 +186,23 @@ bool totp_scene_app_settings_handle_event( } else if(scene_state->selected_control == MinutesInput) { totp_roll_value_uint8_t( &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == Sound) { + scene_state->notification_sound = !scene_state->notification_sound; + } else if(scene_state->selected_control == Vibro) { + scene_state->notification_vibro = !scene_state->notification_vibro; } break; case InputKeyOk: if(scene_state->selected_control == ConfirmButton) { plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + (float)scene_state->tz_offset_minutes / 60.0f; - totp_config_file_update_timezone_offset(plugin_state->timezone_offset); + + plugin_state->notification_method = + (scene_state->notification_sound ? NotificationMethodSound : + NotificationMethodNone) | + (scene_state->notification_vibro ? NotificationMethodVibro : + NotificationMethodNone); + totp_config_file_update_user_settings(plugin_state); if(!scene_state->current_token_index.is_null) { TokenMenuSceneContext generate_scene_context = { diff --git a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.h b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.h index 4f24861d5..1721186ed 100644 --- a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.h +++ b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.h @@ -12,7 +12,7 @@ void totp_scene_app_settings_init(const PluginState* plugin_state); void totp_scene_app_settings_activate( PluginState* plugin_state, const AppSettingsSceneContext* context); -void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state); +void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state); bool totp_scene_app_settings_handle_event( const PluginEvent* const event, PluginState* plugin_state); diff --git a/applications/plugins/totp/ui/scenes/authenticate/totp_scene_authenticate.c b/applications/plugins/totp/ui/scenes/authenticate/totp_scene_authenticate.c index e642f2912..c595b5bd0 100644 --- a/applications/plugins/totp/ui/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/plugins/totp/ui/scenes/authenticate/totp_scene_authenticate.c @@ -139,7 +139,7 @@ bool totp_scene_authenticate_handle_event( AlignCenter, AlignCenter); dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); - dialog_message_show(plugin_state->dialogs, message); + dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); } break; diff --git a/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c index ba7d7400b..c90cc6b23 100644 --- a/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -9,6 +9,7 @@ #include "../../../services/totp/totp.h" #include "../../../services/config/config.h" #include "../../../services/crypto/crypto.h" +#include "../../../services/convert/convert.h" #include "../../../lib/polyfills/memset_s.h" #include "../../../lib/roll_value/roll_value.h" #include "../../scene_director.h" @@ -16,7 +17,6 @@ #include "../../../workers/type_code/type_code.h" #define TOKEN_LIFETIME 30 -#define DIGIT_TO_CHAR(digit) ((digit) + '0') typedef struct { uint16_t current_token_index; @@ -25,59 +25,107 @@ typedef struct { bool need_token_update; uint32_t last_token_gen_time; TotpTypeCodeWorkerContext* type_code_worker_context; + NotificationMessage const** notification_sequence_new_token; + NotificationMessage const** notification_sequence_badusb; } SceneState; -static const NotificationSequence notification_sequence_new_token = { - &message_display_backlight_on, - &message_green_255, - &message_vibro_on, - &message_note_c5, - &message_delay_50, - &message_vibro_off, - &message_sound_off, - NULL, -}; - -static const NotificationSequence notification_sequence_badusb = { - &message_vibro_on, - &message_note_d5, - &message_delay_50, - &message_note_e4, - &message_delay_50, - &message_note_f3, - &message_delay_50, - &message_vibro_off, - &message_sound_off, - NULL, -}; - -static void i_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) { - uint8_t str_token_length = 0; - if(len == TOTP_8_DIGITS) { - str[8] = '\0'; - str_token_length = 8; - } else if(len == TOTP_6_DIGITS) { - str[6] = '\0'; - str_token_length = 6; - } - - if(i_token_code == OTP_ERROR) { - memset(&str[0], '-', str_token_length); - } else { - if(len == TOTP_8_DIGITS) { - str[7] = DIGIT_TO_CHAR(i_token_code % 10); - str[6] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); - str[5] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); - } else if(len == TOTP_6_DIGITS) { - str[5] = DIGIT_TO_CHAR(i_token_code % 10); +static const NotificationSequence* + get_notification_sequence_new_token(const PluginState* plugin_state, SceneState* scene_state) { + if(scene_state->notification_sequence_new_token == NULL) { + uint8_t i = 0; + uint8_t length = 4; + if(plugin_state->notification_method & NotificationMethodVibro) { + length += 2; } - str[4] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); - str[3] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); - str[2] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); - str[1] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); - str[0] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10); + if(plugin_state->notification_method & NotificationMethodSound) { + length += 2; + } + + scene_state->notification_sequence_new_token = malloc(sizeof(void*) * length); + furi_check(scene_state->notification_sequence_new_token != NULL); + scene_state->notification_sequence_new_token[i++] = &message_display_backlight_on; + scene_state->notification_sequence_new_token[i++] = &message_green_255; + if(plugin_state->notification_method & NotificationMethodVibro) { + scene_state->notification_sequence_new_token[i++] = &message_vibro_on; + } + + if(plugin_state->notification_method & NotificationMethodSound) { + scene_state->notification_sequence_new_token[i++] = &message_note_c5; + } + + scene_state->notification_sequence_new_token[i++] = &message_delay_50; + + if(plugin_state->notification_method & NotificationMethodVibro) { + scene_state->notification_sequence_new_token[i++] = &message_vibro_off; + } + + if(plugin_state->notification_method & NotificationMethodSound) { + scene_state->notification_sequence_new_token[i++] = &message_sound_off; + } + + scene_state->notification_sequence_new_token[i++] = NULL; } + + return (NotificationSequence*)scene_state->notification_sequence_new_token; +} + +static const NotificationSequence* + get_notification_sequence_badusb(const PluginState* plugin_state, SceneState* scene_state) { + if(scene_state->notification_sequence_badusb == NULL) { + uint8_t i = 0; + uint8_t length = 3; + if(plugin_state->notification_method & NotificationMethodVibro) { + length += 2; + } + + if(plugin_state->notification_method & NotificationMethodSound) { + length += 6; + } + + scene_state->notification_sequence_badusb = malloc(sizeof(void*) * length); + furi_check(scene_state->notification_sequence_badusb != NULL); + + scene_state->notification_sequence_badusb[i++] = &message_blue_255; + if(plugin_state->notification_method & NotificationMethodVibro) { + scene_state->notification_sequence_badusb[i++] = &message_vibro_on; + } + + if(plugin_state->notification_method & NotificationMethodSound) { + scene_state->notification_sequence_badusb[i++] = &message_note_d5; //-V525 + scene_state->notification_sequence_badusb[i++] = &message_delay_50; + scene_state->notification_sequence_badusb[i++] = &message_note_e4; + scene_state->notification_sequence_badusb[i++] = &message_delay_50; + scene_state->notification_sequence_badusb[i++] = &message_note_f3; + } + + scene_state->notification_sequence_badusb[i++] = &message_delay_50; + + if(plugin_state->notification_method & NotificationMethodVibro) { + scene_state->notification_sequence_badusb[i++] = &message_vibro_off; + } + + if(plugin_state->notification_method & NotificationMethodSound) { + scene_state->notification_sequence_badusb[i++] = &message_sound_off; + } + + scene_state->notification_sequence_badusb[i++] = NULL; + } + + return (NotificationSequence*)scene_state->notification_sequence_badusb; +} + +static void int_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) { + if(i_token_code == OTP_ERROR) { + memset(&str[0], '-', len); + } else { + for(int i = len - 1; i >= 0; i--) { + str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); + i_token_code = i_token_code / 10; + } + } + + str[len] = '\0'; } TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { @@ -137,7 +185,7 @@ void totp_scene_generate_token_activate( AlignCenter); } - dialog_message_show(plugin_state->dialogs, message); + dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); } } @@ -202,10 +250,10 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ uint8_t* key = totp_crypto_decrypt( tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length); - i_token_to_str( + int_token_to_str( totp_at( get_totp_algo_impl(tokenInfo->algo), - token_info_get_digits_count(tokenInfo), + tokenInfo->digits, key, key_length, curr_ts, @@ -218,13 +266,15 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ } else { furi_mutex_acquire( scene_state->type_code_worker_context->string_sync, FuriWaitForever); - i_token_to_str(0, scene_state->last_code, tokenInfo->digits); + int_token_to_str(0, scene_state->last_code, tokenInfo->digits); } furi_mutex_release(scene_state->type_code_worker_context->string_sync); if(is_new_token_time) { - notification_message(plugin_state->notification, ¬ification_sequence_new_token); + notification_message( + plugin_state->notification_app, + get_notification_sequence_new_token(plugin_state, scene_state)); } } @@ -291,8 +341,10 @@ bool totp_scene_generate_token_handle_event( if(event->input.type == InputTypeLong && event->input.key == InputKeyDown) { scene_state = (SceneState*)plugin_state->current_scene_state; totp_type_code_worker_notify( - scene_state->type_code_worker_context, TotpTypeCodeWorkerEvtType); - notification_message(plugin_state->notification, ¬ification_sequence_badusb); + scene_state->type_code_worker_context, TotpTypeCodeWorkerEventType); + notification_message( + plugin_state->notification_app, + get_notification_sequence_badusb(plugin_state, scene_state)); return true; } @@ -347,6 +399,14 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { totp_type_code_worker_stop(scene_state->type_code_worker_context); + if(scene_state->notification_sequence_new_token != NULL) { + free(scene_state->notification_sequence_new_token); + } + + if(scene_state->notification_sequence_badusb != NULL) { + free(scene_state->notification_sequence_badusb); + } + free(scene_state); plugin_state->current_scene_state = NULL; } diff --git a/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c index 0cf57e54a..dc713f0a8 100644 --- a/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c @@ -143,7 +143,7 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt AlignCenter, AlignCenter); DialogMessageButton dialog_result = - dialog_message_show(plugin_state->dialogs, message); + dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); if(dialog_result == DialogMessageButtonRight && !scene_state->current_token_index.is_null) { diff --git a/applications/plugins/totp/ui/totp_scenes_enum.h b/applications/plugins/totp/ui/totp_scenes_enum.h index c90f76bab..0c73af772 100644 --- a/applications/plugins/totp/ui/totp_scenes_enum.h +++ b/applications/plugins/totp/ui/totp_scenes_enum.h @@ -1,9 +1,11 @@ #pragma once +typedef uint8_t Scene; + /** * @brief TOTP application scenes */ -typedef enum { +enum Scenes { /** * @brief Empty scene which does nothing */ @@ -33,4 +35,4 @@ typedef enum { * @brief Scene where user can change application settings */ TotpSceneAppSettings -} Scene; +}; diff --git a/applications/plugins/totp/workers/type_code/type_code.c b/applications/plugins/totp/workers/type_code/type_code.c index ac4f7e9b9..3eb59047a 100644 --- a/applications/plugins/totp/workers/type_code/type_code.c +++ b/applications/plugins/totp/workers/type_code/type_code.c @@ -1,4 +1,5 @@ #include "type_code.h" +#include "../../services/convert/convert.h" static const uint8_t hid_number_keys[10] = { HID_KEYBOARD_0, @@ -20,7 +21,7 @@ static void totp_type_code_worker_restore_usb_mode(TotpTypeCodeWorkerContext* co } static inline bool totp_type_code_worker_stop_requested() { - return furi_thread_flags_get() & TotpTypeCodeWorkerEvtStop; + return furi_thread_flags_get() & TotpTypeCodeWorkerEventStop; } static void totp_type_code_worker_type_code(TotpTypeCodeWorkerContext* context) { @@ -38,7 +39,7 @@ static void totp_type_code_worker_type_code(TotpTypeCodeWorkerContext* context) furi_delay_ms(500); i = 0; while(i < context->string_length && context->string[i] != 0) { - uint8_t digit = context->string[i] - '0'; + uint8_t digit = CONVERT_CHAR_TO_DIGIT(context->string[i]); if(digit > 9) break; uint8_t hid_kb_key = hid_number_keys[digit]; furi_hal_hid_kb_press(hid_kb_key); @@ -63,14 +64,14 @@ static int32_t totp_type_code_worker_callback(void* context) { while(true) { uint32_t flags = furi_thread_flags_wait( - TotpTypeCodeWorkerEvtStop | TotpTypeCodeWorkerEvtType, + TotpTypeCodeWorkerEventStop | TotpTypeCodeWorkerEventType, FuriFlagWaitAny, FuriWaitForever); furi_check((flags & FuriFlagError) == 0); //-V562 - if(flags & TotpTypeCodeWorkerEvtStop) break; + if(flags & TotpTypeCodeWorkerEventStop) break; TotpTypeCodeWorkerContext* h_context = acquire_mutex_block(&context_mutex); - if(flags & TotpTypeCodeWorkerEvtType) { + if(flags & TotpTypeCodeWorkerEventType) { totp_type_code_worker_type_code(h_context); } @@ -98,7 +99,7 @@ TotpTypeCodeWorkerContext* totp_type_code_worker_start() { void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context) { furi_assert(context != NULL); - furi_thread_flags_set(furi_thread_get_id(context->thread), TotpTypeCodeWorkerEvtStop); + furi_thread_flags_set(furi_thread_get_id(context->thread), TotpTypeCodeWorkerEventStop); furi_thread_join(context->thread); furi_thread_free(context->thread); furi_mutex_free(context->string_sync); @@ -108,7 +109,7 @@ void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context) { void totp_type_code_worker_notify( TotpTypeCodeWorkerContext* context, - TotpTypeCodeWorkerEvtFlags event) { + TotpTypeCodeWorkerEvent event) { furi_assert(context != NULL); furi_thread_flags_set(furi_thread_get_id(context->thread), event); } \ No newline at end of file diff --git a/applications/plugins/totp/workers/type_code/type_code.h b/applications/plugins/totp/workers/type_code/type_code.h index 96be43f2f..27f2e02d4 100644 --- a/applications/plugins/totp/workers/type_code/type_code.h +++ b/applications/plugins/totp/workers/type_code/type_code.h @@ -4,6 +4,8 @@ #include #include +typedef uint8_t TotpTypeCodeWorkerEvent; + typedef struct { char* string; uint8_t string_length; @@ -12,14 +14,14 @@ typedef struct { FuriHalUsbInterface* usb_mode_prev; } TotpTypeCodeWorkerContext; -typedef enum { - TotpTypeCodeWorkerEvtReserved = (1 << 0), - TotpTypeCodeWorkerEvtStop = (1 << 1), - TotpTypeCodeWorkerEvtType = (1 << 2) -} TotpTypeCodeWorkerEvtFlags; +enum TotpTypeCodeWorkerEvents { + TotpTypeCodeWorkerEventReserved = (1 << 0), + TotpTypeCodeWorkerEventStop = (1 << 1), + TotpTypeCodeWorkerEventType = (1 << 2) +}; TotpTypeCodeWorkerContext* totp_type_code_worker_start(); void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context); void totp_type_code_worker_notify( TotpTypeCodeWorkerContext* context, - TotpTypeCodeWorkerEvtFlags event); \ No newline at end of file + TotpTypeCodeWorkerEvent event); \ No newline at end of file