/* Chrysalide - Outil d'analyse de fichiers binaires * bookmark.c - boîte de dialogue pour les sauts à une adresse donnée * * Copyright (C) 2012-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 "bookmark.h" #include #include #include #include "..//analysis/db/items/bookmark.h" #include "../gtkext/easygtk.h" /* Filtre les adresses en hexadécimal pendant l'édition. */ static void filter_addresses(GtkEntry *, const gchar *, gint, gint *, gpointer); /* Clôture l'édition d'une adresse. */ static void validate_addresses(GtkEntry *, GtkDialog *); /****************************************************************************** * * * Paramètres : entry = composant GTK concerné par la procédure. * * text = nouveau texte inséré. * * length = taille de ce texte. * * position = point d'insertion. * * data = adresse non utilisée ici. * * * * Description : Filtre les adresses en hexadécimal pendant l'édition. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void filter_addresses(GtkEntry *entry, const gchar *text, gint length, gint *position, gpointer data) { gboolean has_hex; /* Préfixe '0x' déjà présent ? */ gchar *filtered; /* Contenu nouveau approuvé */ gint count; /* Nouvelle taille validée */ gint i; /* Boucle de parcours */ /** * On cherche à empêcher l'édition avant un '0x' présent, * ce qui viendrait fausser le fitrage. */ has_hex = g_str_has_prefix(gtk_entry_get_text(entry), "0x"); filtered = g_new(gchar, length); count = 0; for (i = 0; i < length; i++) switch (text[i]) { case '0' ... '9': case 'a' ... 'f': if (!has_hex || ((i + *position) >= 2)) filtered[count++] = text[i]; break; case 'A' ... 'F': if (!has_hex || ((i + *position) >= 2)) filtered[count++] = tolower(text[i]); break; case 'x': case 'X': if ((i + *position) == 1) filtered[count++] = 'x'; break; } if (count > 0) { g_signal_handlers_block_by_func(G_OBJECT(entry), G_CALLBACK(filter_addresses), data); gtk_editable_insert_text(GTK_EDITABLE(entry), filtered, count, position); g_signal_handlers_unblock_by_func(G_OBJECT(entry), G_CALLBACK(filter_addresses), data); } g_signal_stop_emission_by_name(G_OBJECT(entry), "insert_text"); g_free(filtered); } /****************************************************************************** * * * Paramètres : entry = composant GTK concerné par la procédure. * * dialog = boîte de dialogue à valider. * * * * Description : Clôture l'édition d'une adresse. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void validate_addresses(GtkEntry *entry, GtkDialog *dialog) { gtk_dialog_response(dialog, GTK_RESPONSE_OK); } /****************************************************************************** * * * Paramètres : parent = fenêtre parente à surpasser. * * addr = localisation du point à consigner. * * * * Description : Construit la fenêtre de création de signet. * * * * Retour : Adresse de la fenêtre mise en place. * * * * Remarques : - * * * ******************************************************************************/ GtkWidget *create_bookmark_dialog(GtkWindow *parent, const vmpa2t *addr) { GtkWidget *result; /* Fenêtre à renvoyer */ GtkWidget *dlgvbox; /* Zone principale de la boîte */ GtkWidget *vbox; /* Support à construire #1 */ GtkWidget *frame; /* Support avec encadrement */ GtkWidget *sub_vbox; /* Support à construire #2 */ GtkWidget *hbox; /* Support à construire #3 */ GtkWidget *label; /* Message d'introduction */ GtkWidget *entry; /* Zone de saisie principale */ GtkWidget *radio; /* Définition de localisation */ VMPA_BUFFER(target); /* Désignation humaine de cible*/ result = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(result), _("Add a bookmark")); gtk_window_set_position(GTK_WINDOW(result), GTK_WIN_POS_CENTER); gtk_window_set_modal(GTK_WINDOW(result), TRUE); gtk_window_set_type_hint(GTK_WINDOW(result), GDK_WINDOW_TYPE_HINT_DIALOG); dlgvbox = gtk_dialog_get_content_area(GTK_DIALOG(result)); gtk_widget_show(dlgvbox); vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); gtk_widget_show(vbox); gtk_box_pack_start(GTK_BOX(dlgvbox), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); /* Localisation dans l'espace */ sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); gtk_widget_show(sub_vbox); frame = qck_create_frame(_("Localisation"), sub_vbox, 8, 0, 12, 0); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); /* 1) Adresse */ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(sub_vbox), hbox, FALSE, TRUE, 0); label = qck_create_label(NULL, NULL, _("Target:")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); entry = qck_create_entry(G_OBJECT(result), "addr", NULL); //g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_text_empty_entry), assistant); gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, TRUE, 0); /* 2) Type d'adresse */ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox), 8); radio = qck_create_radio_button(G_OBJECT(result), "phys", _("Value is physical offset"), NULL, NULL, NULL); gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, TRUE, 0); radio = qck_create_radio_button(G_OBJECT(result), "virt", _("Value is virtual address"), GTK_RADIO_BUTTON(radio), NULL, NULL); gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, TRUE, 0); /* Commentaire éventuel */ entry = qck_create_entry(G_OBJECT(result), "comment", NULL); frame = qck_create_frame(_("Optional comment"), entry, 8, 0, 12, 0); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); /* Zone de validation */ gtk_dialog_add_button(GTK_DIALOG(result), _("_Cancel"), GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(result), _("_Ok"), GTK_RESPONSE_OK); /* Remplissage avec les valeurs fournies */ entry = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "addr")); if (addr != NULL && has_virt_addr(addr)) { vmpa2_virt_to_string(addr, MDS_UNDEFINED, target, NULL); radio = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "virt")); } else if (addr != NULL && has_phys_addr(addr)) { vmpa2_virt_to_string(addr, MDS_UNDEFINED, target, NULL); radio = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "virt")); } else radio = NULL; if (radio == NULL) { gtk_entry_set_text(GTK_ENTRY(entry), "0x"); gtk_editable_set_position(GTK_EDITABLE(entry), -1); gtk_widget_grab_focus(entry); } else { gtk_entry_set_text(GTK_ENTRY(entry), target); gtk_editable_set_position(GTK_EDITABLE(entry), -1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); } if (radio != NULL) { entry = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "comment")); gtk_widget_grab_focus(entry); } return result; } /****************************************************************************** * * * Paramètres : dialog = boîte de dialogue ayant reçu une validation. * * * * Description : Fournit le signet conçu via la saisie de l'utilisateur. * * * * Retour : Adresse reccueillie par la boîte de dialogue. * * * * Remarques : - * * * ******************************************************************************/ GDbItem *get_item_from_bookmark_dialog(GtkWidget *dialog) { GDbItem *result; /* Signet nouveau à retourner */ GObject *ref; /* Espace de référencements */ vmpa2t *orig; /* Copie de valeur originale */ vmpa2t addr; /* Localisation finale utilisée*/ GtkWidget *entry; /* Zone de saisie principale */ const gchar *text; /* Adresse en version texte */ GtkToggleButton *radio; /* Définition de localisation */ ref = G_OBJECT(dialog); /* Si la valeur d'origine a été conservée intacte... */ orig = (vmpa2t *)g_object_get_data(ref, "orig"); if (orig == NULL) { entry = GTK_WIDGET(g_object_get_data(ref, "addr")); text = gtk_entry_get_text(GTK_ENTRY(entry)); radio = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "phys")); if (gtk_toggle_button_get_active(radio)) orig = string_to_vmpa_phy(text); else orig = string_to_vmpa_virt(text); } copy_vmpa(&addr, orig); delete_vmpa(orig); /* Récupération du commentaire éventuel */ entry = GTK_WIDGET(g_object_get_data(ref, "comment")); text = gtk_entry_get_text(GTK_ENTRY(entry)); /* Mise en place du signet défini */ if (strlen(text) > 0) result = G_DB_ITEM(g_db_bookmark_new(&addr, text)); else result = G_DB_ITEM(g_db_bookmark_new(&addr, NULL)); return result; }