diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/binary.c | 227 | ||||
-rw-r--r-- | src/binary.h | 34 | ||||
-rw-r--r-- | src/dlg_sections.c | 218 | ||||
-rw-r--r-- | src/dlg_sections.h | 42 | ||||
-rw-r--r-- | src/easygtk.c | 353 | ||||
-rw-r--r-- | src/easygtk.h | 65 | ||||
-rw-r--r-- | src/editor.c | 366 | ||||
-rw-r--r-- | src/project.c | 431 | ||||
-rw-r--r-- | src/project.h | 88 | ||||
-rw-r--r-- | src/xdg.c | 103 | ||||
-rw-r--r-- | src/xdg.h | 34 | ||||
-rw-r--r-- | src/xml.c | 574 | ||||
-rw-r--r-- | src/xml.h | 96 |
14 files changed, 2635 insertions, 3 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 603ba36..b1e31cd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,10 +3,15 @@ bin_PROGRAMS=openida openida_SOURCES = \ binary.h binary.c \ + dlg_sections.h dlg_sections.c \ + easygtk.h easygtk.c \ editor.c \ gtksnippet.h gtksnippet.c \ gtkcodeview.h gtkcodeview.c \ - pan_symbols.h pan_symbols.c + pan_symbols.h pan_symbols.c \ + project.h project.c \ + xdg.h xdg.c \ + xml.h xml.c INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/intl $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) `pkg-config --cflags gthread-2.0` diff --git a/src/binary.c b/src/binary.c index 1bc87cb..8de0bdb 100644 --- a/src/binary.c +++ b/src/binary.c @@ -26,6 +26,7 @@ #include <fcntl.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <sys/mman.h> #include <sys/stat.h> @@ -48,6 +49,13 @@ extern bool find_line_info(const uint8_t *content, off_t *size); + +/* Charge en mémoire le contenu d'un fichier à partir d'XML. */ +openida_binary *load_binary_file_from_xml(xmlXPathObjectPtr); + + + + /* Charge en mémoire le contenu d'un fichier. */ uint8_t *map_binary_file(const char *, size_t *); @@ -55,6 +63,225 @@ uint8_t *map_binary_file(const char *, size_t *); +/* Description d'un fichier binaire */ +struct _openida_binary +{ + char *filename; /* Fichier chargé en mémoire */ + + +}; + + + + + + +/****************************************************************************** +* * +* Paramètres : filename = nom du fichier à charger. * +* * +* Description : Charge en mémoire le contenu d'un fichier. * +* * +* Retour : Adresse de la représentation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +openida_binary *load_binary_file(const char *filename) +{ + openida_binary *result; /* Adresse à retourner */ + + result = (openida_binary *)calloc(1, sizeof(openida_binary)); + + result->filename = strdup(filename); + + + + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xpathObj = point de lecture de tous les éléments. * +* * +* Description : Charge en mémoire le contenu d'un fichier à partir d'XML. * +* * +* Retour : Adresse de la représentation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +openida_binary *load_binary_file_from_xml(xmlXPathObjectPtr xpathObj) +{ + openida_binary *result; /* Adresse à retourner */ + + int i; + + result = (openida_binary *)calloc(1, sizeof(openida_binary)); + + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xpathObj); i++) + if (xmlStrEqual(NODE_FROM_PATH_OBJ(xpathObj, i)->name, BAD_CAST "Filename")) + result->filename = qck_get_node_text_value(NODE_FROM_PATH_OBJ(xpathObj, i)); + + + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à supprimer de la mémoire. * +* * +* Description : Décharge de la mémoire le contenu d'un fichier. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_binary_file(openida_binary *binary) +{ + free(binary->filename); + + free(binary); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à traiter. * +* * +* Description : Fournit une description humaine d'un élément binaire. * +* * +* Retour : Chaîne de caractères humainenement lisible de représentation.* +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *openida_binary_to_string(const openida_binary *binary) +{ + return binary->filename; + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : xpathCtx = contexte à utiliser pour mener les parcours. * +* base = première partie de l'expression XPath d'accès. * +* index = indice de la élément dans la liste des voisins. * +* * +* Description : Lit un élément binaire depuis un fichier XML. * +* * +* Retour : Représentation mise en place à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +openida_binary *read_openida_binary_from_xml(xmlXPathContextPtr xpathCtx, const char *base, unsigned int index) +{ + openida_binary *result; /* Représentation à retourner */ + size_t expr_len; /* Taille d'une expression */ + char *expr; /* Chemin XPath reconstitué */ + xmlXPathObjectPtr xpathObj; /* Cible d'une recherche */ + char *value; /* Type d'élément rencontré */ + size_t sub_expr_len; /* Taille d'une expression #2 */ + char *sub_expr; /* Chemin XPath reconstitué #2 */ + int i; /* Boucle de parcours */ + + result = NULL; + + /* S'occupe en premier lieu du niveau courant */ + + expr_len = strlen(base) + strlen("/*[position()=") + strlen("4294967295") /* UINT_MAX */ + strlen("]") + 1; + + expr = (char *)calloc(expr_len, sizeof(char)); + snprintf(expr, expr_len, "%s/*[position()=%u]", base, index); + + xpathObj = get_node_xpath_object(xpathCtx, expr); + + value = qck_get_node_prop_value(NODE_FROM_PATH_OBJ(xpathObj, 0), "type"); + + xmlXPathFreeObject(xpathObj); + + if (value == NULL) goto robfx_err1; + + /* Raffinement au second passage */ + + sub_expr_len = expr_len + strlen("/*"); + sub_expr = (char *)calloc(sub_expr_len, sizeof(char)); + snprintf(sub_expr, sub_expr_len, "%s/*", expr); + + xpathObj = get_node_xpath_object(xpathCtx, sub_expr); + + if (strcmp(value, "file") == 0) result = load_binary_file_from_xml(xpathObj); + + xmlXPathFreeObject(xpathObj); + + free(sub_expr); + + robfx_err1: + + free(expr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à traiter. * +* writer = rédacteur dédié à l'écriture. * +* * +* Description : Ecrit une sauvegarde du binaire dans un fichier XML. * +* * +* Retour : true si l'opération a bien tourné, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_openida_binary_to_xml(const openida_binary *binary, xmlTextWriterPtr writer) +{ + bool result; /* Bilan à faire remonter */ + + result = open_xml_element(writer, "Binary"); + + result &= write_xml_attribute(writer, "type", "file"); + + result &= write_xml_element_with_content(writer, "Filename", "%s", binary->filename); + + result &= close_xml_element(writer); + + return result; + +} + + + + + /****************************************************************************** * * * Paramètres : filename = nom du fichier à charger. * diff --git a/src/binary.h b/src/binary.h index d2dacc5..e1cc97b 100644 --- a/src/binary.h +++ b/src/binary.h @@ -25,11 +25,45 @@ #define _BINARY_H +#include <stdbool.h> +#include "xml.h" + + + +/* Description d'un fichier binaire */ +typedef struct _openida_binary openida_binary; + + +/* Charge en mémoire le contenu d'un fichier. */ +openida_binary *load_binary_file(const char *); + +/* Décharge de la mémoire le contenu d'un fichier. */ +void unload_binary_file(openida_binary *); + +/* Fournit une description humaine d'un élément binaire. */ +const char *openida_binary_to_string(const openida_binary *); + + + +/* Lit un élément binaire depuis un fichier XML. */ +openida_binary *read_openida_binary_from_xml(xmlXPathContextPtr, const char *, unsigned int); + +/* Ecrit une sauvegarde du binaire dans un fichier. */ +bool write_openida_binary_to_xml(const openida_binary *, xmlTextWriterPtr); + + + + #include "gtksnippet.h" + + + + + void fill_snippet(GtkSnippet *snippet, GtkWidget *panel); diff --git a/src/dlg_sections.c b/src/dlg_sections.c new file mode 100644 index 0000000..2aae552 --- /dev/null +++ b/src/dlg_sections.c @@ -0,0 +1,218 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dlg_sections.h - boîte de dialogue permettant une sélection des sections + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "dlg_sections.h" + + +#include "easygtk.h" + + + +#define _(str) str + + + + +/* Charge les sections sélectionnées pour le projet courant. */ +void load_project_sections(openida_project *, GObject *); + + + + +/****************************************************************************** +* * +* Paramètres : project = informations sur le project actuellement ouvert. * +* * +* Description : Construit la fenêtre de sélection des sections. * +* * +* Retour : Adresse de la fenêtre mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *create_sections_dialog(openida_project *project) +{ + GtkWidget *result; /* Fenêtre à renvoyer */ + + + + + + GtkWidget *vbox1; + GtkWidget *hbox1; + + + GtkWidget *label; /* Etiquette à afficher */ + + + GtkWidget *combobox1; + + GtkWidget *alignment; /* Adaptation de disposition */ + GtkWidget *frame; /* Support avec encadrement */ + + GtkWidget *vbox2; + GtkWidget *hbox2; + GtkWidget *comboboxentry1; + GtkWidget *hbox3; + GtkWidget *scrolledwindow1; + GtkWidget *treeview1; + GtkWidget *vbuttonbox1; + GtkWidget *hbuttonbox1; + + GtkWidget *button; /* Bouton de commande */ + + result = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_size_request(result, 400, 300); + gtk_container_set_border_width(GTK_CONTAINER(result), 8); + gtk_window_set_title(GTK_WINDOW(result), _("Sections selection")); + gtk_window_set_position(GTK_WINDOW(result), GTK_WIN_POS_CENTER); + gtk_window_set_default_size(GTK_WINDOW(result), 500, 400); + gtk_window_set_type_hint(GTK_WINDOW(result), GDK_WINDOW_TYPE_HINT_DIALOG); + + vbox1 = gtk_vbox_new(FALSE, 8); + gtk_widget_show(vbox1); + gtk_container_add(GTK_CONTAINER(result), vbox1); + + hbox1 = gtk_hbox_new(FALSE, 8); + gtk_widget_show(hbox1); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0); + + label = qck_create_label(NULL, NULL, _("Binary :")); + gtk_box_pack_start(GTK_BOX(hbox1), label, FALSE, FALSE, 0); + + combobox1 = gtk_combo_box_new_text(); + gtk_widget_show(combobox1); + gtk_box_pack_start(GTK_BOX(hbox1), combobox1, TRUE, TRUE, 0); + + + frame = qck_create_frame(_("<b>Content to display</b>"), &alignment, 4, 4, 12, 0); + gtk_box_pack_start(GTK_BOX(vbox1), frame, TRUE, TRUE, 0); + + + + + vbox2 = gtk_vbox_new(FALSE, 8); + gtk_widget_show(vbox2); + gtk_container_add(GTK_CONTAINER(alignment), vbox2); + + hbox2 = gtk_hbox_new(FALSE, 8); + gtk_widget_show(hbox2); + gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); + + label = qck_create_label(NULL, NULL, _("Model :")); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + comboboxentry1 = qck_create_combobox(NULL, NULL, G_CALLBACK(NULL), NULL); + gtk_box_pack_start(GTK_BOX(hbox2), comboboxentry1, TRUE, TRUE, 0); + + + button = qck_create_button_with_img(NULL, NULL, "gtk-add", G_CALLBACK(NULL), NULL); + gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0); + + button = qck_create_button_with_img(NULL, NULL, "gtk-remove", G_CALLBACK(NULL), NULL); + gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0); + + + + + hbox3 = gtk_hbox_new(FALSE, 8); + gtk_widget_show(hbox3); + gtk_box_pack_start(GTK_BOX(vbox2), hbox3, TRUE, TRUE, 0); + + scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrolledwindow1); + gtk_box_pack_start(GTK_BOX(hbox3), scrolledwindow1, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow1), GTK_SHADOW_IN); + + treeview1 = gtk_tree_view_new(); + gtk_widget_show(treeview1); + gtk_container_add(GTK_CONTAINER(scrolledwindow1), treeview1); + + vbuttonbox1 = gtk_vbutton_box_new(); + gtk_widget_show(vbuttonbox1); + gtk_box_pack_start(GTK_BOX(hbox3), vbuttonbox1, FALSE, FALSE, 0); + gtk_button_box_set_layout(GTK_BUTTON_BOX(vbuttonbox1), GTK_BUTTONBOX_SPREAD); + + + + + button = qck_create_button_with_img(NULL, NULL, "gtk-add", G_CALLBACK(NULL), NULL); + gtk_container_add(GTK_CONTAINER(vbuttonbox1), button); + + button = qck_create_button_with_img(NULL, NULL, "gtk-remove", G_CALLBACK(NULL), NULL); + gtk_container_add(GTK_CONTAINER(vbuttonbox1), button); + + + + + + hbuttonbox1 = gtk_hbutton_box_new(); + gtk_widget_show(hbuttonbox1); + gtk_box_pack_start(GTK_BOX(vbox1), hbuttonbox1, FALSE, FALSE, 0); + gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox1), GTK_BUTTONBOX_END); + + + button = qck_create_button_from_stock(NULL, NULL, "gtk-ok", G_CALLBACK(NULL), NULL); + gtk_container_add(GTK_CONTAINER(hbuttonbox1), button); + + button = qck_create_button_from_stock(NULL, NULL, "gtk-cancel", G_CALLBACK(NULL), NULL); + gtk_container_add(GTK_CONTAINER(hbuttonbox1), button); + + return result; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : project = informations sur le project actuellement ouvert. * +* ref = espace de référencement principal. * +* * +* Description : Charge les sections sélectionnées pour le projet courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void load_project_sections(openida_project *project, GObject *ref) +{ + + + + /* + gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), _("Never automatically")); + gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), _("When the window gets the focus")); + gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), _("On click on the window")); + + */ + +} diff --git a/src/dlg_sections.h b/src/dlg_sections.h new file mode 100644 index 0000000..2541d2b --- /dev/null +++ b/src/dlg_sections.h @@ -0,0 +1,42 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dlg_sections.h - prototypes pour la boîte de dialogue permettant une sélection des sections + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DLG_SECTIONS_H +#define _DLG_SECTIONS_H + + +#include <gtk/gtk.h> + + +#include "project.h" + + + +/* Construit la fenêtre de sélection des sections. */ +GtkWidget *create_sections_dialog(openida_project *); + + + + + +#endif /* _DLG_SECTIONS_H */ diff --git a/src/easygtk.c b/src/easygtk.c new file mode 100644 index 0000000..93ba653 --- /dev/null +++ b/src/easygtk.c @@ -0,0 +1,353 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * easygtk.c - mise en place rapide de composants GTK + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "easygtk.h" + + + + +/****************************************************************************** +* * +* Paramètres : pt = espace imposé à la zone supérieure. * +* pb = espace imposé à la zone inférieure. * +* pl = espace imposé à la zone gauche. * +* pr = espace imposé à la zone droite. * +* * +* Description : Met en place un aligement dont les bordures sont à ajuster. * +* * +* Retour : Composant 'GtkWidget' ici créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_padded_alignment(guint pt, guint pb, guint pl, guint pr) +{ + GtkWidget *result; /* Instance à renvoyer */ + + result = gtk_alignment_new(0.5, 0.5, 1, 1); + gtk_widget_show(result); + gtk_alignment_set_padding(GTK_ALIGNMENT(result), pt, pb, pl, pr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : caption = contenu de l'étiqutte à placer. * +* alignment = conteneur réel à utiliser pour la suite. [OUT] * +* pt = espace imposé à la zone supérieure. * +* pb = espace imposé à la zone inférieure. * +* pl = espace imposé à la zone gauche. * +* pr = espace imposé à la zone droite. * +* * +* * +* Description : Met en place une frame. * +* * +* Retour : Composant 'GtkWidget' ici créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_frame(const char *caption, GtkWidget **alignment, guint pt, guint pb, guint pl, guint pr) +{ + GtkWidget *result; /* Instance à renvoyer */ + GtkWidget *label; /* Etiquette à utiliser */ + + result = gtk_frame_new(NULL); + gtk_widget_show(result); + + gtk_frame_set_shadow_type(GTK_FRAME(result), GTK_SHADOW_NONE); + + label = qck_create_label(NULL, NULL, caption); + gtk_frame_set_label_widget(GTK_FRAME(result), label); + gtk_label_set_use_markup(GTK_LABEL(label), TRUE); + + *alignment = qck_create_padded_alignment(pt, pb, pl, pr); + gtk_container_add(GTK_CONTAINER(result), *alignment); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * +* caption = intitulé apparaissant sur le composant. * +* * +* Description : Crée un composant 'GtkLabel'. * +* * +* Retour : Champ d'indication mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_label(GObject *object, const char *name, const char *caption) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_label_new(caption); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * +* caption = intitulé du bouton à créer. * +* 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 'GtkButton'. * +* * +* Retour : Simple bouton mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_button(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_button_new_with_label(caption); + GTK_WIDGET_SET_FLAGS(result, GTK_CAN_DEFAULT); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "clicked", handler, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * +* stock = désignation du type de bouton GTK. * +* 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 'GtkButton'. * +* * +* Retour : Simple bouton mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_button_from_stock(GObject *object, const char *name, const char *stock, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_button_new_from_stock(stock); + GTK_WIDGET_SET_FLAGS(result, GTK_CAN_DEFAULT); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "clicked", handler, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * +* image = nom de l'image stockée dans GTK. * +* 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 'GtkButton'. * +* * +* Retour : Simple bouton mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_button_with_img(GObject *object, const char *name, const char *image, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + GtkWidget *render; /* Image à ajouter au bouton */ + + result = gtk_button_new(); + GTK_WIDGET_SET_FLAGS(result, GTK_CAN_DEFAULT); + + render = gtk_image_new_from_stock(image, GTK_ICON_SIZE_BUTTON); + gtk_widget_show(render); + gtk_container_add(GTK_CONTAINER(result), render); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "clicked", handler, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * +* 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 'GtkComboBox'. * +* * +* Retour : Composant mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_combobox(GObject *object, const char *name, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_combo_box_new_text(); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "changed", 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. * +* * +* Description : Crée et enregistre un composant 'GtkMenuItem'. * +* * +* Retour : Simple élément de menu mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_menu_item(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_menu_item_new_with_mnemonic(caption); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "activate", handler, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée et enregistre un composant 'GtkSeparatorMenuItem'. * +* * +* Retour : Simple élément de menu mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_menu_separator(void) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_separator_menu_item_new(); + gtk_widget_show(result); + + return result; + +} diff --git a/src/easygtk.h b/src/easygtk.h new file mode 100644 index 0000000..7499815 --- /dev/null +++ b/src/easygtk.h @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * easygtk.h - prototypes pour la mise en place rapide de composants GTK + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _EASYGTK_H +#define _EASYGTK_H + + +#include <gtk/gtk.h> + + + +/* Met en place un aligement dont les bordures sont à ajuster. */ +GtkWidget *qck_create_padded_alignment(guint, guint, guint, guint); + +/* Met en place une frame. */ +GtkWidget *qck_create_frame(const char *, GtkWidget **, guint, guint, guint, guint); + +/* Crée un composant 'GtkLabel'. */ +GtkWidget *qck_create_label(GObject *, const char *, const char *); + +/* Crée et enregistre un composant 'GtkButton'. */ +GtkWidget *qck_create_button(GObject *, const char *, const char *, GCallback, gpointer); + +/* Crée et enregistre un composant 'GtkButton'. */ +GtkWidget *qck_create_button_from_stock(GObject *, const char *, const char *, GCallback, gpointer); + +/* Crée et enregistre un composant 'GtkButton'. */ +GtkWidget *qck_create_button_with_img(GObject *, const char *, const char *, GCallback, gpointer); + +/* Crée et enregistre un composant 'GtkComboBox'. */ +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 'GtkSeparatorMenuItem'. */ +GtkWidget *qck_create_menu_separator(void); + + + + +#endif /* _EASYGTK_H */ diff --git a/src/editor.c b/src/editor.c index dbdc2d3..0673110 100644 --- a/src/editor.c +++ b/src/editor.c @@ -50,6 +50,8 @@ #include "binary.h" +#include "dlg_sections.h" +#include "easygtk.h" #include "gtksnippet.h" #include "gtkcodeview.h" #include "pan_symbols.h" @@ -70,6 +72,36 @@ void destroy_editor(GtkWidget *, gpointer); +/* Réagit au menu "Fichier -> Enregistrer le projet". */ +void mcb_file_save_project(GtkMenuItem *, gpointer); + +/* Réagit au menu "Fichier -> Enregistrer le projet sous...". */ +void mcb_file_save_project_as(GtkMenuItem *, gpointer); + + + +/* Charge un projet récent et met à jour la liste. */ +void mcb_open_recent_project(GtkMenuItem *, gpointer); + + + +/* Affiche la boîte d'ajout d'un binaire au projet courant. */ +void mcb_project_add_binary(GtkMenuItem *, gpointer); + +/* Retire un binaire du projet courant. */ +void mcb_project_remove_binary(GtkMenuItem *, gpointer); + + + +/* Affiche la boîte de sélection des sections. */ +void mcb_select_sections(GtkMenuItem *, gpointer); + + + +/* Met à jour le contenu du menu 'Projet'. */ +void reload_menu_project(GObject *); + + /****************************************************************************** @@ -355,6 +387,11 @@ on_button2_clicked (GtkButton *button, GtkWidget *create_editor(void) { GtkWidget *result; /* Fenêtre à renvoyer */ + GtkWidget *menuboard; /* Barre de menus principale */ + GtkWidget *menuitem; /* Elément de menu */ + GtkWidget *menubar; /* Support pour éléments */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + GtkWidget *submenubar; /* Support pour sous-éléments */ GtkWidget *vbox1; GtkWidget *vpaned1; @@ -393,6 +430,9 @@ GtkWidget *create_editor(void) GtkWidget *panel; + openida_project *project; + + #if 0 GtkWidget *vbox; /* Support à divisions vert. */ GtkWidget *notebook; /* Support à onglets */ @@ -414,12 +454,73 @@ GtkWidget *create_editor(void) - - vbox1 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox1); gtk_container_add (GTK_CONTAINER (result), vbox1); + + /* Intégration des menus */ + + menuboard = gtk_menu_bar_new(); + gtk_widget_show(menuboard); + gtk_box_pack_start(GTK_BOX(vbox1), menuboard, FALSE, FALSE, 0); + + menuitem = gtk_menu_item_new_with_mnemonic(_("_File")); + gtk_widget_show(menuitem); + gtk_container_add(GTK_CONTAINER(menuboard), menuitem); + + menubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menubar); + + submenuitem = qck_create_menu_item(NULL, NULL, _("Save project"), G_CALLBACK(mcb_file_save_project), result); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_item(NULL, NULL, _("Save project as..."), G_CALLBACK(mcb_file_save_project_as), result); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_item(G_OBJECT(result), "menu_recent_prjs", _("Recent projects..."), NULL, NULL); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), submenubar); + + menuitem = gtk_menu_item_new_with_mnemonic(_("_Project")); + gtk_widget_show(menuitem); + gtk_container_add(GTK_CONTAINER(menuboard), menuitem); + + menubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menubar); + + submenuitem = qck_create_menu_item(NULL, NULL, _("Add a binary..."), G_CALLBACK(mcb_project_add_binary), result); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_item(G_OBJECT(result), "menu_prj_remove_bin", _("Remove a binary"), NULL, NULL); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), submenubar); + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_item(NULL, NULL, _("Select sections..."), G_CALLBACK(mcb_select_sections), NULL); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + + + load_recent_openida_projects_list(G_OBJECT(result), G_CALLBACK(mcb_open_recent_project)); + + + project = load_openida_project_from_xml("/home/ocb/test.oip")/*create_empty_openida_project()*/; + set_current_openida_project(project); + + reload_menu_project(G_OBJECT(result)); + + + vpaned1 = gtk_vpaned_new (); gtk_widget_show (vpaned1); gtk_box_pack_start (GTK_BOX (vbox1), vpaned1, TRUE, TRUE, 0); @@ -688,5 +789,266 @@ void destroy_editor(GtkWidget *widget, gpointer data) +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Réagit au menu "Fichier -> Enregistrer le projet". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_file_save_project(GtkMenuItem *menuitem, gpointer data) +{ + openida_project *project; /* Projet courant */ + + project = get_current_openida_project(); + + if (has_storing_filename(project)) + write_openida_project_to_xml(project, NULL); + + else + mcb_file_save_project_as(menuitem, data); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Réagit au menu "Fichier -> Enregistrer le projet sous...". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_file_save_project_as(GtkMenuItem *menuitem, gpointer data) +{ + GtkWidget *dialog; /* Boîte à afficher */ + gchar *filename; /* Nom du fichier à intégrer */ + + dialog = gtk_file_chooser_dialog_new (_("Save the project as..."), GTK_WINDOW(data), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + write_openida_project_to_xml(get_current_openida_project(), filename); + + g_free(filename); + + } + + gtk_widget_destroy(dialog); + +} + + + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Charge un projet récent et met à jour la liste. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_open_recent_project(GtkMenuItem *menuitem, gpointer data) +{ + const gchar *caption; /* Etiquette du menu */ + openida_project *project; /* Nouveau projet chargé */ + + caption = gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem)))); + + project = load_openida_project_from_xml(caption); + + if (project != NULL) + { + set_current_openida_project(project); + /* TODO ... */ + } + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Affiche la boîte d'ajout d'un binaire au projet courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_project_add_binary(GtkMenuItem *menuitem, gpointer data) +{ + GtkWidget *dialog; /* Boîte à afficher */ + gchar *filename; /* Nom du fichier à intégrer */ + openida_binary *binary; /* Représentation chargée */ + + dialog = gtk_file_chooser_dialog_new (_("Open a binary file"), GTK_WINDOW(data), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + binary = load_binary_file(filename); + + if (binary != NULL) + { + attach_binary_to_openida_project(get_current_openida_project(), binary); + reload_menu_project(G_OBJECT(data)); + } + + g_free(filename); + + } + + gtk_widget_destroy(dialog); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Retire un binaire du projet courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_project_remove_binary(GtkMenuItem *menuitem, gpointer data) +{ + openida_binary *binary; /* Représentation chargée */ + + binary = g_object_get_data(G_OBJECT(menuitem), "binary"); + + detach_binary_to_openida_project(get_current_openida_project(), binary); + unload_binary_file(binary); + + reload_menu_project(G_OBJECT(data)); + +} + + + + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Affiche la boîte de sélection des sections. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_select_sections(GtkMenuItem *menuitem, gpointer data) +{ + GtkWidget *dialog; /* Boîte de dialogue à montrer */ + + dialog = create_sections_dialog(create_empty_openida_project()/* FIXME */); + gtk_widget_show(dialog); + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements global. * +* * +* Description : Met à jour le contenu du menu 'Projet'. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reload_menu_project(GObject *ref) +{ + GtkWidget *menuitem; /* Menu principal à compléter */ + GtkWidget *menubar; /* Support pour éléments */ + GList *list; /* Liste des éléments en place */ + GList *iter; /* Boucle de parcours #1 */ + size_t count; /* Nombre de binaires attachés */ + const openida_binary **binaries; /* Liste de ces binaires */ + size_t i; /* Boucle de parcours #2 */ + const char *desc; /* Description à afficher */ + GtkWidget *submenuitem; /* Sous-menu à ajouter */ + + menuitem = GTK_WIDGET(g_object_get_data(ref, "menu_prj_remove_bin")); + menubar = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuitem)); + + /* Remise à zéro */ + + list = gtk_container_get_children(GTK_CONTAINER(menubar)); + + for (iter = list; iter != NULL; iter = g_list_next(iter)) + gtk_container_remove(GTK_CONTAINER(menubar), GTK_WIDGET(iter->data)); + + g_list_free(list); + + /* Ajout des entrées */ + + binaries = get_openida_project_binaries(get_current_openida_project(), &count); + + for (i = 0; i < count; i++) + { + desc = openida_binary_to_string(binaries[i]); + + submenuitem = qck_create_menu_item(NULL, NULL, desc, G_CALLBACK(mcb_project_remove_binary), ref); + g_object_set_data(G_OBJECT(submenuitem), "binary", binaries[i]); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + } + + gtk_widget_set_sensitive(menuitem, count > 0); + +} diff --git a/src/project.c b/src/project.c new file mode 100644 index 0000000..2ec9e09 --- /dev/null +++ b/src/project.c @@ -0,0 +1,431 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * project.c - gestion d'un groupe de fichiers binaires + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "project.h" + + +#include <dirent.h> +#include <malloc.h> +#include <string.h> +#include <unistd.h> + + +#include "easygtk.h" +#include "xdg.h" +#include "xml.h" + + + + +/* Propriétés d'un ensemble de fichiers ouverts */ +struct openida_project +{ + char *filename; /* Lieu d'enregistrement */ + + openida_binary **binaries; /* Fichiers binaires associés */ + size_t binaries_count; /* Nombre de ces fichiers */ + + + +}; + + + + + + + + +/****************************************************************************** +* * +* Paramètres : project = éventuel adresse à renvoyer désormais. * +* * +* Description : Fournit l'adresse du projet courant. * +* * +* Retour : Adresse du projet ouvert ou NULL si aucun (!). * +* * +* Remarques : - * +* * +******************************************************************************/ + +openida_project *_get_current_openida_project(openida_project *project) +{ + static openida_project *result = NULL; /* Adresse à retourner */ + + if (project != NULL) + { + if (result != NULL) close_openida_project(result); + result = project; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un projet vide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +openida_project *create_empty_openida_project(void) +{ + openida_project *result; /* Adresse à retourner */ + + result = (openida_project *)calloc(1, sizeof(openida_project)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : filename = chemin d'accès au fichier à charger. * +* * +* Description : Crée un projet à partir du contenu XML d'un fichier. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +openida_project *load_openida_project_from_xml(const char *filename) +{ + openida_project *result; /* Adresse à retourner */ + xmlDoc *xdoc; /* Structure XML chargée */ + xmlNode *xroot; /* Noeud premier de la def. */ + xmlXPathContextPtr xpathCtx; /* Contexte pour les XPath */ + xmlXPathObjectPtr xpathObj; /* Cible d'une recherche */ + unsigned int i; /* Boucle de parcours */ + openida_binary *binary; /* Représentation à intégrer */ + + if (!open_xml_file(filename, &xdoc, &xroot, &xpathCtx)) return NULL; + + result = (openida_project *)calloc(1, sizeof(openida_project)); + + + + xpathObj = get_node_xpath_object(xpathCtx, "/OpenIDAProject/Binaries/*"); + + printf("nodes :: %d\n", XPATH_OBJ_NODES_COUNT(xpathObj)); + + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xpathObj); i++) + { + binary = read_openida_binary_from_xml(xpathCtx, "/OpenIDAProject/Binaries", i + 1); + + if (binary != NULL) + attach_binary_to_openida_project(result, binary); + + } + + if(xpathObj != NULL) + xmlXPathFreeObject(xpathObj); + + + + + + + + + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(xdoc); + xmlCleanupParser(); + + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à effacer de la mémoire. * +* * +* Description : Ferme un projet et libère la mémoire associée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void close_openida_project(openida_project *project) +{ + + + + + free(project); + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à consulter. * +* * +* Description : Indique si un projet a tous les éléments pour être sauvé. * +* * +* Retour : true si aucun nom de fichier n'a à être fourni. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool has_storing_filename(const openida_project *project) +{ + return (project->filename != NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à sauvegarder. * +* filename = nom de fichier à utiliser ou NULL pour l'existant.* +* * +* Description : Procède à l'enregistrement d'un projet donné. * +* * +* Retour : true si l'enregistrement s'est déroule sans encombre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_openida_project_to_xml(openida_project *project, const char *filename) +{ + bool result; /* Bilan à faire remonter */ + xmlTextWriterPtr writer; /* Rédacteur pour la sortie XML*/ + size_t i; /* Boucle de parcours */ + + writer = start_writing_xml_file(filename); + + result = open_xml_element(writer, "OpenIDAProject"); + + /* Enregistrement des éléments binaires attachés */ + + result &= open_xml_element(writer, "Binaries"); + + for (i = 0; i < project->binaries_count && result; i++) + write_openida_binary_to_xml(project->binaries[i], writer); + + result &= close_xml_element(writer); + + result &= close_xml_element(writer); + + result &= end_writing_xml_file(writer); + + if (result) + { + if (project->filename != NULL) free(project->filename); + project->filename = strdup(filename); + } + + return result; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : project = project à effacer de la mémoire. * +* binary = fichier binaire à associer au projet actuel. * +* * +* Description : Attache un fichier donné à un projet donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void attach_binary_to_openida_project(openida_project *project, openida_binary *binary) +{ + project->binaries = (openida_binary **)realloc(project->binaries, + ++project->binaries_count * sizeof(openida_binary *)); + + + + + + project->binaries[project->binaries_count - 1] = binary; + + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à effacer de la mémoire. * +* binary = fichier binaire à dissocier au projet actuel. * +* * +* Description : Détache un fichier donné à un projet donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void detach_binary_to_openida_project(openida_project *project, openida_binary *binary) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < project->binaries_count; i++) + if (project->binaries[i] == binary) break; + + if ((i + 1) < project->binaries_count) + memmove(&project->binaries[i], &project->binaries[i + 1], (project->binaries_count - i - 1) * sizeof(openida_binary *)); + + project->binaries = (openida_binary **)realloc(project->binaries, + --project->binaries_count * sizeof(openida_binary *)); + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à effacer de la mémoire. * +* count = nombre de binaires pris en compte. [OUT] * +* * +* Description : Fournit l'ensemble des binaires associés à un projet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +const openida_binary **get_openida_project_binaries(const openida_project *project, size_t *count) +{ + *count = project->binaries_count; + + return project->binaries; + +} + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTIE GRAPHIQUE DES [DE]CHARGEMENTS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : ref = espace global de référencement. * +* func = fonction à appeler lors d'un clic sur les menus. * +* * +* Description : Met en place les menus rechargeant les projets récents. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void load_recent_openida_projects_list(GObject *ref, GCallback *func) +{ + gboolean one_entry; /* Au moins en entrée chargée */ + GtkWidget *menuitem; /* Menu principal à compléter */ + GtkWidget *menubar; /* Support pour éléments */ + char *directory; /* Répertoire prévu pour proj. */ + DIR *dir; /* Répertoire avec contenu ? */ + struct dirent *entry; /* Elément de répertoire */ + char *filename; /* Nom de fichier à ouvrir */ + char realfile[PATH_MAX]; /* Nom du fichier pointé */ + ssize_t ret; /* Bilan de la lecture */ + GtkWidget *submenuitem; /* Sous-menu à ajouter */ + + one_entry = false; + + menuitem = GTK_WIDGET(g_object_get_data(ref, "menu_recent_prjs")); + menubar = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuitem)); + + directory = get_xdg_config_dir("openida/recents"); + + dir = opendir(directory); + /* TODO :: check */ + + if (dir != NULL) + { + for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) + { + if (strcmp(entry->d_name, ".") == 0) continue; + if (strcmp(entry->d_name, "..") == 0) continue; + + if (strlen(entry->d_name) <= 4) continue; + if (strcmp(&entry->d_name[strlen(entry->d_name) - 4], ".xml") != 0) continue; + + filename = (char *)calloc(strlen(directory) + 2 + strlen(entry->d_name) + 1, sizeof(char)); + strcpy(filename, directory); + strcat(filename, "/"); + strcat(filename, entry->d_name); + + ret = readlink(filename, realfile, PATH_MAX); + /* TODO :: check */ + + if (ret == -1) goto process_next_recent; + + submenuitem = qck_create_menu_item(NULL, NULL, realfile, func, ref); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + one_entry = true; + + process_next_recent: + + free(filename); + + } + + closedir(dir); + + } + + free(directory); + + recent_list_end: + + gtk_widget_set_sensitive(menuitem, one_entry); + +} diff --git a/src/project.h b/src/project.h new file mode 100644 index 0000000..a08039d --- /dev/null +++ b/src/project.h @@ -0,0 +1,88 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * project.h - prototypes pour la gestion d'un groupe de fichiers binaires + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PROJECT_H +#define _PROJECT_H + + +#include "binary.h" + + + +/* Propriétés d'un ensemble de fichiers ouverts */ +typedef struct openida_project openida_project; + + + +#define set_current_openida_project(prj) _get_current_openida_project(prj) +#define get_current_openida_project() _get_current_openida_project(NULL) + + +/* Fournit l'adresse du projet courant. */ +openida_project *_get_current_openida_project(openida_project *); + +/* Crée un projet vide. */ +openida_project *create_empty_openida_project(void); + +/* Crée un projet à partir du contenu XML d'un fichier. */ +openida_project *load_openida_project_from_xml(const char *); + +/* Ferme un projet et libère la mémoire associée. */ +void close_openida_project(openida_project *); + +/* Indique si un projet a tous les éléments pour être sauvé. */ +bool has_storing_filename(const openida_project *); + + + +/* Procède à l'enregistrement d'un projet donné. */ +bool write_openida_project_to_xml(openida_project *, const char *); + + + +/* Attache un fichier donné à un projet donné. */ +void attach_binary_to_openida_project(openida_project *, openida_binary *); + +/* Détache un fichier donné à un projet donné. */ +void detach_binary_to_openida_project(openida_project *, openida_binary *); + +/* Fournit l'ensemble des binaires associés à un projet. */ +const openida_binary **get_openida_project_binaries(const openida_project *, size_t *); + + + + + +/* ---------------------- PARTIE GRAPHIQUE DES [DE]CHARGEMENTS ---------------------- */ + + +/* Met en place les menus rechargeant les projets récents. */ +void load_recent_openida_projects_list(GObject *, GCallback *); + + + + + + + +#endif /* _PROJECT_H */ diff --git a/src/xdg.c b/src/xdg.c new file mode 100644 index 0000000..6541e89 --- /dev/null +++ b/src/xdg.c @@ -0,0 +1,103 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * xdg.c - compléments mineurs au support Freedesktop + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "xdg.h" + + +#include <dirent.h> +#include <malloc.h> +#include <stdlib.h> +#include <string.h> + + + +/****************************************************************************** +* * +* Paramètres : suffix = élément visé dans le répertoire de configuration. * +* * +* Description : Détermine le chemin d'un répertoire selon les specs. XDG. * +* * +* Retour : Chemin d'accès aux configurations personnelles ou NULL. * +* * +* Remarques : cf. http://standards.freedesktop.org/basedir-spec/. * +* * +******************************************************************************/ + +char *get_xdg_config_dir(const char *suffix) +{ + char *result; /* Chemin d'accès à renvoyer */ + const char *env; /* Valeur de l'environnement */ + DIR *directory; /* Répertoire avec contenu ? */ + struct dirent *entry; /* Elément de répertoire */ + + result = NULL; + + env = getenv("XDG_CONFIG_HOME"); + + if (env != NULL && env[0] != '\0') + { + directory = opendir(env); + if (directory == NULL) goto default_cfg_dir; + + for (entry = readdir(directory); entry != NULL && result == NULL; entry = readdir(directory)) + { + if (strcmp(entry->d_name, ".") == 0) continue; + if (strcmp(entry->d_name, "..") == 0) continue; + + result = (char *)calloc(strlen(env) + 2 + strlen(suffix) + 1, sizeof(char)); + strcpy(result, env); + + if (env[strlen(env) - 1] != '/') + strcat(result, "/"); + + strcat(result, "."); + strcat(result, suffix); + + } + + closedir(directory); + + } + + default_cfg_dir: + + if (result == NULL) + { + env = getenv("HOME"); + if (env == NULL || env[0] == '\0') return NULL; + + result = (char *)calloc(strlen(env) + 1 + strlen(".config/") + strlen(suffix) + 1, sizeof(char)); + + strcpy(result, env); + + if (env[strlen(env) - 1] != '/') + strcat(result, "/"); + + strcat(result, ".config/"); + strcat(result, suffix); + + } + + return result; + +} diff --git a/src/xdg.h b/src/xdg.h new file mode 100644 index 0000000..c8cd97d --- /dev/null +++ b/src/xdg.h @@ -0,0 +1,34 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * xdg.h - prototypes pour des compléments mineurs au support Freedesktop + * + * Copyright (C) 2008 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _XDG_H +#define _XDG_H + + + +/* Détermine le chemin d'un répertoire selon les specs. XDG. */ +char *get_xdg_config_dir(const char *); + + + +#endif /* _XDG_H */ diff --git a/src/xml.c b/src/xml.c new file mode 100644 index 0000000..baa4eb2 --- /dev/null +++ b/src/xml.c @@ -0,0 +1,574 @@ + +/* Firebox Tools - Outils de configurations pour le WM Firebox + * xml.c - lecture ou écriture de documents XML + * + * Copyright (C) 2006-2007 Cyrille Bagard + * + * This file is part of Firebox Tools. + * + * Firebox Tools 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 2 of the License, or + * (at your option) any later version. + * + * Firebox Tools 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 "xml.h" + + +#include <stdarg.h> +#include <string.h> + + +#ifdef DEBUG +# define XML_LOG fprintf +#else +# define XML_LOG if (FALSE) fprintf +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERATIONS DE LECTURE D'UN FICHIER XML */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : filename = nom du fichier à ouvrir. * +* xdoc = structure XML chargée. [OUT] * +* xroot = noeud premier de l'ensemble des définitions.[OUT] * +* xpathCtx = contexte à utiliser pour les recherches. [OUT] * +* * +* Description : Ouvre un fichier XML de façon encadrée. * +* * +* Retour : true si l'opération a pu s'effectuer, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gboolean open_xml_file(const char *filename, xmlDoc **xdoc, xmlNode **xroot, xmlXPathContextPtr *xpathCtx) +{ + *xdoc = xmlParseFile(filename); + + if (*xdoc == NULL) + { + XML_LOG(stderr, "Can not parse the XML file '%s'\n", filename); + return FALSE; + } + + *xroot = xmlDocGetRootElement(*xdoc); + + if (*xroot == NULL) + { + XML_LOG(stderr, "Can not access the root node in '%s'\n", filename); + xmlFreeDoc(*xdoc); + return FALSE; + } + + *xpathCtx = xmlXPathNewContext(*xdoc); + + if (*xpathCtx == NULL) + { + XML_LOG(stderr, "Unable to create new XPath context\n"); + xmlFreeDoc(*xdoc); + return FALSE; + } + + return TRUE; + +} + + +/****************************************************************************** +* * +* Paramètres : xpathCtx = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* * +* Description : Obtient de façon encadrée l'accès à un noeud défini. * +* * +* Retour : Adresse de l'accès trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +xmlXPathObjectPtr get_node_xpath_object(xmlXPathContextPtr xpathCtx, const char *path) +{ + xmlXPathObjectPtr result; /* Noeud XML à renvoyer */ + + result = xmlXPathEvalExpression(BAD_CAST path, xpathCtx); + + if (result == NULL) + { + XML_LOG(stderr, "Unable to evaluate xpath expression '%s'\n", path); + return NULL; + } + + if (result->nodesetval == NULL) + { + XML_LOG(stderr, "Node '%s' not found\n", path); + xmlXPathFreeObject(result); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud dont une propriété est à lire. * +* * +* Description : Obtient une valeur placée entre <...> et </...>. * +* * +* Retour : Valeur sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *qck_get_node_text_value(xmlNodePtr node) +{ + char *result; /* Valeur en question renvoyée */ + + result = NULL; + + if (node != NULL) + if (node->children != NULL) + if (node->children->content != NULL) + result = strdup((char *)node->children->content); + + if (result == NULL) XML_LOG(stderr, "No text value for node '%s'\n", node->name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xpathCtx = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* * +* Description : Obtient une valeur placée entre <...> et </...>. * +* * +* Retour : Valeur sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *get_node_text_value(xmlXPathContextPtr xpathCtx, const char *path) +{ + char *result; /* Valeur en question renvoyée */ + xmlXPathObjectPtr xpathObj; /* Point de départ XML */ + + result = NULL; + + xpathObj = get_node_xpath_object(xpathCtx, path); + if (xpathObj == NULL) return NULL; + + if (xpathObj->nodesetval->nodeNr > 0) + result = qck_get_node_text_value(xpathObj->nodesetval->nodeTab[0]); + + xmlXPathFreeObject(xpathObj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud dont une propriété est à lire. * +* name = nom de la propriété à lire. * +* * +* Description : Obtient la valeur d'une propriété d'un élément. * +* * +* Retour : Valeur sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *qck_get_node_prop_value(xmlNodePtr node, const char *name) +{ + char *result; /* Valeur en question renvoyée */ + xmlAttrPtr attrib; /* Liste d'attributs présents */ + + result = NULL; + + if (node == NULL) return NULL; + + /* Lecture de la valeur */ + + for (attrib = node->properties; attrib != NULL && result == NULL; attrib = attrib->next) + if (xmlStrEqual(attrib->name, BAD_CAST name)) result = strdup((char *)attrib->children->content); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xpathCtx = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud à traiter. * +* name = nom de la propriété à lire. * +* * +* Description : Obtient la valeur d'une propriété d'un élément. * +* * +* Retour : Valeur sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *get_node_prop_value(xmlXPathContextPtr xpathCtx, const char *path, const char *name) +{ + char *result; /* Valeur en question renvoyée */ + xmlXPathObjectPtr xpathObj; /* Point de départ XML */ + + result = NULL; + + xpathObj = get_node_xpath_object(xpathCtx, path); + if (xpathObj == NULL) return NULL; + + if (xpathObj->nodesetval->nodeNr > 0) + result = qck_get_node_prop_value(xpathObj->nodesetval->nodeTab[0], name); + + xmlXPathFreeObject(xpathObj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud de texte avec un lien avec le document XML. * +* * +* Description : Construit un chemin d'accès complet selon le fichier XML. * +* * +* Retour : Valeur à libérer de la mémoire après usage ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *qck_build_filename_with_doc_url(xmlNodePtr node) +{ + char *result; /* Construction à retourner */ + char *text; /* Valeur du texte lu */ + char *last; /* Point de remplacement */ + + result = NULL; + + text = qck_get_node_text_value(node); + + if (text != NULL) + { + result = (char *)calloc(xmlStrlen(node->doc->URL) + strlen(text) + 1, sizeof(char)); + + strcpy(result, (const char *)node->doc->URL); + + last = strrchr(result, '/'); + last++; + + strcpy(last, text); + free(text); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xpathCtx = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud à traiter. * +* * +* Description : Construit un chemin d'accès complet selon le fichier XML. * +* * +* Retour : Valeur sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *build_filename_with_doc_url(xmlXPathContextPtr xpathCtx, const char *path) +{ + char *result; /* Valeur en question renvoyée */ + xmlXPathObjectPtr xpathObj; /* Point de départ XML */ + + result = NULL; + + xpathObj = get_node_xpath_object(xpathCtx, path); + if (xpathObj == NULL) return NULL; + + if (xpathObj->nodesetval->nodeNr > 0) + result = qck_build_filename_with_doc_url(xpathObj->nodesetval->nodeTab[0]); + + xmlXPathFreeObject(xpathObj); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERATIONS D'ECRITURE D'UN FICHIER XML */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : filename = nom du fichier à ouvrir. * +* * +* Description : Amorce l'écriture d'un nouveau fichier XML. * +* * +* Retour : Rédacteur mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +xmlTextWriterPtr start_writing_xml_file(const char *filename) +{ + xmlTextWriterPtr result; /* Moyen à retourner */ + int retval; /* Bilan d'une opération */ + + result = xmlNewTextWriterFilename(filename, 0); + + if (result == NULL) + { + XML_LOG(stderr, "Error creating the xml writer\n"); + return NULL; + } + + retval = xmlTextWriterStartDocument(result, NULL, "UTF-8", "yes"); + if (retval < 0) + { + XML_LOG(stderr, "Error at xmlTextWriterStartDocument\n"); + xmlFreeTextWriter(result); + return NULL; + } + + retval = xmlTextWriterSetIndent(result, 1); + if (retval < 0) + { + XML_LOG(stderr, "Error setting indentation\n"); + xmlFreeTextWriter(result); + return NULL; + } + + retval = xmlTextWriterSetIndentString(result, BAD_CAST "\t"); + if (retval < 0) + { + XML_LOG(stderr, "Error setting indentation string\n"); + xmlFreeTextWriter(result); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : writer = rédacteur dédié à l'écriture. * +* * +* Description : Met fin à l'écriture d'un nouveau fichier XML. * +* * +* Retour : Bilan de l'opération : true ou false. * +* * +* Remarques : Ferme au besoin toutes les balises encore ouvertes. * +* * +******************************************************************************/ + +bool end_writing_xml_file(xmlTextWriterPtr writer) +{ + int retval; /* Bilan de l'opération */ + + retval = xmlTextWriterEndDocument(writer); + if (retval < 0) + { + XML_LOG(stderr, "Error at xmlTextWriterEndDocument\n"); + return false; + } + + xmlFreeTextWriter(writer); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : writer = rédacteur dédié à l'écriture. * +* name = nom de la balise à écrire. * +* * +* Description : Ecrit une balise et ne la referme pas. * +* * +* Retour : Bilan de l'opération : true ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool open_xml_element(xmlTextWriterPtr writer, const char *name) +{ + int retval; /* Bilan de l'opération */ + + retval = xmlTextWriterStartElement(writer, BAD_CAST name); + + if (retval < 0) + XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n"); + + return (retval >= 0); + +} + + +/****************************************************************************** +* * +* Paramètres : writer = rédacteur dédié à l'écriture. * +* * +* Description : Ferme la dernière balise laissée ouverte. * +* * +* Retour : Bilan de l'opération : true ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool close_xml_element(xmlTextWriterPtr writer) +{ + int retval; /* Bilan de l'opération */ + + retval = xmlTextWriterEndElement(writer); + + if (retval < 0) + XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n"); + + return (retval >= 0); + +} + + +/****************************************************************************** +* * +* Paramètres : writer = rédacteur dédié à l'écriture. * +* name = nom de la balise à écrire. * +* format = format de la chaîne à traiter. * +* ... = informations à inscrire. * +* * +* Description : Ecrit une balise avec un contenu textuel. * +* * +* Retour : Bilan de l'opération : true ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_xml_element_with_content(xmlTextWriterPtr writer, const char *name, const char *format, ...) +{ + va_list ap; /* Liste d'arguments variable */ + int retval; /* Bilan de l'opération */ + + va_start(ap, format); + + retval = xmlTextWriterWriteVFormatElement(writer, BAD_CAST name, format, ap); + + if (retval < 0) + XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n"); + + va_end(ap); + + return (retval >= 0); + +} + + +/****************************************************************************** +* * +* Paramètres : writer = rédacteur dédié à l'écriture. * +* name = nom de l'attribut à écrire. * +* format = format de la chaîne à traiter. * +* ... = informations à inscrire. * +* * +* Description : Ecrit un attribut avec un contenu textuel. * +* * +* Retour : Bilan de l'opération : true ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_xml_attribute(xmlTextWriterPtr writer, const char *name, const char *format, ...) +{ + va_list ap; /* Liste d'arguments variable */ + int retval; /* Bilan de l'opération */ + + va_start(ap, format); + + retval = xmlTextWriterWriteVFormatAttribute(writer, BAD_CAST name, format, ap); + + if (retval < 0) + XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n"); + + va_end(ap); + + return (retval >= 0); + +} + + +/****************************************************************************** +* * +* Paramètres : writer = rédacteur dédié à l'écriture. * +* format = format de la chaîne à traiter. * +* ... = informations à inscrire. * +* * +* Description : Ecrit un contenu textuel. * +* * +* Retour : Bilan de l'opération : true ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_xml_content(xmlTextWriterPtr writer, const char *format, ...) +{ + va_list ap; /* Liste d'arguments variable */ + int retval; /* Bilan de l'opération */ + + va_start(ap, format); + + retval = xmlTextWriterWriteVFormatString(writer, format, ap); + + if (retval < 0) + XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n"); + + va_end(ap); + + return (retval >= 0); + +} diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 0000000..2d35cc6 --- /dev/null +++ b/src/xml.h @@ -0,0 +1,96 @@ + +/* Firebox Tools - Outils de configurations pour le WM Firebox + * xml.h - prototypes pour la lecture ou l'écriture de documents XML + * + * Copyright (C) 2006-2007 Cyrille Bagard + * + * This file is part of Firebox Tools. + * + * Firebox Tools 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 2 of the License, or + * (at your option) any later version. + * + * Firebox Tools 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 _XML_H +#define _XML_H + + +#include <stdbool.h> +#include <glib/gtypes.h> +#include <libxml/tree.h> +#include <libxml/xmlwriter.h> +#include <libxml/xpath.h> + + + +/* --------------------- OPERATIONS DE LECTURE D'UN FICHIER XML --------------------- */ + + +#define XPATH_OBJ_NODES_COUNT(obj) (obj != NULL ? obj->nodesetval->nodeNr : 0) +#define NODE_FROM_PATH_OBJ(obj, i) obj->nodesetval->nodeTab[i] + + +/* Ouvre un fichier XML de façon encadrée. */ +gboolean open_xml_file(const char *filename, xmlDoc **, xmlNode **, xmlXPathContextPtr *); + +/* Obtient de façon encadrée l'accès à un noeud défini. */ +xmlXPathObjectPtr get_node_xpath_object(xmlXPathContextPtr, const char *); + +/* Obtient une valeur placée entre <...> et </...>. */ +char *qck_get_node_text_value(xmlNodePtr); + +/* Obtient une valeur placée entre <...> et </...>. */ +char *get_node_text_value(xmlXPathContextPtr, const char *); + +/* Obtient la valeur d'une propriété d'un élément. */ +char *qck_get_node_prop_value(xmlNodePtr, const char *); + +/* Obtient la valeur d'une propriété d'un élément. */ +char *get_node_prop_value(xmlXPathContextPtr, const char *, const char *); + +/* Construit un chemin d'accès complet selon le fichier XML. */ +char *qck_build_filename_with_doc_url(xmlNodePtr); + +/* Construit un chemin d'accès complet selon le fichier XML. */ +char *build_filename_with_doc_url(xmlXPathContextPtr xpathCtx, const char *path); + + + +/* --------------------- OPERATIONS D'ECRITURE D'UN FICHIER XML --------------------- */ + + +/* Amorce l'écriture d'un nouveau fichier XML. */ +xmlTextWriterPtr start_writing_xml_file(const char *); + +/* Met fin à l'écriture d'un nouveau fichier XML. */ +bool end_writing_xml_file(xmlTextWriterPtr); + +/* Ecrit une balise et ne la referme pas. */ +bool open_xml_element(xmlTextWriterPtr, const char *); + +/* Ferme la dernière balise laissée ouverte. */ +bool close_xml_element(xmlTextWriterPtr); + +/* Ecrit une balise avec un contenu textuel. */ +bool write_xml_element_with_content(xmlTextWriterPtr, const char *, const char *, ...); + +/* Ecrit un attribut avec un contenu textuel. */ +bool write_xml_attribute(xmlTextWriterPtr, const char *, const char *, ...); + +/* Ecrit un contenu textuel. */ +bool write_xml_content(xmlTextWriterPtr, const char *, ...); + + + +#endif /* _XML_H */ |