From 3b9ee94581383ed16bbb0a8a741a6c61e1955f63 Mon Sep 17 00:00:00 2001 From: Ivan Yarcev Date: Fri, 18 Jul 2025 18:00:52 +0600 Subject: [PATCH] WIP Added password window --- gresource.xml | 1 + libublsettingsui-gtk3-password.glade | 333 ++++++++++++++++++++++++ source/CMakeLists.txt | 2 + source/libublsettingsui-gtk3-password.c | 228 ++++++++++++++++ source/libublsettingsui-gtk3.h | 39 +++ 5 files changed, 603 insertions(+) create mode 100644 libublsettingsui-gtk3-password.glade create mode 100644 source/libublsettingsui-gtk3-password.c diff --git a/gresource.xml b/gresource.xml index 6f92e06..a0718a8 100644 --- a/gresource.xml +++ b/gresource.xml @@ -10,6 +10,7 @@ libublsettingsui-gtk3-config-window.glade libublsettingsui-gtk3-service-control.glade libublsettingsui-gtk3-app-chooser.glade + libublsettingsui-gtk3-password.glade libublsettingsui-gtk3.css diff --git a/libublsettingsui-gtk3-password.glade b/libublsettingsui-gtk3-password.glade new file mode 100644 index 0000000..81710d0 --- /dev/null +++ b/libublsettingsui-gtk3-password.glade @@ -0,0 +1,333 @@ + + + + + + True + False + com.ublinux.libublsettingsui-gtk3.cancel-uncolored-symbolic + + + True + False + com.ublinux.libublsettingsui-gtk3.accept-symbolic + + + False + False + True + 450 + com.ublinux.ubl-settings-update + + + True + False + 5 + vertical + 5 + + + True + False + vertical + + + + + + False + True + 0 + + + + + True + False + 5 + 5 + vertical + 5 + + + True + False + vertical + 5 + + + True + False + 5 + + + True + False + Password: + 0 + + + False + True + 0 + + + + + True + True + Password + False + * + True + ******** + password + + + True + True + 1 + + + + + True + True + 1 + + + + + True + False + 5 + + + True + False + Repeat password: + 0 + + + False + True + 0 + + + + + True + True + Repeat password + False + * + True + ******** + password + + + True + True + 1 + + + + + True + True + 2 + + + + + False + True + 0 + + + + + True + False + 5 + + + True + False + Encryption: + 0 + + + False + True + 0 + + + + + True + False + Encryption + 0 + + Default (None) + SHA-512 + SHA-256 + + + + True + True + 1 + + + + + True + True + 1 + + + + + Do not encrypt password + True + False + True + False + True + + + False + True + 2 + + + + + True + False + + + False + True + 3 + + + + + True + False + vertical + 5 + + + True + False + 5 + + + True + False + Password hash: + 0 + + + False + True + 0 + + + + + True + False + True + Password hash + False + * + + + True + True + 1 + + + + + True + True + 2 + + + + + False + True + 4 + + + + + False + True + 2 + + + + + + + True + False + + + True + False + Password input + + + + + + + + Cancel + True + True + True + image4 + + + + + + Accept + True + True + True + image5 + + + + end + 1 + + + + + + + + + + + + + diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 9aeefed..8578725 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -46,6 +46,7 @@ set(DEPENDFILES ../libublsettingsui-gtk3-config-window.glade ../libublsettingsui-gtk3-service-control.glade ../libublsettingsui-gtk3-app-chooser.glade + ../libublsettingsui-gtk3-password.glade ../gresource.xml ../libublsettingsui-gtk3-banner.png ../libublsettingsui-gtk3.css @@ -85,6 +86,7 @@ add_library(${PROJECT_NAME} SHARED libublsettingsui-gtk3-service.c libublsettingsui-gtk3-app-chooser.c libublsettingsui-gtk3-standard-callbacks.c + libublsettingsui-gtk3-password.c libublsettingsui-gtk3.h ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C}) diff --git a/source/libublsettingsui-gtk3-password.c b/source/libublsettingsui-gtk3-password.c new file mode 100644 index 0000000..6b6ce7a --- /dev/null +++ b/source/libublsettingsui-gtk3-password.c @@ -0,0 +1,228 @@ +#include "libublsettingsui-gtk3.h" + + +#define sha256_encrypt_command(target) yon_char_unite("echo -n \"",target,"\" | sha256sum | cut -f 1 -d ' '",NULL) +#define sha512_encrypt_command(target) yon_char_unite("echo -n \"",target,"\" | sha512sum | cut -f 1 -d ' '",NULL) + +yon_password_window *yon_password_window_new(); + +char *yon_password_unencrypted_password_get(yon_password_window *window){ + const char *password = gtk_entry_get_text(GTK_ENTRY(window->PasswordEntry)); + const char *password_repeat = gtk_entry_get_text(GTK_ENTRY(window->RepeatPasswordEntry)); + if (strpbrk(password,"!@#%^&*\'")){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_PASSWORD_RESTRICTED_SYMBOL_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordEntry); + return NULL; + } + if (strcmp(password,password_repeat)){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_PASSWORD_MISMATCH_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordEntry); + yon_ubl_status_highlight_incorrect(window->RepeatPasswordEntry); + return NULL; + } + if (yon_char_is_empty(password)){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_EMPTY_IMPORTANT_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordEntry); + return NULL; + } + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(window->NoEncriptionCheck))){ + const char *encryption = gtk_combo_box_get_active_id(GTK_COMBO_BOX(window->EncryptionCombo)); + char *final = yon_char_unite(encryption,"|",password,NULL); + return final; + } else { + return yon_char_new(password); + } +} + +char *yon_password_hash_get(yon_password_window *window){ + int encription_active = gtk_combo_box_get_active(GTK_COMBO_BOX(window->EncryptionCombo)); + const char *encription = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(window->EncryptionCombo)); + const char *encription_command = gtk_combo_box_get_active_id(GTK_COMBO_BOX(window->EncryptionCombo)); + const char *hash = gtk_entry_get_text(GTK_ENTRY(window->PasswordHashEntry)); + if (!yon_char_is_empty(hash)){ + // if (!yon_char_is_empty(window->old_password)&&strcmp(hash,window->old_password)){ + switch(encription_active){ + case 1:{ + if (strlen(hash)!=128){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_INCORRECT_HASH_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordHashEntry); + return NULL; + } + } + break; + case 2:{ + if (strlen(hash)!=64){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_INCORRECT_HASH_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordHashEntry); + return NULL; + } + } + break; + } + // } + char *final = yon_char_unite(encription,"|",hash,NULL); + return final; + } else { + const char *password = gtk_entry_get_text(GTK_ENTRY(window->PasswordEntry)); + const char *password_repeat = gtk_entry_get_text(GTK_ENTRY(window->RepeatPasswordEntry)); + if (strpbrk(password,"!@#%^&*\'")){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_PASSWORD_RESTRICTED_SYMBOL_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordEntry); + return NULL; + } + if (yon_char_is_empty(password_repeat)){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_EMPTY_IMPORTANT_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->RepeatPasswordEntry); + return NULL; + } + if (strcmp(password,password_repeat)){ + yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),_PASSWORD_MISMATCH_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE); + yon_ubl_status_highlight_incorrect(window->PasswordEntry); + yon_ubl_status_highlight_incorrect(window->RepeatPasswordEntry); + return NULL; + } + + int size; + config_str hash = yon_config_load(yon_debug_output("%s\n",encription_active==1?sha512_encrypt_command(password):sha256_encrypt_command(password)),&size); + yon_char_remove_last_symbol(hash[0],'\n'); + + char *final = hash[0]; + if (gtk_widget_get_visible(window->EncryptionCombo)){ + final = yon_char_unite(encription,"|",hash[0],NULL); + } + return final; + } + return NULL; +} + +void on_password_encryption_changed(GtkComboBox *self, yon_password_window *dialog){ + int active = gtk_combo_box_get_active(self); + gtk_widget_set_sensitive(dialog->NoEncriptionCheck,!!active); + if (!active) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->NoEncriptionCheck),0); +} + +void yon_hash_entry_sensitiveness_update(GtkWidget *, yon_password_window *dialog){ + int hash_type_sensitive = gtk_combo_box_get_active(GTK_COMBO_BOX(dialog->EncryptionCombo)); + int encrypt_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->NoEncriptionCheck)); + if (!encrypt_sensitive&&hash_type_sensitive) gtk_widget_set_sensitive(dialog->PasswordHashEntry,1); + else gtk_widget_set_sensitive(dialog->PasswordHashEntry,0); +} + +void yon_password_hash_list_set(yon_password_window *window, config_str hashes, config_str get_hash_commands, int size){ + gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(window->EncryptionCombo)); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(window->EncryptionCombo),_ENCRYPTION_DEFAULT_LABEL,""); + + for (int i=0;iEncryptionCombo),hashes[i],get_hash_commands[i]); + } +} + +void on_password_hash_sensitiveness(GtkWidget *,yon_password_window *window){ + const char *password = gtk_entry_get_text(GTK_ENTRY(window->PasswordEntry)); + const char *repeat_password = gtk_entry_get_text(GTK_ENTRY(window->RepeatPasswordEntry)); + const char *hash = gtk_entry_get_text(GTK_ENTRY(window->PasswordHashEntry)); + const char *hash_command = gtk_combo_box_get_active_id(GTK_COMBO_BOX(window->EncryptionCombo)); + if (!yon_char_is_empty(hash_command)){ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(window->NoEncriptionCheck),1); + gtk_widget_set_sensitive(window->NoEncriptionCheck,0); + } else { + gtk_widget_set_sensitive(window->NoEncriptionCheck,1); + } + if (!yon_char_is_empty(password)||!yon_char_is_empty(repeat_password)){ + gtk_widget_set_sensitive(window->HashBox,0); + gtk_widget_set_sensitive(window->PasswordBox,1); + } else if (yon_char_is_empty(password)&&yon_char_is_empty(repeat_password)&& + gtk_combo_box_get_active(GTK_COMBO_BOX(window->EncryptionCombo))>0&& + yon_char_is_empty(hash)&&!yon_char_is_empty(hash_command)){ + gtk_widget_set_sensitive(window->HashBox,1); + gtk_widget_set_sensitive(window->PasswordBox,1); + gtk_widget_set_sensitive(window->NoEncriptionCheck,1); + } else if (!yon_char_is_empty(hash)&&!yon_char_is_empty(hash_command)) { + gtk_widget_set_sensitive(window->HashBox,1); + gtk_widget_set_sensitive(window->PasswordBox,0); + gtk_widget_set_sensitive(window->NoEncriptionCheck,0); + } else { + gtk_widget_set_sensitive(window->HashBox,0); + gtk_widget_set_sensitive(window->PasswordBox,1); + } +} + +void on_password_accept(GtkWidget *,dictionary *dict){ + yon_password_window *window = yon_dictionary_get_data(dict->first,yon_password_window*); + GtkWidget *target = yon_dictionary_get_data(dict->first->next,GtkWidget*); + + int encription_active = gtk_combo_box_get_active(GTK_COMBO_BOX(window->EncryptionCombo)); + char *final = NULL; + if (encription_active == 0||gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(window->NoEncriptionCheck))){ + final = yon_password_unencrypted_password_get(window); + if (!final) return; + } else { + final = yon_password_hash_get(window); + if (!final) return; + } + gtk_entry_set_text(GTK_ENTRY(target),final); + gtk_widget_destroy(window->Window); +} + +yon_password_window *yon_password_window_new(){ + GtkBuilder *builder = gtk_builder_new_from_resource(ui_glade_path_password); + yon_password_window *window = malloc(sizeof(yon_password_window)); + window->Window = yon_gtk_builder_get_widget(builder,"PasswordWindow"); + window->HeadLabel = yon_gtk_builder_get_widget(builder,"userTitleNameLabel"); + window->StatusBox = yon_gtk_builder_get_widget(builder,"StatusBox"); + window->PasswordEntry = yon_gtk_builder_get_widget(builder,"PasswordEntry"); + window->RepeatPasswordEntry = yon_gtk_builder_get_widget(builder,"RepeatPasswordEntry"); + window->EncryptionCombo = yon_gtk_builder_get_widget(builder,"EncryptionCombo"); + window->NoEncriptionCheck = yon_gtk_builder_get_widget(builder,"NoEncriptionCheck"); + window->PasswordHashEntry = yon_gtk_builder_get_widget(builder,"PasswordHashEntry"); + window->UserCancelButton = yon_gtk_builder_get_widget(builder,"UserCancelButton"); + window->AcceptButton = yon_gtk_builder_get_widget(builder,"UserOkButton"); + window->PasswordBox = yon_gtk_builder_get_widget(builder,"PasswordBox"); + window->HashBox = yon_gtk_builder_get_widget(builder,"HashBox"); + + window->old_password=NULL; + g_signal_connect(G_OBJECT(window->UserCancelButton),"clicked",G_CALLBACK(on_subwindow_close),NULL); + g_signal_connect(G_OBJECT(window->EncryptionCombo),"changed",G_CALLBACK(on_password_hash_sensitiveness),window); + g_signal_connect(G_OBJECT(window->NoEncriptionCheck),"toggled",G_CALLBACK(on_password_hash_sensitiveness),window); + g_signal_connect(G_OBJECT(window->PasswordHashEntry),"changed",G_CALLBACK(on_password_hash_sensitiveness),window); + g_signal_connect(G_OBJECT(window->PasswordEntry),"changed",G_CALLBACK(on_password_hash_sensitiveness),window); + g_signal_connect(G_OBJECT(window->RepeatPasswordEntry),"changed",G_CALLBACK(on_password_hash_sensitiveness),window); + gtk_widget_show(window->Window); + return window; +} + +yon_password_window *yon_password_open(GtkEntry *target){ + g_return_val_if_fail(GTK_IS_ENTRY(target),NULL); + + yon_password_window *dialog = yon_password_window_new(); + + g_signal_connect(G_OBJECT(dialog->NoEncriptionCheck),"toggled",G_CALLBACK(yon_hash_entry_sensitiveness_update),dialog); + g_signal_connect(G_OBJECT(dialog->EncryptionCombo),"changed",G_CALLBACK(yon_hash_entry_sensitiveness_update),dialog); + + yon_gtk_entry_set_password_visibility_icon(GTK_ENTRY(dialog->PasswordEntry)); + yon_gtk_entry_set_password_visibility_icon(GTK_ENTRY(dialog->PasswordHashEntry)); + yon_gtk_entry_set_password_visibility_icon(GTK_ENTRY(dialog->RepeatPasswordEntry)); + + char *old_password = yon_char_new(gtk_entry_get_text(target)); + char *hash_type = NULL; + if (!yon_char_is_empty(old_password)&&strstr(old_password,"|")){ + hash_type = yon_char_divide(old_password,6); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(dialog->EncryptionCombo),hash_type); + } + if (!yon_char_is_empty(old_password)&&(strlen(old_password)==128||strlen(old_password)==64)){ + dialog->old_password = old_password; + gtk_entry_set_text(GTK_ENTRY(dialog->PasswordHashEntry),old_password); + } else if (!yon_char_is_empty(old_password)){ + dialog->old_password = old_password; + gtk_entry_set_text(GTK_ENTRY(dialog->PasswordEntry),old_password); + gtk_entry_set_text(GTK_ENTRY(dialog->RepeatPasswordEntry),old_password); + } + dictionary *dict = NULL; + yon_dictionary_add_or_create_if_exists_with_data(dict,"window",dialog); + yon_dictionary_add_or_create_if_exists_with_data(dict,"target",target); + g_signal_connect(G_OBJECT(dialog->AcceptButton),"clicked",G_CALLBACK(on_password_accept),dict); + g_signal_connect(G_OBJECT(dialog->EncryptionCombo),"changed",G_CALLBACK(on_password_encryption_changed),dialog); + return dialog; +} \ No newline at end of file diff --git a/source/libublsettingsui-gtk3.h b/source/libublsettingsui-gtk3.h index 02b7638..c018ade 100644 --- a/source/libublsettingsui-gtk3.h +++ b/source/libublsettingsui-gtk3.h @@ -45,6 +45,9 @@ /**Путь до файла окна выбора приложений утилит ubl-settings-**/ #define ui_glade_path_app_chooser "/com/ublinux/ui/libublsettingsui-gtk3-app-chooser.glade" +/**Путь до файла окна ввода пароля */ +#define ui_glade_path_password "/com/ublinux/ui/libublsettingsui-gtk3-password.glade" + /**Путь до основного баннера утилит ubl-settings-**/ #define ui_banner_path "/com/ublinux/images/libublsettingsui-gtk3-banner.png" @@ -456,6 +459,34 @@ int yon_app_chooser_window_select(yon_app_chooser_window *window,config_str sele config_str yon_app_chooser_window_run(yon_app_chooser_window *window, int *size); yon_app_chooser_window *yon_app_chooser_window_new(int multiple_choise); +typedef struct { + GtkWidget *Window; + GtkWidget *HeadLabel; + GtkWidget *StatusBox; + + GtkWidget *PasswordEntry; + GtkWidget *RepeatPasswordEntry; + GtkWidget *EncryptionCombo; + GtkWidget *NoEncriptionCheck; + GtkWidget *PasswordHashEntry; + GtkWidget *UserCancelButton; + GtkWidget *AcceptButton; + + GtkWidget *PasswordBox; + GtkWidget *HashBox; + + const char *old_password; +} yon_password_window; + +/// @brief +/// @param window окно с паролем +/// @param hashes массив с названиями типов хэша +/// @param get_hash_commands массив с командами получения хэша. Если команда == NULL, получение хэша пароля блокируется +/// @param size размер hashes и get_hash_commands. Оба массива должны быть одного размера +void yon_password_hash_list_set(yon_password_window *window, config_str hashes, config_str get_hash_commands, int size); + +yon_password_window *yon_password_open(GtkEntry *target); + #define VERSION_LABEL yon_char_unite(_("Version:")," ",!yon_char_is_empty(template_app_information.app_version)?template_app_information.app_version:"","\n",NULL) #define HELP_LABEL(rest) yon_char_unite(template_app_information.app_tech_name,_(" version:")," ", !yon_char_is_empty(template_app_information.app_version)?template_app_information.app_version:"","\n",\ template_app_information.app_title,"\n",_("Usage:"), " ",template_app_information.app_tech_name," ",_("[OPTIONS]"),"\n",\ @@ -575,6 +606,14 @@ yon_app_chooser_window *yon_app_chooser_window_new(int multiple_choise); #define _SERVICE_ACTIVE_STATUS_LABEL(target) yon_char_unite("\"",target,"\" ", yon_char_get_localised_from_lib(_("service is active")),NULL) #define _SERVICE_INACTIVE_STATUS_LABEL(target) yon_char_unite("\"",target,"\" ",yon_char_get_localised_from_lib(_("service is inactive")),NULL) + #define _PASSWORD_TITLE_LABEL yon_char_get_localised_from_lib("Password") + #define UNSAVED_LABEL yon_char_get_localised_from_lib("The changes were not saved to either the local or global configuration file.\nQuit without saving?") #define EXIT_LABEL yon_char_get_localised_from_lib("Exit") + + #define _PASSWORD_MISMATCH_LABEL yon_char_get_localised_from_lib("Passwords do not match") + #define _PASSWORD_RESTRICTED_SYMBOL_LABEL yon_char_get_localised_from_lib("Password contains restricted symbols") + #define _EMPTY_IMPORTANT_LABEL yon_char_get_localised_from_lib("Empty important field!") + #define _INCORRECT_HASH_LABEL yon_char_get_localised_from_lib("Invalid hash") + #define _ENCRYPTION_DEFAULT_LABEL yon_char_get_localised_from_lib("Default (None)") #endif \ No newline at end of file