/* 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 *subalign; /* Disposition des options */
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 */
GtkWidget *action_area; /* Zone de contrôle inférieure */
GtkWidget *button; /* Bouton de contrôle */
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 */
frame = qck_create_frame(_("Identity"), &subalign, 0, 0, 12, 0);
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
gtk_widget_show(hbox);
gtk_container_add(GTK_CONTAINER(subalign), hbox);
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 */
frame = qck_create_frame(_("Server to contact"), &subalign, 0, 0, 12, 0);
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
subvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_show(subvbox);
gtk_container_add(GTK_CONTAINER(subalign), subvbox);
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 */
action_area = gtk_dialog_get_action_area(GTK_DIALOG(result));
gtk_widget_show(action_area);
gtk_button_box_set_layout(GTK_BUTTON_BOX(action_area), GTK_BUTTONBOX_END);
button = qck_create_button(NULL, NULL, _("_Cancel"), NULL, NULL);
gtk_dialog_add_action_widget(GTK_DIALOG(result), button, GTK_RESPONSE_CANCEL);
button = qck_create_button(NULL, NULL, _("_Ok"), G_CALLBACK(save_storage_params), result);
gtk_dialog_add_action_widget(GTK_DIALOG(result), button, 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_SEGMENTS_DISPLAY:
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);
}