summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/analysis/scan
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/analysis/scan')
-rw-r--r--plugins/pychrysalide/analysis/scan/Makefile.am28
-rw-r--r--plugins/pychrysalide/analysis/scan/constants.c128
-rw-r--r--plugins/pychrysalide/analysis/scan/constants.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/context.c432
-rw-r--r--plugins/pychrysalide/analysis/scan/context.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/core.c179
-rw-r--r--plugins/pychrysalide/analysis/scan/core.h39
-rw-r--r--plugins/pychrysalide/analysis/scan/expr.c393
-rw-r--r--plugins/pychrysalide/analysis/scan/expr.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/Makefile.am15
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/constants.c128
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/constants.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/literal.c281
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/literal.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/module.c103
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/item.c740
-rw-r--r--plugins/pychrysalide/analysis/scan/item.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/module.c125
-rw-r--r--plugins/pychrysalide/analysis/scan/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/options.c511
-rw-r--r--plugins/pychrysalide/analysis/scan/options.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/Makefile.am22
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backend.c202
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backend.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am15
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/acism.c214
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/acism.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c214
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/module.c106
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifier.c416
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifier.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am18
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c211
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c320
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c112
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c211
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c211
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c210
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/module.c114
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.c487
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/space.c283
-rw-r--r--plugins/pychrysalide/analysis/scan/space.h45
53 files changed, 7482 insertions, 0 deletions
diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am
new file mode 100644
index 0000000..8c9fb77
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/Makefile.am
@@ -0,0 +1,28 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscan.la
+
+libpychrysaanalysisscan_la_SOURCES = \
+ constants.h constants.c \
+ context.h context.c \
+ core.h core.c \
+ expr.h expr.c \
+ item.h item.c \
+ module.h module.c \
+ options.h options.c \
+ scanner.h scanner.c \
+ space.h space.c
+
+libpychrysaanalysisscan_la_LIBADD = \
+ exprs/libpychrysaanalysisscanexprs.la \
+ patterns/libpychrysaanalysisscanpatterns.la
+
+libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscan_la_SOURCES:%c=)
+
+
+SUBDIRS = exprs patterns
diff --git a/plugins/pychrysalide/analysis/scan/constants.c b/plugins/pychrysalide/analysis/scan/constants.c
new file mode 100644
index 0000000..d030df2
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/constants.c
@@ -0,0 +1,128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - ajout des constantes de base pour les types
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "constants.h"
+
+
+#include <analysis/scan/expr.h>
+
+
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives aux expressions de scan. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_expression_value_type_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "PENDING", SRS_PENDING);
+ if (result) result = add_const_to_group(values, "REDUCED", SRS_REDUCED);
+ if (result) result = add_const_to_group(values, "WAIT_FOR_SCAN", SRS_WAIT_FOR_SCAN);
+ if (result) result = add_const_to_group(values, "UNRESOLVABLE", SRS_UNRESOLVABLE);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "ScanReductionState", values,
+ "State of a scanexpression during the reduction process.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 constante ScanReductionState. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_reduction_state(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+ 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 ScanReductionState");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > SRS_UNRESOLVABLE)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for ScanReductionState");
+ result = 0;
+ }
+
+ else
+ *((ScanReductionState *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/constants.h b/plugins/pychrysalide/analysis/scan/constants.h
new file mode 100644
index 0000000..aa6c571
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'ajout des constantes de base pour les types
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives aux expressions de scan. */
+bool define_expression_value_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante ScanReductionState. */
+int convert_to_scan_reduction_state(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c
new file mode 100644
index 0000000..9becaf7
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/context.c
@@ -0,0 +1,432 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - équivalent Python du fichier "analysis/scan/context.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "context.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/context-int.h>
+#include <analysis/scan/expr.h>
+
+#include "expr.h"
+#include "../content.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_context, G_TYPE_SCAN_CONTEXT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_context_init(PyObject *, PyObject *, PyObject *);
+
+/* Note que la phase d'analyse de contenu est terminée. */
+static PyObject *py_scan_context_mark_scan_as_done(PyObject *, PyObject *);
+
+/* Indique si une correspondance globale a pu être établie. */
+static PyObject *py_scan_context_has_match_for_rule(PyObject *, PyObject *);
+
+/* Fournit une référence au contenu principal analysé. */
+static PyObject *py_scan_context_get_content(PyObject *, void *);
+
+/* Définit le contenu principal à analyser. */
+static int py_scan_context_set_content(PyObject *, PyObject *, void *);
+
+/* Indique si la phase d'analyse de contenu est terminée. */
+static PyObject *py_scan_context_is_scan_done(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_context_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_CONTEXT_DOC \
+ "A ScanContext object tracks results of a run analysis process" \
+ " against binary contents.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanContext()"
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "");
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Note que la phase d'analyse de contenu est terminée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_mark_scan_as_done(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanContext *context; /* Contexte de suivi d'analyse */
+
+#define SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD PYTHON_METHOD_DEF \
+( \
+ mark_scan_as_done, "$self", \
+ METH_NOARGS, py_scan_context, \
+ "Note that the analysis operations are finished." \
+)
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ g_scan_context_mark_scan_as_done(context);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Indique si une correspondance globale a pu être établie. *
+* *
+* Retour : Bilan final d'une analyse (False par défaut). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ const char *name; /* Désignation de règle */
+ int ret; /* Bilan de lecture des args. */
+ GScanContext *context; /* Contexte de suivi d'analyse */
+ bool matched; /* Bilan d'analyse à renvoyer */
+
+#define SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD PYTHON_METHOD_DEF \
+( \
+ has_match_for_rule, "$self, name, /", \
+ METH_VARARGS, py_scan_context, \
+ "Provide the match status for a given scan rule.\n" \
+ "\n" \
+ "The *name* argument points to the registered rule to query.\n" \
+ "\n" \
+ "The method returns the scan final status as a boolean: *True*" \
+ " in case of match, *False* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &name);
+ if (!ret) return NULL;
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ matched = g_scan_context_has_match_for_rule(context, name);
+
+ result = matched ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant une routine binaire. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Fournit une référence au contenu principal analysé. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_get_content(PyObject *self, void *closure)
+{
+ PyObject *result; /* Eléments à retourner */
+ GScanContext *context; /* Version native */
+ GBinContent *content; /* Contenu binaire à référencer*/
+
+#define SCAN_CONTEXT_CONTENT_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ content, py_scan_context, \
+ "Link to the scanned binary content.\n" \
+ "\n" \
+ "The result is a pychrysalide.analysis.BinContent for" \
+ " fully initialized context." \
+)
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+ content = g_scan_context_get_content(context);
+
+ result = pygobject_new(G_OBJECT(content));
+
+ g_object_unref(G_OBJECT(content));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = non utilisé ici. *
+* *
+* Description : Définit le contenu principal à analyser. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_context_set_content(PyObject *self, PyObject *value, void *closure)
+{
+ GScanContext *context; /* Elément à consulter */
+ int ret; /* Bilan de lecture des args. */
+ GBinContent *content; /* Contenu binaire à référencer*/
+
+ ret = PyObject_IsInstance(value, (PyObject *)get_python_binary_content_type());
+ if (!ret) return -1;
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+ content = G_BIN_CONTENT(pygobject_get(value));
+
+ // FIXME g_scan_context_set_content(context, content);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique si la phase d'analyse de contenu est terminée. *
+* *
+* Retour : True si la phase de scan est terminée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_is_scan_done(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GScanContext *context; /* Contexte de suivi d'analyse */
+ bool status; /* Bilan de consultation */
+
+#define SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB PYTHON_IS_DEF_FULL \
+( \
+ scan_done, py_scan_context, \
+ "Tell if the analysis operations are finished.\n" \
+ "\n" \
+ "The result is a boolean: *True* if the scan is marked as" \
+ " done, *False* otherwise." \
+)
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ status = g_scan_context_is_scan_done(context);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_context_type(void)
+{
+ static PyMethodDef py_scan_context_methods[] = {
+ SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD,
+ SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_context_getseters[] = {
+ SCAN_CONTEXT_CONTENT_ATTRIB,
+ SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_context_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanContext",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_CONTEXT_DOC,
+
+ .tp_methods = py_scan_context_methods,
+ .tp_getset = py_scan_context_getseters,
+
+ .tp_init = py_scan_context_init,
+ .tp_new = py_scan_context_new,
+
+ };
+
+ return &py_scan_context_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....scan.ScanContext. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_context_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanContext' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_context_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_CONTEXT, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 contexte de suivi d'analyse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_context(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_context_type());
+
+ 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 scan context");
+ break;
+
+ case 1:
+ *((GScanContext **)dst) = G_SCAN_CONTEXT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/context.h b/plugins/pychrysalide/analysis/scan/context.h
new file mode 100644
index 0000000..477205b
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/context.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour l'équivalent Python du fichier "analysis/scan/context.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_context_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanContext'. */
+bool ensure_python_scan_context_is_registered(void);
+
+/* Tente de convertir en contexte de suivi d'analyse. */
+int convert_to_scan_context(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H */
diff --git a/plugins/pychrysalide/analysis/scan/core.c b/plugins/pychrysalide/analysis/scan/core.c
new file mode 100644
index 0000000..16df9a9
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/core.c
@@ -0,0 +1,179 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - équivalent Python du fichier "analysis/scan/core.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "core.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/core.h>
+
+
+#include "patterns/modifier.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+/* Inscrit un modificateur dans la liste des disponibles. */
+static PyObject *py_scan_register_token_modifier(PyObject *, PyObject *);
+
+/* Fournit le modificateur correspondant à un nom. */
+static PyObject *py_scan_find_token_modifiers_for_name(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Inscrit un modificateur dans la liste des disponibles. *
+* *
+* Retour : Bilan des enregistrements effectués : True si nouveauté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_register_token_modifier(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ PyObject *instance; /* Instance Python fournie */
+ GScanTokenModifier *modifier; /* Version native */
+ int ret; /* Bilan de lecture des args. */
+ bool status; /* Bilan d'un enregistrement */
+
+#define SCAN_REGISTER_TOKEN_MODIFIER_METHOD PYTHON_METHOD_DEF \
+( \
+ register_token_modifier, "inst, /", \
+ METH_VARARGS, py_scan, \
+ "Register a token modifier for byte patterns to scan.\n" \
+ "\n" \
+ "This instance will be used as singleton and has to be a" \
+ " subclass of pychrysalide.analysis.scan.patterns.TokenModifier." \
+)
+
+ ret = PyArg_ParseTuple(args, "O!", get_python_scan_token_modifier_type(), &instance);
+ if (!ret) return NULL;
+
+ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(instance));
+
+ status = register_scan_token_modifier(modifier);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Fournit le modificateur correspondant à un nom. *
+* *
+* Retour : Instance du modificateur identifié ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_find_token_modifiers_for_name(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ sized_string_t name; /* Nom d'appel à rechercher */
+ Py_ssize_t len; /* Taille de ce nom */
+ int ret; /* Bilan de lecture des args. */
+ GScanTokenModifier *modifier; /* Instance mise en place */
+
+#define SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD PYTHON_METHOD_DEF \
+( \
+ find_token_modifiers_for_name, "name, /", \
+ METH_VARARGS, py_scan, \
+ "Provide the registered instance of a pattern modifier linked" \
+ " to a given *name* provided as a key string.\n" \
+ "\n" \
+ "The returned instance is an object inherited from" \
+ " pychrysalide.analysis.scan.patterns.TokenModifier or *None*" \
+ " if no instance was found for the provided name." \
+)
+
+ ret = PyArg_ParseTuple(args, "s#", &name.static_data, &len);
+ if (!ret) return NULL;
+
+ name.len = len;
+
+ modifier = find_scan_token_modifiers_for_name(&name);
+
+ if (modifier != NULL)
+ {
+ result = pygobject_new(G_OBJECT(modifier));
+ g_object_unref(G_OBJECT(modifier));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Définit une extension du module 'scan' à compléter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_scan_module_with_core_methods(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Module à recompléter */
+
+ static PyMethodDef py_core_methods[] = {
+ SCAN_REGISTER_TOKEN_MODIFIER_METHOD,
+ SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD,
+ { NULL }
+ };
+
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ result = register_python_module_methods(module, py_core_methods);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/core.h b/plugins/pychrysalide/analysis/scan/core.h
new file mode 100644
index 0000000..e283f91
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/core.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'équivalent Python du fichier "analysis/scan/core.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_CORE_CORE_H
+#define _PLUGINS_PYCHRYSALIDE_CORE_CORE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'scan' à compléter. */
+bool populate_scan_module_with_core_methods(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_CORE_CORE_H */
diff --git a/plugins/pychrysalide/analysis/scan/expr.c b/plugins/pychrysalide/analysis/scan/expr.c
new file mode 100644
index 0000000..2d8245a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/expr.c
@@ -0,0 +1,393 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.c - équivalent Python du fichier "analysis/scan/expr.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "expr.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/expr-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/glibext/comparison.h>
+
+
+#include "constants.h"
+
+
+
+/* Initialise la classe générique des expressions d'évaluation. */
+static void py_scan_expression_init_gclass(GScanExpressionClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_expression, G_TYPE_SCAN_EXPRESSION, py_scan_expression_init_gclass);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_expression_init(PyObject *, PyObject *, PyObject *);
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
+
+/* Indique l'état de réduction d'une expression. */
+static PyObject *py_scan_expression_get_state(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe générique des expressions d'évaluation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_scan_expression_init_gclass(GScanExpressionClass *class, gpointer unused)
+{
+ class->cmp_rich = py_scan_expression_compare_rich_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_expression_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ ScanReductionState state; /* Etat de réduction initial */
+ int ret; /* Bilan de lecture des args. */
+ GScanExpression *expr; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "state", NULL };
+
+#define SCAN_EXPRESSION_DOC \
+ "A ScanExpression is an abstract object which defines an expression"\
+ " involved in data matching when running a scan.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object expect"\
+ " the following arguments as keyword parameters:\n" \
+ "* *state*: initial state of reduction for the expression, as a" \
+ " pychrysalide.analysis.scan.ScanExpression.ScanReductionState" \
+ " value." \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.analysis.scan.ScanExpression._cmp_rich().\n"
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, convert_to_scan_reduction_state, &state);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ expr = G_SCAN_EXPRESSION(pygobject_get(self));
+
+ if (!g_scan_expression_create(expr, state))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create scan expression."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à cnsulter pour une comparaison. *
+* other = second objet à cnsulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *item, const GScanExpression *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+#define SCAN_EXPRESSION_CMP_RICH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, other, op, /", \
+ METH_VARARGS, \
+ "Abstract method used to compare the expression against another" \
+ " one.\n" \
+ "\n" \
+ "The second *other* instance is built from the same type as *self*."\
+ " The *op* argument points to a" \
+ " pychrysalide.glibext.ComparableItem.RichCmpOperation mode" \
+ " describing the expected comparison.\n" \
+ "\n" \
+ "The result is a boolean status or *None* if the comparison" \
+ " process is undefined." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_cmp_rich"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(other)));
+ PyTuple_SetItem(args, 1, cast_with_constants_group_from_type(get_python_comparable_item_type(),
+ "RichCmpOperation", op));
+
+ pyret = run_python_method(pyobj, "_cmp_rich", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyBool_Check(pyret);
+
+ if (ret)
+ {
+ *status = (pyret == Py_True);
+ result = true;
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique l'état de réduction d'une expression. *
+* *
+* Retour : Etat courant associé à l'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_expression_get_state(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GScanExpression *expr; /* Version GLib de l'opérande */
+ ScanReductionState state; /* Etat courant de l'expression*/
+
+#define SCAN_EXPRESSION_STATE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ state, py_scan_expression, \
+ "Current state of the expression, relative to the reduction" \
+ " process, as a" \
+ " pychrysalide.analysis.scan.ScanExpression.ScanReductionState" \
+ " value." \
+)
+
+ expr = G_SCAN_EXPRESSION(pygobject_get(self));
+
+ state = g_scan_expression_get_state(expr);
+
+ result = cast_with_constants_group_from_type(get_python_scan_expression_type(), "ScanReductionState", state);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_expression_type(void)
+{
+ static PyMethodDef py_scan_expression_methods[] = {
+ SCAN_EXPRESSION_CMP_RICH_WRAPPER,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_expression_getseters[] = {
+ SCAN_EXPRESSION_STATE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_expression_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanExpression",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_EXPRESSION_DOC,
+
+ .tp_methods = py_scan_expression_methods,
+ .tp_getset = py_scan_expression_getseters,
+
+ .tp_init = py_scan_expression_init,
+ .tp_new = py_scan_expression_new,
+
+ };
+
+ return &py_scan_expression_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanExpression'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_expression_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanExpression'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_expression_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_comparable_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_EXPRESSION, type))
+ return false;
+
+ if (!define_expression_value_type_constants(type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 expression d'évaluation généraliste. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_expression(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_expression_type());
+
+ 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 match expression");
+ break;
+
+ case 1:
+ *((GScanExpression **)dst) = G_SCAN_EXPRESSION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/expr.h b/plugins/pychrysalide/analysis/scan/expr.h
new file mode 100644
index 0000000..42f5350
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/expr.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.h - prototypes pour l'équivalent Python du fichier "analysis/scan/expr.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_expression_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanExpression'. */
+bool ensure_python_scan_expression_is_registered(void);
+
+/* Tente de convertir en expression d'évaluation généraliste. */
+int convert_to_scan_expression(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/Makefile.am b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am
new file mode 100644
index 0000000..e40d4de
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanexprs.la
+
+libpychrysaanalysisscanexprs_la_SOURCES = \
+ constants.h constants.c \
+ literal.h literal.c \
+ module.h module.c
+
+libpychrysaanalysisscanexprs_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanexprs_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.c b/plugins/pychrysalide/analysis/scan/exprs/constants.c
new file mode 100644
index 0000000..b11ac4c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/constants.c
@@ -0,0 +1,128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - ajout des constantes de base pour les expressions
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "constants.h"
+
+
+#include <analysis/scan/exprs/literal.h>
+
+
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives aux expressions de scan. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_literal_expression_value_type_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "LVT_BOOLEAN", LVT_BOOLEAN);
+ if (result) result = add_const_to_group(values, "SIGNED_INTEGER", LVT_SIGNED_INTEGER);
+ if (result) result = add_const_to_group(values, "UNSIGNED_INTEGER", LVT_UNSIGNED_INTEGER);
+ if (result) result = add_const_to_group(values, "STRING", LVT_STRING);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "LiteralValueType", values,
+ "Type of value carried by a literal scan expression.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 constante LiteralValueType. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_literal_expression_value_type(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+ 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 LiteralValueType");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > LVT_REG_EXPR)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for LiteralValueType");
+ result = 0;
+ }
+
+ else
+ *((LiteralValueType *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.h b/plugins/pychrysalide/analysis/scan/exprs/constants.h
new file mode 100644
index 0000000..e5b8e8c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'ajout des constantes de base pour les expressions
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives aux expressions litérales. */
+bool define_literal_expression_value_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante LiteralValueType. */
+int convert_to_literal_expression_value_type(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.c b/plugins/pychrysalide/analysis/scan/exprs/literal.c
new file mode 100644
index 0000000..d7ae002
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/literal.c
@@ -0,0 +1,281 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.c - équivalent Python du fichier "analysis/scan/exprs/literal.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "literal.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/exprs/literal-int.h>
+
+
+#include "constants.h"
+#include "../expr.h"
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_literal_expression, G_TYPE_SCAN_LITERAL_EXPRESSION);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_literal_expression_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_literal_expression_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_value; /* Valeur en version Python */
+ int ret; /* Bilan de lecture des args. */
+ LiteralValueType vtype; /* Valeur à porter */
+ bool arg_boolean; /* Argument natif booléen */
+ unsigned long long arg_uinteger; /* Argument natif entier */
+ sized_string_t arg_string; /* Argument natif textuel */
+ Py_ssize_t arg_str_length; /* Taille de ce texte */
+ void *arg_ptr; /* Pointeur vers un argument */
+ GScanLiteralExpression *expr; /* Création GLib à transmettre */
+
+#define SCAN_LITERAL_EXPRESSION_DOC \
+ "A ScanLiteralExpression object defines expression carrying" \
+ " literal values available for scan match conditions.\n" \
+ "\n" \
+ "Instances can be created using one of the following" \
+ " constructors:\n" \
+ "\n" \
+ " ScanLiteralExpression(value)" \
+ "\n" \
+ "\n" \
+ "Where *value* is either a boolean, an integer or bytes."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O", &py_value);
+ if (!ret) return -1;
+
+ if (PyBool_Check(py_value))
+ {
+ vtype = LVT_BOOLEAN;
+
+ arg_boolean = (py_value == Py_True);
+ arg_ptr = &arg_boolean;
+
+ }
+
+ else if (PyLong_Check(py_value))
+ {
+ if (1 /* sign - TODO */)
+ ;
+
+ vtype = LVT_UNSIGNED_INTEGER;
+
+ arg_uinteger = PyLong_AsUnsignedLongLong(py_value);
+ arg_ptr = &arg_uinteger;
+
+ }
+
+ else if (PyBytes_Check(py_value))
+ {
+ vtype = LVT_STRING;
+
+ ret = PyBytes_AsStringAndSize(py_value, &arg_string.data, &arg_str_length);
+ if (ret == -1) return -1;
+
+ arg_string.len = arg_str_length;
+ arg_ptr = &arg_string;
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unsupported Python value for a literal scan expression."));
+ return -1;
+ }
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ expr = G_SCAN_LITERAL_EXPRESSION(pygobject_get(self));
+
+ if (!g_scan_literal_expression_create(expr, vtype, arg_ptr))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create literal expression."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_literal_expression_type(void)
+{
+ static PyMethodDef py_scan_literal_expression_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_literal_expression_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_literal_expression_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.exprs.ScanLiteralExpression",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_LITERAL_EXPRESSION_DOC,
+
+ .tp_methods = py_scan_literal_expression_methods,
+ .tp_getset = py_scan_literal_expression_getseters,
+
+ .tp_init = py_scan_literal_expression_init,
+ .tp_new = py_scan_literal_expression_new,
+
+ };
+
+ return &py_scan_literal_expression_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....PlainModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_literal_expression_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'PlainModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_literal_expression_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.exprs");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_expression_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_LITERAL_EXPRESSION, type))
+ return false;
+
+ if (!define_literal_expression_value_type_constants(type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 transmission d'octets à l'identique. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_literal_expression(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_literal_expression_type());
+
+ 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 scan literal expression");
+ break;
+
+ case 1:
+ *((GScanLiteralExpression **)dst) = G_SCAN_LITERAL_EXPRESSION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.h b/plugins/pychrysalide/analysis/scan/exprs/literal.h
new file mode 100644
index 0000000..8e7ea70
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/literal.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.h - équivalent Python du fichier "analysis/scan/exprs/literal.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_literal_expression_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.exprs.ScanLiteralExpression'. */
+bool ensure_python_scan_literal_expression_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_literal_expression(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.c b/plugins/pychrysalide/analysis/scan/exprs/module.c
new file mode 100644
index 0000000..4f38430
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/module.c
@@ -0,0 +1,103 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire exprs en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "literal.h"
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis....modifiers' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_exprs_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC \
+ "This module provide expressions used to build a match condition."
+
+ static PyModuleDef py_chrysalide_analysis_scan_exprs_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.exprs",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_exprs_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis...patterns.modifiers'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_exprs_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_literal_expression_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.h b/plugins/pychrysalide/analysis/scan/exprs/module.h
new file mode 100644
index 0000000..ee4b8ab
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire exprs en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.exprs' à un module Python. */
+bool add_analysis_scan_exprs_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.exprs'. */
+bool populate_analysis_scan_exprs_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c
new file mode 100644
index 0000000..014ae24
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/item.c
@@ -0,0 +1,740 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - équivalent Python du fichier "analysis/scan/item.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "item.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/item-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "context.h"
+
+
+
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Initialise la classe des éléments appelables enregistrés. */
+static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_registered_item, G_TYPE_SCAN_REGISTERED_ITEM, py_scan_registered_item_init_gclass);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_registered_item_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue un appel à une fonction enregistrée. */
+static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
+/* Lance une résolution d'élément à appeler. */
+static PyObject *py_scan_registered_item_resolve(PyObject *, PyObject *);
+
+/* Fournit le désignation associée à un composant nommé. */
+static PyObject *py_scan_registered_item_get_name(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe des éléments appelables enregistrés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *class, gpointer unused)
+{
+ class->get_name = py_scan_registered_item_get_name_wrapper;
+ class->resolve = py_scan_registered_item_resolve_wrapper;
+ class->reduce = py_scan_registered_item_reduce_wrapper;
+ class->run_call = py_scan_registered_item_run_call_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_REGISTERED_ITEM_DOC \
+ "The *RegisteredItem* class is an abstract definition which is" \
+ " the base for all keywords involved in a match condition" \
+ " expression.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object" \
+ " expect no particular argument.\n" \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._resolve();\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._reduce();\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._call().\n" \
+ "\n" \
+ "One item has to be defined as class attributes in the final" \
+ " class:\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._name.\n"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *item)
+{
+ char *result; /* Désignation à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyname; /* Nom en objet Python */
+ int ret; /* Bilan d'une conversion */
+
+#define SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF \
+( \
+ _name, \
+ "Provide the keyword of the expression item to be evaluated.\n" \
+ "\n" \
+ "The result has to be a string." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (PyObject_HasAttrString(pyobj, "_name"))
+ {
+ pyname = PyObject_GetAttrString(pyobj, "_name");
+
+ if (pyname != NULL)
+ {
+ ret = PyUnicode_Check(pyname);
+
+ if (ret)
+ result = strdup(PyUnicode_AsUTF8(pyname));
+
+ Py_DECREF(pyname);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, target, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to resolve an item by name.\n" \
+ "\n" \
+ "The *target* argument provide the name of the searched item;" \
+ " *ctx* is a pychrysalide.analysis.scan.ScanContext instance" \
+ " providing information about the current state; *scope* is a" \
+ " pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.RegisteredItem" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_resolve"))
+ {
+ args = PyTuple_New(3);
+ PyTuple_SetItem(args, 0, PyUnicode_FromString(target));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_resolve", args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_SCAN_REGISTERED_ITEM(gobj_ret))
+ {
+ *out = G_SCAN_REGISTERED_ITEM(gobj_ret);
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define SCAN_REGISTERED_ITEM_REDUCE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to replace the item by an equivalent reduced" \
+ " value.\n" \
+ "\n" \
+ "The *ctx* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance providing information about the current state; *scope*" \
+ " is a pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.ScanExpression" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_reduce"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_reduce", args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_SCAN_EXPRESSION(gobj_ret))
+ {
+ *out = G_SCAN_EXPRESSION(gobj_ret);
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Effectue un appel à une fonction enregistrée. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *sub_args; /* Sous-arguments pour l'appel */
+ size_t i; /* Boucle de parcours */
+ PyObject *py_args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define SCAN_REGISTERED_ITEM_CALL_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, args, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to replace the item and its arguments by an" \
+ " equivalent reduced value.\n" \
+ "\n" \
+ "The *args* argument is a tuple of already reduced" \
+ " pychrysalide.analysis.scan.ScanExpression objects; ctx* argument" \
+ " is a pychrysalide.analysis.scan.ScanContext instance providing" \
+ " information about the current state; *scope* is a" \
+ " pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.ScanExpression" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_call"))
+ {
+ sub_args = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(sub_args, 1, pygobject_new(G_OBJECT(args[i])));
+
+ py_args = PyTuple_New(3);
+ PyTuple_SetItem(py_args, 0, sub_args);
+ PyTuple_SetItem(py_args, 1, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(py_args, 2, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_call", py_args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_OBJECT(gobj_ret))
+ {
+ *out = gobj_ret;
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(py_args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = élément d'appel à consulter. *
+* args = arguments fournis pour l'opération. *
+* *
+* Description : Lance une résolution d'élément à appeler. *
+* *
+* Retour : Nouvel élément d'appel identifié ou None. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_registered_item_resolve(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ const char *target; /* Désignation de la cible */
+ GScanContext *ctx; /* Contexte d'analyse */
+ GScanScope *scope; /* Portée de variables locales */
+ int ret; /* Bilan de lecture des args. */
+ GScanRegisteredItem *item; /* Version native */
+ bool status; /* Bilan d'exécution */
+ GScanRegisteredItem *resolved; /* Elément trouvé */
+
+#define SCAN_REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF \
+( \
+ resolve, "$self, target, /, ctx=None, scope=None", \
+ METH_VARARGS, py_scan_registered_item, \
+ "Resolve a name into a scan item." \
+ "\n" \
+ "The *target* name is the only mandatory parameter and has to point"\
+ " to only one item. The *ctx* argument points to an optional useful"\
+ " storage for resolution lookup, as a" \
+ " pychrysalide.analysis.scan.ScanContext instance. The *args* list" \
+ " defines an optional list of arguments, as" \
+ " pychrysalide.analysis.scan.ScanExpression instances, to use for" \
+ " building the resolved item. The *final* flag states if the" \
+ " scanning process is about to conclude or not." \
+ "\n" \
+ "The result is an object inheriting from" \
+ " pychrysalide.analysis.scan.RegisteredItem or *None* if the" \
+ " resolution operation failed." \
+)
+
+ ctx = NULL;
+ scope = NULL;
+
+ ret = PyArg_ParseTuple(args, "s|O&", &target,
+ convert_to_scan_context, &ctx);
+ if (!ret) return NULL;
+
+ item = G_SCAN_REGISTERED_ITEM(pygobject_get(self));
+
+ status = g_scan_registered_item_resolve(item, target, ctx, scope, &resolved);
+
+ if (!status)
+ {
+ result = NULL;
+ PyErr_Format(PyExc_RuntimeError, _("Unable to resolve any target from the item"));
+ }
+ else
+ {
+ if (resolved != NULL)
+ {
+ result = pygobject_new(G_OBJECT(resolved));
+ g_object_unref(G_OBJECT(resolved));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un composant nommé à manipuler.*
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le désignation associée à un composant nommé. *
+* *
+* Retour : Description courante. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_registered_item_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Décompte à retourner */
+ GScanRegisteredItem *item; /* Version native */
+ char *name; /* Désignation à convertir */
+
+#define SCAN_REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_scan_registered_item, \
+ "Name linked to the registered item.\n" \
+ "\n" \
+ "The result should be a string, or *None* for the root namespace." \
+)
+
+ item = G_SCAN_REGISTERED_ITEM(pygobject_get(self));
+
+ name = g_scan_registered_item_get_name(item);
+
+ if (name == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = PyUnicode_FromString(name);
+ free(name);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_registered_item_type(void)
+{
+ static PyMethodDef py_scan_registered_item_methods[] = {
+ SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER,
+ SCAN_REGISTERED_ITEM_REDUCE_WRAPPER,
+ SCAN_REGISTERED_ITEM_CALL_WRAPPER,
+ SCAN_REGISTERED_ITEM_RESOLVE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_registered_item_getseters[] = {
+ SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER,
+ SCAN_REGISTERED_ITEM_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_registered_item_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanRegisteredItem",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_REGISTERED_ITEM_DOC,
+
+ .tp_methods = py_scan_registered_item_methods,
+ .tp_getset = py_scan_registered_item_getseters,
+
+ .tp_init = py_scan_registered_item_init,
+ .tp_new = py_scan_registered_item_new,
+
+ };
+
+ return &py_scan_registered_item_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...ScanRegisteredItem'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_registered_item_is_registered(void)
+{
+ PyTypeObject *type; /* Type 'ScanRegisteredItem' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_registered_item_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REGISTERED_ITEM, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 expression d'évaluation généraliste. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_registered_item(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_registered_item_type());
+
+ 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 generic scan expression");
+ break;
+
+ case 1:
+ *((GScanRegisteredItem **)dst) = G_SCAN_REGISTERED_ITEM(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/item.h b/plugins/pychrysalide/analysis/scan/item.h
new file mode 100644
index 0000000..773908c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/item.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour l'équivalent Python du fichier "analysis/scan/item.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_registered_item_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanRegisteredItem'. */
+bool ensure_python_scan_registered_item_is_registered(void);
+
+/* Tente de convertir en expression d'évaluation généraliste. */
+int convert_to_scan_registered_item(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H */
diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c
new file mode 100644
index 0000000..9ae0e52
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/module.c
@@ -0,0 +1,125 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire scan en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "context.h"
+#include "core.h"
+#include "expr.h"
+#include "item.h"
+#include "options.h"
+#include "scanner.h"
+#include "space.h"
+#include "exprs/module.h"
+#include "patterns/module.h"
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.scan' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_module);
+
+ result = (module != NULL);
+
+ if (result) result = add_analysis_scan_exprs_module(module);
+ if (result) result = add_analysis_scan_patterns_module(module);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis.scan'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_content_scanner_is_registered();
+ if (result) result = ensure_python_scan_context_is_registered();
+ if (result) result = ensure_python_scan_expression_is_registered();
+ if (result) result = ensure_python_scan_registered_item_is_registered();
+ if (result) result = ensure_python_scan_options_is_registered();
+ if (result) result = ensure_python_scan_namespace_is_registered();
+
+ if (result) result = populate_scan_module_with_core_methods();
+
+ if (result) result = populate_analysis_scan_exprs_module();
+ if (result) result = populate_analysis_scan_patterns_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/module.h b/plugins/pychrysalide/analysis/scan/module.h
new file mode 100644
index 0000000..a5e84b5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire scan en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan' à un module Python. */
+bool add_analysis_scan_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan'. */
+bool populate_analysis_scan_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/options.c b/plugins/pychrysalide/analysis/scan/options.c
new file mode 100644
index 0000000..84c1784
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/options.c
@@ -0,0 +1,511 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.c - équivalent Python du fichier "analysis/scan/options.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "options.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/options-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_options, G_TYPE_SCAN_OPTIONS);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_options_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le type d'un moteur d'analyse de données sélectionné. */
+static PyObject *py_scan_options_get_backend_for_data(PyObject *, void *);
+
+/* Sélectionne un type de moteur d'analyse pour données brutes. */
+static int py_scan_options_set_backend_for_data(PyObject *, PyObject *, void *);
+
+/* Impose le format JSON comme type de sortie. */
+static PyObject *py_scan_options_get_print_json(PyObject *, void *);
+
+/* Mémorise le format JSON comme type de sortie. */
+static int py_scan_options_set_print_json(PyObject *, PyObject *, void *);
+
+/* Indique un besoin d'affichage des correspondances finales. */
+static PyObject *py_scan_options_get_print_strings(PyObject *, void *);
+
+/* Mémorise un besoin d'affichage des correspondances finales. */
+static int py_scan_options_set_print_strings(PyObject *, PyObject *, void *);
+
+/* Indique un besoin de statistiques en fin de compilation. */
+static PyObject *py_scan_options_get_print_stats(PyObject *, void *);
+
+/* Mémorise un besoin de statistiques en fin de compilation. */
+static int py_scan_options_set_print_stats(PyObject *, PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_OPTIONS_DOC \
+ "The *ScanOptions* class stores all parameters used to tune" \
+ " a scanning process.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanOptions()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique le type d'un moteur d'analyse de données sélectionné.*
+* *
+* Retour : Type d'objet, idéalement valide. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_backend_for_data(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ GType type; /* Type à transcrire */
+
+#define SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ backend_for_data, py_scan_options, \
+ "Type of the selected scan algorithm." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ type = g_scan_options_get_backend_for_data(options);
+
+ result = pyg_type_wrapper_new(type);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Sélectionne un type de moteur d'analyse pour données brutes. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_backend_for_data(PyObject *self, PyObject *value, void *closure)
+{
+ GType type; /* Type à transcrit */
+ GScanOptions *options; /* Version native */
+
+ type = pyg_type_from_object(value);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_backend_for_data(options, type);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Impose le format JSON comme type de sortie. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_json(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_JSON_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_json, py_scan_options, \
+ "Define if the process summary is output into a JSON" \
+ " format at the end of the scan or not." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_json(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise le format JSON comme type de sortie. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_json(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_json(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique un besoin d'affichage des correspondances finales. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_strings(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_STRINGS_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_strings, py_scan_options, \
+ "Define if the matching patterns are printed with found" \
+ " offset at the end of the scan or not." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_strings(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise un besoin d'affichage des correspondances finales. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_strings(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_strings(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_stats(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_STATS_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_stats, py_scan_options, \
+ "Control the output of final statistics afer a scan." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_stats(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_stats(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_stats(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_options_type(void)
+{
+ static PyMethodDef py_scan_options_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_options_getseters[] = {
+ SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB,
+ SCAN_OPTIONS_PRINT_JSON_ATTRIB,
+ SCAN_OPTIONS_PRINT_STRINGS_ATTRIB,
+ SCAN_OPTIONS_PRINT_STATS_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_options_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanOptions",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = SCAN_OPTIONS_DOC,
+
+ .tp_methods = py_scan_options_methods,
+ .tp_getset = py_scan_options_getseters,
+
+ .tp_init = py_scan_options_init,
+ .tp_new = py_scan_options_new,
+
+ };
+
+ return &py_scan_options_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanOptions'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_options_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanOptions' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_options_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_OPTIONS, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 ensemble d'options d'analyses. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_options(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_options_type());
+
+ 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 scan options");
+ break;
+
+ case 1:
+ *((GScanOptions **)dst) = G_SCAN_OPTIONS(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/options.h b/plugins/pychrysalide/analysis/scan/options.h
new file mode 100644
index 0000000..3e83880
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/options.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.h - prototypes pour l'équivalent Python du fichier "analysis/scan/options.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_options_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanOptions'. */
+bool ensure_python_scan_options_is_registered(void);
+
+/* Tente de convertir en ensemble d'options d'analyses. */
+int convert_to_scan_options(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
new file mode 100644
index 0000000..dd26fa5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
@@ -0,0 +1,22 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatterns.la
+
+libpychrysaanalysisscanpatterns_la_SOURCES = \
+ backend.h backend.c \
+ modifier.h modifier.c \
+ module.h module.c
+
+libpychrysaanalysisscanpatterns_la_LIBADD = \
+ backends/libpychrysaanalysisscanpatternsbackends.la \
+ modifiers/libpychrysaanalysisscanpatternsmodifiers.la
+
+libpychrysaanalysisscanpatterns_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatterns_la_SOURCES:%c=)
+
+
+SUBDIRS = backends modifiers
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.c b/plugins/pychrysalide/analysis/scan/patterns/backend.c
new file mode 100644
index 0000000..03db143
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backend.c
@@ -0,0 +1,202 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.c - équivalent Python du fichier "analysis/scan/backend.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "backend.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/patterns/backend-int.h>
+
+
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(engine_backend, G_TYPE_ENGINE_BACKEND, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_engine_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_engine_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define ENGINE_BACKEND_DOC \
+ "An *EngineBackend* object is the root class of all scan algorithm" \
+ " looking for data patterns."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_engine_backend_type(void)
+{
+ static PyMethodDef py_engine_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_engine_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_engine_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.EngineBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = ENGINE_BACKEND_DOC,
+
+ .tp_methods = py_engine_backend_methods,
+ .tp_getset = py_engine_backend_getseters,
+
+ .tp_init = py_engine_backend_init,
+ .tp_new = py_engine_backend_new,
+
+ };
+
+ return &py_engine_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....EngineBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_engine_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanNamespace' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_engine_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ENGINE_BACKEND, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 méthode de recherches. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_engine_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_engine_backend_type());
+
+ 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 engine backend");
+ break;
+
+ case 1:
+ *((GEngineBackend **)dst) = G_ENGINE_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.h b/plugins/pychrysalide/analysis/scan/patterns/backend.h
new file mode 100644
index 0000000..6b1f4cd
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backend.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.h - prototypes pour l'équivalent Python du fichier "analysis/scan/backend.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_engine_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.EngineBackend'. */
+bool ensure_python_engine_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherches. */
+int convert_to_engine_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am
new file mode 100644
index 0000000..cccfc2d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsbackends.la
+
+libpychrysaanalysisscanpatternsbackends_la_SOURCES = \
+ acism.h acism.c \
+ bitap.h bitap.c \
+ module.h module.c
+
+libpychrysaanalysisscanpatternsbackends_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatternsbackends_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c
new file mode 100644
index 0000000..56d0b55
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.c - équivalent Python du fichier "analysis/scan/patterns/backends/acism.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "acism.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/backends/acism-int.h>
+
+
+#include "../backend.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(acism_backend, G_TYPE_ACISM_BACKEND);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_acism_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_acism_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define ACISM_BACKEND_DOC \
+ "A *AcismBackend* class provide an implementation of the Aho-Corasick" \
+ " search algorithm with Interleaved State-transition Matrix (ACISM)." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " AcismBackend()" \
+ "\n" \
+ "See the relative white paper for more information:" \
+ " https://docs.google.com/document/d/1e9Qbn22__togYgQ7PNyCz3YzIIVPKvrf8PCrFa74IFM"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_acism_backend_type(void)
+{
+ static PyMethodDef py_acism_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_acism_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_acism_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.backends.AcismBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = ACISM_BACKEND_DOC,
+
+ .tp_methods = py_acism_backend_methods,
+ .tp_getset = py_acism_backend_getseters,
+
+ .tp_init = py_acism_backend_init,
+ .tp_new = py_acism_backend_new,
+
+ };
+
+ return &py_acism_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....AcismBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_acism_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'AcismBackend'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_acism_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_engine_backend_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ACISM_BACKEND, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 méthode de recherche ACISM. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_acism_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_acism_backend_type());
+
+ 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 ACISM backend");
+ break;
+
+ case 1:
+ *((GAcismBackend **)dst) = G_ACISM_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h
new file mode 100644
index 0000000..9ed61fa
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/acism.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_acism_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.AcismBackend'. */
+bool ensure_python_acism_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherche ACISM. */
+int convert_to_acism_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c
new file mode 100644
index 0000000..c910f26
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.c - équivalent Python du fichier "analysis/scan/patterns/backends/bitap.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "bitap.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/backends/bitap-int.h>
+
+
+#include "../backend.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(bitap_backend, G_TYPE_BITAP_BACKEND);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_bitap_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_bitap_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define BITAP_BACKEND_DOC \
+ "A *BitapBackend* class provide an implementation of the Bitap" \
+ " search algorithm." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " BitapBackend()" \
+ "\n" \
+ "See the relative white paper for more information:" \
+ " https://en.wikipedia.org/wiki/Bitap_algorithm"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_bitap_backend_type(void)
+{
+ static PyMethodDef py_bitap_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_bitap_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_bitap_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.backends.BitapBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = BITAP_BACKEND_DOC,
+
+ .tp_methods = py_bitap_backend_methods,
+ .tp_getset = py_bitap_backend_getseters,
+
+ .tp_init = py_bitap_backend_init,
+ .tp_new = py_bitap_backend_new,
+
+ };
+
+ return &py_bitap_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....BitapBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_bitap_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'BitapBackend'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_bitap_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_engine_backend_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_BITAP_BACKEND, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 méthode de recherche BITAP. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_bitap_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_bitap_backend_type());
+
+ 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 Bitap backend");
+ break;
+
+ case 1:
+ *((GBitapBackend **)dst) = G_BITAP_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h
new file mode 100644
index 0000000..f7853d4
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/bitap.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_bitap_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.BitapBackend'. */
+bool ensure_python_bitap_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherche Bitap. */
+int convert_to_bitap_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.c b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c
new file mode 100644
index 0000000..f4a0293
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c
@@ -0,0 +1,106 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire backends en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "acism.h"
+#include "bitap.h"
+#include "../../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.....backends' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_backends_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_backends_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns.backends",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_backends_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis....patterns.backends'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_backends_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_acism_backend_is_registered();
+ if (result) result = ensure_python_bitap_backend_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.h b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h
new file mode 100644
index 0000000..ab1aad5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire backends en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns.backends' à un module Python. */
+bool add_analysis_scan_patterns_backends_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns.backends'. */
+bool populate_analysis_scan_patterns_backends_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.c b/plugins/pychrysalide/analysis/scan/patterns/modifier.c
new file mode 100644
index 0000000..6547d91
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.c
@@ -0,0 +1,416 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.c - équivalent Python du fichier "analysis/scan/modifier.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "modifier.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_token_modifier, G_TYPE_SCAN_TOKEN_MODIFIER, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_token_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_token_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_TOKEN_MODIFIER_DOC \
+ "An *TokenModifier* object is the root class of all modifiers" \
+ " for byte patterns."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = tampon de données à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Liste des nouvelle(s) séquence(s) d'octets obtenue(s). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_token_modifier_transform(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ PyObject *py_src; /* Motifs Python en entrée */
+ PyObject *py_arg; /* Eventuel paramètre de config*/
+ sized_binary_t src; /* Entrée au format adapté */
+ Py_ssize_t len; /* Quantité de ces données */
+ int ret; /* Bilan de lecture des args. */
+ sized_binary_t *src_list; /* Entrées au format adapté */
+ size_t scount; /* Taille de cette liste */
+ bool dyn_src; /* Allocation dynamique ? */
+ Py_ssize_t size; /* Taille d'une séquence */
+ Py_ssize_t k; /* Boucle de parcours #1 */
+ PyObject *item; /* Elément de liste de motifs */
+ modifier_arg_t arg; /* Eventuelle précision */
+ GScanTokenModifier *modifier; /* Version native de l'instance*/
+ sized_binary_t *dest; /* Liste des nouvelles chaînes */
+ size_t dcount; /* Taille de cette liste */
+ bool status; /* Bilan de l'opération */
+ size_t i; /* Boucle de parcours #2 */
+
+#define SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD PYTHON_METHOD_DEF \
+( \
+ transform, "$self, data, /, arg", \
+ METH_VARARGS, py_scan_token_modifier, \
+ "Transform data from a byte pattern for an incoming scan.\n" \
+ "\n" \
+ "The data has to be provided as bytes.\n" \
+ "\n" \
+ "The method returns a tuple of transformed data as bytes, or" \
+ " *None* in case of error." \
+)
+
+ py_arg = NULL;
+
+ ret = PyArg_ParseTuple(args, "O|O", &py_src, &py_arg);
+ if (!ret) return NULL;
+
+ /* Constitution des motifs d'entrée */
+
+ if (PyBytes_Check(py_src))
+ {
+ ret = PyBytes_AsStringAndSize(py_src, &src.data, &len);
+ if (ret == -1) return NULL;
+
+ src.len = len;
+
+ src_list = &src;
+ scount = 1;
+
+ dyn_src = false;
+
+ }
+
+ else if (PySequence_Check(py_src))
+ {
+ size = PySequence_Size(py_src);
+
+ src_list = malloc(size * sizeof(sized_binary_t));
+ scount = size;
+
+ dyn_src = true;
+
+ for (k = 0; k < size; k++)
+ {
+ item = PySequence_ITEM(py_src, k);
+
+ if (PyBytes_Check(item))
+ {
+ ret = PyBytes_AsStringAndSize(item, &src_list[k].data, &len);
+ if (ret == -1) return NULL;
+
+ src_list[k].len = len;
+
+ }
+ else
+ {
+ free(src_list);
+
+ PyErr_SetString(PyExc_TypeError, "lists of items other than bytes are not supported");
+ return NULL;
+ }
+
+ }
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "only bytes and lists of bytes are expected as input for modifiers");
+ return NULL;
+ }
+
+ /* Récupération d'une éventuelle précision opérationnelle */
+
+ if (py_arg != NULL)
+ {
+ if (PyLong_Check(py_arg))
+ {
+ arg.type = MAT_UNSIGNED_INTEGER;
+ arg.value.u_integer = PyLong_AsUnsignedLongLong(py_arg);
+ }
+
+ else
+ {
+ if (dyn_src)
+ free(src_list);
+
+ PyErr_SetString(PyExc_TypeError, "unable to handle the argument type for calling a modifier");
+ return NULL;
+
+ }
+
+ }
+
+ /* Création des nouveaux motifs */
+
+ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self));
+
+ if (py_arg == NULL)
+ status = g_scan_token_modifier_transform(modifier, src_list, scount, &dest, &dcount);
+ else
+ status = g_scan_token_modifier_transform_with_arg(modifier, src_list, scount, &arg, &dest, &dcount);
+
+ if (dyn_src)
+ free(src_list);
+
+ if (status)
+ {
+ result = PyTuple_New(dcount);
+
+ for (i = 0; i < dcount; i++)
+ {
+ PyTuple_SetItem(result, i, PyBytes_FromStringAndSize(dest[i].data, dest[i].len));
+ exit_szstr(&dest[i]);
+ }
+
+ free(dest);
+
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un composant nommé à manipuler.*
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le désignation associée à un composant nommé. *
+* *
+* Retour : Description courante. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_token_modifier_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Décompte à retourner */
+ GScanTokenModifier *modifier; /* Version native */
+ char *name; /* Désignation à convertir */
+
+#define SCAN_TOKEN_MODIFIER_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_scan_token_modifier, \
+ "Call name for the modifier.\n" \
+ "\n" \
+ "The result is a string." \
+)
+
+ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self));
+
+ name = g_scan_token_modifier_get_name(modifier);
+
+ if (name == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = PyUnicode_FromString(name);
+ free(name);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_token_modifier_type(void)
+{
+ static PyMethodDef py_scan_token_modifier_methods[] = {
+ SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_token_modifier_getseters[] = {
+ SCAN_TOKEN_MODIFIER_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_token_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.TokenModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_TOKEN_MODIFIER_DOC,
+
+ .tp_methods = py_scan_token_modifier_methods,
+ .tp_getset = py_scan_token_modifier_getseters,
+
+ .tp_init = py_scan_token_modifier_init,
+ .tp_new = py_scan_token_modifier_new,
+
+ };
+
+ return &py_scan_token_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....TokenModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_token_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'TokenModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_token_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_TOKEN_MODIFIER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 transformation de séquence d'octets. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_token_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_token_modifier_type());
+
+ 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 token modifier");
+ break;
+
+ case 1:
+ *((GScanTokenModifier **)dst) = G_SCAN_TOKEN_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.h b/plugins/pychrysalide/analysis/scan/patterns/modifier.h
new file mode 100644
index 0000000..770b2c1
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.h - prototypes pour l'équivalent Python du fichier "analysis/scan/modifier.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_token_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.TokenModifier'. */
+bool ensure_python_scan_token_modifier_is_registered(void);
+
+/* Tente de convertir en transformation de séquence d'octets. */
+int convert_to_scan_token_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
new file mode 100644
index 0000000..ae53e45
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsmodifiers.la
+
+libpychrysaanalysisscanpatternsmodifiers_la_SOURCES = \
+ hex.h hex.c \
+ list.h list.c \
+ module.h module.c \
+ plain.h plain.c \
+ rev.h rev.c \
+ xor.h xor.c
+
+libpychrysaanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatternsmodifiers_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
new file mode 100644
index 0000000..503580d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "hex.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/hex.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_hex_modifier, G_TYPE_SCAN_HEX_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_hex_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_hex_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_HEX_MODIFIER_DOC \
+ "The *HexModifier* class transforms a byte pattern into its" \
+ " corresponding byte sequence in lower case." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " HexModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_hex_modifier_type(void)
+{
+ static PyMethodDef py_scan_hex_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_hex_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_hex_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.HexModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_HEX_MODIFIER_DOC,
+
+ .tp_methods = py_scan_hex_modifier_methods,
+ .tp_getset = py_scan_hex_modifier_getseters,
+
+ .tp_init = py_scan_hex_modifier_init,
+ .tp_new = py_scan_hex_modifier_new,
+
+ };
+
+ return &py_scan_hex_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....HexModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_hex_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'HexModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_hex_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_HEX_MODIFIER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 transmission d'octets à l'identique. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_hex_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_hex_modifier_type());
+
+ 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 hex modifier");
+ break;
+
+ case 1:
+ *((GScanHexModifier **)dst) = G_SCAN_HEX_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
new file mode 100644
index 0000000..5d70a01
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_hex_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.HexModifier'. */
+bool ensure_python_scan_hex_modifier_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_hex_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
new file mode 100644
index 0000000..7c77d63
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
@@ -0,0 +1,320 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "list.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/list.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_modifier_list, G_TYPE_SCAN_MODIFIER_LIST);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_modifier_list_init(PyObject *, PyObject *, PyObject *);
+
+/* Intègre un nouveau transformateur dans une liste. */
+static PyObject *py_scan_modifier_list_add(PyObject *, PyObject *);
+
+/* Fournit les transformateurs associés à la liste. */
+static PyObject *py_scan_modifier_list_get_modifiers(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_modifier_list_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_MODIFIER_LIST_DOC \
+ "The *ModifierList* class is a special modifier which groups a list of" \
+ " modifiers for byte patterns." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ModifierList()" \
+ "\n" \
+ "The keyword for such a modifier is *(list)*."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = projet d'étude à manipuler. *
+* args = arguments accompagnant l'appel. *
+* *
+* Description : Intègre un nouveau transformateur dans une liste. *
+* *
+* Retour : Bilan de l'ajout : False si un élément similaire est déjà là.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_modifier_list_add(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Absence de retour Python */
+ GScanTokenModifier *modifier; /* Modificateur à intégrer */
+ int ret; /* Bilan de lecture des args. */
+ GScanModifierList *list; /* Version GLib du type */
+ bool status; /* Bilan de l'opération */
+
+#define SCAN_MODIFIER_LIST_ADD_METHOD PYTHON_METHOD_DEF \
+( \
+ add, "$self, modifier, /", \
+ METH_VARARGS, py_scan_modifier_list, \
+ "Add an extra modifier to the list.\n" \
+ "\n" \
+ "This *modifier* parameter has to be a" \
+ " pychrysalide.analysis.scan.patterns.TokenModifier instance." \
+ "\n" \
+ "The function returns *True* if the provided modifier did not already" \
+ " exist in the list, *False* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_token_modifier, &modifier);
+ if (!ret) return NULL;
+
+ list = G_SCAN_MODIFIER_LIST(pygobject_get(self));
+
+ status = g_scan_modifier_list_add(list, modifier);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit les transformateurs associés à la liste. *
+* *
+* Retour : Liste de modificateurs de séquence d'octets. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_modifier_list_get_modifiers(PyObject *self, void *closure)
+{
+ PyObject *result; /* Résultat à retourner */
+ GScanModifierList *list; /* Version GLib du type */
+ size_t count; /* Nombre de transformateurs */
+ size_t i; /* Boucle de parcours */
+ GScanTokenModifier *modifier; /* Modificateur de la liste */
+
+#define SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ modifiers, py_scan_modifier_list, \
+ "List of all modifiers contained in a list.\n" \
+ "\n" \
+ "The returned value is a tuple of pychrysalide.analysis.scan.patterns.TokenModifier" \
+ " instances." \
+)
+
+ list = G_SCAN_MODIFIER_LIST(pygobject_get(self));
+
+ count = g_scan_modifier_list_count(list);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ {
+ modifier = g_scan_modifier_list_get(list, i);
+
+ PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(modifier)));
+
+ g_object_unref(modifier);
+
+ }
+
+ return result;
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_modifier_list_type(void)
+{
+ static PyMethodDef py_scan_modifier_list_methods[] = {
+ SCAN_MODIFIER_LIST_ADD_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_modifier_list_getseters[] = {
+ SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_modifier_list_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.ModifierList",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_MODIFIER_LIST_DOC,
+
+ .tp_methods = py_scan_modifier_list_methods,
+ .tp_getset = py_scan_modifier_list_getseters,
+
+ .tp_init = py_scan_modifier_list_init,
+ .tp_new = py_scan_modifier_list_new,
+
+ };
+
+ return &py_scan_modifier_list_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....ModifierList'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_modifier_list_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ModifierList' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_modifier_list_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_MODIFIER_LIST, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 liste de transormations d'octets. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_modifier_list(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_modifier_list_type());
+
+ 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 modifier list");
+ break;
+
+ case 1:
+ *((GScanModifierList **)dst) = G_SCAN_MODIFIER_LIST(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
new file mode 100644
index 0000000..133de8d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_modifier_list_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ModifierList'. */
+bool ensure_python_scan_modifier_list_is_registered(void);
+
+/* Tente de convertir en liste de transormations d'octets. */
+int convert_to_scan_modifier_list(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
new file mode 100644
index 0000000..ae450dc
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
@@ -0,0 +1,112 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire modifiers en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "hex.h"
+#include "list.h"
+#include "plain.h"
+#include "rev.h"
+#include "xor.h"
+#include "../../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis....modifiers' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_modifiers_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_modifiers_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns.modifiers",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_modifiers_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis...patterns.modifiers'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_modifiers_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_hex_modifier_is_registered();
+ if (result) result = ensure_python_scan_modifier_list_is_registered();
+ if (result) result = ensure_python_scan_plain_modifier_is_registered();
+ if (result) result = ensure_python_scan_reverse_modifier_is_registered();
+ if (result) result = ensure_python_scan_xor_modifier_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
new file mode 100644
index 0000000..8094efc
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire modifiers en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns.modifiers' à un module Python. */
+bool add_analysis_scan_patterns_modifiers_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns.modifiers'. */
+bool populate_analysis_scan_patterns_modifiers_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
new file mode 100644
index 0000000..7a260c1
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "plain.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/plain.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_plain_modifier, G_TYPE_SCAN_PLAIN_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_plain_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_plain_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_PLAIN_MODIFIER_DOC \
+ "The *PlainModifier* class provide an transmision of a byte pattern" \
+ " without any modification." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " PlainModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_plain_modifier_type(void)
+{
+ static PyMethodDef py_scan_plain_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_plain_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_plain_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.PlainModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_PLAIN_MODIFIER_DOC,
+
+ .tp_methods = py_scan_plain_modifier_methods,
+ .tp_getset = py_scan_plain_modifier_getseters,
+
+ .tp_init = py_scan_plain_modifier_init,
+ .tp_new = py_scan_plain_modifier_new,
+
+ };
+
+ return &py_scan_plain_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....PlainModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_plain_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'PlainModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_plain_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_PLAIN_MODIFIER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 transmission d'octets à l'identique. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_plain_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_plain_modifier_type());
+
+ 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 plain modifier");
+ break;
+
+ case 1:
+ *((GScanPlainModifier **)dst) = G_SCAN_PLAIN_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
new file mode 100644
index 0000000..03949d8
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_plain_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.PlainModifier'. */
+bool ensure_python_scan_plain_modifier_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_plain_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
new file mode 100644
index 0000000..841e929
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "rev.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/rev.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_reverse_modifier, G_TYPE_SCAN_REVERSE_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_reverse_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_reverse_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_HEX_MODIFIER_DOC \
+ "The *ReverseModifier* class transforms a byte pattern by reversing" \
+ " the order of each bytes." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ReverseModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_reverse_modifier_type(void)
+{
+ static PyMethodDef py_scan_reverse_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_reverse_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_reverse_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_HEX_MODIFIER_DOC,
+
+ .tp_methods = py_scan_reverse_modifier_methods,
+ .tp_getset = py_scan_reverse_modifier_getseters,
+
+ .tp_init = py_scan_reverse_modifier_init,
+ .tp_new = py_scan_reverse_modifier_new,
+
+ };
+
+ return &py_scan_reverse_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....ReverseModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_reverse_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python ReverseModifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_reverse_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REVERSE_MODIFIER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 transformation d'octets par inverse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_reverse_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_reverse_modifier_type());
+
+ 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 reverse modifier");
+ break;
+
+ case 1:
+ *((GScanReverseModifier **)dst) = G_SCAN_REVERSE_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
new file mode 100644
index 0000000..fe10e1e
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/rev.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_reverse_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier'. */
+bool ensure_python_scan_reverse_modifier_is_registered(void);
+
+/* Tente de convertir en transformation d'octets par inverse. */
+int convert_to_scan_reverse_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c
new file mode 100644
index 0000000..17a32f4
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c
@@ -0,0 +1,210 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * xor.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "xor.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/xor.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_xor_modifier, G_TYPE_SCAN_XOR_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_xor_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_xor_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_XOR_MODIFIER_DOC \
+ "The *XorModifier* class transforms a byte pattern by XORing bytes.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " XorModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_xor_modifier_type(void)
+{
+ static PyMethodDef py_scan_xor_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_xor_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_xor_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.XorModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_XOR_MODIFIER_DOC,
+
+ .tp_methods = py_scan_xor_modifier_methods,
+ .tp_getset = py_scan_xor_modifier_getseters,
+
+ .tp_init = py_scan_xor_modifier_init,
+ .tp_new = py_scan_xor_modifier_new,
+
+ };
+
+ return &py_scan_xor_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....XorModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_xor_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python XorModifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_xor_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_XOR_MODIFIER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 transformation d'octets par inverse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_xor_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_xor_modifier_type());
+
+ 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 XOR modifier");
+ break;
+
+ case 1:
+ *((GScanXorModifier **)dst) = G_SCAN_XOR_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h
new file mode 100644
index 0000000..7b9bb69
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * xor.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_xor_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.XorModifier'. */
+bool ensure_python_scan_xor_modifier_is_registered(void);
+
+/* Tente de convertir en transformation d'octets par inverse. */
+int convert_to_scan_xor_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.c b/plugins/pychrysalide/analysis/scan/patterns/module.c
new file mode 100644
index 0000000..123b23a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.c
@@ -0,0 +1,114 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire patterns en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "backend.h"
+#include "modifier.h"
+#include "backends/module.h"
+#include "modifiers/module.h"
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.scan.patterns' à un module Python.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_module);
+
+ result = (module != NULL);
+
+ if (result) result = add_analysis_scan_patterns_backends_module(module);
+ if (result) result = add_analysis_scan_patterns_modifiers_module(module);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis.scan.patterns'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_engine_backend_is_registered();
+ if (result) result = ensure_python_scan_token_modifier_is_registered();
+
+ if (result) result = populate_analysis_scan_patterns_backends_module();
+ if (result) result = populate_analysis_scan_patterns_modifiers_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.h b/plugins/pychrysalide/analysis/scan/patterns/module.h
new file mode 100644
index 0000000..bc25129
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire patterns en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns' à un module Python. */
+bool add_analysis_scan_patterns_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns'. */
+bool populate_analysis_scan_patterns_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c
new file mode 100644
index 0000000..bc58c9a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/scanner.c
@@ -0,0 +1,487 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.c - équivalent Python du fichier "analysis/scan/scanner.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "scanner.h"
+
+
+#include <malloc.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/context.h>
+#include <analysis/scan/scanner-int.h>
+
+
+#include "context.h"
+#include "options.h"
+#include "../content.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(content_scanner, G_TYPE_CONTENT_SCANNER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_content_scanner_init(PyObject *, PyObject *, PyObject *);
+
+/* Lance une analyse d'un contenu binaire. */
+static PyObject *py_content_scanner_analyze(PyObject *, PyObject *);
+
+/* Convertit un gestionnaire de recherches en JSON. */
+static PyObject *py_content_scanner_convert_to_json(PyObject *, PyObject *);
+
+/* Indique le chemin d'un éventuel fichier de source. */
+static PyObject *py_content_scanner_get_filename(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *text; /* Contenu de règles à traiter */
+ Py_ssize_t len; /* Taille de ce nom */
+ const char *filename; /* Fichier de définitions */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "text", "filename", NULL };
+
+#define CONTENT_SCANNER_DOC \
+ "A ContentScanner object provides support for rules processing" \
+ " against binary contents.\n" \
+ "\n" \
+ "Instances can be created using one of the following" \
+ " constructors:\n" \
+ "\n" \
+ " ContentScanner(text=str)" \
+ "\n" \
+ " ContentScanner(filename=str)" \
+ "\n" \
+ "Where *text* is a string for the rules definitions and" \
+ " *filename* an alternative string for a path pointing to a" \
+ " definition file."
+
+ /* Récupération des paramètres */
+
+ text = NULL;
+ len = 0;
+ filename = NULL;
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "|s#s", kwlist, &text, &len, &filename);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ if (text != NULL)
+ {
+ if (!g_content_scanner_create_from_text(scanner, text, len))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner."));
+ return -1;
+ }
+
+ }
+
+ else if (filename != NULL)
+ {
+ if (!g_content_scanner_create_from_file(scanner, filename))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner."));
+ return -1;
+ }
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create empty content scanner."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Lance une analyse d'un contenu binaire. *
+* *
+* Retour : Contexte de suivi pour l'analyse menée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_analyze(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanOptions *options; /* Paramètres d'analyse */
+ GBinContent *content; /* Contenu binaire à traiter */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ GScanContext *context; /* Contexte de suivi */
+
+#define CONTENT_SCANNER_ANALYZE_METHOD PYTHON_METHOD_DEF \
+( \
+ analyze, "$self, options, content, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Run a scan against a binary content.\n" \
+ "\n" \
+ "The *content* argument is a pychrysalide.analysis.BinContent" \
+ " object pointing to data to analyze.\n" \
+ "\n" \
+ "The method returns a pychrysalide.analysis.scan.ScanContext" \
+ " object tracking all the scan results." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&O&", convert_to_scan_options, &options, convert_to_binary_content, &content);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ context = g_content_scanner_analyze(scanner, options, content);
+
+ result = pygobject_new(G_OBJECT(context));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Convertit un gestionnaire de recherches en texte. *
+* *
+* Retour : Données textuelles ou None en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_convert_to_text(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanContext *context; /* Contexte d'analyse */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ char *out; /* Données en sortie */
+
+#define CONTENT_SCANNER_CONVERT_TO_TEXT_METHOD PYTHON_METHOD_DEF \
+( \
+ convert_to_text, "$self, context, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Output a scan results as text.\n" \
+ "\n" \
+ "The *context* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance provided by a previous call to *self.analyze()*. This" \
+ " context stores all the scan results.\n" \
+ "\n" \
+ "The method returns a string value, or *None* in case of failure." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_context, &context);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ out = g_content_scanner_convert_to_text(scanner, context);
+
+ if (out != NULL)
+ {
+ result = PyUnicode_FromString(out);
+ free(out);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Convertit un gestionnaire de recherches en JSON. *
+* *
+* Retour : Données textuelles au format JSON ou None en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_convert_to_json(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanContext *context; /* Contexte d'analyse */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ char *out; /* Données en sortie */
+
+#define CONTENT_SCANNER_CONVERT_TO_JSON_METHOD PYTHON_METHOD_DEF \
+( \
+ convert_to_json, "$self, context, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Output a scan results as JSON data.\n" \
+ "\n" \
+ "The *context* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance provided by a previous call to *self.analyze()*. This" \
+ " context stores all the scan results.\n" \
+ "\n" \
+ "The method returns JSON data as a string value, or *None* in case" \
+ " of failure." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_context, &context);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ out = g_content_scanner_convert_to_json(scanner, context);
+
+ if (out != NULL)
+ {
+ result = PyUnicode_FromString(out);
+ free(out);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le chemin d'un éventuel fichier de source. *
+* *
+* Retour : Chemin d'un éventuel fichier de définitions ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_get_filename(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GContentScanner *scanner; /* Analyseur à consulter */
+ const char *filename; /* Chemin d'accès à transmettre*/
+
+#define CONTENT_SCANNER_FILENAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ filename, py_content_scanner, \
+ "Provide the access path to the source file of the rules'" \
+ " definition, or *None* if these rules have not been loaded"\
+ " from memory." \
+)
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ filename = g_content_scanner_get_filename(scanner);
+
+ if (filename != NULL)
+ result = PyUnicode_FromString(filename);
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_content_scanner_type(void)
+{
+ static PyMethodDef py_content_scanner_methods[] = {
+ CONTENT_SCANNER_ANALYZE_METHOD,
+ CONTENT_SCANNER_CONVERT_TO_TEXT_METHOD,
+ CONTENT_SCANNER_CONVERT_TO_JSON_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_content_scanner_getseters[] = {
+ CONTENT_SCANNER_FILENAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_content_scanner_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ContentScanner",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = CONTENT_SCANNER_DOC,
+
+ .tp_methods = py_content_scanner_methods,
+ .tp_getset = py_content_scanner_getseters,
+
+ .tp_init = py_content_scanner_init,
+ .tp_new = py_content_scanner_new,
+
+ };
+
+ return &py_content_scanner_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ContentScanner. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_content_scanner_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ContentScanner'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_content_scanner_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_SCANNER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 scanner de contenus binaires. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_content_scanner(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_content_scanner_type());
+
+ 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 content scanner");
+ break;
+
+ case 1:
+ *((GContentScanner **)dst) = G_CONTENT_SCANNER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/scanner.h b/plugins/pychrysalide/analysis/scan/scanner.h
new file mode 100644
index 0000000..b3b1baf
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/scanner.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.h - prototypes pour l'équivalent Python du fichier "analysis/scan/scanner.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_content_scanner_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ContentScanner'. */
+bool ensure_python_content_scanner_is_registered(void);
+
+/* Tente de convertir en scanner de contenus binaires. */
+int convert_to_content_scanner(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H */
diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c
new file mode 100644
index 0000000..6ea87b8
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/space.c
@@ -0,0 +1,283 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - équivalent Python du fichier "analysis/scan/space.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "space.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/item.h>
+#include <analysis/scan/space-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+
+
+#include "item.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_namespace, G_TYPE_SCAN_NAMESPACE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_namespace_init(PyObject *, PyObject *, PyObject *);
+
+/* Intègre un nouvel élément dans l'esapce de noms. */
+static PyObject *py_scan_namespace_register_item(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_namespace_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *name; /* Désignation de l'espace */
+ int ret; /* Bilan de lecture des args. */
+ GScanNamespace *space; /* Création GLib à transmettre */
+
+#define SCAN_NAMESPACE_DOC \
+ "ScanNamespace defines a group of properties and functions for a" \
+ " given scan theme.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanNamespace(name)" \
+ "\n" \
+ "Where *name* is a string providing the name of the new namespace."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "s", &name);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Elément de base */
+
+ space = G_SCAN_NAMESPACE(pygobject_get(self));
+
+ if (!g_scan_namespace_create(space, name))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create scan namespace."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet représentant une table de chaînes. *
+* args = arguments fournis pour l'opération. *
+* *
+* Description : Intègre un nouvel élément dans l'esapce de noms. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_namespace_register_item(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GScanRegisteredItem *item; /* Elément d'évaluation à lier */
+ int ret; /* Bilan de lecture des args. */
+ GScanNamespace *space; /* Version native */
+ bool status; /* Bilan de l'opération */
+
+#define SCAN_NAMESPACE_REGISTER_ITEM_METHOD PYTHON_METHOD_DEF \
+( \
+ register_item, "$self, item, /", \
+ METH_VARARGS, py_scan_namespace, \
+ "Include an item into a namespace.\n" \
+ "\n" \
+ "The *item* argument has to be a pychrysalide.analysis.scan.RegisteredItem" \
+ " instance.\n" \
+ "\n" \
+ "The function returns a boolean value translating the operation status:" \
+ " *True* in case of success, *False* for a failure.\n" \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_registered_item, &item);
+ if (!ret) return NULL;
+
+ space = G_SCAN_NAMESPACE(pygobject_get(self));
+
+ status = g_scan_namespace_register_item(space, item);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_namespace_type(void)
+{
+ static PyMethodDef py_scan_namespace_methods[] = {
+ SCAN_NAMESPACE_REGISTER_ITEM_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_namespace_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_namespace_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanNamespace",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_NAMESPACE_DOC,
+
+ .tp_methods = py_scan_namespace_methods,
+ .tp_getset = py_scan_namespace_getseters,
+
+ .tp_init = py_scan_namespace_init,
+ .tp_new = py_scan_namespace_new,
+
+ };
+
+ return &py_scan_namespace_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanNamespace'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_namespace_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanNamespace' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_namespace_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_NAMESPACE, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 espace de noms pour scan. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_namespace(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_namespace_type());
+
+ 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 scan namespace");
+ break;
+
+ case 1:
+ *((GScanNamespace **)dst) = G_SCAN_NAMESPACE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/space.h b/plugins/pychrysalide/analysis/scan/space.h
new file mode 100644
index 0000000..0166c04
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/space.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour l'équivalent Python du fichier "analysis/scan/space.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_namespace_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanNamespace'. */
+bool ensure_python_scan_namespace_is_registered(void);
+
+/* Tente de convertir en espace de noms pour scan. */
+int convert_to_scan_namespace(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H */