/* Chrysalide - Outil d'analyse de fichiers binaires * storage.c - définition des modes d'enregistrement pour binaires * * Copyright (C) 2014 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA 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. * * OpenIDA 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 Foobar. If not, see . */ #include "storage.h" #include #include "../analysis/db/protocol.h" #include "../common/cpp.h" #include "../gtkext/easygtk.h" /* --------------------------- CORPS PRINCIPAL DU CONTENU --------------------------- */ /* Enumération des colonnes de la liste affichée */ typedef enum StorageColumnTypes { SCT_FEATURE_ID, /* Désignation interne */ SCT_FEATURE_NAME, /* Désignation humaine */ SCT_FEATURE_STORAGE, /* Type d'enregistrement */ SCT_COMBO_COLUMN, /* Fonctionnement du combo */ SCT_COUNT } StorageColumnTypes; /* Construit l'affichage en liste des enregistrements. */ static GtkWidget *build_features_list(void); /* Sauvegarde l'état des enregistrements et clôt la fenêtre. */ static void save_storage_params(GtkButton *, GObject *); /* ---------------------- NOM D'UTILISATEUR ASSOCIE AU BINAIRE ---------------------- */ /* Charge le nom de l'utilisateur associé au binaire. */ static void load_storage_username(GLoadedBinary *, GObject *); /* Sauvegarde le nom de l'utilisateur associé au binaire. */ static void save_storage_username(GLoadedBinary *, GObject *); /* ----------------------- SERVEUR DISTANT ASSOCIE AU BINAIRE ----------------------- */ /* Charge la définition du serveur distant associé au binaire. */ static void load_storage_remote_server(GLoadedBinary *, GObject *); /* Sauvegarde la définition du serveur distant du binaire. */ static void save_storage_remote_server(GLoadedBinary *, GObject *); /* Met à jour l'accès aux paramètres du serveur distant. */ static void on_server_usage_toggle(GtkToggleButton *, GObject *); /* ------------------------- TRAITEMENT DES FONCTIONNALITES ------------------------- */ /* Remplit la vue présentant les fonctionnalités à traiter. */ static void fill_storage_features(GtkTreeView *, GLoadedBinary *); /* Sauvegarde les statuts d'enregistrement des fonctionnalités. */ static void save_storage_features(GLoadedBinary *, GObject *); /* Met à jour un type d'enregistrement. */ static void storage_combo_edited_cb(GtkCellRendererText *, const gchar *, const gchar *, GtkListStore *); /* ---------------------------------------------------------------------------------- */ /* CORPS PRINCIPAL DU CONTENU */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : - * * * * Description : Construit l'affichage en liste des enregistrements. * * * * Retour : Composant graphique prêt à emploi. * * * * Remarques : - * * * ******************************************************************************/ static GtkWidget *build_features_list(void) { GtkListStore *store; GtkWidget *view; GtkCellRenderer *renderer; GtkListStore *combo_store; GtkTreeIter iter; store = gtk_list_store_new(SCT_COUNT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); /* Intitulé des fonctionnalités */ renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, _("Features"), renderer, "text", SCT_FEATURE_NAME, NULL); /* Type d'enregistrement associé */ renderer = gtk_cell_renderer_combo_new(); combo_store = gtk_list_store_new(1, G_TYPE_STRING); gtk_list_store_append(combo_store, &iter); gtk_list_store_set(combo_store, &iter, 0, _("Local storage"), -1); gtk_list_store_append(combo_store, &iter); gtk_list_store_set(combo_store, &iter, 0, _("Remote storage"), -1); gtk_list_store_append(combo_store, &iter); gtk_list_store_set(combo_store, &iter, 0, _("Local storage with remote access"), -1); g_object_set(G_OBJECT(renderer), "model", combo_store, "editable", TRUE, "has-entry", FALSE, NULL); g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(storage_combo_edited_cb), store); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, _("Storage"), renderer, "text", SCT_FEATURE_STORAGE, "text-column", SCT_COMBO_COLUMN, NULL); return view; } /****************************************************************************** * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * parent = fenêtre principale de l'éditeur. * * * * Description : Propose une définition des propriétés d'enregistrement. * * * * Retour : Adresse de la fenêtre mise en place. * * * * Remarques : - * * * ******************************************************************************/ GtkWidget *create_storage_dialog(GLoadedBinary *binary, GtkWindow *parent) { GtkWidget *result; /* Fenêtre à renvoyer */ GtkWidget *content; /* Zone principale de la boîte */ GtkWidget *vbox; /* Support à construire #1 */ GtkWidget *frame; /* Support avec encadrement */ GtkWidget *hbox; /* Support à construire #2 */ GtkWidget *label; /* Etiquette d'indication */ GtkWidget *entry; /* Zone de saisie de texte */ GtkWidget *checkbutton; /* Activation de la distance */ GtkWidget *subvbox; /* Support à construire #3 */ GtkWidget *scrolledwindow; /* Zone de défilement */ GtkWidget *treeview; /* Liste des fonctionnalités */ result = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(result), _("Storage")); gtk_widget_set_size_request(result, 400, 360); gtk_window_set_position(GTK_WINDOW(result), GTK_WIN_POS_CENTER); gtk_window_set_type_hint(GTK_WINDOW(result), GDK_WINDOW_TYPE_HINT_DIALOG); gtk_window_set_modal(GTK_WINDOW(result), TRUE); gtk_window_set_transient_for(GTK_WINDOW(result), parent); g_object_ref(G_OBJECT(binary)); g_object_set_data_full(G_OBJECT(result), "binary", binary, g_object_unref); content = gtk_dialog_get_content_area(GTK_DIALOG(result)); gtk_widget_show(content); vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); gtk_widget_show(vbox); gtk_box_pack_start(GTK_BOX(content), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); /* Définition de l'identité de l'utilisateur */ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); gtk_widget_show(hbox); frame = qck_create_frame(_("Identity"), hbox, 0, 0, 12, 0); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0); label = qck_create_label(NULL, NULL, _("Username: ")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); entry = qck_create_entry(G_OBJECT(result), "username", NULL); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); /* Définition du serveur distant */ subvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_widget_show(subvbox); frame = qck_create_frame(_("Server to contact"), subvbox, 0, 0, 12, 0); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0); checkbutton = qck_create_check_button(G_OBJECT(result), "use_remote", _("Use a remote server:"), G_CALLBACK(on_server_usage_toggle), result); gtk_widget_show(checkbutton); gtk_box_pack_start(GTK_BOX(subvbox), checkbutton, FALSE, FALSE, 0); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(subvbox), hbox, TRUE, TRUE, 0); label = qck_create_label(G_OBJECT(result), "host", _("Host: ")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); entry = qck_create_entry(G_OBJECT(result), "remote_host", NULL); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); label = qck_create_label(G_OBJECT(result), "port", _("Port:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); entry = qck_create_entry(G_OBJECT(result), "remote_port", NULL); gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, TRUE, 0); /* Affichage des propriétés */ scrolledwindow = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow); gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_SHADOW_IN); treeview = build_features_list(); g_object_set_data(G_OBJECT(result), "treeview", treeview); gtk_widget_show(treeview); gtk_container_add(GTK_CONTAINER(scrolledwindow), treeview); /* Zone de contrôle */ gtk_dialog_add_button(GTK_DIALOG(result), _("_Cancel"), GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(result), _("_Ok"), GTK_RESPONSE_OK); /* Chargement des données actuelles */ load_storage_username(binary, G_OBJECT(result)); load_storage_remote_server(binary, G_OBJECT(result)); fill_storage_features(GTK_TREE_VIEW(treeview), binary); return result; } /****************************************************************************** * * * Paramètres : button = bouton 'OK'. * * ref = espace de référencement principal. * * * * Description : Sauvegarde l'état des enregistrements et clôt la fenêtre. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void save_storage_params(GtkButton *button, GObject *ref) { GLoadedBinary *binary; /* Binaire en cours d'édition */ binary = G_LOADED_BINARY(g_object_get_data(ref, "binary")); save_storage_username(binary, ref); save_storage_remote_server(binary, ref); save_storage_features(binary, ref); } /* ---------------------------------------------------------------------------------- */ /* NOM D'UTILISATEUR ASSOCIE AU BINAIRE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * ref = espace de référencement global. * * * * Description : Charge le nom de l'utilisateur associé au binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void load_storage_username(GLoadedBinary *binary, GObject *ref) { GtkEntry *entry; /* Zone de saisie de texte */ entry = GTK_ENTRY(g_object_get_data(ref, "username")); gtk_entry_set_text(entry, g_loaded_binary_get_username(binary)); } /****************************************************************************** * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * ref = espace de référencement global. * * * * Description : Sauvegarde le nom de l'utilisateur associé au binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void save_storage_username(GLoadedBinary *binary, GObject *ref) { GtkEntry *entry; /* Zone de saisie de texte */ const gchar *text; /* Texte à récupérer */ entry = GTK_ENTRY(g_object_get_data(ref, "username")); text = gtk_entry_get_text(entry); g_loaded_binary_set_username(binary, text); } /* ---------------------------------------------------------------------------------- */ /* SERVEUR DISTANT ASSOCIE AU BINAIRE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * ref = espace de référencement global. * * * * Description : Charge la définition du serveur distant associé au binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void load_storage_remote_server(GLoadedBinary *binary, GObject *ref) { const char *host; /* Hôte à contacter */ unsigned short port; /* Port de connexion */ char port_str[sizeof(XSTR(USHRT_MAX)) + 1]; /* Version chaînée */ bool use_remote; /* Utilisation du serveur ? */ GtkEntry *entry; /* Zone de saisie de texte */ GtkToggleButton *checkbutton; /* Activation de la distance */ use_remote = g_loaded_binary_get_remote_server(binary, &host, &port); sprintf(port_str, "%hu", port); entry = GTK_ENTRY(g_object_get_data(ref, "remote_host")); gtk_entry_set_text(entry, host); entry = GTK_ENTRY(g_object_get_data(ref, "remote_port")); gtk_entry_set_text(entry, port_str); checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "use_remote")); gtk_toggle_button_set_active(checkbutton, !use_remote); gtk_toggle_button_set_active(checkbutton, use_remote); } /****************************************************************************** * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * ref = espace de référencement global. * * * * Description : Sauvegarde la définition du serveur distant du binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void save_storage_remote_server(GLoadedBinary *binary, GObject *ref) { GtkEntry *entry; /* Zone de saisie de texte */ const gchar *text; /* Texte à récupérer */ unsigned short port; /* Port de connexion */ GtkToggleButton *checkbutton; /* Activation de la distance */ entry = GTK_ENTRY(g_object_get_data(ref, "remote_port")); text = gtk_entry_get_text(entry); port = atoi(text); entry = GTK_ENTRY(g_object_get_data(ref, "remote_host")); text = gtk_entry_get_text(entry); checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "use_remote")); g_loaded_binary_set_remote_server(binary, text, port, gtk_toggle_button_get_active(checkbutton)); } /****************************************************************************** * * * Paramètres : button = oche dont le status vient de changer. * * ref = espace de référencement global. * * * * Description : Met à jour l'accès aux paramètres du serveur distant. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void on_server_usage_toggle(GtkToggleButton *button, GObject *ref) { gboolean state; /* Etat du bouton courant */ GtkWidget *widget; /* Element dont l'accès change */ state = gtk_toggle_button_get_active(button); widget = GTK_WIDGET(g_object_get_data(ref, "host")); if (widget != NULL) gtk_widget_set_sensitive(widget, state); widget = GTK_WIDGET(g_object_get_data(ref, "remote_host")); if (widget != NULL) gtk_widget_set_sensitive(widget, state); widget = GTK_WIDGET(g_object_get_data(ref, "port")); if (widget != NULL) gtk_widget_set_sensitive(widget, state); widget = GTK_WIDGET(g_object_get_data(ref, "remote_port")); if (widget != NULL) gtk_widget_set_sensitive(widget, state); } /* ---------------------------------------------------------------------------------- */ /* TRAITEMENT DES FONCTIONNALITES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : treeview = vue à compléter. * * binary = binaire à manipuler. * * * * Description : Remplit la vue présentant les fonctionnalités à traiter. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void fill_storage_features(GtkTreeView *treeview, GLoadedBinary *binary) { GtkListStore *store; /* Gestionnaire de liste */ DBFeatures i; /* Boucle de parcours */ DBStorage storage; /* Type d'enregistrement */ char *human_feature; /* Description humaine #1 */ char *human_value; /* Description humaine #2 */ GtkTreeIter iter; /* Point d'insertion */ store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); for (i = 0; i < DBF_COUNT; i++) { storage = g_loaded_binary_get_storage(binary, i); switch (i) { case DBF_COMMENTS: human_feature = _("Comments"); break; case DBF_DISPLAY_SWITCHERS: human_feature = _("Segments display"); break; case DBF_BOOKMARKS: human_feature = _("Bookmarks"); break; default: /* Pour GCC... */ break; } switch (storage) { case DBS_ALL_LOCAL: human_value = _("Local storage"); break; case DBS_ALL_REMOTE: human_value = _("Remote storage"); break; case DBS_LOCAL_AND_REMOTE: human_value = _("Local storage with remote access"); break; } gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, SCT_FEATURE_ID, i, SCT_FEATURE_NAME, human_feature, SCT_FEATURE_STORAGE, human_value, -1); } } /****************************************************************************** * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * ref = espace de référencement global. * * * * Description : Sauvegarde les statuts d'enregistrement des fonctionnalités. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void save_storage_features(GLoadedBinary *binary, GObject *ref) { GtkTreeView *treeview; /* Liste des fonctionnalités */ GtkTreeModel *store; /* Gestionnaire de liste */ GtkTreeIter iter; /* Point de lecture */ gboolean valid; /* Point courant valide ? */ DBFeatures feature; /* Fonctionnalité traitée */ char *human_value; /* Description humaine */ DBStorage storage; /* Type d'enregistrement */ treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview")); store = GTK_TREE_MODEL(gtk_tree_view_get_model(treeview)); for (valid = gtk_tree_model_get_iter_first(store, &iter); valid; valid = gtk_tree_model_iter_next(store, &iter)) { gtk_tree_model_get(store, &iter, SCT_FEATURE_ID, &feature, SCT_FEATURE_STORAGE, &human_value, -1); if (g_strcmp0(human_value, _("Remote storage")) == 0) storage = DBS_ALL_REMOTE; else if (g_strcmp0(human_value, _("Local storage with remote access")) == 0) storage = DBS_LOCAL_AND_REMOTE; else storage = DBS_ALL_LOCAL; g_loaded_binary_set_storage(binary, feature, storage); } } /****************************************************************************** * * * Paramètres : cell = cellule du tableau à mettre à jour. * * path = chemin d'accès à l'élément concerné. * * value = nouvelle valeur à prendre en compte. * * store = gestionnaire de liste sur lequel s'appuyer. * * * * Description : Met à jour un type d'enregistrement. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void storage_combo_edited_cb(GtkCellRendererText *cell, const gchar *path, const gchar *value, GtkListStore *store) { GtkTreePath *tpath; /* Chemin instancié */ GtkTreeIter iter; /* Point d'accès pour la maj */ tpath = gtk_tree_path_new_from_string(path); if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, tpath)) gtk_list_store_set(store, &iter, SCT_FEATURE_STORAGE, value, -1); gtk_tree_path_free(tpath); }