From a9c607a1be25b43a17ea55b21459a0433f4f3d5b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 24 Oct 2019 23:59:55 +0200 Subject: Provided a dialog box to manage snapshots. --- pixmaps/Makefile.am | 8 +- pixmaps/snapshot.png | Bin 0 -> 1214 bytes pixmaps/snapshot.xcf | Bin 0 -> 210520 bytes pixmaps/snapshot_current.png | Bin 0 -> 1525 bytes plugins/pychrysalide/analysis/db/item.c | 5 +- src/analysis/db/client.c | 73 +++ src/analysis/db/client.h | 9 + src/gui/core/Makefile.am | 4 +- src/gui/core/gresource.xml | 2 + src/gui/dialogs/Makefile.am | 2 + src/gui/dialogs/gresource.xml | 1 + src/gui/dialogs/snapshots.c | 873 ++++++++++++++++++++++++++++++++ src/gui/dialogs/snapshots.h | 40 ++ src/gui/dialogs/snapshots.ui | 427 ++++++++++++++++ src/gui/menus/binary.c | 57 ++- 15 files changed, 1495 insertions(+), 6 deletions(-) create mode 100644 pixmaps/snapshot.png create mode 100644 pixmaps/snapshot.xcf create mode 100644 pixmaps/snapshot_current.png create mode 100644 src/gui/dialogs/snapshots.c create mode 100644 src/gui/dialogs/snapshots.h create mode 100644 src/gui/dialogs/snapshots.ui diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am index 2844877..ecf6a68 100644 --- a/pixmaps/Makefile.am +++ b/pixmaps/Makefile.am @@ -45,6 +45,11 @@ MISC = \ chrysalide_text.png \ welcome.png +CORE = \ + snapshot.xcf \ + snapshot.png \ + snapshot_current.png + EXTRA_DIST = \ chrysalide.xcf \ openida.xcf \ @@ -55,7 +60,8 @@ EXTRA_DIST = \ $(TOOLBAR_BUTTONS) \ $(LIST_ICONS) \ $(ERROR_ICONS) \ - $(MISC) + $(MISC) \ + $(CORE) pix_DATA = $(APP_ICONS) $(REVISION_PIX) $(TOOLBAR_BUTTONS) $(LIST_ICONS) $(ERROR_ICONS) $(OTHER_ICONS) $(MISC) diff --git a/pixmaps/snapshot.png b/pixmaps/snapshot.png new file mode 100644 index 0000000..925ff3c Binary files /dev/null and b/pixmaps/snapshot.png differ diff --git a/pixmaps/snapshot.xcf b/pixmaps/snapshot.xcf new file mode 100644 index 0000000..0537bad Binary files /dev/null and b/pixmaps/snapshot.xcf differ diff --git a/pixmaps/snapshot_current.png b/pixmaps/snapshot_current.png new file mode 100644 index 0000000..e601b5b Binary files /dev/null and b/pixmaps/snapshot_current.png differ diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c index fe51752..1d09923 100644 --- a/plugins/pychrysalide/analysis/db/item.c +++ b/plugins/pychrysalide/analysis/db/item.c @@ -62,7 +62,10 @@ static int py_db_item_set_flags(PyObject *, PyObject *, void *); #define DB_ITEM_DOC \ "DbItem handles all kinds of updates applied to the disassebled code." \ "\n" \ - "These items are managed using a client/server model." + "These items are managed using a client/server model." \ + "\n" \ + "See the pychrysalide.analysis.db.items package for a full list of" \ + " existing items." diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 9558f85..b4e856f 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -1569,3 +1569,76 @@ bool g_hub_client_set_snapshot_desc(GHubClient *client, const snapshot_id_t *id, return result; } + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* id = identifiant d'instantané à traiter. * +* * +* Description : Restaure un ancien instantané. * +* * +* Retour : true si la commande a bien été envoyée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hub_client_restore_snapshot(GHubClient *client, const snapshot_id_t *id) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* id = identifiant d'instantané à traiter. * +* * +* Description : Crée un nouvel instantané à partir d'un autre. * +* * +* Retour : true si la commande a bien été envoyée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hub_client_create_snapshot(GHubClient *client, const snapshot_id_t *id) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* id = identifiant d'instantané à traiter. * +* rec = programme une suppression récursive. * +* * +* Description : Supprime un ancien instantané. * +* * +* Retour : true si la commande a bien été envoyée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hub_client_remove_snapshot(GHubClient *client, const snapshot_id_t *id, bool rec) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index 5ad4ed0..af47b5c 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -89,6 +89,15 @@ bool g_hub_client_set_snapshot_name(GHubClient *, const snapshot_id_t *, const c /* Définit la description d'un instantané donné. */ bool g_hub_client_set_snapshot_desc(GHubClient *, const snapshot_id_t *, const char *); +/* Restaure un ancien instantané. */ +bool g_hub_client_restore_snapshot(GHubClient *, const snapshot_id_t *); + +/* Crée un nouvel instantané à partir d'un autre. */ +bool g_hub_client_create_snapshot(GHubClient *, const snapshot_id_t *); + +/* Supprime un ancien instantané. */ +bool g_hub_client_remove_snapshot(GHubClient *, const snapshot_id_t *, bool); + #endif /* _ANALYSIS_DB_CLIENT_H */ diff --git a/src/gui/core/Makefile.am b/src/gui/core/Makefile.am index d23dc07..db9fd47 100644 --- a/src/gui/core/Makefile.am +++ b/src/gui/core/Makefile.am @@ -8,7 +8,9 @@ RES_FILES = \ ../../../pixmaps/collapse.png \ ../../../pixmaps/collapse_dark.png \ ../../../pixmaps/expand.png \ - ../../../pixmaps/expand_dark.png + ../../../pixmaps/expand_dark.png \ + ../../../pixmaps/snapshot.png \ + ../../../pixmaps/snapshot_current.png libguicore_la_SOURCES = \ core.h core.c \ diff --git a/src/gui/core/gresource.xml b/src/gui/core/gresource.xml index ad3688c..6f5cb94 100644 --- a/src/gui/core/gresource.xml +++ b/src/gui/core/gresource.xml @@ -6,5 +6,7 @@ ../../../pixmaps/collapse_dark.png ../../../pixmaps/expand.png ../../../pixmaps/expand_dark.png + ../../../pixmaps/snapshot.png + ../../../pixmaps/snapshot_current.png diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am index ae5180b..575defd 100644 --- a/src/gui/dialogs/Makefile.am +++ b/src/gui/dialogs/Makefile.am @@ -10,6 +10,7 @@ UI_FILES = \ preferences.ui \ prefs_fgraph.ui \ prefs_labels.ui \ + snapshots.ui \ storage.ui libguidialogs_la_SOURCES = \ @@ -25,6 +26,7 @@ libguidialogs_la_SOURCES = \ prefs_fgraph.h prefs_fgraph.c \ prefs_labels.h prefs_labels.c \ resources.h resources.c \ + snapshots.h snapshots.c \ storage.h storage.c libguidialogs_la_LDFLAGS = diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml index 1d18e39..bf81af4 100644 --- a/src/gui/dialogs/gresource.xml +++ b/src/gui/dialogs/gresource.xml @@ -7,6 +7,7 @@ preferences.ui prefs_fgraph.ui prefs_labels.ui + snapshots.ui storage.ui diff --git a/src/gui/dialogs/snapshots.c b/src/gui/dialogs/snapshots.c new file mode 100644 index 0000000..1fcea67 --- /dev/null +++ b/src/gui/dialogs/snapshots.c @@ -0,0 +1,873 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * snapshots.c - gestion des instantanés de base de données + * + * Copyright (C) 2019 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 . + */ + + +#include "snapshots.h" + + +#include +#include +#include + + +#include + + + +/* Colonnes de l'arborescence d'instantanés */ +typedef enum _SnapshotTreeColumn +{ + STC_ICON, /* Image de représentation */ + STC_TITLE, /* Meilleure représentation */ + + STC_ID, /* Identifiant de l'instantané */ + STC_TIMESTAMP, /* Valeur brute d'horodatage */ + STC_NAME, /* Désignation de l'instantané */ + STC_DESC, /* Description de l'instantané */ + +} SnapshotTreeColumn; + + +/* Réagit à une fermeture de la boîte de dialogue. */ +static void on_dialog_destroy(GtkWidget *, GtkBuilder *); + +/* Réagit à un changement dans le choix du serveur. */ +static void on_server_selection_changed(GtkComboBox *, GtkBuilder *); + +/* Recherche un élément d'arborescence selon un identifiant. */ +static bool find_suitable_parent(GtkTreeModel *, GtkTreeIter *, const char *, GtkTreeIter *); + +/* Met à jour l'affichage avec une nouvelle liste d'instantanés. */ +static void on_snapshots_updated(GHubClient *, GtkBuilder *); + +/* Réinitialise la zone d'affichage des informations. */ +static void reset_information_area(GtkBuilder *); + +/* Active ou non l'accès à la zone d'affichage des informations. */ +static void update_information_area_access(GtkBuilder *, bool); + +/* Active ou non l'accès à la zone de contrôle des instantanés. */ +static void update_control_area_access(GtkBuilder *, bool, bool, bool); + +/* Met à jour l'affichage des informations d'un instantané. */ +static void on_tree_selection_changed(GtkTreeSelection *, GtkBuilder *); + +/* Restaure sur demande un nouvel instantané. */ +static void restore_old_snapshot(GtkToolButton *, GtkBuilder *); + +/* Crée sur demande un nouvel instantané. */ +static void create_new_snapshot(GtkToolButton *, GtkBuilder *); + +/* Supprime sur demande un instantané. */ +static void remove_old_snapshot(GtkToolButton *, GtkBuilder *); + +/* Supprime sur demande un instantané et ses successeurs. */ +static void delete_old_snapshot(GtkToolButton *, GtkBuilder *); + +/* Applique à un instantané ses nouvelles informations. */ +static void apply_new_snapshot_info(GtkButton *, GtkBuilder *); + +/* Ferme la boîte de dialogue. */ +static void close_dialog_box(GtkButton *, GtkBuilder *); + + + +/****************************************************************************** +* * +* Paramètres : binary = binaire chargé en mémoire à traiter. * +* parent = fenêtre principale de l'éditeur. * +* outb = constructeur à détruire après usage. [OUT] * +* * +* Description : Affiche un gestionnaire d'instantanés de base de données. * +* * +* Retour : Adresse de la fenêtre mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *create_snapshots_dialog(GLoadedBinary *binary, GtkWindow *parent, GtkBuilder **outb) +{ + GtkWidget *result; /* Fenêtre à renvoyer */ + GtkBuilder *builder; /* Constructeur utilisé */ + GFile *file; /* Accès à une image interne */ + GIcon *icon; /* Image de représentation */ + GtkComboBox *combo; /* Liste de serveurs */ + + builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/snapshots.ui"); + *outb = builder; + + result = GTK_WIDGET(gtk_builder_get_object(builder, "window")); + + gtk_window_set_transient_for(GTK_WINDOW(result), parent); + + g_object_ref(G_OBJECT(result)); + g_object_set_data_full(G_OBJECT(builder), "window", result, g_object_unref); + + g_object_ref(G_OBJECT(binary)); + g_object_set_data_full(G_OBJECT(builder), "binary", binary, g_object_unref); + + file = g_file_new_for_uri("resource:///org/chrysalide/gui/core/images/snapshot.png"); + icon = g_file_icon_new(file); + g_object_set_data_full(G_OBJECT(builder), "icon", icon, g_object_unref); + + file = g_file_new_for_uri("resource:///org/chrysalide/gui/core/images/snapshot_current.png"); + icon = g_file_icon_new(file); + g_object_set_data_full(G_OBJECT(builder), "current_icon", icon, g_object_unref); + + /* Connexion des signaux */ + + gtk_builder_add_callback_symbols(builder, + "on_dialog_destroy", G_CALLBACK(on_dialog_destroy), + "on_server_selection_changed", G_CALLBACK(on_server_selection_changed), + "on_tree_selection_changed", G_CALLBACK(on_tree_selection_changed), + "restore_old_snapshot", G_CALLBACK(restore_old_snapshot), + "create_new_snapshot", G_CALLBACK(create_new_snapshot), + "remove_old_snapshot", G_CALLBACK(remove_old_snapshot), + "delete_old_snapshot", G_CALLBACK(delete_old_snapshot), + "apply_new_snapshot_info", G_CALLBACK(apply_new_snapshot_info), + "close_dialog_box", G_CALLBACK(close_dialog_box), + NULL); + + gtk_builder_connect_signals(builder, builder); + + /* Mise à jour de l'interface */ + + reset_information_area(builder); + update_control_area_access(builder, false, false, false); + + combo = GTK_COMBO_BOX(gtk_builder_get_object(builder, "servers")); + + gtk_combo_box_set_active(combo, 0); + + return result; + +} + +/****************************************************************************** +* * +* Paramètres : dialog = fenêtre en cours de suppression. * +* builder = espace de référencement global. * +* * +* Description : Réagit à une fermeture de la boîte de dialogue. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_dialog_destroy(GtkWidget *dialog, GtkBuilder *builder) +{ + GHubClient *client; /* Cible des interactions */ + + /* Déconnexion de l'ancien */ + + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + if (client != NULL) + g_signal_handlers_disconnect_by_func(client, on_snapshots_updated, builder); + +} + + +/****************************************************************************** +* * +* Paramètres : combo = liste de sélection à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Réagit à un changement dans le choix du serveur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_server_selection_changed(GtkComboBox *combo, GtkBuilder *builder) +{ + GHubClient *client; /* Cible des interactions */ + gint active; /* Indice du serveur retenu */ + GLoadedBinary *binary; /* Binaire en cours d'étude */ + GtkTreeStore *store; /* Modèle de gestion */ + + /* Déconnexion de l'ancien */ + + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + if (client != NULL) + g_signal_handlers_disconnect_by_func(client, on_snapshots_updated, builder); + + /* Connexion nouvelle */ + + active = gtk_combo_box_get_active(combo); + + binary = G_LOADED_BINARY(g_object_get_data(G_OBJECT(builder), "binary")); + + client = g_loaded_binary_get_client(binary, active == 0); + + if (client == NULL) + { + g_object_set_data(G_OBJECT(builder), "client", NULL); + + store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); + gtk_tree_store_clear(store); + + reset_information_area(builder); + update_control_area_access(builder, false, false, false); + + } + + else + { + g_object_ref(G_OBJECT(client)); + g_object_set_data_full(G_OBJECT(builder), "client", client, g_object_unref); + + g_signal_connect(client, "snapshots-updated", G_CALLBACK(on_snapshots_updated), builder); + + on_snapshots_updated(client, builder); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : model = modèle de gestion de données à consulter. * +* iter = point de départ des recherches. * +* id = identifiant de l'instantané recherché. * +* found = emplacement de l'éventuel noeud trouvé. [OUT] * +* * +* Description : Recherche un élément d'arborescence selon un identifiant. * +* * +* Retour : true pour indiquer une recherche fructueuse, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool find_suitable_parent(GtkTreeModel *model, GtkTreeIter *iter, const char *id, GtkTreeIter *found) +{ + bool result; /* Bilan à retourner */ + gchar *value; /* Identifiant courant */ + gint count; /* Quantité de fils présents */ + gint i; /* Boucle de parcours */ + GtkTreeIter child; /* Localisation d'un fils */ +#ifndef NDEBUG + gboolean status; /* Bilan d'une consultation */ +#endif + + gtk_tree_model_get(model, iter, STC_ID, &value, -1); + + result = (strcmp(value, id) == 0); + + g_free(value); + + if (result) + *found = *iter; + + else + { + count = gtk_tree_model_iter_n_children(model, iter); + + for (i = 0; i < count && !result; i++) + { +#ifndef NDEBUG + status = gtk_tree_model_iter_nth_child(model, &child, iter, i); + assert(status); +#else + gtk_tree_model_iter_nth_child(model, &child, iter, i); +#endif + + result = find_suitable_parent(model, &child, id, found); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client connecté à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Met à jour l'affichage avec une nouvelle liste d'instantanés.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_snapshots_updated(GHubClient *client, GtkBuilder *builder) +{ + GtkTreeStore *store; /* Modèle de gestion */ + snapshot_info_t *info; /* Liste d'instantanés présents*/ + size_t count; /* Taille de cette liste */ + bool status; /* Validité de cet identifiant */ + size_t i; /* Boucle de parcours */ + char *id; /* Identifiant du parent */ + GtkTreeIter iter; /* Point d'insertion */ +#ifndef NDEBUG + gboolean check; /* Vérification par principe */ +#endif + GtkTreeIter parent; /* Parent du point d'insertion */ + GIcon *icon; /* Image de représentation */ + char *name; /* Désignation d'instantané */ + snapshot_id_t current; /* Instantané courant */ + GtkTreeView *treeview; /* Arborescence graphique */ + const char *raw; /* Identifiant brut */ + GtkTreeSelection *selection; /* Gestionnaire de sélection */ + + store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); + + gtk_tree_store_clear(store); + + status = g_hub_client_get_snapshots(client, &info, &count); + + if (!status) + { + reset_information_area(builder); + update_control_area_access(builder, false, false, false); + } + + else + { + /* Remplissage */ + + for (i = 0; i < count; i++) + { + id = snapshot_id_as_string(get_snapshot_info_parent_id(&info[i])); + + if (strcmp(id, NO_SNAPSHOT_ROOT) == 0) + gtk_tree_store_append(store, &iter, NULL); + + else + { +#ifndef NDEBUG + check = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); + assert(check); +#else + gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); +#endif + + status = find_suitable_parent(GTK_TREE_MODEL(store), &iter, id, &parent); + assert(status); + + gtk_tree_store_append(store, &iter, &parent); + + } + + id = snapshot_id_as_string(get_snapshot_info_id(&info[i])); + + icon = G_ICON(g_object_get_data(G_OBJECT(builder), "icon")); + + name = get_snapshot_info_name(&info[i]); + + gtk_tree_store_set(store, &iter, + STC_ICON, icon, + STC_TITLE, name != NULL ? name : id, + STC_ID, id, + STC_TIMESTAMP, get_snapshot_info_created(&info[i]), + STC_NAME, name, + STC_DESC, get_snapshot_info_desc(&info[i]), + -1); + + exit_snapshot_info(&info[i]); + + } + + free(info); + + /* Ajout de l'instantané courant */ + + status = g_hub_client_get_current_snapshot(client, ¤t); + + if (status) + { + id = snapshot_id_as_string(¤t); + +#ifndef NDEBUG + check = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); + assert(check); +#else + gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); +#endif + + status = find_suitable_parent(GTK_TREE_MODEL(store), &iter, id, &parent); + + if (status) + { + gtk_tree_store_append(store, &iter, &parent); + + icon = G_ICON(g_object_get_data(G_OBJECT(builder), "current_icon")); + + gtk_tree_store_set(store, &iter, + STC_ICON, icon, + STC_TITLE, _("Current"), + -1); + + } + + } + + /* Plein affichage */ + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + gtk_tree_view_expand_all(treeview); + + /* Remise en place de la dernière sélection */ + + raw = g_object_get_data(G_OBJECT(builder), "selected"); + + if (raw != NULL) + { +#ifndef NDEBUG + check = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); + assert(check); +#else + gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); +#endif + + status = find_suitable_parent(GTK_TREE_MODEL(store), &iter, raw, &iter); + + if (status) + { + selection = gtk_tree_view_get_selection(treeview); + + gtk_tree_selection_select_iter(selection, &iter); + + } + + else + { + reset_information_area(builder); + + update_control_area_access(builder, false, false, false); + + g_object_set_data(G_OBJECT(builder), "selected", NULL); + + } + + } + + } + +} + + +/****************************************************************************** +* * +* Paramètres : builder = espace de référencement global. * +* * +* Description : Réinitialise la zone d'affichage des informations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_information_area(GtkBuilder *builder) +{ + GtkLabel *label; /* Etiquette à faire évoluer */ + GtkEntry *entry; /* Zone de saisie à actualiser */ + + label = GTK_LABEL(gtk_builder_get_object(builder, "identifier")); + gtk_label_set_text(label, "-"); + + label = GTK_LABEL(gtk_builder_get_object(builder, "timestamp")); + gtk_label_set_text(label, "-"); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "name")); + gtk_entry_set_text(entry, ""); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "description")); + gtk_entry_set_text(entry, ""); + + update_information_area_access(builder, false); + +} + + +/****************************************************************************** +* * +* Paramètres : builder = espace de référencement global. * +* state = état des possibilités d'interactions à appliquer. * +* * +* Description : Active ou non l'accès à la zone d'affichage des informations.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_information_area_access(GtkBuilder *builder, bool state) +{ + GtkWidget *widget; /* Composant à traiter */ + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "identifier")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "timestamp")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "name")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "description")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "apply")); + gtk_widget_set_sensitive(widget, state); + +} + + +/****************************************************************************** +* * +* Paramètres : builder = espace de référencement global. * +* restore = accès à la restauration d'un instantané. * +* create = accès à la création d'un nouvel instantané. * +* delete = accès à la suppression d'instantanés. * +* * +* Description : Active ou non l'accès à la zone de contrôle des instantanés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_control_area_access(GtkBuilder *builder, bool restore, bool create, bool delete) +{ + GtkWidget *widget; /* Composant à traiter */ + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "restore")); + gtk_widget_set_sensitive(widget, restore); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "create")); + gtk_widget_set_sensitive(widget, create); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "remove")); + gtk_widget_set_sensitive(widget, delete); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "delete")); + gtk_widget_set_sensitive(widget, delete); + +} + + +/****************************************************************************** +* * +* Paramètres : selection = nouvelle sélection à appliquer. * +* builder = espace de référencement global. * +* * +* Description : Met à jour l'affichage des informations d'un instantané. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_tree_selection_changed(GtkTreeSelection *selection, GtkBuilder *builder) +{ + GtkTreeModel *model; /* Modèle de gestion */ + GtkTreeIter iter; /* Point de sélection */ + gchar *id; /* Identifiant d'instantané */ + guint64 timestamp; /* Horodatage associé */ + gchar *name; /* Eventuelle désignation */ + gchar *desc; /* Eventuelle description */ + GtkLabel *label; /* Etiquette à faire évoluer */ + char buf[27]; /* Tampon pour la date */ + GtkEntry *entry; /* Zone de saisie à actualiser */ + gboolean is_not_root; /* Particularité de sélection */ + + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, + STC_ID, &id, + STC_TIMESTAMP, ×tamp, + STC_NAME, &name, + STC_DESC, &desc, + -1); + + if (id == NULL) + { + assert(name == NULL); + assert(desc == NULL); + + reset_information_area(builder); + + update_control_area_access(builder, false, true, false); + + g_object_set_data(G_OBJECT(builder), "selected", NULL); + + } + + else + { + label = GTK_LABEL(gtk_builder_get_object(builder, "identifier")); + gtk_label_set_text(label, id); + + ctime_r((time_t []) { timestamp / 1000000 }, buf); + buf[strlen(buf) - 1] = 0; + + label = GTK_LABEL(gtk_builder_get_object(builder, "timestamp")); + gtk_label_set_text(label, buf); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "name")); + gtk_entry_set_text(entry, name != NULL ? name : ""); + + if (name != NULL) + g_free(name); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "description")); + gtk_entry_set_text(entry, desc != NULL ? desc : ""); + + if (desc != NULL) + g_free(desc); + + update_information_area_access(builder, true); + + is_not_root = gtk_tree_model_iter_parent(model, (GtkTreeIter []) { { 0 } }, &iter); + + update_control_area_access(builder, true, false, is_not_root); + + g_object_set_data_full(G_OBJECT(builder), "selected", id, g_free); + + } + + } + +} + + +/****************************************************************************** +* * +* Paramètres : button = composant GTK à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Restaure sur demande un nouvel instantané. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void restore_old_snapshot(GtkToolButton *button, GtkBuilder *builder) +{ + const char *raw; /* Identifiant brut */ + snapshot_id_t id; /* Identifiant utilisable */ + bool status; /* Bilan d'une conversion */ + GHubClient *client; /* Cible des interactions */ + + raw = g_object_get_data(G_OBJECT(builder), "selected"); + + status = init_snapshot_id_from_text(&id, raw); + + if (status) + { + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + g_hub_client_restore_snapshot(client, &id); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : button = composant GTK à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Crée sur demande un nouvel instantané. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void create_new_snapshot(GtkToolButton *button, GtkBuilder *builder) +{ + const char *raw; /* Identifiant brut */ + snapshot_id_t id; /* Identifiant utilisable */ + bool status; /* Bilan d'une conversion */ + GHubClient *client; /* Cible des interactions */ + + raw = g_object_get_data(G_OBJECT(builder), "selected"); + + status = init_snapshot_id_from_text(&id, raw); + + if (status) + { + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + g_hub_client_create_snapshot(client, &id); + + } + +} + +/****************************************************************************** +* * +* Paramètres : button = composant GTK à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Supprime sur demande un instantané. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void remove_old_snapshot(GtkToolButton *button, GtkBuilder *builder) +{ + const char *raw; /* Identifiant brut */ + snapshot_id_t id; /* Identifiant utilisable */ + bool status; /* Bilan d'une conversion */ + GHubClient *client; /* Cible des interactions */ + + raw = g_object_get_data(G_OBJECT(builder), "selected"); + + status = init_snapshot_id_from_text(&id, raw); + + if (status) + { + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + g_hub_client_remove_snapshot(client, &id, false); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : button = composant GTK à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Supprime sur demande un instantané et ses successeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void delete_old_snapshot(GtkToolButton *button, GtkBuilder *builder) +{ + const char *raw; /* Identifiant brut */ + snapshot_id_t id; /* Identifiant utilisable */ + bool status; /* Bilan d'une conversion */ + GHubClient *client; /* Cible des interactions */ + + raw = g_object_get_data(G_OBJECT(builder), "selected"); + + status = init_snapshot_id_from_text(&id, raw); + + if (status) + { + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + g_hub_client_remove_snapshot(client, &id, true); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : button = composant GTK à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Applique à un instantané ses nouvelles informations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void apply_new_snapshot_info(GtkButton *button, GtkBuilder *builder) +{ + const char *raw; /* Identifiant brut */ + snapshot_id_t id; /* Identifiant utilisable */ + bool status; /* Bilan d'une conversion */ + GHubClient *client; /* Cible des interactions */ + GtkEntry *entry; /* Zone de saisie à actualiser */ + + raw = g_object_get_data(G_OBJECT(builder), "selected"); + + status = init_snapshot_id_from_text(&id, raw); + + if (status) + { + client = G_HUB_CLIENT(g_object_get_data(G_OBJECT(builder), "client")); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "name")); + g_hub_client_set_snapshot_name(client, &id, gtk_entry_get_text(entry)); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "description")); + g_hub_client_set_snapshot_desc(client, &id, gtk_entry_get_text(entry)); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : button = composant GTK à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Ferme la boîte de dialogue. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void close_dialog_box(GtkButton *button, GtkBuilder *builder) +{ + GtkDialog *dialog; /* Fenêtre à manipuler */ + + dialog = GTK_DIALOG(gtk_builder_get_object(builder, "window")); + + gtk_dialog_response(dialog, GTK_RESPONSE_CLOSE); + +} diff --git a/src/gui/dialogs/snapshots.h b/src/gui/dialogs/snapshots.h new file mode 100644 index 0000000..05f3ac3 --- /dev/null +++ b/src/gui/dialogs/snapshots.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * snapshots.h - prototypes pour la gestion des instantanés de base de données + * + * Copyright (C) 2019 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 . + */ + + +#ifndef _GUI_DIALOGS_SNAPSHOTS_H +#define _GUI_DIALOGS_SNAPSHOTS_H + + +#include + + +#include "../../analysis/binary.h" + + + +/* Affiche un gestionnaire d'instantanés de base de données. */ +GtkWidget *create_snapshots_dialog(GLoadedBinary *, GtkWindow *, GtkBuilder **); + + + +#endif /* _GUI_DIALOGS_SNAPSHOTS_H */ diff --git a/src/gui/dialogs/snapshots.ui b/src/gui/dialogs/snapshots.ui new file mode 100644 index 0000000..7c6d472 --- /dev/null +++ b/src/gui/dialogs/snapshots.ui @@ -0,0 +1,427 @@ + + + + + + True + False + gtk-add + + + True + False + gtk-delete + 3 + + + True + False + gtk-remove + + + True + False + gtk-media-play + 3 + + + + + + + + + + + + + + + + + + + 530 + False + Snapshot management + True + dialog + True + + + + False + 8 + 8 + 8 + 8 + vertical + 2 + + + False + 8 + end + + + gtk-apply + True + True + True + True + + + + True + True + 0 + + + + + gtk-close + True + True + True + True + + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + vertical + 8 + + + True + False + 8 + + + True + False + Server: + + + False + True + 0 + + + + + True + False + + Internal + + + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + + + True + True + in + + + True + True + store + False + + + + + + + + column + + + + 0 + + + + + + 1 + + + + + + + + + True + True + 0 + + + + + True + False + vertical + False + + + True + False + Restore an old snapshot + image-restore + + + + False + False + + + + + True + False + + + False + True + + + + + True + False + Create a new snapshot + image-add + + + + False + True + + + + + True + False + Remove a snapshot from the snapshot tree + image-remove + + + + False + True + + + + + True + False + Delete a snapshot with all its children + image-delete + + + + False + True + + + + + False + True + 1 + + + + + True + True + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + œ + True + False + 8 + 8 + True + + + True + False + Identifier: + 1 + + + 0 + 0 + + + + + True + False + Timestamp: + 1 + + + 0 + 1 + + + + + True + False + Name: + 1 + + + 0 + 2 + + + + + True + False + Description: + 1 + + + 0 + 3 + + + + + True + False + True + - + True + 0 + + + 1 + 0 + + + + + True + False + True + - + True + 0 + + + 1 + 1 + + + + + True + True + True + No name + GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_NONE + + + 1 + 2 + + + + + True + True + True + No description + GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_NONE + + + 1 + 3 + + + + + + + + + True + False + Description + + + + + False + True + 2 + + + + + True + True + 1 + + + + + + + + + diff --git a/src/gui/menus/binary.c b/src/gui/menus/binary.c index cb131d7..aeaf6f6 100644 --- a/src/gui/menus/binary.c +++ b/src/gui/menus/binary.c @@ -34,6 +34,7 @@ #include "../dialogs/export_disass.h" #include "../dialogs/export_graph.h" #include "../dialogs/gotox.h" +#include "../dialogs/snapshots.h" #include "../dialogs/storage.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/gtkdisplaypanel.h" @@ -47,9 +48,12 @@ static void mcb_binary_entry_points(GtkMenuItem *, GMenuBar *); /* Réagit au menu "Binaire -> Attacher un débogueur". */ static void mcb_binary_attach_debugger(GtkMenuItem *, GMenuBar *); -/* Réagit au menu "Binaire -> Enregistrements...". */ +/* Réagit au menu "Binaire -> Enregistrements". */ static void mcb_binary_storage(GtkMenuItem *, GMenuBar *); +/* Réagit au menu "Binaire -> Instantanés". */ +static void mcb_binary_snapshots(GtkMenuItem *, GMenuBar *); + /* Réagit au menu "Binaire -> Exporter -> Désassemblage". */ static void mcb_binary_export_disass(GtkMenuItem *, gpointer); @@ -96,13 +100,21 @@ GtkWidget *build_menu_binary(GObject *ref, GMenuBar *bar) G_CALLBACK(mcb_binary_attach_debugger), bar); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + /* Séparation */ + submenuitem = qck_create_menu_separator(); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - submenuitem = qck_create_menu_item(ref, "mnu_binary_storage", _("Storage..."), + /* Bases de données */ + + submenuitem = qck_create_menu_item(ref, "mnu_binary_storage", _("Storage"), G_CALLBACK(mcb_binary_storage), bar); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + submenuitem = qck_create_menu_item(ref, "mnu_binary_snapshots", _("Snapshots"), + G_CALLBACK(mcb_binary_snapshots), bar); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + /* Séparation */ submenuitem = qck_create_menu_separator(); @@ -271,7 +283,7 @@ static void mcb_binary_attach_debugger(GtkMenuItem *menuitem, GMenuBar *bar) * Paramètres : menuitem = élément de menu sélectionné. * * bar = barre de menu parente. * * * -* Description : Réagit au menu "Binaire -> Enregistrements...". * +* Description : Réagit au menu "Binaire -> Enregistrements". * * * * Retour : - * * * @@ -312,6 +324,45 @@ static void mcb_binary_storage(GtkMenuItem *menuitem, GMenuBar *bar) /****************************************************************************** * * * Paramètres : menuitem = élément de menu sélectionné. * +* bar = barre de menu parente. * +* * +* Description : Réagit au menu "Binaire -> Instantanés". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_binary_snapshots(GtkMenuItem *menuitem, GMenuBar *bar) +{ + GLoadedBinary *binary; /* Edition courante */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkWindow *editor; /* Fenêtre graphique principale*/ + GtkWidget *dialog; /* Boîte de dialogue à montrer */ + + binary = G_LOADED_BINARY(get_current_content()); + + editor = get_editor_window(); + + dialog = create_snapshots_dialog(binary, editor, &builder); + + gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); + + g_object_unref(G_OBJECT(builder)); + + g_object_unref(G_OBJECT(editor)); + + g_object_unref(G_OBJECT(binary)); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * * unused = adresse non utilisée ici. * * * * Description : Réagit au menu "Binaire -> Exporter -> Désassemblage". * -- cgit v0.11.2-87-g4458