summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/analysis
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-11-28 22:41:37 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-11-28 22:41:37 (GMT)
commit48395d4471d87c20bdbd06bbab1ae3af938ff823 (patch)
tree00aaaabb7370d6163ed9a2a4f77f9a177f8126f7 /plugins/pychrysalide/analysis
parent472d566943f527e18eb95f31dbe70c50043396aa (diff)
Improved the API for binary contents a little bit.
Diffstat (limited to 'plugins/pychrysalide/analysis')
-rw-r--r--plugins/pychrysalide/analysis/contents/encapsulated.c159
-rw-r--r--plugins/pychrysalide/analysis/contents/file.c51
-rw-r--r--plugins/pychrysalide/analysis/contents/memory.c25
-rw-r--r--plugins/pychrysalide/analysis/contents/module.c9
-rw-r--r--plugins/pychrysalide/analysis/contents/restricted.c74
-rw-r--r--plugins/pychrysalide/analysis/module.c6
6 files changed, 289 insertions, 35 deletions
diff --git a/plugins/pychrysalide/analysis/contents/encapsulated.c b/plugins/pychrysalide/analysis/contents/encapsulated.c
index 031c49f..7a10e5b 100644
--- a/plugins/pychrysalide/analysis/contents/encapsulated.c
+++ b/plugins/pychrysalide/analysis/contents/encapsulated.c
@@ -40,6 +40,15 @@
/* Crée un nouvel objet Python de type 'BinContent'. */
static PyObject *py_encaps_content_new(PyTypeObject *, PyObject *, PyObject *);
+/* Indique la base d'un contenu binaire encapsulé. */
+static PyObject *py_encaps_content_get_base(PyObject *, void *);
+
+/* Fournit le chemin vers le contenu interne représenté. */
+static PyObject *py_encaps_content_get_path(PyObject *, void *);
+
+/* Indique le contenu binaire embarqué dans une encapsulation. */
+static PyObject *py_encaps_content_get_endpoint(PyObject *, void *);
+
/******************************************************************************
@@ -65,6 +74,25 @@ static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObj
int ret; /* Bilan de lecture des args. */
GBinContent *content; /* Version GLib du contenu */
+#define ENCAPS_CONTENT_DOC \
+ "EncapsulatedContent gathers items relative to a binary encapsulated" \
+ " content.\n" \
+ "\n" \
+ "For instance, if a ZIP archive is processed, the encapsulated content" \
+ " stores:\n" \
+ "* the archive as a base;\n" \
+ "* the access path to the archive member;\n" \
+ "* the content of this extracted member.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " EncapsulatedContent(base, path, endpoint)" \
+ "\n" \
+ "Where base, path and endpoint are the previously described expected" \
+ " properties. The base and the endpoint must be" \
+ " pychrysalide.analysis.BinContent instances and the access path must" \
+ " be provided as a string."
+
ret = PyArg_ParseTuple(args, "O&sO&",
convert_to_binary_content, &base,
&path,
@@ -85,6 +113,132 @@ static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObj
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique la base d'un contenu binaire encapsulé. *
+* *
+* Retour : Instance de contenu binaire ou None si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_encaps_content_get_base(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GEncapsContent *content; /* Contenu binaire à consulter */
+ GBinContent *target; /* Contenu binaire visé */
+
+#define ENCAPS_CONTENT_BASE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ base, py_encaps_content, \
+ "Give access to the base of the encapsulated content." \
+)
+
+ content = G_ENCAPS_CONTENT(pygobject_get(self));
+
+ target = g_encaps_content_get_base(content);
+
+ if (target == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = pygobject_new(G_OBJECT(target));
+ g_object_unref(G_OBJECT(target));
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le chemin vers le contenu interne représenté. *
+* *
+* Retour : Chemin d'accès au contenu binaire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_encaps_content_get_path(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GEncapsContent *content; /* Contenu binaire à consulter */
+ const char *path; /* Chemin d'accès à transmettre*/
+
+#define ENCAPS_CONTENT_PATH_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ path, py_encaps_content, \
+ "Provide the access path to the inner binary content." \
+)
+
+ content = G_ENCAPS_CONTENT(pygobject_get(self));
+
+ path = g_encaps_content_get_path(content);
+
+ result = PyUnicode_FromString(path);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le contenu binaire embarqué dans une encapsulation. *
+* *
+* Retour : Instance de contenu binaire ou None si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_encaps_content_get_endpoint(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GEncapsContent *content; /* Contenu binaire à consulter */
+ GBinContent *target; /* Contenu binaire visé */
+
+#define ENCAPS_CONTENT_ENDPOINT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ endpoint, py_encaps_content, \
+ "Give access to the encapsulated binary content." \
+)
+
+ content = G_ENCAPS_CONTENT(pygobject_get(self));
+
+ target = g_encaps_content_get_base(content);
+
+ if (target == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = pygobject_new(G_OBJECT(target));
+ g_object_unref(G_OBJECT(target));
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -102,6 +256,9 @@ PyTypeObject *get_python_encaps_content_type(void)
};
static PyGetSetDef py_encaps_content_getseters[] = {
+ ENCAPS_CONTENT_BASE_ATTRIB,
+ ENCAPS_CONTENT_PATH_ATTRIB,
+ ENCAPS_CONTENT_ENDPOINT_ATTRIB,
{ NULL }
};
@@ -114,7 +271,7 @@ PyTypeObject *get_python_encaps_content_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide binary encapsulated content",
+ .tp_doc = ENCAPS_CONTENT_DOC,
.tp_methods = py_encaps_content_methods,
.tp_getset = py_encaps_content_getseters,
diff --git a/plugins/pychrysalide/analysis/contents/file.c b/plugins/pychrysalide/analysis/contents/file.c
index f660656..dc7cdf9 100644
--- a/plugins/pychrysalide/analysis/contents/file.c
+++ b/plugins/pychrysalide/analysis/contents/file.c
@@ -39,6 +39,9 @@
/* Crée un nouvel objet Python de type 'BinContent'. */
static PyObject *py_file_content_new(PyTypeObject *, PyObject *, PyObject *);
+/* Fournit le nom de fichier associé au contenu binaire. */
+static PyObject *py_file_content_get_filename(PyObject *, void *);
+
/******************************************************************************
@@ -62,6 +65,15 @@ static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObjec
int ret; /* Bilan de lecture des args. */
GBinContent *content; /* Version GLib du contenu */
+#define FILE_CONTENT_DOC \
+ "FileContent handles binary content loaded from a file.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " FileContent(filename)" \
+ "\n" \
+ "Where filename is a path to an existing file."
+
ret = PyArg_ParseTuple(args, "s", &filename);
if (!ret) return NULL;
@@ -79,6 +91,42 @@ static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObjec
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le nom de fichier associé au contenu binaire. *
+* *
+* Retour : Chemin d'accès au contenu binaire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_file_content_get_filename(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GFileContent *content; /* Contenu binaire à consulter */
+ const char *filename; /* Chemin d'accès à transmettre*/
+
+#define FILE_CONTENT_FILENAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ filename, py_file_content, \
+ "Provide the access path to the binary content." \
+)
+
+ content = G_FILE_CONTENT(pygobject_get(self));
+
+ filename = g_file_content_get_filename(content);
+
+ result = PyUnicode_FromString(filename);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -96,6 +144,7 @@ PyTypeObject *get_python_file_content_type(void)
};
static PyGetSetDef py_file_content_getseters[] = {
+ FILE_CONTENT_FILENAME_ATTRIB,
{ NULL }
};
@@ -108,7 +157,7 @@ PyTypeObject *get_python_file_content_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide binary file content",
+ .tp_doc = FILE_CONTENT_DOC,
.tp_methods = py_file_content_methods,
.tp_getset = py_file_content_getseters,
diff --git a/plugins/pychrysalide/analysis/contents/memory.c b/plugins/pychrysalide/analysis/contents/memory.c
index d1da2e8..b960678 100644
--- a/plugins/pychrysalide/analysis/contents/memory.c
+++ b/plugins/pychrysalide/analysis/contents/memory.c
@@ -58,19 +58,26 @@ static PyObject *py_memory_content_new(PyTypeObject *, PyObject *, PyObject *);
static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *result; /* Instance à retourner */
- PyObject *data; /* Données brutes à charger */
- int ret; /* Bilan de lecture des args. */
- char *buffer; /* Tampon interne de Python */
+ const char *data; /* Tampon interne de Python */
Py_ssize_t length; /* Taille utilisé de ce tampon */
+ int ret; /* Bilan de lecture des args. */
GBinContent *content; /* Version GLib du contenu */
- ret = PyArg_ParseTuple(args, "S", &data);
+#define MEMORY_CONTENT_DOC \
+ "MemoryContent builds a binary content from memory data only." \
+ " Thus no existing file backend is needed." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " MemoryContent(data)" \
+ "\n" \
+ "Where data is provided as string or read-only bytes-like object." \
+ " The string may contain embedded null bytes."
+
+ ret = PyArg_ParseTuple(args, "s#", &data, &length);
if (!ret) return NULL;
- ret = PyBytes_AsStringAndSize(data, &buffer, &length);
- if (ret == -1) Py_RETURN_NONE;
-
- content = g_memory_content_new((const bin_t *)buffer, length);
+ content = g_memory_content_new((const bin_t *)data, length);
result = pygobject_new(G_OBJECT(content));
@@ -113,7 +120,7 @@ PyTypeObject *get_python_memory_content_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide binary memory content",
+ .tp_doc = MEMORY_CONTENT_DOC,
.tp_methods = py_memory_content_methods,
.tp_getset = py_memory_content_getseters,
diff --git a/plugins/pychrysalide/analysis/contents/module.c b/plugins/pychrysalide/analysis/contents/module.c
index d1650ac..3c6d7e4 100644
--- a/plugins/pychrysalide/analysis/contents/module.c
+++ b/plugins/pychrysalide/analysis/contents/module.c
@@ -53,12 +53,19 @@ bool add_analysis_contents_module(PyObject *super)
bool result; /* Bilan à retourner */
PyObject *module; /* Sous-module mis en place */
+#define PYCHRYSALIDE_ANALYSIS_CONTENT_MODULE_DOC \
+ "This module provides several ways to load and deal with raw binary" \
+ " contents.\n" \
+ "\n" \
+ "The most used BinContent implementation is probably the" \
+ " pychrysalide.analysis.contents.FileContent class."
+
static PyModuleDef py_chrysalide_analysis_contents_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "pychrysalide.analysis.contents",
- .m_doc = "Python module for Chrysalide.analysis.contents",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_CONTENT_MODULE_DOC,
.m_size = -1,
diff --git a/plugins/pychrysalide/analysis/contents/restricted.c b/plugins/pychrysalide/analysis/contents/restricted.c
index eb16f13..7db52ed 100644
--- a/plugins/pychrysalide/analysis/contents/restricted.c
+++ b/plugins/pychrysalide/analysis/contents/restricted.c
@@ -44,6 +44,9 @@
/* Crée un nouvel objet Python de type 'BinContent'. */
static PyObject *py_restricted_content_new(PyTypeObject *, PyObject *, PyObject *);
+/* Indique l'espace de restriction appliqué à un contenu. */
+static PyObject *py_restricted_content_get_range(PyObject *, void *);
+
/******************************************************************************
@@ -63,37 +66,63 @@ static PyObject *py_restricted_content_new(PyTypeObject *, PyObject *, PyObject
static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *result; /* Instance à retourner */
- PyObject *content_obj; /* Objet pour le contenu */
- PyObject *range_obj; /* Objet pour la restriction */
- int ret; /* Bilan de lecture des args. */
GBinContent *content; /* Instance GLib correspondante*/
- mrange_t *range; /* Restriction à appliquer */
+ mrange_t range; /* Restriction à appliquer */
+ int ret; /* Bilan de lecture des args. */
GBinContent *restricted; /* Création GLib à transmettre */
- ret = PyArg_ParseTuple(args, "OO", &content_obj, &range_obj);
+#define RESTRICTED_CONTENT_DOC \
+ "RestrictedContent restricts access to a given area for a binary content." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " RestrictedContent(content, range)" \
+ "\n" \
+ "Where content is a pychrysalide.analysis.BinContent instance and range" \
+ " a Python object which can be converted into pychrysalide.arch.mrange."
+
+ ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &content, convert_any_to_mrange, &range);
if (!ret) return NULL;
- ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type());
- if (!ret)
- {
- PyErr_SetString(PyExc_TypeError, _("The first argument must be an instance of BinContent."));
- return NULL;
- }
+ restricted = g_restricted_content_new(content, &range);
- ret = PyObject_IsInstance(range_obj, (PyObject *)get_python_mrange_type());
- if (!ret)
- {
- PyErr_SetString(PyExc_TypeError, _("The second argument must be an instance of mrange."));
- return NULL;
- }
+ result = pygobject_new(G_OBJECT(restricted));
- content = G_BIN_CONTENT(pygobject_get(content_obj));
+ return result;
- range = get_internal_mrange(range_obj);
+}
- restricted = g_restricted_content_new(content, range);
- result = pygobject_new(G_OBJECT(restricted));
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique l'espace de restriction appliqué à un contenu. *
+* *
+* Retour : Couverture mémoire associée au contenu restreint. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_restricted_content_get_range(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GRestrictedContent *content; /* Contenu binaire à consulter */
+ mrange_t range; /* Couverture à transmettre */
+
+#define RESTRICTED_CONTENT_RANGE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ range, py_restricted_content, \
+ "Give the restricting range applied to a binary content." \
+)
+
+ content = G_RESTRICTED_CONTENT(pygobject_get(self));
+
+ g_restricted_content_get_range(content, &range);
+
+ result = build_from_internal_mrange(&range);
return result;
@@ -119,6 +148,7 @@ PyTypeObject *get_python_restricted_content_type(void)
};
static PyGetSetDef py_restricted_content_getseters[] = {
+ RESTRICTED_CONTENT_RANGE_ATTRIB,
{ NULL }
};
@@ -131,7 +161,7 @@ PyTypeObject *get_python_restricted_content_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide binary restricted content",
+ .tp_doc = RESTRICTED_CONTENT_DOC,
.tp_methods = py_restricted_content_methods,
.tp_getset = py_restricted_content_getseters,
diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c
index 1a9a1d9..a54b101 100644
--- a/plugins/pychrysalide/analysis/module.c
+++ b/plugins/pychrysalide/analysis/module.c
@@ -63,12 +63,16 @@ bool add_analysis_module(PyObject *super)
bool result; /* Bilan à retourner */
PyObject *module; /* Sous-module mis en place */
+#define PYCHRYSALIDE_ANALYSIS_MODULE_DOC \
+ "This module provides bindings for all Chrysalide analysis-relative" \
+ " features."
+
static PyModuleDef py_chrysalide_analysis_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "pychrysalide.analysis",
- .m_doc = "Python module for Chrysalide.analysis",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_MODULE_DOC,
.m_size = -1,