diff --git a/src/libply-splash-core/ply-boot-splash-plugin.h b/src/libply-splash-core/ply-boot-splash-plugin.h index d5cd05a7..815a4bef 100644 --- a/src/libply-splash-core/ply-boot-splash-plugin.h +++ b/src/libply-splash-core/ply-boot-splash-plugin.h @@ -103,6 +103,9 @@ typedef struct bool (*validate_input) (ply_boot_splash_plugin_t *plugin, const char *entry_text, const char *add_text); + void (*display_password_clear_text)(ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text); } ply_boot_splash_plugin_interface_t; #endif /* PLY_BOOT_SPLASH_PLUGIN_H */ diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c index 217f455e..ab3d322d 100644 --- a/src/libply-splash-core/ply-boot-splash.c +++ b/src/libply-splash-core/ply-boot-splash.c @@ -707,17 +707,38 @@ void ply_boot_splash_display_normal (ply_boot_splash_t *splash) splash->plugin_interface->display_normal (splash->plugin); } -void ply_boot_splash_display_password (ply_boot_splash_t *splash, - const char *prompt, - int bullets) +static inline void +assert_password_capable (ply_boot_splash_t *splash) { assert (splash != NULL); assert (splash->plugin_interface != NULL); assert (splash->plugin != NULL); +} + +void ply_boot_splash_display_password (ply_boot_splash_t *splash, + const char *prompt, + int bullets) +{ + assert_password_capable (splash); if (splash->plugin_interface->display_password != NULL) splash->plugin_interface->display_password (splash->plugin, prompt, bullets); } +bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash) +{ + assert_password_capable (splash); + return splash->plugin_interface->display_password_clear_text != NULL; +} + +void ply_boot_splash_display_password_clear_text (ply_boot_splash_t *splash, + const char *prompt, + const char *entry_text) +{ + if (!ply_boot_splash_can_display_password_clear_text (splash)) + return; + splash->plugin_interface->display_password_clear_text (splash->plugin, prompt, entry_text); +} + void ply_boot_splash_display_question (ply_boot_splash_t *splash, const char *prompt, const char *entry_text) diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h index df57b8c9..50d51361 100644 --- a/src/libply-splash-core/ply-boot-splash.h +++ b/src/libply-splash-core/ply-boot-splash.h @@ -79,6 +79,10 @@ void ply_boot_splash_display_normal (ply_boot_splash_t *splash); void ply_boot_splash_display_password (ply_boot_splash_t *splash, const char *prompt, int bullets); +bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash); +void ply_boot_splash_display_password_clear_text (ply_boot_splash_t *splash, + const char *prompt, + const char *entry_text); void ply_boot_splash_display_question (ply_boot_splash_t *splash, const char *prompt, const char *entry_text); diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c index dc19f5cc..d69713e0 100644 --- a/src/libply-splash-core/ply-keyboard.c +++ b/src/libply-splash-core/ply-keyboard.c @@ -44,6 +44,7 @@ #define KEY_CTRL_W ('\100' ^ 'W') #define KEY_CTRL_V ('\100' ^ 'V') #define KEY_ESCAPE ('\100' ^ '[') +#define KEY_TAB '\t' #define KEY_RETURN '\n' #define KEY_BACKSPACE '\177' @@ -97,6 +98,7 @@ struct _ply_keyboard ply_list_t *keyboard_input_handler_list; ply_list_t *backspace_handler_list; ply_list_t *escape_handler_list; + ply_list_t *tab_handler_list; ply_list_t *enter_handler_list; uint32_t is_active : 1; @@ -114,6 +116,7 @@ ply_keyboard_new_for_terminal (ply_terminal_t *terminal) keyboard->keyboard_input_handler_list = ply_list_new (); keyboard->backspace_handler_list = ply_list_new (); keyboard->escape_handler_list = ply_list_new (); + keyboard->tab_handler_list = ply_list_new (); keyboard->enter_handler_list = ply_list_new (); keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL; keyboard->provider.if_terminal = calloc (1, sizeof(ply_keyboard_terminal_provider_t)); @@ -136,6 +139,7 @@ ply_keyboard_new_for_renderer (ply_renderer_t *renderer) keyboard->keyboard_input_handler_list = ply_list_new (); keyboard->backspace_handler_list = ply_list_new (); keyboard->escape_handler_list = ply_list_new (); + keyboard->tab_handler_list = ply_list_new (); keyboard->enter_handler_list = ply_list_new (); keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_RENDERER; keyboard->provider.if_renderer = calloc (1, sizeof(ply_keyboard_renderer_provider_t)); @@ -219,6 +223,17 @@ process_keyboard_input (ply_keyboard_t *keyboard, ply_trace ("end escape key handler"); return; + case KEY_TAB: + ply_trace ("tab key!"); + for (node = ply_list_get_first_node (keyboard->tab_handler_list); + node; node = ply_list_get_next_node (keyboard->tab_handler_list, node)) { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + ply_keyboard_tab_handler_t tab_handler = (ply_keyboard_tab_handler_t) closure->function; + tab_handler (closure->user_data); + } + ply_trace ("end tab key handler"); + return; + case KEY_BACKSPACE: ply_trace ("backspace key!"); process_backspace (keyboard); @@ -638,6 +653,40 @@ ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, } } +void +ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler, + void *user_data) +{ + ply_keyboard_closure_t *closure; + + assert (keyboard != NULL); + + closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) tab_handler, + user_data); + ply_list_append_data (keyboard->tab_handler_list, closure); +} + + +void +ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler) +{ + ply_list_node_t *node; + + assert (keyboard != NULL); + + for (node = ply_list_get_first_node (keyboard->tab_handler_list); + node; node = ply_list_get_next_node (keyboard->tab_handler_list, node)) { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + if ((ply_keyboard_tab_handler_t) closure->function == tab_handler) { + ply_keyboard_closure_free (closure); + ply_list_remove_node (keyboard->tab_handler_list, node); + return; + } + } +} + void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, ply_keyboard_enter_handler_t enter_handler, diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h index 101defdb..cb88ae8a 100644 --- a/src/libply-splash-core/ply-keyboard.h +++ b/src/libply-splash-core/ply-keyboard.h @@ -40,6 +40,8 @@ typedef void (*ply_keyboard_backspace_handler_t) (void *user_data); typedef void (*ply_keyboard_escape_handler_t) (void *user_data); +typedef void (*ply_keyboard_tab_handler_t) (void *user_data); + typedef void (*ply_keyboard_enter_handler_t) (void *user_data, const char *line); @@ -63,6 +65,11 @@ void ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard, void *user_data); void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, ply_keyboard_escape_handler_t escape_handler); +void ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler, + void *user_data); +void ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler); void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, ply_keyboard_enter_handler_t enter_handler, void *user_data); diff --git a/src/main.c b/src/main.c index aac5125d..0ebc843b 100644 --- a/src/main.c +++ b/src/main.c @@ -117,6 +117,7 @@ typedef struct uint32_t should_force_details : 1; uint32_t should_force_default_splash : 1; uint32_t splash_is_becoming_idle : 1; + uint32_t should_show_password_clear_text : 1; char *override_splash_path; char *system_default_splash_path; @@ -155,6 +156,7 @@ static void tell_systemd_to_stop_printing_details (state_t *state); #endif static const char *get_cache_file_for_mode (ply_boot_splash_mode_t mode); static void on_escape_pressed (state_t *state); +static void on_tab_pressed (state_t *state); static void on_enter (state_t *state, const char *line); static void on_keyboard_input (state_t *state, @@ -1110,6 +1112,10 @@ on_keyboard_added (state_t *state, ply_keyboard_add_escape_handler (keyboard, (ply_keyboard_escape_handler_t) on_escape_pressed, state); + ply_trace ("listening for tab"); + ply_keyboard_add_tab_handler (keyboard, + (ply_keyboard_tab_handler_t) + on_tab_pressed, state); ply_trace ("listening for backspace"); ply_keyboard_add_backspace_handler (keyboard, (ply_keyboard_backspace_handler_t) @@ -1137,6 +1143,10 @@ on_keyboard_removed (state_t *state, ply_keyboard_remove_escape_handler (keyboard, (ply_keyboard_escape_handler_t) on_escape_pressed); + ply_trace ("no longer listening for tab"); + ply_keyboard_remove_tab_handler (keyboard, + (ply_keyboard_tab_handler_t) + on_tab_pressed); ply_trace ("no longer listening for backspace"); ply_keyboard_remove_backspace_handler (keyboard, (ply_keyboard_backspace_handler_t) @@ -1581,6 +1591,33 @@ validate_input (state_t *state, return input_valid; } +static void +handle_ply_entry_trigger_type_password (state_t *state, + ply_entry_trigger_t *entry_trigger) +{ + bool show_password_clear_text = + state->should_show_password_clear_text && + ply_boot_splash_can_display_password_clear_text (state->boot_splash); + if (show_password_clear_text) { + const char *entry_text = (const char *) ply_buffer_get_bytes (state->entry_buffer); + ply_trace ("WARNING: cleartext password display enabled"); + ply_boot_splash_display_password_clear_text (state->boot_splash, + entry_trigger->prompt, + entry_text); + } else { + int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), + ply_buffer_get_size (state->entry_buffer)); + bullets = MAX (0, bullets); + ply_boot_splash_display_password (state->boot_splash, + entry_trigger->prompt, + bullets); + } + ply_boot_splash_display_prompt (state->boot_splash, + entry_trigger->prompt, + ply_buffer_get_bytes (state->entry_buffer), + true); +} + static void update_display (state_t *state) @@ -1589,32 +1626,24 @@ update_display (state_t *state) ply_list_node_t *node; node = ply_list_get_first_node (state->entry_triggers); - if (node) { - ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node); - if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) { - int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), - ply_buffer_get_size (state->entry_buffer)); - bullets = MAX (0, bullets); - ply_boot_splash_display_password (state->boot_splash, - entry_trigger->prompt, - bullets); - ply_boot_splash_display_prompt (state->boot_splash, - entry_trigger->prompt, - ply_buffer_get_bytes (state->entry_buffer), - true); - } else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) { - ply_boot_splash_display_question (state->boot_splash, - entry_trigger->prompt, - ply_buffer_get_bytes (state->entry_buffer)); - ply_boot_splash_display_prompt (state->boot_splash, - entry_trigger->prompt, - ply_buffer_get_bytes (state->entry_buffer), - false); - } else { - ply_trace ("unkown entry type"); - } - } else { + if (!node) { ply_boot_splash_display_normal (state->boot_splash); + return; + } + + ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node); + if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) { + handle_ply_entry_trigger_type_password (state, entry_trigger); + } else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) { + ply_boot_splash_display_question (state->boot_splash, + entry_trigger->prompt, + ply_buffer_get_bytes (state->entry_buffer)); + ply_boot_splash_display_prompt (state->boot_splash, + entry_trigger->prompt, + ply_buffer_get_bytes (state->entry_buffer), + false); + } else { + ply_trace ("unknown entry type"); } } @@ -1655,6 +1684,28 @@ on_escape_pressed (state_t *state) toggle_between_splash_and_details (state); } +static void +toggle_between_bullets_and_clear_text (state_t *state) +{ + ply_trace ("toggling between bullets and clear text"); + + if (!state->should_show_password_clear_text) { + state->should_show_password_clear_text = true; + } else { + state->should_show_password_clear_text = false; + } + update_display (state); +} + +static void +on_tab_pressed (state_t *state) +{ + ply_trace ("tab key pressed"); + + if (validate_input (state, "", "\t")) + toggle_between_bullets_and_clear_text (state); +} + static void on_keyboard_input (state_t *state, const char *keyboard_input, diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index c810564e..1ae088ed 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -195,6 +195,7 @@ struct _ply_boot_splash_plugin uint32_t background_image_is_scaled : 1; uint32_t dialog_clears_firmware_background : 1; uint32_t message_below_animation : 1; + uint32_t allow_password_clear_text_toggle : 1; char *monospace_font; uint32_t plugin_console_messages_updating : 1; @@ -699,6 +700,8 @@ view_load (view_t *view) ply_trace ("loading entry"); if (!ply_entry_load (view->entry)) return false; + else + ply_entry_set_text_color (view->entry, 1.0, 1.0, 1.0, 1.0); ply_keymap_icon_load (view->keymap_icon); ply_capslock_icon_load (view->capslock_icon); @@ -1360,6 +1363,9 @@ create_plugin (ply_key_file_t *key_file) plugin->message_below_animation = ply_key_file_get_bool (key_file, "two-step", "MessageBelowAnimation"); + plugin->allow_password_clear_text_toggle = + ply_key_file_get_bool (key_file, "two-step", "AllowPasswordClearTextToggle"); + progress_function = ply_key_file_get_value (key_file, "two-step", "ProgressFunction"); if (progress_function != NULL) { @@ -2222,16 +2228,17 @@ display_normal (ply_boot_splash_plugin_t *plugin) } static void -display_password (ply_boot_splash_plugin_t *plugin, - const char *prompt, - int bullets) +display_password_internal (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text, + int bullets) { pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) stop_animation (plugin); plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - show_prompt (plugin, prompt, NULL, bullets); + show_prompt (plugin, prompt, entry_text, bullets); redraw_views (plugin); if (plugin->should_show_console_messages) @@ -2241,6 +2248,31 @@ display_password (ply_boot_splash_plugin_t *plugin, unpause_views (plugin); } +static void +display_password (ply_boot_splash_plugin_t *plugin, + const char *prompt, + int bullets) +{ + display_password_internal (plugin, prompt, NULL, bullets); +} + +static void +display_password_clear_text (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + if (!plugin->allow_password_clear_text_toggle) { + // if function is disabled, fall back to masked bullet mode, + // as dynamically setting function to NULL is not possible + int bullets = ply_utf8_string_get_length (entry_text, + strlen (entry_text)); + bullets = MAX (0, bullets); + display_password_internal (plugin, prompt, NULL, bullets); + return; + } + display_password_internal (plugin, prompt, entry_text, -1); +} + static void display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, @@ -2379,23 +2411,24 @@ ply_boot_splash_plugin_get_interface (void) { static ply_boot_splash_plugin_interface_t plugin_interface = { - .create_plugin = create_plugin, - .destroy_plugin = destroy_plugin, - .add_pixel_display = add_pixel_display, - .remove_pixel_display = remove_pixel_display, - .show_splash_screen = show_splash_screen, - .update_status = update_status, - .on_boot_progress = on_boot_progress, - .hide_splash_screen = hide_splash_screen, - .on_root_mounted = on_root_mounted, - .become_idle = become_idle, - .display_normal = display_normal, - .display_password = display_password, - .display_question = display_question, - .display_message = display_message, - .system_update = system_update, - .on_boot_output = on_boot_output, - .validate_input = validate_input, + .create_plugin = create_plugin, + .destroy_plugin = destroy_plugin, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, + .show_splash_screen = show_splash_screen, + .update_status = update_status, + .on_boot_progress = on_boot_progress, + .hide_splash_screen = hide_splash_screen, + .on_root_mounted = on_root_mounted, + .become_idle = become_idle, + .display_normal = display_normal, + .display_password = display_password, + .display_password_clear_text = display_password_clear_text, + .display_question = display_question, + .display_message = display_message, + .system_update = system_update, + .on_boot_output = on_boot_output, + .validate_input = validate_input, }; return &plugin_interface;