summaryrefslogtreecommitdiff
path: root/src/gui/dialogs/loading.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/dialogs/loading.c')
-rw-r--r--src/gui/dialogs/loading.c517
1 files changed, 517 insertions, 0 deletions
diff --git a/src/gui/dialogs/loading.c b/src/gui/dialogs/loading.c
new file mode 100644
index 0000000..62992fa
--- /dev/null
+++ b/src/gui/dialogs/loading.c
@@ -0,0 +1,517 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * loading.c - fenêtre de chargement de nouveaux contenus
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "loading.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <gdk/gdkkeysyms.h>
+
+
+#include <i18n.h>
+
+
+#include "../../analysis/binary.h"
+#include "../../core/processors.h"
+
+
+
+/* Colonnes de la liste des contenus chargés */
+typedef enum _LoadedContentColumn
+{
+ LCC_NAME, /* Désignation humaine */
+ LCC_CONTENT, /* Contenu chargé */
+ LCC_PROJECT, /* Cadre du chargement */
+ LCC_RECOGNIZED, /* Binaire brut ? */
+
+} LoadedContentColumn;
+
+
+/* Réagit à un changement de sélection des contenus chargés. */
+static void on_loaded_selection_changed(GtkTreeSelection *, GtkBuilder *);
+
+/* Réagit à un changement de mode de chargement. */
+static void on_load_mode_toggled(GtkToggleButton *, GtkBuilder *);
+
+/* Réagit à une pression de la touche "Echappe". */
+static gboolean on_key_press_event(GtkWidget *, GdkEventKey *, GtkBuilder *);
+
+/* Réagit à un clic sur la bouton "Annuler". */
+static void on_cancel_clicked(GtkButton *, GtkBuilder *);
+
+/* Réagit à un clic sur la bouton "Valider". */
+static void on_validate_clicked(GtkButton *, GtkBuilder *);
+
+/* Actualise les moyens affichés dans la boîte de chargement. */
+static void update_loading_dialog(GtkBuilder *);
+
+/* Actualise le décompte des différents types de binaires. */
+static void update_loading_dialog_counter(GtkBuilder *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = fenêtre principale de l'éditeur. *
+* outb = constructeur à détruire après usage. [OUT] *
+* *
+* Description : Construit une boîte de dialogue dédiée aux chargements. *
+* *
+* Retour : Adresse de la fenêtre mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *create_loading_dialog(GtkWindow *parent, GtkBuilder **outb)
+{
+ GtkWidget *result; /* Fenêtre à renvoyer */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeModelFilter *filter; /* Modèle filtrant */
+
+ builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/loading.ui");
+ *outb = builder;
+
+ result = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+
+ gtk_window_set_transient_for(GTK_WINDOW(result), parent);
+
+ filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filtered_store"));
+ gtk_tree_model_filter_set_visible_column(filter, LCC_RECOGNIZED);
+
+ /* Connexion des signaux */
+
+ gtk_builder_add_callback_symbols(builder,
+ "on_loaded_selection_changed", G_CALLBACK(on_loaded_selection_changed),
+ "on_load_mode_toggled", G_CALLBACK(on_load_mode_toggled),
+ "on_key_press_event", G_CALLBACK(on_key_press_event),
+ "on_cancel_clicked", G_CALLBACK(on_cancel_clicked),
+ "on_validate_clicked", G_CALLBACK(on_validate_clicked),
+ NULL);
+
+ gtk_builder_connect_signals(builder, builder);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : selection = gestionnaire de sélection impacté. *
+* builder = constructeur à utiliser. *
+* *
+* Description : Réagit à un changement de sélection des contenus chargés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_loaded_selection_changed(GtkTreeSelection *selection, GtkBuilder *builder)
+{
+ GtkTreeModel *model; /* Modèle de gestion */
+ GtkTreeIter iter; /* Point de sélection */
+ gboolean state; /* Présence d'une sélection */
+ GtkWidget *widget; /* Composant à actualiser */
+ const char *id; /* Identifiant d'architecture */
+ GLoadedContent *loaded; /* Contenu chargé */
+ GExeFormat *format; /* Format binaire reconnu */
+ GtkComboBox *combobox; /* Sélection d'architecture */
+
+ /* Mise à jour des accès */
+
+ state = gtk_tree_selection_get_selected(selection, &model, &iter);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "load_all"));
+ gtk_widget_set_sensitive(widget, state);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "load_one"));
+ gtk_widget_set_sensitive(widget, state);
+
+ on_load_mode_toggled(NULL, builder);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "ok_button"));
+ gtk_widget_set_sensitive(widget, state);
+
+ /* Mise à jour de l'architecture */
+
+ id = "none";
+
+ if (state)
+ {
+ gtk_tree_model_get(model, &iter, LCC_CONTENT, &loaded, -1);
+
+ if (G_IS_LOADED_BINARY(loaded))
+ {
+ format = g_loaded_binary_get_format(G_LOADED_BINARY(loaded));
+
+ id = g_exe_format_get_target_machine(format);
+
+ g_object_unref(G_OBJECT(format));
+
+ }
+
+ g_object_unref(G_OBJECT(loaded));
+
+ }
+
+ combobox = GTK_COMBO_BOX(gtk_builder_get_object(builder, "arch_sel"));
+
+ gtk_combo_box_set_active_id(combobox, id);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Réagit à un changement de mode de chargement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_load_mode_toggled(GtkToggleButton *button, GtkBuilder *builder)
+{
+ GtkToggleButton *all_button; /* Selection de mode */
+ gboolean state; /* Chargement fin ? */
+ GtkTreeView *treeview; /* Vue en arboresence */
+ GtkTreeSelection *selection; /* Sélection associée */
+ GtkWidget *widget; /* Composant à actualiser */
+
+ all_button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "load_all"));
+
+ state = !gtk_toggle_button_get_active(all_button);
+
+ if (state)
+ {
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+ selection = gtk_tree_view_get_selection(treeview);
+
+ state = gtk_tree_selection_get_selected(selection, NULL, NULL);
+
+ }
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "arch_label"));
+ gtk_widget_set_sensitive(widget, state);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "arch_sel"));
+ gtk_widget_set_sensitive(widget, state);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "config_and_run"));
+ gtk_widget_set_sensitive(widget, state);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "process_remaining"));
+ gtk_widget_set_sensitive(widget, state);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : widget = composant graphique visé par la procédure. *
+* event = informations liées à l'événement. *
+* builder = espace de référencement global. *
+* *
+* Description : Réagit à une pression de la touche "Echappe". *
+* *
+* Retour : TRUE pour indiquer une prise en compte, FALSE sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean on_key_press_event(GtkWidget *widget, GdkEventKey *event, GtkBuilder *builder)
+{
+ gboolean result; /* Bilan à retourner */
+
+ if (event->keyval == GDK_KEY_Escape)
+ {
+ on_cancel_clicked(NULL, builder);
+ result = TRUE;
+ }
+
+ else
+ result = FALSE;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Réagit à un clic sur la bouton "Annuler". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_cancel_clicked(GtkButton *button, GtkBuilder *builder)
+{
+ GtkWidget *window; /* Fenêtre à cacher */
+
+
+
+
+ /* Disparition de la fenêtre */
+
+ window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+
+ gtk_widget_hide(window);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Réagit à un clic sur la bouton "Valider". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_validate_clicked(GtkButton *button, GtkBuilder *builder)
+{
+ GtkTreeView *treeview; /* Vue en arboresence */
+ GtkTreeSelection *selection; /* Sélection associée */
+ GtkTreeModel *model; /* Modèle de gestion */
+ GtkTreeIter iter; /* Point de sélection */
+ GLoadedContent *loaded; /* Contenu chargé */
+ GStudyProject *project; /* projet associé */
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+ selection = gtk_tree_view_get_selection(treeview);
+
+ if (gtk_tree_selection_get_selected(selection, &model, &iter))
+ {
+ gtk_tree_model_get(model, &iter, LCC_CONTENT, &loaded, LCC_PROJECT, &project, -1);
+
+ g_signal_connect(loaded, "analyzed", G_CALLBACK(on_loaded_content_analyzed), project);
+
+ g_loaded_content_analyze(loaded, true, true);
+
+ g_object_unref(G_OBJECT(loaded));
+
+ }
+
+
+
+ /* Disparition de la fenêtre ? */
+
+ if (true)
+ on_cancel_clicked(NULL, builder);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : builder = constructeur à utiliser. *
+* *
+* Description : Actualise les moyens affichés dans la boîte de chargement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_loading_dialog(GtkBuilder *builder)
+{
+ GtkComboBoxText *combobox; /* Sélection d'architecture */
+ char **keys; /* Liste des architectures */
+ size_t count; /* Taille de cette liste */
+ size_t i; /* Boucle de parcours */
+ GArchProcessor *proc; /* Processeur à consulter */
+ char *desc; /* Description humaine */
+
+ /* Mise à jour de la liste des architectures */
+
+ combobox = GTK_COMBO_BOX_TEXT(gtk_builder_get_object(builder, "arch_sel"));
+
+ gtk_combo_box_text_remove_all(combobox);
+
+ gtk_combo_box_text_append(combobox, "none", _("None"));
+
+ keys = get_all_processor_keys(&count);
+
+ for (i = 0; i < count; i++)
+ {
+ proc = get_arch_processor_for_key(keys[i]);
+
+ desc = g_arch_processor_get_desc(proc);
+
+ gtk_combo_box_text_append(combobox, keys[i], desc);
+
+ g_object_unref(G_OBJECT(proc));
+ free(keys[i]);
+
+ }
+
+ if (keys != NULL)
+ free(keys);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : builder = constructeur à utiliser. *
+* *
+* Description : Actualise le décompte des différents types de binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_loading_dialog_counter(GtkBuilder *builder)
+{
+
+ unsigned int recognized_counter; /* Compteur de reconnus */
+ unsigned int total_counter; /* Compteur de binaires */
+ GtkTreeModel *model; /* Modèle de gestion */
+ GtkTreeIter iter; /* Point de sélection */
+ gboolean valid; /* Validité de l'itérateur */
+ gboolean recognized; /* Nature du contenu */
+ char *msg; /* Message à faire apparaître */
+ GtkLabel *label; /* Etiquette à mettre à jour */
+
+ recognized_counter = 0;
+ total_counter = 0;
+
+ model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store"));
+
+ for (valid = gtk_tree_model_get_iter_first(model, &iter);
+ valid;
+ valid = gtk_tree_model_iter_next(model, &iter))
+ {
+ gtk_tree_model_get(model, &iter, LCC_RECOGNIZED, &recognized, -1);
+
+ if (recognized)
+ recognized_counter++;
+
+ total_counter++;
+
+ }
+
+ asprintf(&msg, "(%u / %u)", total_counter - recognized_counter, total_counter);
+
+ label = GTK_LABEL(gtk_builder_get_object(builder, "hidden_counter"));
+ gtk_label_set_text(label, msg);
+
+ free(msg);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : builder = constructeur à utiliser. *
+* content = nouveau contenu chargé à intégrer. *
+* project = project impliqué dans l'opération. *
+* *
+* Description : Ajoute un binaire à la liste à charger. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void add_content_to_loading_dialog(GtkBuilder *builder, GLoadedContent *content, GStudyProject *project)
+{
+ GtkListStore *store; /* Modèle de gestion */
+ char *name; /* Désignation complète */
+ gboolean recognized; /* Nature du contenu */
+ GtkTreeIter iter; /* Point d'insertion */
+ GtkTreeView *treeview; /* Vue en arboresence */
+ GtkTreeSelection *selection; /* Gestionnaire de sélection */
+ GtkTreeModelFilter *filter; /* Modèle filtrant */
+ GtkTreeIter filtered_iter; /* Point d'insertion */
+ gboolean status; /* Bilan d'une conversion */
+
+ /* Mise à jour de l'interface (#0) */
+
+ update_loading_dialog(builder);
+
+ /* Inscription */
+
+ asprintf(&name, "%s (%s)",
+ g_loaded_content_describe(content, false),
+ g_loaded_content_get_format_name(content));
+
+ recognized = TRUE;
+
+ store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ LCC_NAME, name,
+ LCC_CONTENT, content,
+ LCC_PROJECT, project,
+ LCC_RECOGNIZED, recognized,
+ -1);
+
+ free(name);
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+ selection = gtk_tree_view_get_selection(treeview);
+
+ if (!gtk_tree_selection_get_selected(selection, NULL, NULL))
+ {
+ filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filtered_store"));
+
+ status = gtk_tree_model_filter_convert_child_iter_to_iter(filter, &filtered_iter, &iter);
+ assert(status);
+
+ if (status)
+ gtk_tree_selection_select_iter(selection, &filtered_iter);
+
+ }
+
+ /* Mise à jour de l'interface (#1) */
+
+ update_loading_dialog_counter(builder);
+
+}