summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--plugins/pychrysalide/analysis/project.c80
-rw-r--r--plugins/pychrysalide/helpers.c45
-rw-r--r--plugins/pychrysalide/helpers.h3
-rw-r--r--src/analysis/project.c69
-rw-r--r--src/analysis/project.h8
-rw-r--r--src/gui/editor.c49
-rw-r--r--src/gui/menus/project.c2
-rw-r--r--src/main.c2
9 files changed, 236 insertions, 24 deletions
diff --git a/configure.ac b/configure.ac
index 9effa17..c8e6cf1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -332,7 +332,7 @@ AC_SUBST(LIBPYGOBJECT_LIBS)
AC_CONFIG_FILES([stamp-h po/Makefile.in], [echo timestamp > stamp-h])
-AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM\nVOID:BOOLEAN,UINT64\nVOID:BOOLEAN,ULONG,ULONG\nVOID:INT,INT\nVOID:OBJECT,BOOLEAN\nVOID:ULONG,BOOLEAN" > src/glibext/chrysamarshal.list])
+AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM\nVOID:BOOLEAN,UINT64\nVOID:BOOLEAN,ULONG,ULONG\nVOID:INT,INT\nVOID:OBJECT,BOOLEAN\nVOID:ULONG,BOOLEAN\nVOID:POINTER,UINT" > src/glibext/chrysamarshal.list])
AC_CONFIG_FILES([Makefile
doc/Makefile
diff --git a/plugins/pychrysalide/analysis/project.c b/plugins/pychrysalide/analysis/project.c
index 1a85f71..137efbf 100644
--- a/plugins/pychrysalide/analysis/project.c
+++ b/plugins/pychrysalide/analysis/project.c
@@ -45,6 +45,9 @@ static PyObject *py_study_project_new(PyTypeObject *, PyObject *, PyObject *);
/* Procède à l'enregistrement d'un projet donné. */
static PyObject *py_study_project_save(PyObject *, PyObject *);
+/* Détermine si un contenu doit être écarté ou conservé. */
+static bool filter_loadable_content_with_python(GLoadedContent *, PyObject *);
+
/* Assure l'intégration de contenus binaires dans un projet. */
static PyObject *py_study_project_discover_binary_content(PyObject *, PyObject *);
@@ -135,6 +138,57 @@ static PyObject *py_study_project_save(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : content = contenu chargeable à étudier ou NULL à la fin. *
+* callable = procédure de filtre en Python. *
+* *
+* Description : Détermine si un contenu doit être écarté ou conservé. *
+* *
+* Retour : true si le contenu doit être conservé, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool filter_loadable_content_with_python(GLoadedContent *content, PyObject *callable)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *arg; /* Argument à fournir au filtre*/
+ PyObject *status; /* Bilan de l'analyse */
+
+ gstate = PyGILState_Ensure();
+
+ if (content == NULL)
+ {
+ Py_DECREF(callable);
+ result = false;
+ }
+
+ else
+ {
+ arg = pygobject_new(G_OBJECT(content));
+
+ status = PyObject_CallFunctionObjArgs(callable, arg, NULL);
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+
+ result = status == NULL || status == Py_False || status == Py_None ? false : true;
+ Py_XDECREF(status);
+
+ Py_DECREF(arg);
+
+ }
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = projet d'étude à manipuler. *
* args = arguments accompagnant l'appel. *
* *
@@ -148,16 +202,32 @@ static PyObject *py_study_project_save(PyObject *self, PyObject *args)
static PyObject *py_study_project_discover_binary_content(PyObject *self, PyObject *args)
{
- GStudyProject *project; /* Version GLib du format */
- int ret; /* Bilan de lecture des args. */
+ PyObject *callable; /* Filtre de contenus éventuel */
GBinContent *content; /* Instance de contenu binaire */
+ int ret; /* Bilan de lecture des args. */
+ GStudyProject *project; /* Version GLib du format */
- project = G_STUDY_PROJECT(pygobject_get(self));
+ callable = NULL;
- ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+ ret = PyArg_ParseTuple(args, "O&|O&",
+ convert_to_binary_content, &content,
+ convert_to_callable, &callable);
if (!ret) return NULL;
- g_study_project_discover_binary_content(project, content);
+ project = G_STUDY_PROJECT(pygobject_get(self));
+
+ if (callable != NULL)
+ {
+ Py_INCREF(callable);
+
+ g_study_project_discover_binary_content(project, content,
+ (filter_loadable_cb)filter_loadable_content_with_python,
+ callable);
+
+ }
+
+ else
+ g_study_project_discover_binary_content(project, content, NULL, NULL);
Py_RETURN_NONE;
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 7e31fa7..2b62e57 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -109,6 +109,51 @@ PyObject *status_to_rich_cmp_state(int status, int op)
/******************************************************************************
* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en élément appelable. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_callable(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyCallable_Check(arg);
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to a callable object");
+ break;
+
+ case 1:
+ *((PyObject **)dst) = arg;
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : target = propriétaire de la routine visée. *
* method = désignation de la fonction à appeler. *
* *
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index ce5840b..f7ebdc3 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -38,6 +38,9 @@
/* Traduit pour Python le bilan d'une comparaison riche. */
PyObject *status_to_rich_cmp_state(int, int);
+/* Tente de convertir en élément appelable. */
+int convert_to_callable(PyObject *, void *);
+
/* Indique si une routine Python existe ou non. */
bool has_python_method(PyObject *, const char *);
diff --git a/src/analysis/project.c b/src/analysis/project.c
index e01a126..8474610 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -38,6 +38,7 @@
#include "../core/logs.h"
#include "../core/params.h"
#include "../core/queue.h"
+#include "../glibext/chrysamarshal.h"
#include "../glibext/delayed-int.h"
@@ -66,6 +67,7 @@ struct _GStudyProjectClass
/* Signaux */
+ void (* contents_available) (GStudyProject, GLoadedContent **, guint);
void (* content_added) (GStudyProject *, GLoadedContent *);
void (* content_removed) (GStudyProject *, GLoadedContent *);
@@ -92,9 +94,6 @@ static void g_study_project_finalize(GStudyProject *);
/* Assure l'intégration de contenus listés dans du XML. */
static void g_study_project_recover_binary_contents(GStudyProject *, xmlDoc *, xmlXPathContext *);
-/* Réceptionne la recette d'une analyse de contenu. */
-static void on_loaded_content_analyzed(GLoadedContent *, gboolean, GStudyProject *);
-
/* ------------------------ CHARGEMENTS DE CONTENUS BINAIRES ------------------------ */
@@ -124,6 +123,9 @@ typedef struct _GLoadingHandler
GCond wait_cond; /* Réveil d'attente de fin */
GMutex mutex; /* Encadrement des accès */
+ filter_loadable_cb filter; /* Filtre des contenus ? */
+ void *data; /* Données utiles au filtrage */
+
} GLoadingHandler;
/* Chargement de contenus binaires (classe) */
@@ -150,7 +152,7 @@ static void g_loading_handler_dispose(GLoadingHandler *);
static void g_loading_handler_finalize(GLoadingHandler *);
/* Crée une tâche de chargement de contenu bianire. */
-static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *, GBinContent *);
+static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *, GBinContent *, filter_loadable_cb, void *);
/* Crée une tâche de chargement de contenu bianire. */
static GLoadingHandler *g_loading_handler_new_recovering(GStudyProject *, xmlDoc *, xmlXPathContext *);
@@ -199,6 +201,14 @@ static void g_study_project_class_init(GStudyProjectClass *klass)
object->dispose = (GObjectFinalizeFunc/* ! */)g_study_project_dispose;
object->finalize = (GObjectFinalizeFunc)g_study_project_finalize;
+ g_signal_new("contents-available",
+ G_TYPE_STUDY_PROJECT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GStudyProjectClass, contents_available),
+ NULL, NULL,
+ g_cclosure_user_marshal_VOID__POINTER_UINT,
+ G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
+
g_signal_new("content-added",
G_TYPE_STUDY_PROJECT,
G_SIGNAL_RUN_LAST,
@@ -545,6 +555,8 @@ static void g_study_project_recover_binary_contents(GStudyProject *project, xmlD
* *
* Paramètres : project = projet dont le contenu est à compléter. *
* content = contenu binaire à mémoriser pour le projet. *
+* filter = procédure de filtrage de contenus chargés. *
+* data = données utiles à la procédure de filtre. *
* *
* Description : Assure l'intégration de contenus binaires dans un projet. *
* *
@@ -554,11 +566,11 @@ static void g_study_project_recover_binary_contents(GStudyProject *project, xmlD
* *
******************************************************************************/
-void g_study_project_discover_binary_content(GStudyProject *project, GBinContent *content)
+void g_study_project_discover_binary_content(GStudyProject *project, GBinContent *content, filter_loadable_cb filter, void *data)
{
GLoadingHandler *handler; /* Encadrement du chargement */
- handler = g_loading_handler_new_discovering(project, content);
+ handler = g_loading_handler_new_discovering(project, content, filter, data);
g_work_queue_schedule_work(get_work_queue(), G_DELAYED_WORK(handler), LOADING_WORK_GROUP);
@@ -579,7 +591,7 @@ void g_study_project_discover_binary_content(GStudyProject *project, GBinContent
* *
******************************************************************************/
-static void on_loaded_content_analyzed(GLoadedContent *content, gboolean success, GStudyProject *project)
+void on_loaded_content_analyzed(GLoadedContent *content, gboolean success, GStudyProject *project)
{
const char *desc; /* Description du contenu */
@@ -908,6 +920,8 @@ static void g_loading_handler_finalize(GLoadingHandler *handler)
* *
* Paramètres : project = projet dont le contenu est à compléter. *
* content = contenu binaire à mémoriser pour le projet. *
+* filter = procédure de filtrage de contenus chargés. *
+* data = données utiles à la procédure de filtre. *
* *
* Description : Crée une tâche de chargement de contenu bianire. *
* *
@@ -917,7 +931,7 @@ static void g_loading_handler_finalize(GLoadingHandler *handler)
* *
******************************************************************************/
-static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *project, GBinContent *content)
+static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *project, GBinContent *content, filter_loadable_cb filter, void *data)
{
GLoadingHandler *result; /* Tâche à retourner */
GContentExplorer *explorer; /* Explorateur de contenus */
@@ -935,6 +949,9 @@ static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *project
result->resolved = 0;
+ result->filter = filter;
+ result->data = data;
+
explorer = get_current_content_explorer();
g_mutex_lock(&result->mutex);
@@ -993,6 +1010,9 @@ static GLoadingHandler *g_loading_handler_new_recovering(GStudyProject *project,
result->resolved = 0;
+ result->filter = NULL;
+ result->data = NULL;
+
explorer = get_current_content_explorer();
explored = 0;
@@ -1211,6 +1231,7 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
{
GLoadedContent **available; /* Contenus chargés valables */
size_t count; /* Quantité de ces contenus */
+ bool keep; /* Conservation finale de liste*/
size_t i; /* Boucle de parcours */
GBinContent *content; /* Contenu brut à manipuler */
const gchar *hash; /* Empreinte d'un contenu */
@@ -1223,6 +1244,8 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
{
available = g_content_resolver_get_all(resolver, wid, &count);
+ keep = false;
+
/* Rechargement à partir d'XML ? */
if (handler->xdoc != NULL)
{
@@ -1295,19 +1318,39 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
*/
g_object_ref(G_OBJECT(available[i]));
- g_signal_connect(available[i], "analyzed",
- G_CALLBACK(on_loaded_content_analyzed), handler->project);
+ }
- g_loaded_content_analyze(available[i]);
+ if (is_batch_mode())
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (handler->filter == NULL || handler->filter(available[i], handler->data))
+ {
+ g_signal_connect(available[i], "analyzed",
+ G_CALLBACK(on_loaded_content_analyzed), handler->project);
- g_object_unref(G_OBJECT(available[i]));
+ g_loaded_content_analyze(available[i]);
+
+ }
+
+ g_object_unref(G_OBJECT(available[i]));
+
+ }
+
+ }
+
+ else
+ {
+ g_signal_emit_by_name(handler->project, "contents-available", available, count);
+
+ keep = true;
}
}
/* Dans tous les cas... */
- if (available != NULL)
+ if (available != NULL && !keep)
free(available);
/* Si c'était la dernière résolution... */
diff --git a/src/analysis/project.h b/src/analysis/project.h
index c634fb2..9b42a47 100644
--- a/src/analysis/project.h
+++ b/src/analysis/project.h
@@ -74,8 +74,14 @@ const char *g_study_project_get_filename(const GStudyProject *);
/* ------------------------ INTEGRATION DE CONTENUS BINAIRES ------------------------ */
+/* Filtre sur les contenus chargeables */
+typedef bool (* filter_loadable_cb) (GLoadedContent *, void *);
+
/* Assure l'intégration de contenus binaires dans un projet. */
-void g_study_project_discover_binary_content(GStudyProject *, GBinContent *);
+void g_study_project_discover_binary_content(GStudyProject *, GBinContent *, filter_loadable_cb, void *);
+
+/* Réceptionne la recette d'une analyse de contenu. */
+void on_loaded_content_analyzed(GLoadedContent *, gboolean, GStudyProject *);
#define g_study_project_lock_contents(p) \
_g_study_project_lock_unlock_contents(p, true)
diff --git a/src/gui/editor.c b/src/gui/editor.c
index 16b7a59..b52ec9d 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -46,6 +46,7 @@
#include "../common/extstr.h"
#include "../core/global.h"
#include "../core/params.h"
+#include "../glibext/chrysamarshal.h"
#include "../glibext/signal.h"
#include "../gtkext/easygtk.h"
#include "../gtkext/gtkdisplaypanel.h"
@@ -129,8 +130,11 @@ static void notify_editor_project_change(GStudyProject *, bool);
/* Assure un positionnement initial idéal. */
static gboolean scroll_for_the_first_time(GtkWidget *, GdkEvent *, GLoadedContent *);
+/* Présente une possibilité de sélection des contenus chargés. */
+static void on_editor_contents_available(GStudyProject *, GLoadedContent **, guint, void *);
+
/* Affiche le contenu qui vient de rejoindre un projet donné. */
-void on_editor_loaded_content_added(GStudyProject *, GLoadedContent *, void *);
+static void on_editor_loaded_content_added(GStudyProject *, GLoadedContent *, void *);
/* Recherche et retirer de l'affichage un contenu chargé. */
static void remove_loaded_content_from_editor(GtkWidget *, GLoadedContent *);
@@ -905,9 +909,15 @@ static void notify_editor_project_change(GStudyProject *project, bool new)
contents = _g_study_project_get_contents(project, &count);
if (new)
+ {
+ g_signal_connect_to_main(project, "contents-available", G_CALLBACK(on_editor_contents_available), NULL,
+ g_cclosure_user_marshal_VOID__POINTER_UINT);
+
g_signal_connect_to_main(project, "content-added", G_CALLBACK(on_editor_loaded_content_added), NULL,
g_cclosure_marshal_VOID__OBJECT);
+ }
+
g_study_project_unlock_contents(project);
if (new)
@@ -934,6 +944,41 @@ static void notify_editor_project_change(GStudyProject *project, bool new)
/******************************************************************************
* *
+* Paramètres : project = project impliqué dans l'opération. *
+* contents = nouveaux contenus à éventuellement charger. *
+* count = taille de la liste fournie. *
+* unused = adresse non utilisée ici. *
+* *
+* Description : Présente une possibilité de sélection des contenus chargés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_editor_contents_available(GStudyProject *project, GLoadedContent **contents, guint count, void *unused)
+{
+ guint i; /* Boucle de parcours */
+
+ for (i = 0; i < count; i++)
+ {
+ g_signal_connect(contents[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project);
+
+ g_loaded_content_analyze(contents[i]);
+
+ g_object_unref(G_OBJECT(contents[i]));
+
+ }
+
+ if (contents != NULL)
+ free(contents);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : project = project impliqué dans l'opération. *
* content = nouveau contenu à présenter dans l'éditeur. *
* unused = adresse non utilisée ici. *
@@ -946,7 +991,7 @@ static void notify_editor_project_change(GStudyProject *project, bool new)
* *
******************************************************************************/
-void on_editor_loaded_content_added(GStudyProject *project, GLoadedContent *content, void *unused)
+static void on_editor_loaded_content_added(GStudyProject *project, GLoadedContent *content, void *unused)
{
GtkWidget *selected; /* Interface de prédilection */
const char *name; /* Titre associé au binaire */
diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c
index a6a078b..80eff6f 100644
--- a/src/gui/menus/project.c
+++ b/src/gui/menus/project.c
@@ -205,7 +205,7 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar)
if (content != NULL)
{
- g_study_project_discover_binary_content(project, content);
+ g_study_project_discover_binary_content(project, content, NULL, NULL);
g_object_unref(G_OBJECT(content));
}
diff --git a/src/main.c b/src/main.c
index f00a61c..92df3fa 100644
--- a/src/main.c
+++ b/src/main.c
@@ -479,7 +479,7 @@ static int open_binaries(char **files, int count)
if (content != NULL)
{
- g_study_project_discover_binary_content(project, content);
+ g_study_project_discover_binary_content(project, content, NULL, NULL);
g_object_unref(G_OBJECT(content));
}