diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-05-24 00:38:15 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-05-24 00:38:15 (GMT) |
commit | 5eab5f1bf3665e948e2054817fb688963dc86935 (patch) | |
tree | 0d0547b7fd90cf51992a449bdca0d9f7b38b3174 /plugins/kaitai/python/parsers | |
parent | 9f4abb8a20871c64b33f88ad5538bbbe111c1d4c (diff) |
Define a first implementation of Kaitai parsing.
Diffstat (limited to 'plugins/kaitai/python/parsers')
-rw-r--r-- | plugins/kaitai/python/parsers/Makefile.am | 19 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/attribute.c | 420 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/attribute.h | 45 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/enum.c | 468 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/enum.h | 45 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/instance.c | 280 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/instance.h | 45 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/meta.c | 366 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/meta.h | 45 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/module.c | 124 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/module.h | 41 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/struct.c | 376 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/struct.h | 45 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/type.c | 278 | ||||
-rw-r--r-- | plugins/kaitai/python/parsers/type.h | 45 |
15 files changed, 2642 insertions, 0 deletions
diff --git a/plugins/kaitai/python/parsers/Makefile.am b/plugins/kaitai/python/parsers/Makefile.am new file mode 100644 index 0000000..4c418af --- /dev/null +++ b/plugins/kaitai/python/parsers/Makefile.am @@ -0,0 +1,19 @@ + +noinst_LTLIBRARIES = libkaitaipythonparsers.la + +libkaitaipythonparsers_la_SOURCES = \ + attribute.h attribute.c \ + enum.h enum.c \ + instance.h instance.c \ + meta.h meta.c \ + module.h module.c \ + struct.h struct.c \ + type.h type.c + +libkaitaipythonparsers_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libkaitaipythonparsers_la_SOURCES:%c=) diff --git a/plugins/kaitai/python/parsers/attribute.c b/plugins/kaitai/python/parsers/attribute.c new file mode 100644 index 0000000..c8ea314 --- /dev/null +++ b/plugins/kaitai/python/parsers/attribute.c @@ -0,0 +1,420 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * attribute.h - équivalent Python du fichier "plugins/kaitai/parsers/attribute.h" + * + * Copyright (C) 2019 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 "attribute.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/yaml/python/node.h> + + +#include "../parser.h" +#include "../../parsers/attribute-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_attribute, G_TYPE_KAITAI_ATTRIBUTE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_attribute_init(PyObject *, PyObject *, PyObject *); + +/* Indique la désignation brute d'un identifiant Kaitai. */ +static PyObject *py_kaitai_attribute_get_raw_id(PyObject *, void *); + +/* Indique la désignation originelle d'un identifiant Kaitai. */ +static PyObject *py_kaitai_attribute_get_original_id(PyObject *, void *); + +/* Fournit une éventuelle documentation concernant l'attribut. */ +static PyObject *py_kaitai_attribute_get_doc(PyObject *, void *); + +/* Détermine si l'attribue porte une valeur entière signée. */ +static PyObject *py_kaitai_attribute_get_handle_signed_integer(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_kaitai_attribute_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GYamlNode *parent; /* Noeud Yaml de l'attribut */ + int ret; /* Bilan de lecture des args. */ + GKaitaiAttribute *attrib; /* Création GLib à transmettre */ + +#define KAITAI_ATTRIBUTE_DOC \ + "KaitaiAttribute is the class providing support for parsing binary" \ + " contents using a special declarative language." \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " KaitaiAttribute(parent)" \ + "\n" \ + "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \ + " to Yaml data to load.\n" \ + "\n" \ + "The class is the Python bindings for a C implementation of the Attribute" \ + " structure described at https://doc.kaitai.io/ksy_diagram.html." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); + + if (!g_kaitai_attribute_create(attrib, parent, true)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai attribute.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique la désignation brute d'un identifiant Kaitai. * +* * +* Retour : Valeur brute de l'identifiant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_attribute_get_raw_id(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiAttribute *attrib; /* Version native de l'attribut*/ + const char *value; /* Valeur à transmettre */ + +#define KAITAI_ATTRIBUTE_RAW_ID_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + raw_id, py_kaitai_attribute, \ + "Raw value used by Kaitai to identify one attribute" \ + " among others.\n" \ + "\n" \ + "The returned indentifier is a string value." \ +) + + attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); + + value = g_kaitai_attribute_get_raw_id(attrib); + assert(value != NULL); + + result = PyUnicode_FromString(value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique la désignation originelle d'un identifiant Kaitai. * +* * +* Retour : Valeur originelle de l'identifiant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_attribute_get_original_id(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiAttribute *attrib; /* Version native de l'attribut*/ + const char *value; /* Valeur à transmettre */ + +#define KAITAI_ATTRIBUTE_ORIGINAL_ID_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + original_id, py_kaitai_attribute, \ + "Optional alternative identifier for the attribute, as seen in" \ + " the original specifications.\n" \ + "\n" \ + "The returned value is a string or *None*." \ +) + + attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); + + value = g_kaitai_attribute_get_original_id(attrib); + + if (value == NULL) + { + result = Py_None; + Py_INCREF(result); + } + else + result = PyUnicode_FromString(value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit une éventuelle documentation concernant l'attribut. * +* * +* Retour : Description enregistrée ou None si absente. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_attribute_get_doc(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiAttribute *attrib; /* Version native de l'attribut*/ + const char *doc; /* Documentation à transmettre */ + +#define KAITAI_ATTRIBUTE_DOC_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + doc, py_kaitai_attribute, \ + "Optional documentation for the attribute.\n" \ + "\n" \ + "The returned value is a string or *None*." \ +) + + attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); + + doc = g_kaitai_attribute_get_doc(attrib); + + if (doc == NULL) + { + result = Py_None; + Py_INCREF(result); + } + else + result = PyUnicode_FromString(doc); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Détermine si l'attribue porte une valeur entière signée. * +* * +* Retour : Bilan de la consultation : True si un entier signé est visé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_attribute_get_handle_signed_integer(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiAttribute *attrib; /* Version native de l'attribut*/ + bool status; /* Bilan d'une consultation */ + +#define KAITAI_ATTRIBUTE_HANDLE_SIGNED_INTEGER_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + handle_signed_integer, py_kaitai_attribute, \ + "Sign of the carried integer value, if any: positive or negative?\n" \ + "\n" \ + "This status is provided as a boolean value." \ +) + + attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); + + status = g_kaitai_attribute_handle_signed_integer(attrib); + + 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_kaitai_attribute_type(void) +{ + static PyMethodDef py_kaitai_attribute_methods[] = { + { NULL } + }; + + static PyGetSetDef py_kaitai_attribute_getseters[] = { + KAITAI_ATTRIBUTE_RAW_ID_ATTRIB, + KAITAI_ATTRIBUTE_ORIGINAL_ID_ATTRIB, + KAITAI_ATTRIBUTE_DOC_ATTRIB, + KAITAI_ATTRIBUTE_HANDLE_SIGNED_INTEGER_ATTRIB, + { NULL } + }; + + static PyTypeObject py_kaitai_attribute_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiAttribute", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = KAITAI_ATTRIBUTE_DOC, + + .tp_methods = py_kaitai_attribute_methods, + .tp_getset = py_kaitai_attribute_getseters, + + .tp_init = py_kaitai_attribute_init, + .tp_new = py_kaitai_attribute_new, + + }; + + return &py_kaitai_attribute_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....KaitaiAttribute. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_attribute_is_registered(void) +{ + PyTypeObject *type; /* Type 'KaitaiAttribute' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_attribute_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_kaitai_parser_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ATTRIBUTE, 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 attribut de données Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_attribute(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_attribute_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 Kaitai attribute"); + break; + + case 1: + *((GKaitaiAttribute **)dst) = G_KAITAI_ATTRIBUTE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/parsers/attribute.h b/plugins/kaitai/python/parsers/attribute.h new file mode 100644 index 0000000..931e769 --- /dev/null +++ b/plugins/kaitai/python/parsers/attribute.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * attribute.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/attribute.h" + * + * Copyright (C) 2019 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_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_attribute_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiAttribute'. */ +bool ensure_python_kaitai_attribute_is_registered(void); + +/* Tente de convertir en attribut de données Kaitai. */ +int convert_to_kaitai_attribute(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H */ diff --git a/plugins/kaitai/python/parsers/enum.c b/plugins/kaitai/python/parsers/enum.c new file mode 100644 index 0000000..9200c6f --- /dev/null +++ b/plugins/kaitai/python/parsers/enum.c @@ -0,0 +1,468 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * enum.h - équivalent Python du fichier "plugins/kaitai/parsers/enum.h" + * + * Copyright (C) 2019 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 "enum.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/yaml/python/node.h> + + +#include "../../parsers/enum-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_enum, G_TYPE_KAITAI_ENUM); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_enum_init(PyObject *, PyObject *, PyObject *); + +/* Traduit une étiquette brute en constante d'énumération. */ +static PyObject *py_kaitai_enum_find_value(PyObject *, PyObject *); + +/* Traduit une constante d'énumération en étiquette brute. */ +static PyObject *py_kaitai_enum_find_label(PyObject *, PyObject *); + +/* Traduit une constante d'énumération en documentation. */ +static PyObject *py_kaitai_enum_find_documentation(PyObject *, PyObject *); + +/* Fournit le nom principal d'une énumération. */ +static PyObject *py_kaitai_enum_get_name(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_kaitai_enum_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GYamlNode *parent; /* Noeud Yaml de l'attribut */ + int ret; /* Bilan de lecture des args. */ + GKaitaiEnum *kenum; /* Création GLib à transmettre */ + +#define KAITAI_ENUM_DOC \ + "The KaitaiEnum class maps integer constants to symbolic names using" \ + " Kaitai definitions.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " KaitaiEnum(parent)" \ + "\n" \ + "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \ + " to Yaml data to load.\n" \ + "\n" \ + "The class is the Python bindings for a C implementation of the EnumSpec" \ + " structure described at https://doc.kaitai.io/ksy_diagram.html." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + kenum = G_KAITAI_ENUM(pygobject_get(self)); + + if (!g_kaitai_enum_create(kenum, parent)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai enumeration.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance de l'énumération Kaitai à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Traduit une étiquette brute en constante d'énumération. * +* * +* Retour : Valeur retrouvée ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_enum_find_value(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + const char *label; /* Etiquette à rechercher */ + int ret; /* Bilan de lecture des args. */ + GKaitaiEnum *kenum; /* Enumération Kaitai courante */ + sized_string_t cstr; /* CHaîne avec sa longueur */ + bool status; /* Bilan de la conversion */ + resolved_value_t value; /* valeur à transformer */ + +#define KAITAI_ENUM_FIND_VALUE_METHOD PYTHON_METHOD_DEF \ +( \ + find_value, "$self, label", \ + METH_VARARGS, py_kaitai_enum, \ + "Translate a given enumeration label into its relative value.\n" \ + "\n" \ + "The *label* argument is expected to be a string.\n" \ + "\n" \ + "The result is an integer or *None* in case of resolution failure." \ +) + + ret = PyArg_ParseTuple(args, "s", &label); + if (!ret) return NULL; + + kenum = G_KAITAI_ENUM(pygobject_get(self)); + + cstr.data = (char *)label; + cstr.len = strlen(label); + + status = g_kaitai_enum_find_value(kenum, &cstr, &value); + + if (status) + { + if (value.type == GVT_UNSIGNED_INTEGER) + result = PyLong_FromUnsignedLongLong(value.unsigned_integer); + else + { + assert(value.type == GVT_SIGNED_INTEGER); + result = PyLong_FromLongLong(value.signed_integer); + } + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance de l'énumération Kaitai à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Traduit une constante d'énumération en étiquette brute. * +* * +* Retour : Désignation ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_enum_find_label(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + int prefix; /* Préfixe attendu ? */ + resolved_value_t value; /* valeur à transformer */ + int ret; /* Bilan de lecture des args. */ + GKaitaiEnum *kenum; /* Enumération Kaitai courante */ + char *label; /* Etiquette reconstruite */ + +#define KAITAI_ENUM_FIND_LABEL_METHOD PYTHON_METHOD_DEF \ +( \ + find_label, "$self, value, / , prefix=False", \ + METH_VARARGS, py_kaitai_enum, \ + "Provide the label linked to a constant value within the current" \ + " enumeration.\n" \ + "\n" \ + "The *value* is a simple integer, and *prefix* is a boolean indicating" \ + " if the result has to integrate the enumeration name as a prefix.\n" \ + "\n" \ + "The result is a string or *None* in case of resolution failure." \ +) + + prefix = 0; + + ret = PyArg_ParseTuple(args, "K|p", &value.unsigned_integer, prefix); + if (!ret) return NULL; + + kenum = G_KAITAI_ENUM(pygobject_get(self)); + + value.type = GVT_UNSIGNED_INTEGER; + label = g_kaitai_enum_find_label(kenum, &value, prefix); + + if (label != NULL) + { + result = PyUnicode_FromString(label); + free(label); + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance de l'énumération Kaitai à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Traduit une constante d'énumération en documentation. * +* * +* Retour : Documentation associée à la valeur indiquée ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_enum_find_documentation(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + resolved_value_t value; /* valeur à transformer */ + int ret; /* Bilan de lecture des args. */ + GKaitaiEnum *kenum; /* Enumération Kaitai courante */ + char *doc; /* Documentation obtenue */ + +#define KAITAI_ENUM_FIND_DOCUMENTATION_METHOD PYTHON_METHOD_DEF \ +( \ + find_documentation, "$self, value", \ + METH_VARARGS, py_kaitai_enum, \ + "Provide the optional documentation linked to a constant value within" \ + " the current enumeration.\n" \ + "\n" \ + "The *value* is a simple integer.\n" \ + "\n" \ + "The result is a string or *None* if no documentation is registered" \ + " for the provided value." \ +) + + ret = PyArg_ParseTuple(args, "K", &value.unsigned_integer); + if (!ret) return NULL; + + kenum = G_KAITAI_ENUM(pygobject_get(self)); + + value.type = GVT_UNSIGNED_INTEGER; + doc = g_kaitai_enum_find_documentation(kenum, &value); + + if (doc != NULL) + { + result = PyUnicode_FromString(doc); + free(doc); + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le nom principal d'une énumération. * +* * +* Retour : Désignation de l'énumération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_enum_get_name(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiEnum *kenum; /* Version native de l'objet */ + const char *name; /* Valeur à transmettre */ + +#define KAITAI_ENUM_NAME_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + name, py_kaitai_enum, \ + "Name of the enumeration group, as a string value." \ +) + + kenum = G_KAITAI_ENUM(pygobject_get(self)); + + name = g_kaitai_enum_get_name(kenum); + + result = PyUnicode_FromString(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_kaitai_enum_type(void) +{ + static PyMethodDef py_kaitai_enum_methods[] = { + KAITAI_ENUM_FIND_VALUE_METHOD, + KAITAI_ENUM_FIND_LABEL_METHOD, + KAITAI_ENUM_FIND_DOCUMENTATION_METHOD, + { NULL } + }; + + static PyGetSetDef py_kaitai_enum_getseters[] = { + KAITAI_ENUM_NAME_ATTRIB, + { NULL } + }; + + static PyTypeObject py_kaitai_enum_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiEnum", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = KAITAI_ENUM_DOC, + + .tp_methods = py_kaitai_enum_methods, + .tp_getset = py_kaitai_enum_getseters, + + .tp_init = py_kaitai_enum_init, + .tp_new = py_kaitai_enum_new + + }; + + return &py_kaitai_enum_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiEnum. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_enum_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'KaitaiEnum' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_enum_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ENUM, 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'énumérations Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_enum(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_enum_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 Kaitai enumeration"); + break; + + case 1: + *((GKaitaiEnum **)dst) = G_KAITAI_ENUM(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/parsers/enum.h b/plugins/kaitai/python/parsers/enum.h new file mode 100644 index 0000000..7172e69 --- /dev/null +++ b/plugins/kaitai/python/parsers/enum.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * enum.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/enum.h" + * + * Copyright (C) 2019 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_KAITAI_PYTHON_PARSERS_ENUM_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_enum_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiEnum'. */ +bool ensure_python_kaitai_enum_is_registered(void); + +/* Tente de convertir en ensemble d'énumérations Kaitai. */ +int convert_to_kaitai_enum(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H */ diff --git a/plugins/kaitai/python/parsers/instance.c b/plugins/kaitai/python/parsers/instance.c new file mode 100644 index 0000000..d55b58c --- /dev/null +++ b/plugins/kaitai/python/parsers/instance.c @@ -0,0 +1,280 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instance.h - équivalent Python du fichier "plugins/kaitai/parsers/instance.h" + * + * Copyright (C) 2019 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 "instance.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/yaml/python/node.h> + + +#include "attribute.h" +#include "../../parsers/instance-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_instance, G_TYPE_KAITAI_INSTANCE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_instance_init(PyObject *, PyObject *, PyObject *); + +/* Indique le nom attribué à une instance Kaitai. */ +static PyObject *py_kaitai_instance_get_name(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_kaitai_instance_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GYamlNode *parent; /* Noeud Yaml de l'attribut */ + int ret; /* Bilan de lecture des args. */ + GKaitaiInstance *attrib; /* Création GLib à transmettre */ + +#define KAITAI_INSTANCE_DOC \ + "KaitaiInstance is the class providing support for Kaitai computed" \ + " values.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " KaitaiInstance(parent)" \ + "\n" \ + "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \ + " to Yaml data to load.\n" \ + "\n" \ + "The class is the Python bindings for a C implementation of the Instance" \ + " structure described at https://doc.kaitai.io/ksy_diagram.html." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + attrib = G_KAITAI_INSTANCE(pygobject_get(self)); + + if (!g_kaitai_instance_create(attrib, parent)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai instance.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique le nom attribué à une instance Kaitai. * +* * +* Retour : Désignation pointant l'instance. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_instance_get_name(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiInstance *inst; /* Version native de l'instance*/ + const char *name; /* Désignation à transmettre */ + +#define KAITAI_INSTANCE_NAME_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + name, py_kaitai_instance, \ + "Name used by Kaitai to identify the instance" \ + " among others.\n" \ + "\n" \ + "The returned indentifier is a string value." \ +) + + inst = G_KAITAI_INSTANCE(pygobject_get(self)); + + name = g_kaitai_instance_get_name(inst); + assert(name != NULL); + + result = PyUnicode_FromString(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_kaitai_instance_type(void) +{ + static PyMethodDef py_kaitai_instance_methods[] = { + { NULL } + }; + + static PyGetSetDef py_kaitai_instance_getseters[] = { + KAITAI_INSTANCE_NAME_ATTRIB, + { NULL } + }; + + static PyTypeObject py_kaitai_instance_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiInstance", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = KAITAI_INSTANCE_DOC, + + .tp_methods = py_kaitai_instance_methods, + .tp_getset = py_kaitai_instance_getseters, + + .tp_init = py_kaitai_instance_init, + .tp_new = py_kaitai_instance_new, + + }; + + return &py_kaitai_instance_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....KaitaiInstance. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_instance_is_registered(void) +{ + PyTypeObject *type; /* Type 'KaitaiInstance' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_instance_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_kaitai_attribute_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_INSTANCE, 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 instance Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_instance(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_instance_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 Kaitai instance"); + break; + + case 1: + *((GKaitaiInstance **)dst) = G_KAITAI_INSTANCE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/parsers/instance.h b/plugins/kaitai/python/parsers/instance.h new file mode 100644 index 0000000..8a0a6cf --- /dev/null +++ b/plugins/kaitai/python/parsers/instance.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instance.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/instance.h" + * + * Copyright (C) 2019 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_KAITAI_PYTHON_PARSERS_INSTANCE_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_instance_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiInstance'. */ +bool ensure_python_kaitai_instance_is_registered(void); + +/* Tente de convertir en instance Kaitai. */ +int convert_to_kaitai_instance(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H */ diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c new file mode 100644 index 0000000..3432640 --- /dev/null +++ b/plugins/kaitai/python/parsers/meta.c @@ -0,0 +1,366 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * meta.h - équivalent Python du fichier "plugins/kaitai/parsers/meta.h" + * + * Copyright (C) 2019 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 "meta.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> +#include <plugins/yaml/python/node.h> + + +#include "../../parsers/meta-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_meta, G_TYPE_KAITAI_META); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_meta_init(PyObject *, PyObject *, PyObject *); + +/* Fournit l'identifié associé à une définiton Kaitai. */ +static PyObject *py_kaitai_meta_get_id(PyObject *, void *); + +/* Fournit la désignation humaine d'une définiton Kaitai. */ +static PyObject *py_kaitai_meta_get_title(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_kaitai_meta_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GYamlNode *parent; /* Noeud Yaml de l'attribut */ + int ret; /* Bilan de lecture des args. */ + GKaitaiMeta *kmeta; /* Création GLib à transmettre */ + +#define KAITAI_META_DOC \ + "The KaitaiMeta class stores general information about a Kaitai definition,"\ + " such as required imports or the default endianness for reading values.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " KaitaiMeta(parent)" \ + "\n" \ + "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \ + " to Yaml data to load.\n" \ + "\n" \ + "The class is the Python bindings for a C implementation of the MetaSpec" \ + " structure described at https://doc.kaitai.io/ksy_diagram.html." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + kmeta = G_KAITAI_META(pygobject_get(self)); + + if (!g_kaitai_meta_create(kmeta, parent)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai global description.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'identifié associé à une définiton Kaitai. * +* * +* Retour : Identifiant de définition complète ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiMeta *meta; /* Version native de l'objet */ + const char *id; /* Valeur à transmettre */ + +#define KAITAI_META_ID_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + id, py_kaitai_meta, \ + "Identifier for the Kaitai definition, as a string" \ + " value or *None* if any." \ +) + + meta = G_KAITAI_META(pygobject_get(self)); + + id = g_kaitai_meta_get_id(meta); + + if (id != NULL) + result = PyUnicode_FromString(id); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la désignation humaine d'une définiton Kaitai. * +* * +* Retour : Intitulé de définition OU None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiMeta *meta; /* Version native de l'objet */ + const char *title; /* Valeur à transmettre */ + +#define KAITAI_META_TITLE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + title, py_kaitai_meta, \ + "Humain description for the Kaitai definition, as a" \ + " string value or *None* if any." \ +) + + meta = G_KAITAI_META(pygobject_get(self)); + + title = g_kaitai_meta_get_title(meta); + + if (title != NULL) + result = PyUnicode_FromString(title); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la désignation humaine d'une définiton Kaitai. * +* * +* Retour : Intitulé de définition OU None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiMeta *meta; /* Version native de l'objet */ + SourceEndian endian; /* Valeur à transmettre */ + +#define KAITAI_META_ENDIAN_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + endian, py_kaitai_meta, \ + "Default endianness for the Kaitai definition, as a" \ + " pychrysalide.analysis.BinContent.SourceEndian value." \ +) + + meta = G_KAITAI_META(pygobject_get(self)); + + endian = g_kaitai_meta_get_endian(meta); + + result = cast_with_constants_group_from_type(get_python_binary_content_type(), "SourceEndian", endian); + + 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_kaitai_meta_type(void) +{ + static PyMethodDef py_kaitai_meta_methods[] = { + { NULL } + }; + + static PyGetSetDef py_kaitai_meta_getseters[] = { + KAITAI_META_ID_ATTRIB, + KAITAI_META_TITLE_ATTRIB, + KAITAI_META_ENDIAN_ATTRIB, + { NULL } + }; + + static PyTypeObject py_kaitai_meta_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiMeta", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = KAITAI_META_DOC, + + .tp_methods = py_kaitai_meta_methods, + .tp_getset = py_kaitai_meta_getseters, + + .tp_init = py_kaitai_meta_init, + .tp_new = py_kaitai_meta_new + + }; + + return &py_kaitai_meta_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiMeta. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_meta_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'KaitaiMeta' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_meta_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_META, 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 description globale Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_meta(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_meta_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 Kaitai global description"); + break; + + case 1: + *((GKaitaiMeta **)dst) = G_KAITAI_META(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/parsers/meta.h b/plugins/kaitai/python/parsers/meta.h new file mode 100644 index 0000000..383cad9 --- /dev/null +++ b/plugins/kaitai/python/parsers/meta.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * meta.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/meta.h" + * + * Copyright (C) 2019 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_KAITAI_PYTHON_PARSERS_META_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_META_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_meta_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiMeta'. */ +bool ensure_python_kaitai_meta_is_registered(void); + +/* Tente de convertir en description globale Kaitai. */ +int convert_to_kaitai_meta(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_META_H */ diff --git a/plugins/kaitai/python/parsers/module.c b/plugins/kaitai/python/parsers/module.c new file mode 100644 index 0000000..549f728 --- /dev/null +++ b/plugins/kaitai/python/parsers/module.c @@ -0,0 +1,124 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire parsers en tant que module + * + * Copyright (C) 2019 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 <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "attribute.h" +#include "enum.h" +#include "instance.h" +#include "meta.h" +#include "struct.h" +#include "type.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Ajoute le module 'plugins.kaitai.parsers' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_kaitai_parsers_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_PLUGINS_KAITAI_PARSERS_DOC \ + "This module provides implementation for several Kaitai" \ + " definitions parsers." + + static PyModuleDef py_chrysalide_kaitai_parsers_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.plugins.kaitai.parsers", + .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_PARSERS_DOC, + + .m_size = -1, + + }; + + result = false; + + super = get_access_to_python_module("pychrysalide.plugins.kaitai"); + + module = build_python_module(super, &py_chrysalide_kaitai_parsers_module); + + result = (module != NULL); + + assert(result); + + if (!result) + Py_XDECREF(module); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les objets du module 'plugins.kaitai.parsers'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_kaitai_parsers_module(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_kaitai_attribute_is_registered(); + if (result) result = ensure_python_kaitai_enum_is_registered(); + if (result) result = ensure_python_kaitai_instance_is_registered(); + if (result) result = ensure_python_kaitai_meta_is_registered(); + if (result) result = ensure_python_kaitai_structure_is_registered(); + if (result) result = ensure_python_kaitai_type_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/kaitai/python/parsers/module.h b/plugins/kaitai/python/parsers/module.h new file mode 100644 index 0000000..d0fdd66 --- /dev/null +++ b/plugins/kaitai/python/parsers/module.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire parsers en tant que module + * + * Copyright (C) 2019 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_KAITAI_PYTHON_PARSERS_MODULE_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H + + +#include <stdbool.h> + + + +/* Ajoute le module 'plugins.kaitai.parsers' au module Python. */ +bool add_kaitai_parsers_module(void); + +/* Intègre les objets du module 'plugins.kaitai.parsers'. */ +bool populate_kaitai_parsers_module(void); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H */ diff --git a/plugins/kaitai/python/parsers/struct.c b/plugins/kaitai/python/parsers/struct.c new file mode 100644 index 0000000..900cd1b --- /dev/null +++ b/plugins/kaitai/python/parsers/struct.c @@ -0,0 +1,376 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * struct.h - équivalent Python du fichier "plugins/kaitai/struct.h" + * + * Copyright (C) 2019 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 "struct.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> + + +#include "../parser.h" +#include "../../parsers/struct-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_structure, G_TYPE_KAITAI_STRUCT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_structure_init(PyObject *, PyObject *, PyObject *); + +/* Parcourt un contenu binaire selon une description Kaitai. */ +static PyObject *py_kaitai_structure_parse(PyObject *, PyObject *); + +/* Fournit la désignation humaine d'une définiton Kaitai. */ +static PyObject *py_kaitai_structure_get_meta(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_kaitai_structure_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + const char *text; /* Contenu de règles à traiter */ + const char *filename; /* Fichier de définitions */ + int ret; /* Bilan de lecture des args. */ + GKaitaiStruct *kstruct; /* Création GLib à transmettre */ + + static char *kwlist[] = { "text", "filename", NULL }; + +#define KAITAI_STRUCT_DOC \ + "KaitaiStruct is the class providing support for parsing binary contents" \ + " using a special declarative language." \ + "\n" \ + "Instances can be created using one of the following constructors:\n" \ + "\n" \ + " KaitaiStruct(text=str)" \ + "\n" \ + " KaitaiStruct(filename=str)" \ + "\n" \ + "Where *text* is a string containg a markup content to parse; the" \ + " *filename* argument is an alternative string for a path pointing to the" \ + " same kind of content. This path can be a real filename or a resource" \ + " URI." \ + "\n" \ + "It is the Python bindings for a C implementation of the specifications" \ + " described at http://kaitai.io/." + + /* Récupération des paramètres */ + + text = NULL; + filename = NULL; + + ret = PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist, &text, &filename); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + kstruct = G_KAITAI_STRUCT(pygobject_get(self)); + + if (text != NULL) + { + if (!g_kaitai_structure_create_from_text(kstruct, text)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai structure.")); + return -1; + } + + } + + else if (filename != NULL) + { + if (!g_kaitai_structure_create_from_file(kstruct, filename)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai structure.")); + return -1; + } + + } + + else + { + PyErr_SetString(PyExc_ValueError, _("Unable to create empty Kaitai structure.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance de l'interpréteur Kaitai à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Parcourt un contenu binaire selon une description Kaitai. * +* * +* Retour : Arborescence d'éléments rencontrés selon les spécifications. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_structure_parse(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + GBinContent *content; /* Contenu binaire à traiter */ + int ret; /* Bilan de lecture des args. */ + GKaitaiStruct *kstruct; /* Interpréteur Kaitai courant */ + GMatchRecord *record; /* Ensemble de correspondances */ + +#define KAITAI_STRUCTURE_PARSE_METHOD PYTHON_METHOD_DEF \ +( \ + parse, "$self, content", \ + METH_VARARGS, py_kaitai_structure, \ + "Parse a binary content with the loaded specifications." \ + "\n" \ + "The content has to be a pychrysalide.analysis.BinContent instance.\n" \ + "\n" \ + "The result is *None* if the parsing failed, or a" \ + " pychrysalide.plugins.kaitai.MatchRecord object for each attribute" \ + " met." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content); + if (!ret) return NULL; + + kstruct = G_KAITAI_STRUCT(pygobject_get(self)); + + record = g_kaitai_structure_parse(kstruct, content); + + if (record != NULL) + { + result = pygobject_new(G_OBJECT(record)); + g_object_unref(G_OBJECT(record)); + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la désignation humaine d'une définiton Kaitai. * +* * +* Retour : Intitulé de définition OU None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_structure_get_meta(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiStruct *kstruct; /* Version native de l'objet */ + GKaitaiMeta *meta; /* Informations à transmettre */ + +#define KAITAI_STRUCTURE_META_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + meta, py_kaitai_structure, \ + "Global description provided for the Kaitai definition, as a" \ + " pychrysalide.plugins.kaitai.parsers.KaitaiMeta instance." \ +) + + kstruct = G_KAITAI_STRUCT(pygobject_get(self)); + + meta = g_kaitai_structure_get_meta(kstruct); + + if (meta != NULL) + { + result = pygobject_new(G_OBJECT(meta)); + g_object_unref(G_OBJECT(meta)); + } + 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_kaitai_structure_type(void) +{ + static PyMethodDef py_kaitai_structure_methods[] = { + KAITAI_STRUCTURE_PARSE_METHOD, + { NULL } + }; + + static PyGetSetDef py_kaitai_structure_getseters[] = { + KAITAI_STRUCTURE_META_ATTRIB, + { NULL } + }; + + static PyTypeObject py_kaitai_structure_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiStruct", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = KAITAI_STRUCT_DOC, + + .tp_methods = py_kaitai_structure_methods, + .tp_getset = py_kaitai_structure_getseters, + + .tp_init = py_kaitai_structure_init, + .tp_new = py_kaitai_structure_new + + }; + + return &py_kaitai_structure_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiStruct.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_structure_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'KaitaiStruct' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_structure_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_kaitai_parser_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_STRUCT, 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 structure de données Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_structure(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_structure_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 Kaitai structure"); + break; + + case 1: + *((GKaitaiStruct **)dst) = G_KAITAI_STRUCT(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/parsers/struct.h b/plugins/kaitai/python/parsers/struct.h new file mode 100644 index 0000000..872f744 --- /dev/null +++ b/plugins/kaitai/python/parsers/struct.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * struct.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/struct.h" + * + * Copyright (C) 2019 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_KAITAI_PYTHON_PARSERS_STRUCT_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_structure_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiStruct'. */ +bool ensure_python_kaitai_structure_is_registered(void); + +/* Tente de convertir en structure de données Kaitai. */ +int convert_to_kaitai_structure(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H */ diff --git a/plugins/kaitai/python/parsers/type.c b/plugins/kaitai/python/parsers/type.c new file mode 100644 index 0000000..64a3419 --- /dev/null +++ b/plugins/kaitai/python/parsers/type.c @@ -0,0 +1,278 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * type.h - équivalent Python du fichier "plugins/kaitai/parsers/type.h" + * + * Copyright (C) 2019 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 "type.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/yaml/python/node.h> + + +#include "struct.h" +#include "../../parsers/type-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_type, G_TYPE_KAITAI_TYPE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_type_init(PyObject *, PyObject *, PyObject *); + +/* Indique le nom de scène du type représenté. */ +static PyObject *py_kaitai_type_get_name(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_kaitai_type_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GYamlNode *parent; /* Noeud Yaml de l'attribut */ + int ret; /* Bilan de lecture des args. */ + GKaitaiType *attrib; /* Création GLib à transmettre */ + +#define KAITAI_TYPE_DOC \ + "The KaitaiType class provides support for user-defined type used in" \ + " Kaitai definitions.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " KaitaiType(parent)" \ + "\n" \ + "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \ + " to Yaml data to load.\n" \ + "\n" \ + "The class is the Python bindings for a C implementation of the TypesSpec" \ + " structure described at https://doc.kaitai.io/ksy_diagram.html." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + attrib = G_KAITAI_TYPE(pygobject_get(self)); + + if (!g_kaitai_type_create(attrib, parent)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai type.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique le nom de scène du type représenté. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_type_get_name(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiType *type; /* Version native du type */ + const char *name; /* Désignation à transmettre */ + +#define KAITAI_TYPE_NAME_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + name, py_kaitai_type, \ + "Name of the user-defined type, provided as a unique" \ + " string value." \ +) + + type = G_KAITAI_TYPE(pygobject_get(self)); + + name = g_kaitai_type_get_name(type); + assert(name != NULL); + + result = PyUnicode_FromString(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_kaitai_type_type(void) +{ + static PyMethodDef py_kaitai_type_methods[] = { + { NULL } + }; + + static PyGetSetDef py_kaitai_type_getseters[] = { + KAITAI_TYPE_NAME_ATTRIB, + { NULL } + }; + + static PyTypeObject py_kaitai_type_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiType", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = KAITAI_TYPE_DOC, + + .tp_methods = py_kaitai_type_methods, + .tp_getset = py_kaitai_type_getseters, + + .tp_init = py_kaitai_type_init, + .tp_new = py_kaitai_type_new, + + }; + + return &py_kaitai_type_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....parsers.KaitaiType. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_type_is_registered(void) +{ + PyTypeObject *type; /* Type 'KaitaiType' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_type_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_kaitai_structure_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TYPE, 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 type particulier pour Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_type(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_type_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 Kaitai type"); + break; + + case 1: + *((GKaitaiType **)dst) = G_KAITAI_TYPE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/parsers/type.h b/plugins/kaitai/python/parsers/type.h new file mode 100644 index 0000000..320bc71 --- /dev/null +++ b/plugins/kaitai/python/parsers/type.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * type.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/type.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_KAITAI_PYTHON_PARSERS_TYPE_H +#define _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_type_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiType'. */ +bool ensure_python_kaitai_type_is_registered(void); + +/* Tente de convertir en type particulier pour Kaitai. */ +int convert_to_kaitai_type(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H */ |