Skip to content

Commit fd60525

Browse files
authored
Implemented #95 (#97)
1 parent 03a7f93 commit fd60525

36 files changed

+914
-420
lines changed

cli/cli.c

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "cli_helpers.h"
66
#include "commands/list/list.h"
77
#include "commands/add/add.h"
8+
#include "commands/update/update.h"
89
#include "commands/delete/delete.h"
910
#include "commands/timezone/timezone.h"
1011
#include "commands/help/help.h"
@@ -13,6 +14,7 @@
1314
#include "commands/notification/notification.h"
1415
#include "commands/reset/reset.h"
1516
#include "commands/automation/automation.h"
17+
#include "commands/details/details.h"
1618

1719
static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
1820
TOTP_CLI_PRINTF_ERROR(
@@ -62,6 +64,12 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
6264
totp_cli_command_automation_handle(plugin_state, args, cli);
6365
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_RESET) == 0) {
6466
totp_cli_command_reset_handle(cli, cli_context->event_queue);
67+
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_UPDATE) == 0) {
68+
totp_cli_command_update_handle(plugin_state, args, cli);
69+
} else if(
70+
furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DETAILS) == 0 ||
71+
furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DETAILS_ALT) == 0) {
72+
totp_cli_command_details_handle(plugin_state, args, cli);
6573
} else {
6674
totp_cli_print_unknown_command(cmd);
6775
}

cli/cli_helpers.c

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cli_helpers.h"
22
#include <cli/cli.h>
3+
#include <lib/toolbox/args.h>
34
#include "../types/plugin_event.h"
45

56
bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) {
@@ -59,4 +60,22 @@ bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input) {
5960
}
6061

6162
return true;
62-
}
63+
}
64+
65+
bool args_read_uint8_and_trim(FuriString* args, uint8_t* value) {
66+
int int_value;
67+
if(!args_read_int_and_trim(args, &int_value) || int_value < 0 || int_value > UINT8_MAX) {
68+
return false;
69+
}
70+
71+
*value = (uint8_t)int_value;
72+
return true;
73+
}
74+
75+
void furi_string_secure_free(FuriString* str) {
76+
for(long i = furi_string_size(str) - 1; i >= 0; i--) {
77+
furi_string_set_char(str, i, '\0');
78+
}
79+
80+
furi_string_free(str);
81+
}

cli/cli_helpers.h

+14
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,17 @@ void totp_cli_force_close_app(FuriMessageQueue* event_queue);
8989
* @return \c true if line successfully read and confirmed; \c false otherwise
9090
*/
9191
bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input);
92+
93+
/**
94+
* @brief Extracts \c uint8_t value and trims arguments string
95+
* @param args arguments string
96+
* @param[out] value parsed value
97+
* @return \c true if value successfully read and parsed as \c uint8_t ; \c false otherwise
98+
*/
99+
bool args_read_uint8_and_trim(FuriString* args, uint8_t* value);
100+
101+
/**
102+
* @brief Free \c FuriString instance in a secure manner by clearing it first
103+
* @param str instance to free
104+
*/
105+
void furi_string_secure_free(FuriString* str);

cli/commands/add/add.c

+33-107
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,7 @@
77
#include "../../../services/convert/convert.h"
88
#include "../../cli_helpers.h"
99
#include "../../../ui/scene_director.h"
10-
11-
#define TOTP_CLI_COMMAND_ADD_ARG_NAME "name"
12-
#define TOTP_CLI_COMMAND_ADD_ARG_ALGO "algo"
13-
#define TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX "-a"
14-
#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS "digits"
15-
#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d"
16-
#define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u"
17-
#define TOTP_CLI_COMMAND_ADD_ARG_DURATION "duration"
18-
#define TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX "-l"
19-
20-
static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) {
21-
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) {
22-
token_info->algo = SHA1;
23-
return true;
24-
}
25-
26-
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME) == 0) {
27-
token_info->algo = SHA256;
28-
return true;
29-
}
30-
31-
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME) == 0) {
32-
token_info->algo = SHA512;
33-
return true;
34-
}
35-
36-
return false;
37-
}
38-
39-
static bool args_read_uint8_and_trim(FuriString* args, uint8_t* value) {
40-
int int_value;
41-
if(!args_read_int_and_trim(args, &int_value) || int_value < 0 || int_value > UINT8_MAX) {
42-
return false;
43-
}
44-
45-
*value = (uint8_t)int_value;
46-
return true;
47-
}
10+
#include "../../common_command_arguments.h"
4811

4912
void totp_cli_command_add_docopt_commands() {
5013
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD ", " TOTP_CLI_COMMAND_ADD_ALT
@@ -54,42 +17,46 @@ void totp_cli_command_add_docopt_commands() {
5417
void totp_cli_command_add_docopt_usage() {
5518
TOTP_CLI_PRINTF(
5619
" " TOTP_CLI_COMMAND_NAME
57-
" " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_ADD " | " TOTP_CLI_COMMAND_ADD_ALT " | " TOTP_CLI_COMMAND_ADD_ALT2) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_NAME) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_ALGO))) " " DOCOPT_OPTIONAL(
20+
" " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_ADD " | " TOTP_CLI_COMMAND_ADD_ALT " | " TOTP_CLI_COMMAND_ADD_ALT2) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_NAME) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_ALGO_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_ALGO))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_DIGITS))) " " DOCOPT_OPTIONAL(
5821
DOCOPT_OPTION(
59-
TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX,
22+
TOTP_CLI_COMMAND_ARG_DURATION_PREFIX,
6023
DOCOPT_ARGUMENT(
61-
TOTP_CLI_COMMAND_ADD_ARG_DIGITS))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_DURATION))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX)) "\r\n");
24+
TOTP_CLI_COMMAND_ARG_DURATION))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX)) " " DOCOPT_MULTIPLE(DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)))) "\r\n");
6225
}
6326

6427
void totp_cli_command_add_docopt_arguments() {
65-
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD_ARG_NAME " Token name\r\n");
28+
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ARG_NAME " Token name\r\n");
6629
}
6730

6831
void totp_cli_command_add_docopt_options() {
6932
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
70-
TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX,
71-
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_ALGO)) " Token hashing algorithm.\r\n");
72-
TOTP_CLI_PRINTF(
73-
" Could be one of: sha1, sha256, sha512 " DOCOPT_DEFAULT("sha1") "\r\n");
74-
cli_nl();
33+
TOTP_CLI_COMMAND_ARG_ALGO_PREFIX,
34+
DOCOPT_ARGUMENT(
35+
TOTP_CLI_COMMAND_ARG_ALGO)) " Token hashing algorithm. Must be one of: " TOTP_TOKEN_ALGO_SHA1_NAME
36+
", " TOTP_TOKEN_ALGO_SHA256_NAME
37+
", " TOTP_TOKEN_ALGO_SHA512_NAME
38+
" " DOCOPT_DEFAULT(TOTP_TOKEN_ALGO_SHA1_NAME) "\r\n");
7539
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
76-
TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX,
40+
TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX,
7741
DOCOPT_ARGUMENT(
78-
TOTP_CLI_COMMAND_ADD_ARG_DIGITS)) " Number of digits to generate, one of: 6, 8 " DOCOPT_DEFAULT("6") "\r\n");
42+
TOTP_CLI_COMMAND_ARG_DIGITS)) " Number of digits to generate, one of: 6, 8 " DOCOPT_DEFAULT("6") "\r\n");
7943
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
80-
TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX,
44+
TOTP_CLI_COMMAND_ARG_DURATION_PREFIX,
8145
DOCOPT_ARGUMENT(
82-
TOTP_CLI_COMMAND_ADD_ARG_DURATION)) " Token lifetime duration in seconds, between: 15 and 255 " DOCOPT_DEFAULT("30") "\r\n");
46+
TOTP_CLI_COMMAND_ARG_DURATION)) " Token lifetime duration in seconds, between: 15 and 255 " DOCOPT_DEFAULT("30") "\r\n");
8347
TOTP_CLI_PRINTF(" " DOCOPT_SWITCH(
84-
TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n");
85-
}
86-
87-
static void furi_string_secure_free(FuriString* str) {
88-
for(long i = furi_string_size(str) - 1; i >= 0; i--) {
89-
furi_string_set_char(str, i, '\0');
90-
}
91-
92-
furi_string_free(str);
48+
TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n");
49+
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
50+
TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX,
51+
DOCOPT_ARGUMENT(
52+
TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)) " Token automation features to be enabled. Must be one of: " TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME
53+
", " TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME
54+
" " DOCOPT_DEFAULT(
55+
TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME) "\r\n");
56+
TOTP_CLI_PRINTF(" # " TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME
57+
" - No features\r\n");
58+
TOTP_CLI_PRINTF(" # " TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME
59+
" - Type <Enter> key at the end of token input automation\r\n");
9360
}
9461

9562
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
@@ -113,53 +80,12 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
11380
bool mask_user_input = true;
11481
while(args_read_string_and_trim(args, temp_str)) {
11582
bool parsed = false;
116-
if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX) == 0) {
117-
if(!args_read_string_and_trim(args, temp_str)) {
118-
TOTP_CLI_PRINTF_ERROR(
119-
"Missed value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX "\"\r\n");
120-
} else if(!token_info_set_algo_from_str(token_info, temp_str)) {
121-
TOTP_CLI_PRINTF_ERROR(
122-
"\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX
123-
"\"\r\n",
124-
furi_string_get_cstr(temp_str));
125-
} else {
126-
parsed = true;
127-
}
128-
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX) == 0) {
129-
uint8_t digit_value;
130-
if(!args_read_uint8_and_trim(args, &digit_value)) {
131-
TOTP_CLI_PRINTF_ERROR(
132-
"Missed or incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
133-
"\"\r\n");
134-
} else if(!token_info_set_digits_from_int(token_info, digit_value)) {
135-
TOTP_CLI_PRINTF_ERROR(
136-
"\"%" PRIu8
137-
"\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
138-
"\"\r\n",
139-
digit_value);
140-
} else {
141-
parsed = true;
142-
}
143-
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX) == 0) {
144-
uint8_t duration_value;
145-
if(!args_read_uint8_and_trim(args, &duration_value)) {
146-
TOTP_CLI_PRINTF_ERROR(
147-
"Missed or incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX
148-
"\"\r\n");
149-
} else if(!token_info_set_duration_from_int(token_info, duration_value)) {
150-
TOTP_CLI_PRINTF_ERROR(
151-
"\"%" PRIu8
152-
"\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX
153-
"\"\r\n",
154-
duration_value);
155-
} else {
156-
parsed = true;
157-
}
158-
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) == 0) {
159-
mask_user_input = false;
160-
parsed = true;
161-
} else {
162-
TOTP_CLI_PRINTF_ERROR("Unknown argument \"%s\"\r\n", furi_string_get_cstr(temp_str));
83+
if(!totp_cli_try_read_algo(token_info, temp_str, args, &parsed) &&
84+
!totp_cli_try_read_digits(token_info, temp_str, args, &parsed) &&
85+
!totp_cli_try_read_duration(token_info, temp_str, args, &parsed) &&
86+
!totp_cli_try_read_unsecure_flag(temp_str, &parsed, &mask_user_input) &&
87+
!totp_cli_try_read_automation_features(token_info, temp_str, args, &parsed)) {
88+
totp_cli_printf_unknown_argument(temp_str);
16389
}
16490

16591
if(!parsed) {

cli/commands/automation/automation.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ void totp_cli_command_automation_docopt_usage() {
2323
void totp_cli_command_automation_docopt_arguments() {
2424
TOTP_CLI_PRINTF(
2525
" " TOTP_CLI_COMMAND_AUTOMATION_ARG_METHOD
26-
" Automation method to be set. Must be one of [" TOTP_CLI_COMMAND_AUTOMATION_METHOD_NONE
26+
" Automation method to be set. Must be one of: " TOTP_CLI_COMMAND_AUTOMATION_METHOD_NONE
2727
", " TOTP_CLI_COMMAND_AUTOMATION_METHOD_USB
2828
#ifdef TOTP_BADBT_TYPE_ENABLED
2929
", " TOTP_CLI_COMMAND_AUTOMATION_METHOD_BT
3030
#endif
31-
"]\r\n");
31+
"\r\n");
3232
}
3333

3434
static void totp_cli_command_automation_print_method(AutomationMethod method, char* color) {

cli/commands/delete/delete.c

+11-11
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
#include "../../../services/config/config.h"
88
#include "../../cli_helpers.h"
99
#include "../../../ui/scene_director.h"
10+
#include "../../common_command_arguments.h"
1011

11-
#define TOTP_CLI_COMMAND_DELETE_ARG_INDEX "index"
12-
#define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX "-f"
12+
#define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX "-f"
1313

1414
void totp_cli_command_delete_docopt_commands() {
1515
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DELETE ", " TOTP_CLI_COMMAND_DELETE_ALT
@@ -20,19 +20,23 @@ void totp_cli_command_delete_docopt_usage() {
2020
TOTP_CLI_PRINTF(
2121
" " TOTP_CLI_COMMAND_NAME
2222
" " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_DELETE " | " TOTP_CLI_COMMAND_DELETE_ALT) " " DOCOPT_ARGUMENT(
23-
TOTP_CLI_COMMAND_DELETE_ARG_INDEX) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX)) "\r\n");
23+
TOTP_CLI_COMMAND_ARG_INDEX) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX)) "\r\n");
2424
}
2525

2626
void totp_cli_command_delete_docopt_arguments() {
27-
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DELETE_ARG_INDEX " Token index in the list\r\n");
27+
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ARG_INDEX " Token index in the list\r\n");
2828
}
2929

3030
void totp_cli_command_delete_docopt_options() {
3131
TOTP_CLI_PRINTF(" " DOCOPT_SWITCH(
32-
TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX) " Force command to do not ask user for interactive confirmation\r\n");
32+
TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX) " Force command to do not ask user for interactive confirmation\r\n");
3333
}
3434

3535
void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
36+
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
37+
return;
38+
}
39+
3640
int token_number;
3741
if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 ||
3842
token_number > plugin_state->tokens_count) {
@@ -43,21 +47,17 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
4347
FuriString* temp_str = furi_string_alloc();
4448
bool confirm_needed = true;
4549
if(args_read_string_and_trim(args, temp_str)) {
46-
if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX) == 0) {
50+
if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX) == 0) {
4751
confirm_needed = false;
4852
} else {
49-
TOTP_CLI_PRINTF("Unknown argument \"%s\"\r\n", furi_string_get_cstr(temp_str));
53+
totp_cli_printf_unknown_argument(temp_str);
5054
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
5155
furi_string_free(temp_str);
5256
return;
5357
}
5458
}
5559
furi_string_free(temp_str);
5660

57-
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
58-
return;
59-
}
60-
6161
ListNode* list_node = list_element_at(plugin_state->tokens_list, token_number - 1);
6262

6363
TokenInfo* token_info = list_node->data;

cli/commands/details/details.c

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "details.h"
2+
#include <stdlib.h>
3+
#include <lib/toolbox/args.h>
4+
#include "../../../lib/list/list.h"
5+
#include "../../../types/token_info.h"
6+
#include "../../../services/config/constants.h"
7+
#include "../../cli_helpers.h"
8+
#include "../../common_command_arguments.h"
9+
10+
static void print_automation_features(const TokenInfo* token_info) {
11+
if(token_info->automation_features == TOKEN_AUTOMATION_FEATURE_NONE) {
12+
TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", "Automation features", "None");
13+
return;
14+
}
15+
16+
if(token_info->automation_features & TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END) {
17+
TOTP_CLI_PRINTF(
18+
"| %-20s | %-28.28s |\r\n", "Automation features", "Type <Enter> key at the end");
19+
}
20+
}
21+
22+
void totp_cli_command_details_docopt_commands() {
23+
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DETAILS ", " TOTP_CLI_COMMAND_DETAILS_ALT
24+
" Displays token details\r\n");
25+
}
26+
27+
void totp_cli_command_details_docopt_usage() {
28+
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED(
29+
TOTP_CLI_COMMAND_DETAILS
30+
" | " TOTP_CLI_COMMAND_DETAILS_ALT) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_INDEX) "\r\n");
31+
}
32+
33+
void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
34+
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
35+
return;
36+
}
37+
38+
int token_number;
39+
if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 ||
40+
token_number > plugin_state->tokens_count) {
41+
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
42+
return;
43+
}
44+
45+
ListNode* list_node = list_element_at(plugin_state->tokens_list, token_number - 1);
46+
47+
TokenInfo* token_info = list_node->data;
48+
49+
TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n");
50+
TOTP_CLI_PRINTF("| %-20s | %-28s |\r\n", "Property", "Value");
51+
TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n");
52+
TOTP_CLI_PRINTF("| %-20s | %-28d |\r\n", "Index", token_number);
53+
TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", "Name", token_info->name);
54+
TOTP_CLI_PRINTF(
55+
"| %-20s | %-28s |\r\n", "Hashing algorithm", token_info_get_algo_as_cstr(token_info));
56+
TOTP_CLI_PRINTF("| %-20s | %-28" PRIu8 " |\r\n", "Number of digits", token_info->digits);
57+
TOTP_CLI_PRINTF(
58+
"| %-20s | %" PRIu8 " sec.%-21s |\r\n", "Token lifetime", token_info->duration, " ");
59+
print_automation_features(token_info);
60+
TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n");
61+
}

0 commit comments

Comments
 (0)