From c3aba0893c29cc098c029306fd7a4c8c1fa2eee2 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 28 Oct 2012 15:59:12 +0000 Subject: Updated the code of the old panel and displayed found strings again. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@276 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 33 ++++ src/arch/archbase.c | 9 +- src/format/dex/dex.c | 8 + src/format/dex/pool.c | 38 +++++ src/format/dex/pool.h | 3 + src/format/symbol.c | 2 +- src/gtkext/easygtk.c | 38 +++++ src/gtkext/easygtk.h | 3 + src/gui/panels/Makefile.am | 1 + src/gui/panels/panel-int.h | 2 +- src/gui/panels/panel.c | 206 ++++++++++++++++++------ src/gui/panels/strings.c | 392 +++++++++++++++++++++++++++++++++++++++++++++ src/gui/panels/strings.h | 65 ++++++++ src/gui/panels/symbols.c | 6 +- src/gui/panels/symbols.h | 2 +- 15 files changed, 753 insertions(+), 55 deletions(-) create mode 100644 src/gui/panels/strings.c create mode 100644 src/gui/panels/strings.h diff --git a/ChangeLog b/ChangeLog index f4f1c1d..af9d3e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +12-10-28 Cyrille Bagard + + * src/arch/archbase.c: + Remove GCC warnings about print format. + + * src/format/dex/dex.c: + * src/format/dex/pool.c: + * src/format/dex/pool.h: + Register all strings found in the Dex pool. + + * src/format/symbol.c: + Remove a GCC warning by fixing a typo. + + * src/gtkext/easygtk.c: + * src/gtkext/easygtk.h: + Provide a function to create menus with image. + + * src/gui/panels/Makefile.am: + Add the strings.[ch] files to libguipanels_la_SOURCES. + + * src/gui/panels/panel.c: + * src/gui/panels/panel-int.h: + Rewrite some parts of the code to improve panel docking. + + * src/gui/panels/strings.c: + * src/gui/panels/strings.h: + Move entries: update the code of the old panel and display found + strings again. + + * src/gui/panels/symbols.c: + * src/gui/panels/symbols.h: + Typo and clean the code. + 12-10-22 Cyrille Bagard * src/panel/log.c: diff --git a/src/arch/archbase.c b/src/arch/archbase.c index 61e2396..6241164 100644 --- a/src/arch/archbase.c +++ b/src/arch/archbase.c @@ -24,6 +24,7 @@ #include "archbase.h" +#include #include @@ -49,22 +50,22 @@ size_t vmpa_to_string(vmpa_t addr, MemoryDataSize msize, char buffer[VMPA_MAX_SI switch (msize) { case MDS_8_BITS: - snprintf(buffer, VMPA_MAX_SIZE,"0x%02llx", addr); + snprintf(buffer, VMPA_MAX_SIZE,"0x%02" PRIx64, addr); result = 4; break; case MDS_16_BITS: - snprintf(buffer, VMPA_MAX_SIZE, "0x%04llx", addr); + snprintf(buffer, VMPA_MAX_SIZE, "0x%04" PRIx64, addr); result = 6; break; case MDS_32_BITS: - snprintf(buffer, VMPA_MAX_SIZE, "0x%08llx", addr); + snprintf(buffer, VMPA_MAX_SIZE, "0x%08" PRIx64, addr); result = 10; break; case MDS_64_BITS: - snprintf(buffer, VMPA_MAX_SIZE, "0x%016llx", addr); + snprintf(buffer, VMPA_MAX_SIZE, "0x%016" PRIx64, addr); result = 18; break; diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index b286f7c..f0fb421 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -197,6 +197,14 @@ GBinFormat *g_dex_format_new(const bin_t *content, off_t length) g_dex_format_find_all_sources(result); + + if (!find_all_dex_strings(result)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return G_BIN_FORMAT(result); } diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c index 9237839..f8c5a4a 100644 --- a/src/format/dex/pool.c +++ b/src/format/dex/pool.c @@ -24,6 +24,9 @@ #include "pool.h" +#include + + #include "dex-int.h" #include "../mangling/demangler.h" @@ -31,6 +34,41 @@ /****************************************************************************** * * +* Paramètres : format = description de l'exécutable à analyser. * +* * +* Description : Charge en mémoire toutes les chaînes trouvées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_all_dex_strings(GDexFormat *format) +{ + uint32_t i; /* Boucle de parcours */ + const char *text; /* Texte issu du binaire */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + for (i = 0; i < format->header.string_ids_size; i++) + { + text = get_string_from_dex_pool(format, i); + if (text == NULL) continue; + + symbol = g_binary_symbol_new(STP_STRING, NULL, i); + g_binary_symbol_set_alt_name(symbol, strdup(text)); + + g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); + + } + + return true; + +} + + +/****************************************************************************** +* * * Paramètres : format = représentation interne du format DEX à consulter. * * index = index du type recherchée. * * * diff --git a/src/format/dex/pool.h b/src/format/dex/pool.h index 6894da1..62c3aef 100644 --- a/src/format/dex/pool.h +++ b/src/format/dex/pool.h @@ -30,6 +30,9 @@ +/* Charge en mémoire toutes les chaînes trouvées. */ +bool find_all_dex_strings(GDexFormat *); + /* Extrait une chaîne de caractères d'une table DEX. */ const char *get_string_from_dex_pool(const GDexFormat *, uint32_t); diff --git a/src/format/symbol.c b/src/format/symbol.c index 3ac2d6d..986586c 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -247,7 +247,7 @@ off_t g_binary_symbol_get_size(const GBinSymbol *symbol) void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt) { - return symbol->alt = alt; + symbol->alt = alt; } diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c index cdf3689..8aea549 100644 --- a/src/gtkext/easygtk.c +++ b/src/gtkext/easygtk.c @@ -557,6 +557,44 @@ GtkWidget *qck_create_menu_item(GObject *object, const char *name, const char *c * * * Paramètres : object = espace dédié à l'inscription de références. * * name = nom à donner au nouveau composant. * +* id = identifiant du menu prédéfini. * +* handler = éventuelle fonction de sélection associée. * +* data = données à transmettre avec l'événement si besoin. * +* * +* Description : Crée et enregistre un composant 'GtkImageMenuItem'. * +* * +* Retour : Simple élément de menu mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_menu_item_with_stock_img(GObject *object, const char *name, const char *id, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_image_menu_item_new_from_stock(id, NULL); + + if (G_IS_OBJECT(object) && name != NULL) + { + g_object_ref(G_OBJECT(result)); + g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "activate", handler, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * * caption = intitulé du menu à créer. * * handler = éventuelle fonction de sélection associée. * * data = données à transmettre avec l'événement si besoin. * diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h index e46efee..ea234e0 100644 --- a/src/gtkext/easygtk.h +++ b/src/gtkext/easygtk.h @@ -77,6 +77,9 @@ GtkWidget *qck_create_combobox(GObject *, const char *, GCallback, gpointer); /* Crée et enregistre un composant 'GtkMenuItem'. */ GtkWidget *qck_create_menu_item(GObject *, const char *, const char *, GCallback, gpointer); +/* Crée et enregistre un composant 'GtkImageMenuItem'. */ +GtkWidget *qck_create_menu_item_with_stock_img(GObject *, const char *, const char *, GCallback, gpointer); + /* Crée et enregistre un composant 'GtkCheckMenuItem'. */ GtkWidget *qck_create_check_menu_item(GObject *, const char *, const char *, GCallback, gpointer); diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am index 2678d54..f2ea661 100644 --- a/src/gui/panels/Makefile.am +++ b/src/gui/panels/Makefile.am @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libguipanels.la libguipanels_la_SOURCES = \ log.h log.c \ panel.h panel.c \ + strings.h strings.c \ symbols.h symbols.c \ welcome.h welcome.c diff --git a/src/gui/panels/panel-int.h b/src/gui/panels/panel-int.h index e1c8932..def1934 100644 --- a/src/gui/panels/panel-int.h +++ b/src/gui/panels/panel-int.h @@ -56,7 +56,7 @@ typedef struct _panel_node { struct _panel_node *parent; /* Noeud parent */ - char path; /* Chemin du nom courant */ + char *path; /* Chemin du nom courant */ size_t depth; /* Profondeur utilisée */ bool simple; /* Noeud sans division */ diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c index cf4423d..3ad60b6 100644 --- a/src/gui/panels/panel.c +++ b/src/gui/panels/panel.c @@ -32,6 +32,7 @@ #include "log.h" #include "panel-int.h" +#include "strings.h" #include "symbols.h" #include "welcome.h" #include "../../gtkext/easygtk.h" @@ -71,8 +72,14 @@ static void switch_panel_node_into_paned(panel_node *, bool, bool); /* Met en place un nouveau noeud dans une division. */ static void attach_panel_node_to_paned(panel_node *, panel_node *, bool); -/* Indique si un noeud correspond à la branche recherchée. */ -static bool is_panel_node_matching(const panel_node *, char); +/* Valorise la correspondance entre un noeud et un chemin. */ +static int compute_panel_node_matching_score(const panel_node *, const char *); + +/* Calcule la longueur du plus court chemin vers un 'M'. */ +static size_t _compute_panel_node_main_level(const panel_node *); + +/* Recherche le noeud constituant la branche principale. */ +static panel_node *find_main_panel_node_branch(panel_node *, panel_node *); /* Place au bon endroit un panneau donné. */ static void insert_item_as_panel_node(GPanelItem *, panel_node *, const char *, size_t); @@ -350,6 +357,9 @@ void load_main_panels(GObject *ref) item = create_symbols_panel(ref); g_panel_item_dock(item); + item = create_strings_panel(ref); + g_panel_item_dock(item); + } @@ -380,7 +390,7 @@ static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const cha result = (panel_node *)calloc(1, sizeof(panel_node)); - result->path = path[depth]; + result->path = strdup(path); result->depth = depth; result->simple = true; @@ -438,7 +448,7 @@ static void switch_panel_node_into_paned(panel_node *current, bool horiz, bool f /* Achève la transformation */ - current->path = '\0'; + current->path = NULL; current->simple = false; @@ -507,7 +517,51 @@ static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, boo * Paramètres : node = noeud d'où lancer les recherches. * * target = identifiant de la position visée. * * * -* Description : Indique si un noeud correspond à la branche recherchée. * +* Description : Valorise la correspondance entre un noeud et un chemin. * +* * +* Retour : Bilan de l'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int compute_panel_node_matching_score(const panel_node *node, const char *target) +{ + int result; /* Bilan à retourner */ + size_t len; /* Longueur de comparaison */ + size_t i; /* Boucle de parcours */ + + if (node->simple) + { + result = 0; + + len = strlen(node->path); + len = MIN(len, strlen(target)); + + for (i = 0; i < len; i++) + { + if (node->path[i] != target[i]) break; + else result++; + } + + } + + else + { + result = compute_panel_node_matching_score(node->first, target); + result = MAX(result, compute_panel_node_matching_score(node->second, target)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud d'où lancer les recherches. * +* * +* Description : Calcule la longueur du plus court chemin vers un 'M'. * * * * Retour : Bilan de l'évaluation. * * * @@ -515,16 +569,59 @@ static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, boo * * ******************************************************************************/ -static bool is_panel_node_matching(const panel_node *node, char target) +static size_t _compute_panel_node_main_level(const panel_node *node) { - if (node->path == target) - return true; + size_t result; /* Plus petit chemin à renvoyer*/ if (node->simple) - return false; + { + result = strcspn(&node->path[node->depth], "M"); + + if (node->path[node->depth + result] == '\0') + result = SIZE_MAX; - return is_panel_node_matching(node->first, target) - || is_panel_node_matching(node->second, target); + } + + else + { + result = _compute_panel_node_main_level(node->first); + result = MIN(result, _compute_panel_node_main_level(node->second)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = première branche à analyser. * +* b = seconde branche à analyser. * +* * +* Description : Recherche le noeud constituant la branche principale. * +* * +* Retour : Branche principale ou NULL si aucune n'est idéale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static panel_node *find_main_panel_node_branch(panel_node *a, panel_node *b) +{ + panel_node *result; /* Trouvaille à remonter */ + size_t main_a; /* Proximité du 'M' côté a */ + size_t main_b; /* Proximité du 'M' côté b */ + + main_a = _compute_panel_node_main_level(a); + main_b = _compute_panel_node_main_level(b); + + if (main_a == SIZE_MAX && main_b == SIZE_MAX) + result = NULL; + + else + result = (main_a < main_b ? a : b); + + return result; } @@ -550,15 +647,17 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const bool horiz; /* Traduction en composant */ bool first; /* Point d'insertion */ panel_node *new; /* Nouveau noeud créé */ + int score1; /* Score de la 1ère branche */ + int score2; /* Score de la 2nde branche */ panel_node *support; /* Noeud d'accueil désigné */ if (node->simple) { /* Si on est sur la bonne voie... */ - if (path[depth] == '\0' || path[depth] == node->path) + if (compute_panel_node_matching_score(node, path) > 0) { /* Le parcours s'arrête ici ! */ - if (path[depth] == '\0' || path[depth + 1] == '\0') + if (strcmp(node->path, path) == 0) gtk_dock_panel_add_widget(GTK_DOCK_STATION(node->station), G_EDITOR_ITEM(item)->widget, G_EDITOR_ITEM(item)->name); @@ -566,13 +665,13 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const /* On ne peut aller plus loin, on doit diviser... */ else { - div = toupper(path[depth + 1]); + div = toupper(path[depth]); first = (div == 'E' || div == 'S'); horiz = (div == 'W' || div == 'E'); switch_panel_node_into_paned(node, horiz, first); - new = create_simple_panel_node_for_item(item, path, depth + 1); + new = create_simple_panel_node_for_item(item, path, depth); attach_panel_node_to_paned(node, new, !first); @@ -603,50 +702,64 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const /* On regarde des autres côtés... */ - else if (is_panel_node_matching(node->first, path[depth])) - insert_item_as_panel_node(item, node->first, path, depth + (node->first->simple ? 1 : 0)); - - else if (is_panel_node_matching(node->second, path[depth])) - insert_item_as_panel_node(item, node->second, path, depth + (node->second->simple ? 1 : 0)); - - /* On doit diviser qqch... */ else { - /* Si l'élément doit passer en force */ - if (isupper(path[depth])) - { - div = path[depth]; - first = (div == 'E' || div == 'S'); - horiz = (div == 'W' || div == 'E'); + score1 = compute_panel_node_matching_score(node->first, path); + score2 = compute_panel_node_matching_score(node->second, path); - switch_panel_node_into_paned(node, horiz, first); - - new = create_simple_panel_node_for_item(item, path, depth); + /* Si une descente est possible... */ + if (score1 > 0 || score2 > 0) + { + if (node->first->simple || node->second->simple) + depth++; - attach_panel_node_to_paned(node, new, !first); + if (score1 > score2) + insert_item_as_panel_node(item, node->first, path, depth); - rebuild_panels_interface(node); + else + insert_item_as_panel_node(item, node->second, path, depth); } + /* Sinon, on doit diviser qqch... */ else { - if (is_panel_node_matching(node->second, 'M')) - support = node->second; + /* Si l'élément doit passer en force */ + if (isupper(path[depth])) + { + div = path[depth]; + first = (div == 'E' || div == 'S'); + horiz = (div == 'W' || div == 'E'); + + switch_panel_node_into_paned(node, horiz, first); + + new = create_simple_panel_node_for_item(item, path, depth); + + attach_panel_node_to_paned(node, new, !first); + + rebuild_panels_interface(node); + + } + else - support = node->first; + { + support = find_main_panel_node_branch(node->first, node->second); + if (support == NULL) + support = node->first; - div = toupper(path[depth]); - first = (div == 'E' || div == 'S'); - horiz = (div == 'W' || div == 'E'); + div = toupper(path[depth]); + first = (div == 'E' || div == 'S'); + horiz = (div == 'W' || div == 'E'); - switch_panel_node_into_paned(support, horiz, first); + switch_panel_node_into_paned(support, horiz, first); - new = create_simple_panel_node_for_item(item, path, depth); + new = create_simple_panel_node_for_item(item, path, depth); - attach_panel_node_to_paned(support, new, !first); + attach_panel_node_to_paned(support, new, !first); - rebuild_panels_interface(support); + rebuild_panels_interface(support); + + } } @@ -796,6 +909,7 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi GtkRequisition first_req; /* Taille demandée par n°1 */ GtkRequisition second_req; /* Taille demandée par n°2 */ gint handle_size; /* Taille de la séparation */ + panel_node *main_node; /* Branche principale */ gint position; /* Position de la séparation */ bool can_lower; /* Diminution possible ? */ bool can_upper; /* Augmentation possible ? */ @@ -813,8 +927,10 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi * Définitions des bornes dans chacun des cas. */ + main_node = find_main_panel_node_branch(node->first, node->second); + /* Le premier noeud est le principal... */ - if (is_panel_node_matching(node->first, 'M')) + if (node->first == main_node) { if (GTK_IS_HPANED(node->paned)) position = (space->width * MAIN_PART_PERCENT) / 100; @@ -827,7 +943,7 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi } /* Le second noeud est le principal... */ - else if (is_panel_node_matching(node->second, 'M')) + else if (node->second == main_node) { if (GTK_IS_HPANED(node->paned)) position = space->width - (space->width * MAIN_PART_PERCENT) / 100; diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c new file mode 100644 index 0000000..605a700 --- /dev/null +++ b/src/gui/panels/strings.c @@ -0,0 +1,392 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * strings.c - panneau d'affichage des chaînes de caractères + * + * Copyright (C) 2008-2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "strings.h" + + +#include + + +#include "panel-int.h" +#include "../../common/extstr.h" +#include "../../gtkext/easygtk.h" + + + +/* -------------------------- PARTIE PRINCIPALE DU PANNEAU -------------------------- */ + + +/* Panneau d'aperçu de graphiques (instance) */ +struct _GStringsPanel +{ + GPanelItem parent; /* A laisser en premier */ + + GtkTreeView *treeview; /* Composant d'affichage */ + GtkTreeStore *store; /* Modèle de gestion */ + + GLoadedBinary *binary; /* Binaire à prendre en compte */ + + GtkWidget *menubar; /* Support pour l'édition */ + +}; + + +/* Panneau d'aperçu de graphiques (classe) */ +struct _GStringsPanelClass +{ + GPanelItemClass parent; /* A laisser en premier */ + +}; + + +/* Colonnes de la liste des symboles */ +typedef enum _StringsColumn +{ + STC_ADDRESS, /* Adresse mémoire du symbole */ + STC_STRING, /* Désignation humaine */ + STC_RAW, /* Données non retouchées */ + + STC_COUNT /* Nombre de colonnes */ + +} StringsColumn; + + +/* Réagit à un changement d'affichage principal de contenu. */ +static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary *); + + + +/* ------------------------- GESTIONS DES MENUS CONTEXTUELS ------------------------- */ + + +/* Affiche le menu d'édition propre aux chaînes trouvées. */ +static gboolean on_strings_button_press_event(GtkTreeView *, GdkEventButton *, GStringsPanel *); + +/* Réagit avec le menu "--- -> Copier". */ +static void mcb_strings_copy(GtkMenuItem *, GtkTreeView *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTIE PRINCIPALE DU PANNEAU */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type définit pour un panneau d'aperçu de graphiques. */ +G_DEFINE_TYPE(GStringsPanel, g_strings_panel, G_TYPE_PANEL_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des panneaux d'aperçu de graphiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_strings_panel_class_init(GStringsPanelClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : panel = instance à initialiser. * +* * +* Description : Initialise une instance de panneau d'aperçu de graphiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_strings_panel_init(GStringsPanel *panel) +{ + GEditorItem *base; /* Version basique d'instance */ + GObject *ref; /* Espace de référencement */ + GtkWidget *scrollwnd; /* Support défilant */ + GtkTreeStore *store; /* Modèle de gestion */ + GtkWidget *treeview; /* Affichage de la liste */ + GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ + GtkTreeViewColumn *column; /* Colonne de la liste */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + + base = G_EDITOR_ITEM(panel); + + base->widget = gtk_vbox_new(FALSE, 0); + gtk_widget_show(base->widget); + + ref = G_OBJECT(base->widget); + g_object_set_data(ref, "panel", panel); + + /* Liste des chaînes */ + + scrollwnd = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrollwnd); + gtk_box_pack_start(GTK_BOX(base->widget), scrollwnd, TRUE, TRUE, 0); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN); + + store = gtk_tree_store_new(STC_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + g_object_set_data(G_OBJECT(panel), "store", store); + + treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_widget_show(treeview); + gtk_container_add(GTK_CONTAINER(scrollwnd), treeview); + + g_object_unref(G_OBJECT(store)); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer, + "text", STC_ADDRESS, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("String"), renderer, + "markup", STC_STRING, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + /* Menu contextuel */ + + panel->menubar = gtk_menu_new(); + + submenuitem = qck_create_menu_item_with_stock_img(NULL, NULL, GTK_STOCK_COPY, + G_CALLBACK(mcb_strings_copy), treeview); + gtk_container_add(GTK_CONTAINER(panel->menubar), submenuitem); + + submenuitem = qck_create_menu_item(NULL, NULL, _("Find references..."), NULL, NULL); + gtk_container_add(GTK_CONTAINER(panel->menubar), submenuitem); + + g_signal_connect(G_OBJECT(treeview), "button_release_event", + G_CALLBACK(on_strings_button_press_event), panel); + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencement global. * +* * +* Description : Crée un panneau d'affichage des symboles. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GEditorItem *g_strings_panel_new(GObject *ref) +{ + GEditorItem *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_STRINGS_PANEL, NULL); + + g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_STRINGS_ID, + _("Strings"), G_EDITOR_ITEM(result)->widget, "SE"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencement global. * +* * +* Description : Construit et intègre un panneau d'affichage des symboles. * +* * +* Retour : Adresse du panneau mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GPanelItem *create_strings_panel(GObject *ref) +{ + GEditorItem *result; /* Elément réactif à renvoyer */ + + result = g_strings_panel_new(ref); + + /* Enregistre correctement le tout */ + result->update_binary = (update_item_binary_fc)change_strings_panel_current_binary; + register_editor_item(result); + + return G_PANEL_ITEM(result); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau à mettre à jour. * +* binary = nouvelle instance de binaire analysé. * +* * +* Description : Réagit à un changement d'affichage principal de contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBinary *binary) +{ + GtkTreeStore *store; /* Modèle de gestion */ + GExeFormat *format; /* Format de travail */ + size_t count; /* Nombre des chaînes */ + GBinSymbol **symbols; /* Liste des chaînes trouvées */ + size_t i; /* Boucle de parcours */ + char address[VMPA_MAX_SIZE]; /* Conversion de l'adresse */ + const char *raw; /* Texte brut trouvé */ + char *text; /* Version imprimable du texte */ + GtkTreeIter iter; /* Point d'insertion */ + + store = g_object_get_data(G_OBJECT(panel), "store"); + + format = g_loaded_binary_get_format(binary); + symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count); + + for (i = 0; i < count; i++) + { + if (g_binary_symbol_get_target_type(symbols[i]) != STP_STRING) continue; + + /* FIXME : adresses autres que 32 bits */ + snprintf(address, VMPA_MAX_SIZE, "0x%08" PRIx64, g_binary_symbol_get_address(symbols[i])); + + raw = g_binary_symbol_to_string(symbols[i]); + + text = strdup(raw); + text = strrpl(text, "&", "&"); + text = strrpl(text, "<", "<"); + text = strrpl(text, ">", ">"); + text = strrpl(text, "\r", "\\r"); + text = strrpl(text, "\n", "\\n"); + + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, + STC_ADDRESS, address, + STC_STRING, text, + STC_RAW, raw, + -1); + + free(text); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTIONS DES MENUS CONTEXTUELS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : treeview = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* data = référence vers le panneau contenant le menu. * +* * +* Description : Affiche le menu d'édition propre aux chaînes trouvées. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean on_strings_button_press_event(GtkTreeView *treeview, GdkEventButton *event, GStringsPanel *panel) +{ + gboolean result; /* Bilan d'action à renvoyer */ + + result = FALSE; + + if (event->type == GDK_BUTTON_RELEASE && event->button == 3) + { + gtk_menu_popup(GTK_MENU(panel->menubar), + NULL, NULL, NULL, NULL, + event->button, event->time); + + result = TRUE; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* treeview = arbre contenant la sélection à exporter. * +* * +* Description : Réagit avec le menu "--- -> Copier". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_strings_copy(GtkMenuItem *menuitem, GtkTreeView *treeview) +{ + GtkTreeSelection *selection; /* Sélection de l'arbre */ + GtkTreeIter iter; /* Point de sélection */ + GtkTreeModel *model; /* Modèle de gestion */ + gchar *string; /* Chaîne sélectionnée */ + GtkClipboard *clipboard; /* Presse-papiers d'arrivée */ + + selection = gtk_tree_view_get_selection(treeview); + + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, STC_RAW, &string, -1); + + if (string != NULL) + { + clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), + GDK_SELECTION_PRIMARY); + + gtk_clipboard_set_text(clipboard, string, strlen(string)); + g_free(string); + + } + + } + +} diff --git a/src/gui/panels/strings.h b/src/gui/panels/strings.h new file mode 100644 index 0000000..2ac2fbf --- /dev/null +++ b/src/gui/panels/strings.h @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * strings.h - prototypes pour le panneau d'affichage des chaînes de caractères + * + * Copyright (C) 2008-2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _GUI_PANELS_STRINGS_H +#define _GUI_PANELS_STRINGS_H + + +#include + + +#include "panel.h" + + + +#define PANEL_STRINGS_ID _("Strings") + + +#define G_TYPE_STRINGS_PANEL g_strings_panel_get_type() +#define G_STRINGS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_strings_panel_get_type(), GStringsPanel)) +#define G_IS_STRINGS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_strings_panel_get_type())) +#define G_STRINGS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRINGS_PANEL, GStringsPanelClass)) +#define G_IS_STRINGS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRINGS_PANEL)) +#define G_STRINGS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRINGS_PANEL, GStringsPanelClass)) + + +/* Panneau d'affichage des symboles (instance) */ +typedef struct _GStringsPanel GStringsPanel; + +/* Panneau d'affichage des symboles (classe) */ +typedef struct _GStringsPanelClass GStringsPanelClass; + + +/* Indique le type définit pour un panneau d'affichage des symboles. */ +GType g_strings_panel_get_type(void); + +/* Crée un panneau d'affichage des symboles. */ +GEditorItem *g_strings_panel_new(GObject *); + +/* Construit et intègre un panneau d'affichage des symboles. */ +GPanelItem *create_strings_panel(GObject *); + + + +#endif /* _GUI_PANELS_STRINGS_H */ diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c index c51b2d1..87cdfa4 100644 --- a/src/gui/panels/symbols.c +++ b/src/gui/panels/symbols.c @@ -84,7 +84,7 @@ static void g_symbols_panel_init(GSymbolsPanel *); static void on_symbols_selection_change(GtkTreeSelection *, GSymbolsPanel *); /* Réagit à un changement d'affichage principal de contenu. */ -void change_symbols_panel_current_binary(GSymbolsPanel *, GLoadedBinary *); +static void change_symbols_panel_current_binary(GSymbolsPanel *, GLoadedBinary *); @@ -296,7 +296,7 @@ GEditorItem *g_symbols_panel_new(GObject *ref) result = g_object_new(G_TYPE_SYMBOLS_PANEL, NULL); - g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_SYMBOL_ID, + g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_SYMBOLS_ID, _("Binary symbols"), G_EDITOR_ITEM(result)->widget, "e"); return result; @@ -383,7 +383,7 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan * * ******************************************************************************/ -void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBinary *binary) +static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBinary *binary) { GtkToggleToolButton *button; /* Mode de représentation */ GtkRequisition req; /* Nouvelle taille idéale */ diff --git a/src/gui/panels/symbols.h b/src/gui/panels/symbols.h index 182238a..1a9316d 100644 --- a/src/gui/panels/symbols.h +++ b/src/gui/panels/symbols.h @@ -33,7 +33,7 @@ -#define PANEL_SYMBOL_ID _("Symbols") +#define PANEL_SYMBOLS_ID _("Symbols") #define G_TYPE_SYMBOLS_PANEL g_symbols_panel_get_type() -- cgit v0.11.2-87-g4458