diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..0a306dec --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,34 @@ +version: 1.3.{build} + +environment: + matrix: + - python: 27 + - python: 27-x64 + - python: 35 + - python: 35-x64 + - python: 36 + - python: 36-x64 + +install: + - SET PATH=C:\\Python%PYTHON%;c:\\Python%PYTHON%\\scripts;%PATH% + - python -m pip.__main__ install -U pip wheel setuptools + - pip install -r requirements-test.txt + +build: off +build_script: + # configure version + - ps: >- + If ($env:APPVEYOR_REPO_TAG -Eq "true" ) { + $version = "$env:APPVEYOR_REPO_TAG_NAME" + } Else { + $version = "$env:APPVEYOR_BUILD_VERSION.dev0" + } + $version | Set-Content version.txt + - python setup.py build bdist_wheel + - ps: Get-ChildItem dist\*.whl | % { pip install $_.FullName } + +test: off +test_script: + - pip list + - py.test -v tests + - ps: Get-ChildItem dist\*.whl | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } diff --git a/.gitignore b/.gitignore index f39e8aba..be6e8c15 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .* !.editorconfig !.travis* +!.appveyor* !.git* # Python diff --git a/.travis.yml b/.travis.yml index ba838201..47af0630 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ addons: - libxslt1-dev - pkg-config before_install: -- sed -i "s/1.0.1/${TRAVIS_TAG:-1.0.1}/" setup.py +- echo "${TRAVIS_TAG:-1.0.1.dev}" >version.txt install: - travis_retry pip install -r requirements-test.txt - travis_retry pip install -e "." diff --git a/MANIFEST.in b/MANIFEST.in index 07ed1203..0b0468dc 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,6 @@ include src/* include requirements*.txt include LICENSE - +include version.txt +include setupinfo.py +include extra.py diff --git a/README.rst b/README.rst index a1ca111a..ffd73c17 100644 --- a/README.rst +++ b/README.rst @@ -3,6 +3,8 @@ python-xmlsec .. image:: https://travis-ci.org/mehcode/python-xmlsec.png?branch=master :target: https://travis-ci.org/mehcode/python-xmlsec +.. image:: https://ci.appveyor.com/api/projects/status/20rtt2wv96gag9cy?svg=true + :target: https://ci.appveyor.com/project/bgaifullin/python-xmlsec .. image:: https://img.shields.io/pypi/v/xmlsec.svg :target: https://pypi.python.org/pypi/xmlsec .. image:: https://img.shields.io/badge/docs-latest-green.svg @@ -80,27 +82,52 @@ Mac If you get any fatal errors about missing .h files, update your C_INCLUDE_PATH environment variable to include the appropriate files from the libxml2 and libxmlsec1 libraries. + +Windows (Wheel) +^^^^^^^^^^^^^^^ + +#. Download appropriate binary wheel from `ci.appveyor.com `_ (see build`s artifacts). + +#. Install wheel + + .. code-block:: bash + + pip install + + +Windows (pip) +^^^^^^^^^^^^^ + +#. Configure build environment, see `wiki.python.org `_ for more details. + +#. Install from pip + + .. code-block:: bash + + pip install xmlsec + + Manual ------ -1. Clone the **xmlsec** repository to your local computer. +#. Clone the **xmlsec** repository to your local computer. -.. code-block:: bash + .. code-block:: bash - git clone git://github.com/mehcode/python-xmlsec.git + git clone git://github.com/mehcode/python-xmlsec.git -2. Change into the **xmlsec** root directory. +#. Change into the **xmlsec** root directory. -.. code-block:: bash + .. code-block:: bash - cd /path/to/xmlsec + cd /path/to/xmlsec -3. Install the project and all its dependencies using `pip`. +#. Install the project and all its dependencies using `pip`. -.. code-block:: bash + .. code-block:: bash - pip install . + pip install . ************ @@ -110,44 +137,43 @@ Contributing Setting up your environment --------------------------- -1. Follow steps 1 and 2 of the [manual installation instructions][]. +#. Follow steps 1 and 2 of the `manual installation instructions <#manual>`_. -[manual installation instructions]: #manual -2. Initialize a virtual environment to develop in. +#. Initialize a virtual environment to develop in. This is done so as to ensure every contributor is working with close-to-identicial versions of packages. -.. code-block:: bash + .. code-block:: bash - mkvirtualenv xmlsec + mkvirtualenv xmlsec - The `mkvirtualenv` command is available from `virtualenvwrapper` which - can be installed by following: http://virtualenvwrapper.readthedocs.org/en/latest/install.html#basic-installation + The `mkvirtualenv` command is available from `virtualenvwrapper` which + can be installed by following `link `_ -3. Install **xmlsec** in development mode with testing enabled. +#. Install **xmlsec** in development mode with testing enabled. This will download all dependencies required for running the unit tests. -.. code-block:: bash + .. code-block:: bash - pip install -r requirements-test.txt - pip install -e "." + pip install -r requirements-test.txt + pip install -e "." Running the test suite ---------------------- -1. [Set up your environment](#setting-up-your-environment). +#. [Set up your environment](#setting-up-your-environment). -2. Run the unit tests. +#. Run the unit tests. -.. code-block:: bash + .. code-block:: bash - py.test tests + py.test tests -3. Tests configuration -Env variable **PYXMLSEC_TEST_ITERATIONS** specifies number of test iterations to detect memory leaks. +#. Tests configuration + Env variable **PYXMLSEC_TEST_ITERATIONS** specifies number of test iterations to detect memory leaks. Reporting a issue ----------------- diff --git a/doc/source/install.rst b/doc/source/install.rst index 43987710..a60d4cff 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -40,3 +40,28 @@ Mac brew install libxml2 libxmlsec1 pip install xmlsec + + +Windows (Wheel) +^^^^^^^^^^^^^^^ + +#. Download appropriate binary wheels from `appveyor `_ (see build`s artifacts). + +#. Install downloaded wheel + + .. code-block:: bash + + pip install + + +Windows (pip) +^^^^^^^^^^^^^ + +#. Configure build environment, see `wiki.python.org `_ for more details. + +#. Install from pip + + .. code-block:: bash + + pip install xmlsec + diff --git a/extra.py b/extra.py new file mode 100644 index 00000000..fe9c899d --- /dev/null +++ b/extra.py @@ -0,0 +1,101 @@ +import os +import sys + +try: + from urlparse import urljoin + from urllib import urlretrieve, urlcleanup +except ImportError: + from urllib.parse import urljoin + from urllib.request import urlretrieve, urlcleanup + + +# use pre-built libraries on Windows +def get_prebuilt_libs(download_dir, static_include_dirs, static_library_dirs): + assert sys.platform.startswith('win') + libs = download_and_extract_windows_binaries(download_dir) + for ln, path in libs.items(): + if ln == 'xmlsec1': + i = os.path.join(path, 'include', 'xmlsec1') + else: + i = os.path.join(path, 'include') + + l = os.path.join(path, 'lib') + assert os.path.exists(i), 'does not exist: %s' % i + assert os.path.exists(l), 'does not exist: %s' % l + static_include_dirs.append(i) + static_library_dirs.append(l) + + +def download_and_extract_windows_binaries(destdir): + if sys.version_info < (3, 5): + if sys.maxsize > 2147483647: + url = "https://ci.appveyor.com/api/buildjobs/7q4nvmkdnu05dul6/artifacts/" + suffix = "vs2008.win64" + else: + url = "https://ci.appveyor.com/api/buildjobs/tdpx6rprr5431ec9/artifacts/" + suffix = "vs2008.win32" + else: + if sys.maxsize > 2147483647: + url = "https://ci.appveyor.com/api/buildjobs/hij3a6776pdv2007/artifacts/" + suffix = "win64" + else: + url = "https://ci.appveyor.com/api/buildjobs/7k878q7rvogcdyd9/artifacts/" + suffix = "win32" + + libs = { + 'libxml2': 'libxml2-2.9.4.{}.zip'.format(suffix), + 'libxslt': 'libxslt-1.1.29.{}.zip'.format(suffix), + 'zlib': 'zlib-1.2.8.{}.zip'.format(suffix), + 'iconv': 'iconv-1.14.{}.zip'.format(suffix), + 'openssl': 'openssl-1.0.1.{}.zip'.format(suffix), + 'xmlsec': 'xmlsec-1.2.24.{}.zip'.format(suffix), + } + + if not os.path.exists(destdir): + os.makedirs(destdir) + + for ln, fn in libs.items(): + srcfile = urljoin(url, fn) + destfile = os.path.join(destdir, fn) + if os.path.exists(destfile + ".keep"): + print('Using local copy of "{}"'.format(srcfile)) + else: + print('Retrieving "%s" to "%s"' % (srcfile, destfile)) + urlcleanup() # work around FTP bug 27973 in Py2.7.12+ + urlretrieve(srcfile, destfile) + + libs[ln] = unpack_zipfile(destfile, destdir) + + return libs + + +def find_top_dir_of_zipfile(zipfile): + topdir = None + files = [f.filename for f in zipfile.filelist] + dirs = [d for d in files if d.endswith('/')] + if dirs: + dirs.sort(key=len) + topdir = dirs[0] + topdir = topdir[:topdir.index("/")+1] + for path in files: + if not path.startswith(topdir): + topdir = None + break + assert topdir, ( + "cannot determine single top-level directory in zip file %s" % + zipfile.filename) + return topdir.rstrip('/') + + +def unpack_zipfile(zipfn, destdir): + assert zipfn.endswith('.zip') + import zipfile + print('Unpacking %s into %s' % (os.path.basename(zipfn), destdir)) + f = zipfile.ZipFile(zipfn) + try: + extracted_dir = os.path.join(destdir, find_top_dir_of_zipfile(f)) + f.extractall(path=destdir) + finally: + f.close() + assert os.path.exists(extracted_dir), 'missing: %s' % extracted_dir + return extracted_dir diff --git a/setup.py b/setup.py index 65ff5e6b..191499cd 100644 --- a/setup.py +++ b/setup.py @@ -1,110 +1,52 @@ -from __future__ import print_function - -import glob -import os from setuptools import setup from setuptools import Extension from setuptools.command import build_ext - -__name__ = "xmlsec" -__version__ = "1.0.1" -__description__ = "Python bindings for the XML Security Library" - - -def is_debug(): - return bool(os.getenv("PYXMLSEC_DEBUG")) - - -macroses = [("MODULE_NAME", __name__), ("MODULE_VERSION", __version__), ("MODULE_DOC", __description__)] -cflags = ["-g", "-std=c99", "-fno-strict-aliasing", "-Wno-error=declaration-after-statement", "-Werror=implicit-function-declaration"] - - -if is_debug(): - macroses.append(("PYXMLSEC_ENABLE_DEBUG", "1")) - cflags.extend(["-Wall", "-O0"]) -else: - cflags.extend(["-Os"]) - - -def add_to_list(target, up, need_to_escape=None): - if up is None: - return target - - value = set(target) - if need_to_escape: - for x in up: - if x[0] in need_to_escape: - value.add((x[0], '"{0}"'.format(x[1]))) - else: - value.add(x) - else: - value.update(up) - target[:] = list(value) - - -def find_sources(path): - return glob.glob(os.path.join(path, "*.c")) - - -def parse_requirements(filename, __cache={}): - try: - return __cache[filename] - except KeyError: - with open(filename) as stream: - result = __cache[filename] = [x for x in (y.strip() for y in stream) if x and not x.startswith('#')] - return result +import setupinfo class BuildExt(build_ext.build_ext): def run(self): - self.patch_xmlsec() - build_ext.build_ext.run(self) - - def patch_xmlsec(self): # at this moment all setup_requires are installed and we can safety import them - pkgconfig = __import__("pkgconfig") - lxml = __import__("lxml") - - ext = self.ext_map[__name__] - config = pkgconfig.parse("xmlsec1") - # need to escape XMLSEC_CRYPTO - # added build flags from pkg-config - for item in ('libraries', 'library_dirs', 'include_dirs'): - add_to_list(getattr(ext, item), config.get(item)) + self.patch_options() + build_ext.build_ext.run(self) - add_to_list(ext.define_macros, config.get('define_macros'), {"XMLSEC_CRYPTO"}) - add_to_list(ext.include_dirs, lxml.get_include()) + def patch_options(self): + ext = self.ext_map[setupinfo.name()] + ext.define_macros.extend(setupinfo.define_macros()) + ext.include_dirs.extend(setupinfo.include_dirs()) + ext.libraries.extend(setupinfo.libraries()) + ext.library_dirs.extend(setupinfo.library_dirs()) _xmlsec = Extension( - __name__, - sources=find_sources("./src"), - extra_compile_args=cflags, + setupinfo.name(), + sources=setupinfo.sources(), + extra_compile_args=setupinfo.cflags(), libraries=[], library_dirs=[], include_dirs=[], - define_macros=macroses + define_macros=[], ) setup( - name=__name__, - version=__version__, - description=__description__, + name=setupinfo.name(), + version=setupinfo.version(), + description=setupinfo.description(), ext_modules=[_xmlsec], cmdclass={'build_ext': BuildExt}, - setup_requires=parse_requirements('requirements.txt'), - install_requires=parse_requirements('requirements.txt'), + setup_requires=setupinfo.requirements(), + install_requires=setupinfo.requirements(), author="Bulat Gaifullin", author_email='support@mehcode.com', maintainer='Bulat Gaifullin', maintainer_email='gaifullinbf@gmail.com', url='https://github.com/mehcode/python-xmlsec', - download_url="https://github.com/mehcode/python-xmlsec/archive/v%s.tar.gz" % __version__, + download_url="https://github.com/mehcode/python-xmlsec/archive/v%s.tar.gz" % setupinfo.version(), license='MIT', keywords=["xmlsec"], classifiers=[ - 'Development Status :: 4 - Beta', + setupinfo.dev_status(), 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: MIT License', @@ -112,8 +54,9 @@ def patch_xmlsec(self): 'Programming Language :: C', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Text Processing :: Markup :: XML' ], ) diff --git a/setupinfo.py b/setupinfo.py new file mode 100644 index 00000000..c126fb52 --- /dev/null +++ b/setupinfo.py @@ -0,0 +1,256 @@ +from __future__ import print_function + +import glob +import os +import pkg_resources +import sys + +from distutils.errors import DistutilsOptionError + + +WIN32 = sys.platform.lower().startswith('win') + +__MODULE_NAME = "xmlsec" +__MODULE_VERSION = None +__MODULE_DESCRIPTION = "Python bindings for the XML Security Library" +__MODULE_REQUIREMENTS = None +__XMLSEC_CONFIG = None + + +def name(): + return __MODULE_NAME + + +def version(): + global __MODULE_VERSION + if __MODULE_VERSION is None: + with open(os.path.join(get_base_dir(), 'version.txt')) as f: + __MODULE_VERSION = f.read().strip() + return __MODULE_VERSION + + +def description(): + return __MODULE_DESCRIPTION + + +def sources(): + return glob.glob(os.path.join(get_base_dir(), "src", "*.c")) + + +def define_macros(): + macros = [ + ("MODULE_NAME", __MODULE_NAME), + ("MODULE_VERSION", version()), + ] + if OPTION_ENABLE_DEBUG: + macros.append(("PYXMLSEC_ENABLE_DEBUG", "1")) + + macros.extend(xmlsec_config()['define_macros']) + + return macros + + +def cflags(): + options = [] + if WIN32: + options.append("/Zi") + else: + options.append("-g") + options.append("-std=c99") + options.append("-fno-strict-aliasing") + options.append("-Wno-error=declaration-after-statement") + options.append("-Werror=implicit-function-declaration") + + if OPTION_ENABLE_DEBUG: + options.append("-Wall") + options.append("-O0") + else: + options.append("-Os") + + return options + + +def include_dirs(): + import lxml + + dirs = xmlsec_config()['include_dirs'] + dirs.extend(lxml.get_include()) + return dirs + + +def libraries(): + return xmlsec_config()['libraries'] + + +def library_dirs(): + return xmlsec_config()['library_dirs'] + + +def dev_status(): + _version = version() + if 'a' in _version: + return 'Development Status :: 3 - Alpha' + elif 'b' in _version or 'c' in _version: + return 'Development Status :: 4 - Beta' + else: + return 'Development Status :: 5 - Production/Stable' + + +def requirements(): + global __MODULE_REQUIREMENTS + if __MODULE_REQUIREMENTS is None: + with open(os.path.join(get_base_dir(), "requirements.txt")) as f: + __MODULE_REQUIREMENTS = [str(req) for req in pkg_resources.parse_requirements(f)] + return __MODULE_REQUIREMENTS + + +def xmlsec_config(): + global __XMLSEC_CONFIG + + if __XMLSEC_CONFIG is None: + __XMLSEC_CONFIG = load_xmlsec1_config() + + return __XMLSEC_CONFIG + + +def load_xmlsec1_config(): + config = None + + if WIN32: + import extra + + config = { + 'define_macros': [ + ('XMLSEC_CRYPTO', '\\"openssl\\"'), + ('__XMLSEC_FUNCTION__', '__FUNCTION__'), + ('XMLSEC_NO_GOST', '1'), + ('XMLSEC_NO_XKMS', '1'), + ('XMLSEC_NO_CRYPTO_DYNAMIC_LOADING', '1'), + ('XMLSEC_CRYPTO_OPENSSL', '1'), + ('UNICODE', '1'), + ('_UNICODE', '1'), + ('LIBXML_ICONV_ENABLED', 1), + ('LIBXML_STATIC', '1'), + ('LIBXSLT_STATIC', '1'), + ('XMLSEC_STATIC', '1'), + ('inline', '__inline'), + ], + 'libraries': [ + 'libxmlsec_a', + 'libxmlsec-openssl_a', + 'libeay32', + 'iconv_a', + 'libxslt_a', + 'libexslt_a', + 'libxml2_a', + 'zlib', + 'WS2_32', + 'Advapi32', + 'User32', + 'Gdi32', + 'Crypt32', + ], + 'include_dirs': [], + 'library_dirs': [], + } + + extra.get_prebuilt_libs( + OPTION_DOWNLOAD_DIR, config['include_dirs'], config['library_dirs'] + ) + else: + import pkgconfig + + try: + config = pkgconfig.parse('xmlsec1') + except EnvironmentError: + pass + + if config is None or not config.get('libraries'): + fatal_xmlsec1_error() + + config.setdefault('libraries', []) + config.setdefault('include_dirs', []) + config.setdefault('library_dirs', []) + # fix macros + macros = config.setdefault('define_macros', []) + for i, v in enumerate(macros): + if v[0] == 'XMLSEC_CRYPTO': + macros[i] = ('XMLSEC_CRYPTO', '"{0}"'.format(v[1])) + break + return config + + +def fatal_xmlsec1_error(): + print('*********************************************************************************') + print('Could not find xmlsec1 config. Are libxmlsec1-dev and pkg-config installed?') + if sys.platform in ('darwin',): + print('Perhaps try: xcode-select --install') + print('*********************************************************************************') + sys.exit(1) + + +def get_base_dir(): + return os.path.abspath(os.path.dirname(sys.argv[0])) + + +if sys.version_info[0] >= 3: + _system_encoding = sys.getdefaultencoding() + if _system_encoding is None: + _system_encoding = "iso-8859-1" + + def decode_input(data): + if isinstance(data, str): + return data + return data.decode(_system_encoding) +else: + def decode_input(data): + return data + + +def env_var(n): + value = os.getenv(n) + if value: + value = decode_input(value) + if sys.platform == 'win32' and ';' in value: + return value.split(';') + else: + return value.split() + else: + return [] + + +def env_var_name(n): + return "PYXMLSEC_" + n.upper().replace('-', '_') + + +# Option handling: + +def has_option(n): + try: + sys.argv.remove('--%s' % n) + return True + except ValueError: + pass + # allow passing all cmd line options also as environment variables + env_val = os.getenv(env_var_name(n), 'false').lower() + return env_val in ("true", "1") + + +def option_value(n, default=None): + for index, option in enumerate(sys.argv): + if option == '--' + n: + if index+1 >= len(sys.argv): + raise DistutilsOptionError( + 'The option %s requires a value' % option) + value = sys.argv[index+1] + sys.argv[index:index+2] = [] + return value + if option.startswith('--' + n + '='): + value = option[len(n)+3:] + sys.argv[index:index+1] = [] + return value + return os.getenv(env_var_name(n), default) + + +OPTION_ENABLE_DEBUG = has_option('enable-debug') +OPTION_DOWNLOAD_DIR = option_value('download-dir', 'build/extra') diff --git a/src/common.h b/src/common.h index 5f91bc2f..243ed651 100644 --- a/src/common.h +++ b/src/common.h @@ -16,10 +16,6 @@ #define MODULE_NAME "xmlsec" #endif -#ifndef MODULE_DOC -#define MODULE_DOC "The tiny python wrapper around xmlsec1 library." -#endif - #define JOIN(X,Y) DO_JOIN1(X,Y) #define DO_JOIN1(X,Y) DO_JOIN2(X,Y) #define DO_JOIN2(X,Y) X##Y diff --git a/src/constants.c b/src/constants.c index e4f3e440..81f94560 100644 --- a/src/constants.c +++ b/src/constants.c @@ -103,9 +103,9 @@ static PyTypeObject _PyXmlSec_TransformType = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_alloc */ 0, /* tp_new */ - PyObject_Del /* tp_free */ + 0, /* tp_free */ }; PyTypeObject* PyXmlSec_TransformType = &_PyXmlSec_TransformType; @@ -197,9 +197,9 @@ static PyTypeObject _PyXmlSec_KeyDataType = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_alloc */ 0, /* tp_new */ - PyObject_Del /* tp_free */ + 0, /* tp_free */ }; PyTypeObject* PyXmlSec_KeyDataType = &_PyXmlSec_KeyDataType; diff --git a/src/ds.c b/src/ds.c index b6bf4152..5986f566 100644 --- a/src/ds.c +++ b/src/ds.c @@ -34,10 +34,10 @@ static PyObject* PyXmlSec_SignatureContext__new__(PyTypeObject *type, PyObject * static int PyXmlSec_SignatureContext__init__(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "manager", NULL}; - + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_KeysManager* manager = NULL; + PYXMLSEC_DEBUGF("%p: init sign context", self); - PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:__init__", kwlist, PyXmlSec_KeysManagerConvert, &manager)) { goto ON_FAIL; } @@ -47,6 +47,7 @@ static int PyXmlSec_SignatureContext__init__(PyObject* self, PyObject* args, PyO goto ON_FAIL; } ctx->manager = manager; + PYXMLSEC_DEBUGF("%p: signMethod: %p", self, ctx->handle->signMethod); PYXMLSEC_DEBUGF("%p: init sign context - ok, manager - %p", self, manager); return 0; ON_FAIL: @@ -56,8 +57,8 @@ static int PyXmlSec_SignatureContext__init__(PyObject* self, PyObject* args, PyO } static void PyXmlSec_SignatureContext__del__(PyObject* self) { - PYXMLSEC_DEBUGF("%p: delete sign context", self); PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; + PYXMLSEC_DEBUGF("%p: delete sign context", self); if (ctx->handle != NULL) { xmlSecDSigCtxDestroy(ctx->handle); } @@ -69,29 +70,33 @@ static void PyXmlSec_SignatureContext__del__(PyObject* self) { static const char PyXmlSec_SignatureContextKey__doc__[] = "Signature key.\n"; static PyObject* PyXmlSec_SignatureContextKeyGet(PyObject* self, void* closure) { PyXmlSec_SignatureContext* ctx = ((PyXmlSec_SignatureContext*)self); + PyXmlSec_Key* key; + if (ctx->handle->signKey == NULL) { Py_RETURN_NONE; } - PyXmlSec_Key* key = PyXmlSec_NewKey(); + key = PyXmlSec_NewKey(); key->handle = ctx->handle->signKey; key->is_own = 0; return (PyObject*)key; } static int PyXmlSec_SignatureContextKeySet(PyObject* self, PyObject* value, void* closure) { + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; + PyXmlSec_Key* key; + PYXMLSEC_DEBUGF("%p, %p", self, value); if (!PyObject_IsInstance(value, (PyObject*)PyXmlSec_KeyType)) { PyErr_SetString(PyExc_TypeError, "instance of *xmlsec.Key* expected."); return -1; } - PyXmlSec_Key* key = (PyXmlSec_Key*)value; + key = (PyXmlSec_Key*)value; if (key->handle == NULL) { PyErr_SetString(PyExc_TypeError, "empty key."); return -1; } - PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; if (ctx->handle->signKey != NULL) { xmlSecKeyDestroy(ctx->handle->signKey); } @@ -117,7 +122,8 @@ static PyObject* PyXmlSec_SignatureContextRegisterId(PyObject* self, PyObject* a const char* id_ns = NULL; xmlChar* name = NULL; - xmlAttrPtr attr = NULL; + xmlAttrPtr attr; + xmlAttrPtr tmpAttr; PYXMLSEC_DEBUGF("%p: register id - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|sz:register_id", kwlist, @@ -138,7 +144,7 @@ static PyObject* PyXmlSec_SignatureContextRegisterId(PyObject* self, PyObject* a } name = xmlNodeListGetString(node->_c_node->doc, attr->children, 1); - xmlAttrPtr tmpAttr = xmlGetID(node->_c_node->doc, name); + tmpAttr = xmlGetID(node->_c_node->doc, name); if (tmpAttr != attr) { if (tmpAttr != NULL) { PyErr_SetString(PyXmlSec_Error, "duplicated id."); @@ -165,18 +171,18 @@ static const char PyXmlSec_SignatureContextSign__doc__[] = \ static PyObject* PyXmlSec_SignatureContextSign(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "node", NULL}; + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_LxmlElementPtr node = NULL; + int rv; PYXMLSEC_DEBUGF("%p: sign - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:sign", kwlist, PyXmlSec_LxmlElementConverter, &node)) { goto ON_FAIL; } - xmlSecDSigCtxPtr ctx = ((PyXmlSec_SignatureContext*)self)->handle; - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecDSigCtxSign(ctx, node->_c_node); - PYXMLSEC_DUMP(xmlSecDSigCtxDebugDump, ctx); + rv = xmlSecDSigCtxSign(ctx->handle, node->_c_node); + PYXMLSEC_DUMP(xmlSecDSigCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; if (rv < 0) { PyXmlSec_SetLastError("failed to sign"); @@ -197,25 +203,25 @@ static const char PyXmlSec_SignatureContextVerify__doc__[] = \ static PyObject* PyXmlSec_SignatureContextVerify(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "node", NULL}; + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_LxmlElementPtr node = NULL; + int rv; PYXMLSEC_DEBUGF("%p: verify - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:verify", kwlist, PyXmlSec_LxmlElementConverter, &node)) { goto ON_FAIL; } - xmlSecDSigCtxPtr ctx = ((PyXmlSec_SignatureContext*)self)->handle; - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecDSigCtxVerify(ctx, node->_c_node); - PYXMLSEC_DUMP(xmlSecDSigCtxDebugDump, ctx); + rv = xmlSecDSigCtxVerify(ctx->handle, node->_c_node); + PYXMLSEC_DUMP(xmlSecDSigCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; if (rv < 0) { PyXmlSec_SetLastError("failed to verify"); goto ON_FAIL; } - if (ctx->status != xmlSecDSigStatusSucceeded) { + if (ctx->handle->status != xmlSecDSigStatusSucceeded) { PyErr_SetString(PyXmlSec_VerificationError, "Signature is invalid."); goto ON_FAIL; } @@ -227,54 +233,55 @@ static PyObject* PyXmlSec_SignatureContextVerify(PyObject* self, PyObject* args, } // common helper for operations binary_verify and binary_sign -static int PyXmlSec_ProcessSignBinary(xmlSecDSigCtxPtr ctx, const xmlSecByte* data, xmlSecSize data_size, xmlSecTransformId method) { +static int PyXmlSec_ProcessSignBinary(PyXmlSec_SignatureContext* ctx, const xmlSecByte* data, xmlSecSize data_size, xmlSecTransformId method) { + int rv; + if (!(method->usage & xmlSecTransformUsageSignatureMethod)) { PyErr_SetString(PyXmlSec_Error, "incompatible signature method"); return -1; } - if (ctx->signKey == NULL) { + if (ctx->handle->signKey == NULL) { PyErr_SetString(PyXmlSec_Error, "Sign key is not specified."); } - if (ctx->signMethod != NULL) { + if (ctx->handle->signMethod != NULL) { + PYXMLSEC_DEBUGF("%p: signMethod: %p", ctx, ctx->handle->signMethod); PyErr_SetString(PyXmlSec_Error, "Signature context already used; it is designed for one use only."); return -1; } - ctx->signMethod = xmlSecTransformCtxCreateAndAppend(&(ctx->transformCtx), method); - if (ctx->signMethod == NULL) { + ctx->handle->signMethod = xmlSecTransformCtxCreateAndAppend(&(ctx->handle->transformCtx), method); + if (ctx->handle->signMethod == NULL) { PyXmlSec_SetLastError("could not create signature transform."); return -1; } - int rv; - - ctx->signMethod->operation = ctx->operation; - xmlSecTransformSetKeyReq(ctx->signMethod, &(ctx->keyInfoReadCtx.keyReq)); - rv = xmlSecKeyMatch(ctx->signKey, NULL, &(ctx->keyInfoReadCtx.keyReq)); + ctx->handle->signMethod->operation = ctx->handle->operation; + xmlSecTransformSetKeyReq(ctx->handle->signMethod, &(ctx->handle->keyInfoReadCtx.keyReq)); + rv = xmlSecKeyMatch(ctx->handle->signKey, NULL, &(ctx->handle->keyInfoReadCtx.keyReq)); if (rv != 1) { PyXmlSec_SetLastError("inappropriate key type."); return -1; } - rv = xmlSecTransformSetKey(ctx->signMethod, ctx->signKey); + rv = xmlSecTransformSetKey(ctx->handle->signMethod, ctx->handle->signKey); if (rv < 0) { PyXmlSec_SetLastError("cannot set key."); return -1; } - ctx->transformCtx.result = NULL; - ctx->transformCtx.status = xmlSecTransformStatusNone; + ctx->handle->transformCtx.result = NULL; + ctx->handle->transformCtx.status = xmlSecTransformStatusNone; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecTransformCtxBinaryExecute(&(ctx->transformCtx), data, data_size); + rv = xmlSecTransformCtxBinaryExecute(&(ctx->handle->transformCtx), data, data_size); Py_END_ALLOW_THREADS; if (rv < 0) { PyXmlSec_SetLastError("failed to transform."); return -1; } - ctx->result = ctx->transformCtx.result; + ctx->handle->result = ctx->handle->transformCtx.result; return 0; } @@ -286,7 +293,7 @@ static const char PyXmlSec_SignatureContextSignBinary__doc__[] = \ ":return: the signature\n"; static PyObject* PyXmlSec_SignatureContextSignBinary(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "bytes", "transform", NULL}; - + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_Transform* transform = NULL; const char* data = NULL; Py_ssize_t data_size = 0; @@ -298,8 +305,7 @@ static PyObject* PyXmlSec_SignatureContextSignBinary(PyObject* self, PyObject* a goto ON_FAIL; } - xmlSecDSigCtxPtr ctx = ((PyXmlSec_SignatureContext*)self)->handle; - ctx->operation = xmlSecTransformOperationSign; + ctx->handle->operation = xmlSecTransformOperationSign; if (PyXmlSec_ProcessSignBinary(ctx, (const xmlSecByte*)data, (xmlSecSize)data_size, transform->id) != 0) { goto ON_FAIL; @@ -307,7 +313,8 @@ static PyObject* PyXmlSec_SignatureContextSignBinary(PyObject* self, PyObject* a PYXMLSEC_DEBUGF("%p: sign_binary - ok", self); return PyBytes_FromStringAndSize( - (const char*)xmlSecBufferGetData(ctx->result), (Py_ssize_t)xmlSecBufferGetSize(ctx->result) + (const char*)xmlSecBufferGetData(ctx->handle->result), + (Py_ssize_t)xmlSecBufferGetSize(ctx->handle->result) ); ON_FAIL: PYXMLSEC_DEBUGF("%p: sign_binary - fail", self); @@ -323,11 +330,13 @@ static const char PyXmlSec_SignatureContextVerifyBinary__doc__[] = \ static PyObject* PyXmlSec_SignatureContextVerifyBinary(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "bytes", "transform", "signature", NULL}; + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_Transform* transform = NULL; const char* data = NULL; Py_ssize_t data_size = 0; const char* sign = NULL; Py_ssize_t sign_size = 0; + int rv; PYXMLSEC_DEBUGF("%p: verify binary - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#O!s#:verify_binary", kwlist, @@ -336,15 +345,13 @@ static PyObject* PyXmlSec_SignatureContextVerifyBinary(PyObject* self, PyObject* goto ON_FAIL; } - xmlSecDSigCtxPtr ctx = ((PyXmlSec_SignatureContext*)self)->handle; - ctx->operation = xmlSecTransformOperationVerify; + ctx->handle->operation = xmlSecTransformOperationVerify; if (PyXmlSec_ProcessSignBinary(ctx, (const xmlSecByte*)data, (xmlSecSize)data_size, transform->id) != 0) { goto ON_FAIL; } - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecTransformVerify(ctx->signMethod, (const xmlSecByte*)sign, (xmlSecSize)sign_size, &(ctx->transformCtx)); + rv = xmlSecTransformVerify(ctx->handle->signMethod, (const xmlSecByte*)sign, (xmlSecSize)sign_size, &(ctx->handle->transformCtx)); Py_END_ALLOW_THREADS; if (rv < 0) { @@ -352,7 +359,7 @@ static PyObject* PyXmlSec_SignatureContextVerifyBinary(PyObject* self, PyObject* goto ON_FAIL; } - if (ctx->signMethod->status != xmlSecTransformStatusOk) { + if (ctx->handle->signMethod->status != xmlSecTransformStatusOk) { PyXmlSec_SetLastError2(PyXmlSec_VerificationError, "Signature is invalid."); goto ON_FAIL; } @@ -372,7 +379,9 @@ static const char PyXmlSec_SignatureContextEnableReferenceTransform__doc__[] = \ static PyObject* PyXmlSec_SignatureContextEnableReferenceTransform(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "transform", NULL}; + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_Transform* transform = NULL; + int rv; PYXMLSEC_DEBUGF("%p: enable_reference_transform - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:enable_reference_transform", kwlist, PyXmlSec_TransformType, &transform)) @@ -380,9 +389,8 @@ static PyObject* PyXmlSec_SignatureContextEnableReferenceTransform(PyObject* sel goto ON_FAIL; } - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecDSigCtxEnableReferenceTransform(((PyXmlSec_SignatureContext*)self)->handle, transform->id); + rv = xmlSecDSigCtxEnableReferenceTransform(ctx->handle, transform->id); Py_END_ALLOW_THREADS; if (rv < 0) { @@ -405,16 +413,17 @@ static const char PyXmlSec_SignatureContextEnableSignatureTransform__doc__[] = \ static PyObject* PyXmlSec_SignatureContextEnableSignatureTransform(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "transform", NULL}; + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyXmlSec_Transform* transform = NULL; + int rv; PYXMLSEC_DEBUGF("%p: enable_signature_transform - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:enable_signature_transform", kwlist, PyXmlSec_TransformType, &transform)) { goto ON_FAIL; } - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecDSigCtxEnableSignatureTransform(((PyXmlSec_SignatureContext*)self)->handle, transform->id); + rv = xmlSecDSigCtxEnableSignatureTransform(ctx->handle, transform->id); Py_END_ALLOW_THREADS; if (rv < 0) { @@ -435,9 +444,11 @@ static const char PyXmlSec_SignatureContextSetEnabledKeyData__doc__[] = \ static PyObject* PyXmlSec_SignatureContextSetEnabledKeyData(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "keydata_list", NULL}; + PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self; PyObject* keydata_list = NULL; PyObject* iter = NULL; PyObject* item = NULL; + xmlSecPtrListPtr enabled_list; PYXMLSEC_DEBUGF("%p: set_enabled_key_data - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_enabled_key_data", kwlist, &keydata_list)) { @@ -445,7 +456,7 @@ static PyObject* PyXmlSec_SignatureContextSetEnabledKeyData(PyObject* self, PyOb } if ((iter = PyObject_GetIter(keydata_list)) == NULL) goto ON_FAIL; - xmlSecPtrListPtr enabled_list = &(((PyXmlSec_SignatureContext*)self)->handle->keyInfoReadCtx.enabledKeyData); + enabled_list = &(ctx->handle->keyInfoReadCtx.enabledKeyData); xmlSecPtrListEmpty(enabled_list); while ((item = PyIter_Next(iter)) != NULL) { @@ -571,9 +582,9 @@ static PyTypeObject _PyXmlSec_SignatureContextType = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ PyXmlSec_SignatureContext__init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_alloc */ PyXmlSec_SignatureContext__new__, /* tp_new */ - PyObject_Del /* tp_free */ + 0, /* tp_free */ }; PyTypeObject* PyXmlSec_SignatureContextType = &_PyXmlSec_SignatureContextType; diff --git a/src/enc.c b/src/enc.c index 2362ad69..bb5a6833 100644 --- a/src/enc.c +++ b/src/enc.c @@ -38,6 +38,7 @@ static int PyXmlSec_EncryptionContext__init__(PyObject* self, PyObject* args, Py PyXmlSec_KeysManager* manager = NULL; PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; + PYXMLSEC_DEBUGF("%p: init enc context", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:__init__", kwlist, PyXmlSec_KeysManagerConvert, &manager)) { goto ON_FAIL; @@ -57,8 +58,10 @@ static int PyXmlSec_EncryptionContext__init__(PyObject* self, PyObject* args, Py } static void PyXmlSec_EncryptionContext__del__(PyObject* self) { - PYXMLSEC_DEBUGF("%p: delete enc context", self); PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; + + PYXMLSEC_DEBUGF("%p: delete enc context", self); + if (ctx->handle != NULL) { xmlSecEncCtxDestroy(ctx->handle); } @@ -70,35 +73,39 @@ static void PyXmlSec_EncryptionContext__del__(PyObject* self) { static const char PyXmlSec_EncryptionContextKey__doc__[] = "Encryption key.\n"; static PyObject* PyXmlSec_EncryptionContextKeyGet(PyObject* self, void* closure) { PyXmlSec_EncryptionContext* ctx = ((PyXmlSec_EncryptionContext*)self); + PyXmlSec_Key* key; + if (ctx->handle->encKey == NULL) { Py_RETURN_NONE; } - PyXmlSec_Key* key = PyXmlSec_NewKey(); + key = PyXmlSec_NewKey(); key->handle = ctx->handle->encKey; key->is_own = 0; return (PyObject*)key; } static int PyXmlSec_EncryptionContextKeySet(PyObject* self, PyObject* value, void* closure) { + PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; + PyXmlSec_Key* key; + PYXMLSEC_DEBUGF("%p, %p", self, value); if (!PyObject_IsInstance(value, (PyObject*)PyXmlSec_KeyType)) { PyErr_SetString(PyExc_TypeError, "instance of *xmlsec.Key* expected."); return -1; } - xmlSecKeyPtr keyHandle = ((PyXmlSec_Key*)value)->handle; - if (keyHandle == NULL) { + key = (PyXmlSec_Key*)value; + if (key->handle == NULL) { PyErr_SetString(PyExc_TypeError, "empty key."); return -1; } - PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; if (ctx->handle->encKey != NULL) { xmlSecKeyDestroy(ctx->handle->encKey); } - ctx->handle->encKey = xmlSecKeyDuplicate(keyHandle); + ctx->handle->encKey = xmlSecKeyDuplicate(key->handle); if (ctx->handle->encKey == NULL) { PyXmlSec_SetLastError("failed to duplicate key"); return -1; @@ -109,11 +116,12 @@ static int PyXmlSec_EncryptionContextKeySet(PyObject* self, PyObject* value, voi static const char PyXmlSec_EncryptionContextReset__doc__[] = \ "Resets *context*, user settings are not touched.\n"; static PyObject* PyXmlSec_EncryptionContextReset(PyObject* self, PyObject* args, PyObject* kwargs) { + PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; + PYXMLSEC_DEBUGF("%p: reset context - start", self); - xmlSecEncCtxPtr ctx = ((PyXmlSec_EncryptionContext*)self)->handle; Py_BEGIN_ALLOW_THREADS; - xmlSecEncCtxReset(ctx); - PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx); + xmlSecEncCtxReset(ctx->handle); + PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; PYXMLSEC_DEBUGF("%p: reset context - ok", self); Py_RETURN_NONE; @@ -128,9 +136,11 @@ static const char PyXmlSec_EncryptionContextEncryptBinary__doc__[] = \ static PyObject* PyXmlSec_EncryptionContextEncryptBinary(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "template", "data", NULL}; + PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; PyXmlSec_LxmlElementPtr template = NULL; const char* data = NULL; Py_ssize_t data_size = 0; + int rv; PYXMLSEC_DEBUGF("%p: encrypt_binary - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s#:encrypt_binary", kwlist, @@ -138,11 +148,10 @@ static PyObject* PyXmlSec_EncryptionContextEncryptBinary(PyObject* self, PyObjec { goto ON_FAIL; } - xmlSecEncCtxPtr ctx = ((PyXmlSec_EncryptionContext*)self)->handle; - int rv; + Py_BEGIN_ALLOW_THREADS; - rv = xmlSecEncCtxBinaryEncrypt(ctx, template->_c_node, (const xmlSecByte*)data, (xmlSecSize)data_size); - PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx); + rv = xmlSecEncCtxBinaryEncrypt(ctx->handle, template->_c_node, (const xmlSecByte*)data, (xmlSecSize)data_size); + PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; if (rv < 0) { @@ -163,6 +172,7 @@ static void PyXmlSec_ClearReplacedNodes(xmlSecEncCtxPtr ctx, PyXmlSec_LxmlDocume // release the replaced nodes in a way safe for `lxml` xmlNodePtr n = ctx->replacedNodeList; xmlNodePtr nn; + while (n != NULL) { PYXMLSEC_DEBUGF("clear replaced node %p", n); nn = n->next; @@ -185,10 +195,12 @@ static const char PyXmlSec_EncryptionContextEncryptXml__doc__[] = \ static PyObject* PyXmlSec_EncryptionContextEncryptXml(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "template", "node", NULL}; + PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; PyXmlSec_LxmlElementPtr template = NULL; PyXmlSec_LxmlElementPtr node = NULL; xmlNodePtr xnew_node = NULL; xmlChar* tmpType = NULL; + int rv = 0; PYXMLSEC_DEBUGF("%p: encrypt_xml - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:encrypt_xml", kwlist, @@ -206,9 +218,7 @@ static PyObject* PyXmlSec_EncryptionContextEncryptXml(PyObject* self, PyObject* // at `node._c_node` or its children by an extended subtree rooted at "c_node". // We set `XMLSEC_ENC_RETURN_REPLACED_NODE` to prevent deallocation // of the replaced node. This is important as `node` is still referencing it - xmlSecEncCtxPtr ctx = ((PyXmlSec_EncryptionContext*)self)->handle; - ctx->flags = XMLSEC_ENC_RETURN_REPLACED_NODE; - int rv = 0; + ctx->handle->flags = XMLSEC_ENC_RETURN_REPLACED_NODE; // try to do all actions whithin single python-free section // rv has the following codes, 1 - failed to copy node, -1 - op failed, 0 - success @@ -221,17 +231,17 @@ static PyObject* PyXmlSec_EncryptionContextEncryptXml(PyObject* self, PyObject* rv = 1; } } - if (rv == 0 && xmlSecEncCtxXmlEncrypt(ctx, xnew_node != NULL ? xnew_node: template->_c_node, node->_c_node) < 0) { + if (rv == 0 && xmlSecEncCtxXmlEncrypt(ctx->handle, xnew_node != NULL ? xnew_node: template->_c_node, node->_c_node) < 0) { rv = -1; if (xnew_node != NULL) { xmlFreeNode(xnew_node); xnew_node = NULL; } } - PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx); + PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; - PyXmlSec_ClearReplacedNodes(ctx, node->_doc); + PyXmlSec_ClearReplacedNodes(ctx->handle, node->_doc); if (rv != 0) { if (rv > 0) { @@ -259,19 +269,19 @@ static const char PyXmlSec_EncryptionContextEncryptUri__doc__[] = \ static PyObject* PyXmlSec_EncryptionContextEncryptUri(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "template", "uri", NULL}; + PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; PyXmlSec_LxmlElementPtr template = NULL; const char* uri = NULL; + int rv; PYXMLSEC_DEBUGF("%p: encrypt_uri - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s:encrypt_uri", kwlist, PyXmlSec_LxmlElementConverter, &template, &uri)) { goto ON_FAIL; } - xmlSecEncCtxPtr ctx = ((PyXmlSec_EncryptionContext*)self)->handle; - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecEncCtxUriEncrypt(ctx, template->_c_node, (const xmlSecByte*)uri); - PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx); + rv = xmlSecEncCtxUriEncrypt(ctx->handle, template->_c_node, (const xmlSecByte*)uri); + PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; if (rv < 0) { @@ -298,18 +308,25 @@ static const char PyXmlSec_EncryptionContextDecrypt__doc__[] = \ static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "node", NULL}; + PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self; PyXmlSec_LxmlElementPtr node = NULL; PyObject* node_num = NULL; PyObject* parent = NULL; + PyObject* tmp; + xmlNodePtr root; + xmlNodePtr xparent; + int rv; + xmlChar* ttype; + int notContent; PYXMLSEC_DEBUGF("%p: decrypt - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:decrypt", kwlist, PyXmlSec_LxmlElementConverter, &node)) { goto ON_FAIL; } - xmlNodePtr xparent = node->_c_node->parent; + xparent = node->_c_node->parent; if (xparent != NULL && !PyXmlSec_IsElement(xparent)) { xparent = NULL; } @@ -325,40 +342,38 @@ static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* arg PYXMLSEC_DEBUGF("parent: %p, %p", parent, node_num); } - xmlSecEncCtxPtr ctx = ((PyXmlSec_EncryptionContext*)self)->handle; - int rv; - Py_BEGIN_ALLOW_THREADS; - ctx->flags = XMLSEC_ENC_RETURN_REPLACED_NODE; - ctx->mode = xmlSecCheckNodeName(node->_c_node, xmlSecNodeEncryptedKey, xmlSecEncNs) ? xmlEncCtxModeEncryptedKey : xmlEncCtxModeEncryptedData; - PYXMLSEC_DEBUGF("mode: %d", ctx->mode); - rv = xmlSecEncCtxDecrypt(ctx, node->_c_node); - PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx); + ctx->handle->flags = XMLSEC_ENC_RETURN_REPLACED_NODE; + ctx->handle->mode = xmlSecCheckNodeName(node->_c_node, xmlSecNodeEncryptedKey, xmlSecEncNs) ? xmlEncCtxModeEncryptedKey : xmlEncCtxModeEncryptedData; + PYXMLSEC_DEBUGF("mode: %d", ctx->handle->mode); + rv = xmlSecEncCtxDecrypt(ctx->handle, node->_c_node); + PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle); Py_END_ALLOW_THREADS; - PyXmlSec_ClearReplacedNodes(ctx, node->_doc); + PyXmlSec_ClearReplacedNodes(ctx->handle, node->_doc); if (rv < 0) { PyXmlSec_SetLastError("failed to decrypt"); goto ON_FAIL; } - if (!ctx->resultReplaced) { + if (!ctx->handle->resultReplaced) { Py_XDECREF(node_num); Py_XDECREF(parent); PYXMLSEC_DEBUGF("%p: binary.decrypt - ok", self); return PyBytes_FromStringAndSize( - (const char*)xmlSecBufferGetData(ctx->result), (Py_ssize_t)xmlSecBufferGetSize(ctx->result) + (const char*)xmlSecBufferGetData(ctx->handle->result), + (Py_ssize_t)xmlSecBufferGetSize(ctx->handle->result) ); } if (xparent != NULL) { - xmlChar* ttype = xmlGetProp(node->_c_node, XSTR("Type")); - int notContent = (ttype == NULL || !xmlStrEqual(ttype, xmlSecTypeEncContent)); + ttype = xmlGetProp(node->_c_node, XSTR("Type")); + notContent = (ttype == NULL || !xmlStrEqual(ttype, xmlSecTypeEncContent)); xmlFree(ttype); if (notContent) { - PyObject* tmp = PyObject_GetItem(parent, node_num); + tmp = PyObject_GetItem(parent, node_num); if (tmp == NULL) goto ON_FAIL; Py_DECREF(parent); parent = tmp; @@ -369,7 +384,7 @@ static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* arg } // root has been replaced - xmlNodePtr root = xmlDocGetRootElement(node->_doc->_c_doc); + root = xmlDocGetRootElement(node->_doc->_c_doc); if (root == NULL) { PyErr_SetString(PyXmlSec_Error, "decryption resulted in a non well formed document"); goto ON_FAIL; @@ -470,9 +485,9 @@ static PyTypeObject _PyXmlSec_EncryptionContextType = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ PyXmlSec_EncryptionContext__init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_alloc */ PyXmlSec_EncryptionContext__new__, /* tp_new */ - PyObject_Del /* tp_free */ + 0 /* tp_free */ }; PyTypeObject* PyXmlSec_EncryptionContextType = &_PyXmlSec_EncryptionContextType; diff --git a/src/exception.c b/src/exception.c index 6e9dce7b..2ca5ab57 100644 --- a/src/exception.c +++ b/src/exception.c @@ -68,6 +68,9 @@ void PyXmlSec_ErrorHolderFree(PyXmlSec_ErrorHolder* h) { // saves new error in TLS and returns previous static PyXmlSec_ErrorHolder* PyXmlSec_ExchangeLastError(PyXmlSec_ErrorHolder* e) { + PyXmlSec_ErrorHolder* v; + int r; + if (PyXmlSec_LastErrorKey == 0) { PYXMLSEC_DEBUG("WARNING: There is no error key."); PyXmlSec_ErrorHolderFree(e); @@ -75,9 +78,9 @@ static PyXmlSec_ErrorHolder* PyXmlSec_ExchangeLastError(PyXmlSec_ErrorHolder* e) } // get_key_value and set_key_value are gil free - PyXmlSec_ErrorHolder* v = (PyXmlSec_ErrorHolder*)PyThread_get_key_value(PyXmlSec_LastErrorKey); + v = (PyXmlSec_ErrorHolder*)PyThread_get_key_value(PyXmlSec_LastErrorKey); PyThread_delete_key_value(PyXmlSec_LastErrorKey); - int r = PyThread_set_key_value(PyXmlSec_LastErrorKey, (void*)e); + r = PyThread_set_key_value(PyXmlSec_LastErrorKey, (void*)e); PYXMLSEC_DEBUGF("set_key_value returns %d", r); return v; } @@ -114,11 +117,13 @@ static void PyXmlSec_ErrorCallback(const char* file, int line, const char* func, // the gil should be acquired static PyObject* PyXmlSec_GetLastError(PyObject* type, const char* msg) { PyXmlSec_ErrorHolder* h = PyXmlSec_ExchangeLastError(NULL); + PyObject* exc; + if (h == NULL) { return NULL; } - PyObject* exc = PyObject_CallFunction(type, "is", h->reason, msg); + exc = PyObject_CallFunction(type, "is", h->reason, msg); if (exc == NULL) goto ON_FAIL; PyXmlSec_SetLongAttr(exc, "code", h->reason); diff --git a/src/keys.c b/src/keys.c index 0d0d0d3e..01d7fa30 100644 --- a/src/keys.c +++ b/src/keys.c @@ -27,8 +27,8 @@ static PyObject* PyXmlSec_Key__new__(PyTypeObject *type, PyObject *args, PyObjec } static void PyXmlSec_Key__del__(PyObject* self) { - PYXMLSEC_DEBUGF("%p: delete key", self); PyXmlSec_Key* key = (PyXmlSec_Key*)self; + PYXMLSEC_DEBUGF("%p: delete key", self); if (key->is_own) { PYXMLSEC_DEBUGF("%p: delete handle - %p", self, key->handle); xmlSecKeyDestroy(key->handle); @@ -41,10 +41,12 @@ static PyXmlSec_Key* PyXmlSec_NewKey1(PyTypeObject* type) { } static PyObject* PyXmlSec_Key__copy__(PyObject* self) { + xmlSecKeyPtr handle = ((PyXmlSec_Key*)self)->handle; + PyXmlSec_Key* key2; + PYXMLSEC_DEBUGF("%p: copy key", self); - xmlSecKeyPtr handle = ((PyXmlSec_Key*)self)->handle; - PyXmlSec_Key* key2 = PyXmlSec_NewKey1(Py_TYPE(self)); + key2 = PyXmlSec_NewKey1(Py_TYPE(self)); if (handle == NULL || key2 == NULL) { PYXMLSEC_DEBUGF("%p: null key", self); @@ -223,6 +225,7 @@ static PyObject* PyXmlSec_KeyFromBinaryFile(PyObject* self, PyObject* args, PyOb PyObject* filepath = NULL; PyXmlSec_Key* key = NULL; + const char* filename; PYXMLSEC_DEBUG("load symmetric key - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O&:from_binary_file", kwlist, @@ -231,7 +234,7 @@ static PyObject* PyXmlSec_KeyFromBinaryFile(PyObject* self, PyObject* args, PyOb goto ON_FAIL; } - const char* filename = PyBytes_AsString(filepath); + filename = PyBytes_AsString(filepath); if (filename == NULL) goto ON_FAIL; if ((key = PyXmlSec_NewKey1((PyTypeObject*)self)) == NULL) goto ON_FAIL; @@ -307,19 +310,19 @@ static const char PyXmlSec_KeyCertFromMemory__doc__[] = \ static PyObject* PyXmlSec_KeyCertFromMemory(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "data", "format", NULL}; + PyXmlSec_Key* key = (PyXmlSec_Key*)self; const char* data = NULL; Py_ssize_t data_size = 0; unsigned int format = 0; PyObject* tmp = NULL; + int rv = 0; PYXMLSEC_DEBUGF("%p: load certificate from memory - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#I:load_cert_from_memory", kwlist, &data, &data_size, &format)) { goto ON_FAIL; } - PyXmlSec_Key* key = (PyXmlSec_Key*)self; - int rv = 0; Py_BEGIN_ALLOW_THREADS; rv = xmlSecCryptoAppKeyCertLoadMemory(key->handle, (const xmlSecByte*)data, (xmlSecSize)data_size, format); Py_END_ALLOW_THREADS; @@ -343,6 +346,8 @@ static const char PyXmlSec_KeyCertFromFile__doc__[] = \ static PyObject* PyXmlSec_KeyCertFromFile(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "file", "format", NULL}; + PyXmlSec_Key* key = (PyXmlSec_Key*)self; + PyObject* file = NULL; unsigned int format = 0; @@ -350,6 +355,7 @@ static PyObject* PyXmlSec_KeyCertFromFile(PyObject* self, PyObject* args, PyObje int is_content = 0; const char* data = NULL; Py_ssize_t data_size = 0; + int rv = 0; PYXMLSEC_DEBUGF("%p: load certificate from memory - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OI:load_cert_from_file", kwlist, &file, &format)) { @@ -366,8 +372,6 @@ static PyObject* PyXmlSec_KeyCertFromFile(PyObject* self, PyObject* args, PyObje if (data == NULL) goto ON_FAIL; - PyXmlSec_Key* key = (PyXmlSec_Key*)self; - int rv = 0; Py_BEGIN_ALLOW_THREADS; if (is_content) { rv = xmlSecCryptoAppKeyCertLoadMemory(key->handle, (const xmlSecByte*)data, (xmlSecSize)data_size, format); @@ -391,13 +395,15 @@ static PyObject* PyXmlSec_KeyCertFromFile(PyObject* self, PyObject* args, PyObje static const char PyXmlSec_KeyName__doc__[] = "the name of *key*.\n"; static PyObject* PyXmlSec_KeyNameGet(PyObject* self, void* closure) { + PyXmlSec_Key* key = (PyXmlSec_Key*)self; + const char* cname; + PYXMLSEC_DEBUGF("%p: get name of key", self); - xmlSecKeyPtr handle = ((PyXmlSec_Key*)self)->handle; - if (handle == NULL) { + if (key->handle == NULL) { PyErr_SetString(PyExc_ValueError, "key is not ready"); return NULL; } - const char* cname = (const char*)xmlSecKeyGetName(handle); + cname = (const char*)xmlSecKeyGetName(key->handle); if (cname != NULL) { return PyString_FromString(cname); } @@ -405,18 +411,20 @@ static PyObject* PyXmlSec_KeyNameGet(PyObject* self, void* closure) { } static int PyXmlSec_KeyNameSet(PyObject* self, PyObject* value, void* closure) { + PyXmlSec_Key* key = (PyXmlSec_Key*)self; + const char* name; + PYXMLSEC_DEBUGF("%p: set name of key %p", self, value); - xmlSecKeyPtr handle = ((PyXmlSec_Key*)self)->handle; - if (handle == NULL) { + if (key->handle == NULL) { PyErr_SetString(PyExc_ValueError, "key is not ready"); return -1; } - const char* name = PyString_AsString(value); + name = PyString_AsString(value); if (name == NULL) return -1; - xmlSecKeySetName(handle, XSTR(name)); + xmlSecKeySetName(key->handle, XSTR(name)); return 0; } @@ -526,9 +534,9 @@ static PyTypeObject _PyXmlSec_KeyType = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_alloc */ PyXmlSec_Key__new__, /* tp_new */ - PyObject_Del /* tp_free */ + 0, /* tp_free */ }; PyTypeObject* PyXmlSec_KeyType = &_PyXmlSec_KeyType; @@ -550,8 +558,9 @@ static PyObject* PyXmlSec_KeysManager__new__(PyTypeObject *type, PyObject *args, } static int PyXmlSec_KeysManager__init__(PyObject* self, PyObject* args, PyObject* kwargs) { - PYXMLSEC_DEBUGF("%p: init key manager", self); xmlSecKeysMngrPtr handle = xmlSecKeysMngrCreate(); + + PYXMLSEC_DEBUGF("%p: init key manager", self); if (handle == NULL) { PyXmlSec_SetLastError("failed to create xmlsecKeyManger"); return -1; @@ -567,11 +576,13 @@ static int PyXmlSec_KeysManager__init__(PyObject* self, PyObject* args, PyObject } static void PyXmlSec_KeysManager__del__(PyObject* self) { + PyXmlSec_KeysManager* mgr = (PyXmlSec_KeysManager*)self; + PYXMLSEC_DEBUGF("%p: delete KeysManager", self); - PyXmlSec_KeysManager* manager = (PyXmlSec_KeysManager*)self; - if (manager->handle != NULL) { - PYXMLSEC_DEBUGF("%p: delete KeysManager handle - %p", self, manager->handle); - xmlSecKeysMngrDestroy(manager->handle); + + if (mgr->handle != NULL) { + PYXMLSEC_DEBUGF("%p: delete KeysManager handle - %p", self, mgr->handle); + xmlSecKeysMngrDestroy(mgr->handle); } Py_TYPE(self)->tp_free(self); } @@ -582,7 +593,10 @@ static const char PyXmlSec_KeysManagerAddKey__doc__[] = \ static PyObject* PyXmlSec_KeysManagerAddKey(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "key", NULL}; + PyXmlSec_KeysManager* mgr = (PyXmlSec_KeysManager*)self; PyXmlSec_Key* key = NULL; + xmlSecKeyPtr key2; + int rv; PYXMLSEC_DEBUGF("%p(%p): add key - start", self, ((PyXmlSec_KeysManager*)self)->handle); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:add_key", kwlist, PyXmlSec_KeyType, &key)) { @@ -594,7 +608,6 @@ static PyObject* PyXmlSec_KeysManagerAddKey(PyObject* self, PyObject* args, PyOb goto ON_FAIL; } - xmlSecKeyPtr key2; Py_BEGIN_ALLOW_THREADS key2 = xmlSecKeyDuplicate(key->handle); Py_END_ALLOW_THREADS; @@ -604,9 +617,8 @@ static PyObject* PyXmlSec_KeysManagerAddKey(PyObject* self, PyObject* args, PyOb goto ON_FAIL; } - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecCryptoAppDefaultKeysMngrAdoptKey(((PyXmlSec_KeysManager*)self)->handle, key2); + rv = xmlSecCryptoAppDefaultKeysMngrAdoptKey(mgr->handle, key2); Py_END_ALLOW_THREADS; if (rv < 0) { PyXmlSec_SetLastError("cannot add key"); @@ -628,21 +640,24 @@ static const char PyXmlSec_KeysManagerLoadCert__doc__[] = \ static PyObject* PyXmlSec_KeysManagerLoadCert(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "filename", "format", "type", NULL}; + PyXmlSec_KeysManager* mgr = (PyXmlSec_KeysManager*)self; PyObject* filepath = NULL; unsigned int format = 0; unsigned int type = 0; + const char* filename; + int rv; + PYXMLSEC_DEBUGF("%p: load cert - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&II:load_cert", kwlist, PyString_FSConverter, &filepath, &format, &type)) { goto ON_FAIL; } - const char* filename = PyBytes_AsString(filepath); + filename = PyBytes_AsString(filepath); - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecCryptoAppKeysMngrCertLoad(((PyXmlSec_KeysManager*)self)->handle, filename, format, type); + rv = xmlSecCryptoAppKeysMngrCertLoad(mgr->handle, filename, format, type); Py_END_ALLOW_THREADS; if (rv < 0) { PyXmlSec_SetLastError("cannot load cert"); @@ -665,20 +680,21 @@ static const char PyXmlSec_KeysManagerLoadCertFromMemory__doc__[] = \ static PyObject* PyXmlSec_KeysManagerLoadCertFromMemory(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { "data", "format", "type", NULL}; + PyXmlSec_KeysManager* mgr = (PyXmlSec_KeysManager*)self; + const char* data = NULL; unsigned int type = 0; unsigned int format = 0; Py_ssize_t data_size = 0; + int rv; PYXMLSEC_DEBUGF("%p: load cert from memory - start", self); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#II:load_cert", kwlist, &data, &data_size, &format, &type)) { goto ON_FAIL; } - xmlSecKeysMngrPtr handle = ((PyXmlSec_KeysManager*)self)->handle; - int rv; Py_BEGIN_ALLOW_THREADS; - rv = xmlSecCryptoAppKeysMngrCertLoadMemory(handle, (const xmlSecByte*)data, (xmlSecSize)data_size, format, type); + rv = xmlSecCryptoAppKeysMngrCertLoadMemory(mgr->handle, (const xmlSecByte*)data, (xmlSecSize)data_size, format, type); Py_END_ALLOW_THREADS; if (rv < 0) { PyXmlSec_SetLastError("cannot load cert from memory"); @@ -750,9 +766,9 @@ static PyTypeObject _PyXmlSec_KeysManagerType = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ PyXmlSec_KeysManager__init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_alloc */ PyXmlSec_KeysManager__new__, /* tp_new */ - PyObject_Del /* tp_free */ + 0, /* tp_free */ }; PyTypeObject* PyXmlSec_KeysManagerType = &_PyXmlSec_KeysManagerType; diff --git a/src/main.c b/src/main.c index c9121fa9..490a37e6 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,9 @@ static int free_mode = _FREE_NONE; +#define MODULE_DOC "The tiny python wrapper around xmlsec1 (" XMLSEC_VERSION ") library" + + static void PyXmlSec_Free(int what) { PYXMLSEC_DEBUGF("free resources %d", what); switch (what) { @@ -160,7 +163,7 @@ static int PyXmlSec_PyClear(PyObject *self) { static PyModuleDef PyXmlSecModule = { PyModuleDef_HEAD_INIT, STRINGIFY(MODULE_NAME), /* name of module */ - STRINGIFY(MODULE_DOC), /* module documentation, may be NULL */ + MODULE_DOC, /* module documentation, may be NULL */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ PyXmlSec_MainMethods, /* m_methods */ @@ -218,7 +221,7 @@ PYENTRY_FUNC_NAME(void) #ifdef PY3K module = PyModule_Create(&PyXmlSecModule); #else - module = Py_InitModule3(STRINGIFY(MODULE_NAME), PyXmlSec_MainMethods, STRINGIFY(MODULE_DOC)); + module = Py_InitModule3(STRINGIFY(MODULE_NAME), PyXmlSec_MainMethods, MODULE_DOC); #endif if (!module) { PY_MOD_RETURN(NULL); /* this really should never happen */ diff --git a/src/template.c b/src/template.c index d7bf5826..9a68dbd7 100644 --- a/src/template.c +++ b/src/template.c @@ -34,6 +34,7 @@ static PyObject* PyXmlSec_TemplateCreate(PyObject* self, PyObject *args, PyObjec PyXmlSec_Transform* sign = NULL; const char* id = NULL; const char* ns = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template create - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!O!|zzz:create", kwlist, @@ -42,7 +43,6 @@ static PyObject* PyXmlSec_TemplateCreate(PyObject* self, PyObject *args, PyObjec goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplSignatureCreateNsPref(node->_doc->_c_doc, c14n->id, sign->id, XSTR(id), XSTR(ns)); Py_END_ALLOW_THREADS; @@ -76,6 +76,7 @@ static PyObject* PyXmlSec_TemplateAddReference(PyObject* self, PyObject *args, P const char* id = NULL; const char* uri = NULL; const char* type = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template add_reference - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!|zzz:add_reference", kwlist, @@ -83,7 +84,6 @@ static PyObject* PyXmlSec_TemplateAddReference(PyObject* self, PyObject *args, P { goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplSignatureAddReference(node->_c_node, digest->id, XSTR(id), XSTR(uri), XSTR(type)); Py_END_ALLOW_THREADS; @@ -110,6 +110,7 @@ static PyObject* PyXmlSec_TemplateAddTransform(PyObject* self, PyObject *args, P PyXmlSec_LxmlElementPtr node = NULL; PyXmlSec_Transform* transform = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template add_transform - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!:add_transform", kwlist, @@ -117,7 +118,6 @@ static PyObject* PyXmlSec_TemplateAddTransform(PyObject* self, PyObject *args, P { goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplReferenceAddTransform(node->_c_node, transform->id); Py_END_ALLOW_THREADS; @@ -144,13 +144,14 @@ static PyObject* PyXmlSec_TemplateEnsureKeyInfo(PyObject* self, PyObject *args, PyXmlSec_LxmlElementPtr node = NULL; const char* id = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template ensure_key_info - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|z:ensure_key_info", kwlist, PyXmlSec_LxmlElementConverter, &node, &id)) { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplSignatureEnsureKeyInfo(node->_c_node, XSTR(id)); Py_END_ALLOW_THREADS; @@ -177,6 +178,7 @@ static PyObject* PyXmlSec_TemplateAddKeyName(PyObject* self, PyObject *args, PyO PyXmlSec_LxmlElementPtr node = NULL; const char* name = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template add_key_name - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|z:add_key_name", kwlist, PyXmlSec_LxmlElementConverter, &node, &name)) @@ -184,7 +186,6 @@ static PyObject* PyXmlSec_TemplateAddKeyName(PyObject* self, PyObject *args, PyO goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplKeyInfoAddKeyName(node->_c_node, XSTR(name)); Py_END_ALLOW_THREADS; @@ -209,6 +210,7 @@ static PyObject* PyXmlSec_TemplateAddKeyValue(PyObject* self, PyObject *args, Py static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template add_key_value - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:add_key_value", kwlist, PyXmlSec_LxmlElementConverter, &node)) @@ -216,7 +218,6 @@ static PyObject* PyXmlSec_TemplateAddKeyValue(PyObject* self, PyObject *args, Py goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplKeyInfoAddKeyValue(node->_c_node); Py_END_ALLOW_THREADS; @@ -241,6 +242,7 @@ static PyObject* PyXmlSec_TemplateAddX509Data(PyObject* self, PyObject *args, Py static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template add_x509_data - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:add_x509_data", kwlist, PyXmlSec_LxmlElementConverter, &node)) @@ -248,7 +250,6 @@ static PyObject* PyXmlSec_TemplateAddX509Data(PyObject* self, PyObject *args, Py goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplKeyInfoAddX509Data(node->_c_node); Py_END_ALLOW_THREADS; @@ -273,6 +274,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddIssuerSerial(PyObject* self, PyO static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_data_add_issuer_serial - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:x509_data_add_issuer_serial", kwlist, @@ -280,7 +282,6 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddIssuerSerial(PyObject* self, PyO { goto ON_FAIL; } - xmlNodePtr res; Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509DataAddIssuerSerial(node->_c_node); Py_END_ALLOW_THREADS; @@ -307,6 +308,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataIssuerSerialAddIssuerName(PyObject* PyXmlSec_LxmlElementPtr node = NULL; const char* name = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_issuer_serial_add_issuer_name - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|z:x509_issuer_serial_add_issuer_name", kwlist, @@ -314,7 +316,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataIssuerSerialAddIssuerName(PyObject* { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509IssuerSerialAddIssuerName(node->_c_node, XSTR(name)); Py_END_ALLOW_THREADS; @@ -341,6 +343,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataIssuerSerialAddIssuerSerialNumber(P PyXmlSec_LxmlElementPtr node = NULL; const char* serial = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_issuer_serial_add_serial_number - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|z:x509_issuer_serial_add_serial_number", kwlist, @@ -348,7 +351,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataIssuerSerialAddIssuerSerialNumber(P { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509IssuerSerialAddSerialNumber(node->_c_node, XSTR(serial)); Py_END_ALLOW_THREADS; @@ -373,6 +376,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddSubjectName(PyObject* self, PyOb static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_data_add_subject_name - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:x509_data_add_subject_name", kwlist, @@ -380,7 +384,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddSubjectName(PyObject* self, PyOb { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509DataAddSubjectName(node->_c_node); Py_END_ALLOW_THREADS; @@ -405,6 +409,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddSKI(PyObject* self, PyObject *ar static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_data_add_ski - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:x509_data_add_ski", kwlist, @@ -412,7 +417,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddSKI(PyObject* self, PyObject *ar { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509DataAddSKI(node->_c_node); Py_END_ALLOW_THREADS; @@ -437,6 +442,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddCertificate(PyObject* self, PyOb static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_data_add_certificate - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:x509_data_add_certificate", kwlist, @@ -444,7 +450,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddCertificate(PyObject* self, PyOb { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509DataAddCertificate(node->_c_node); Py_END_ALLOW_THREADS; @@ -469,6 +475,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddCRL(PyObject* self, PyObject *ar static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template x509_data_add_crl - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:x509_data_add_crl", kwlist, @@ -476,7 +483,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddCRL(PyObject* self, PyObject *ar { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplX509DataAddCRL(node->_c_node); Py_END_ALLOW_THREADS; @@ -509,6 +516,7 @@ static PyObject* PyXmlSec_TemplateAddEncryptedKey(PyObject* self, PyObject *args const char* id = NULL; const char* type = NULL; const char* recipient = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template add_encrypted_key - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!|zzz:add_encrypted_key", kwlist, @@ -516,7 +524,7 @@ static PyObject* PyXmlSec_TemplateAddEncryptedKey(PyObject* self, PyObject *args { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplKeyInfoAddEncryptedKey(node->_c_node, method->id, XSTR(id), XSTR(type), XSTR(recipient)); Py_END_ALLOW_THREADS; @@ -553,6 +561,7 @@ static PyObject* PyXmlSec_TemplateCreateEncryptedData(PyObject* self, PyObject * const char* mime_type = NULL; const char* encoding = NULL; const char* ns = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template encrypted_data_create - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!|zzzzz:encrypted_data_create", kwlist, @@ -560,7 +569,7 @@ static PyObject* PyXmlSec_TemplateCreateEncryptedData(PyObject* self, PyObject * { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplEncDataCreate(node->_doc->_c_doc, method->id, XSTR(id), XSTR(type), XSTR(mime_type), XSTR(encoding)); Py_END_ALLOW_THREADS; @@ -592,6 +601,7 @@ static PyObject* PyXmlSec_TemplateEncryptedDataEnsureKeyInfo(PyObject* self, PyO PyXmlSec_LxmlElementPtr node = NULL; const char* id = NULL; const char* ns = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template encrypted_data_ensure_key_info - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|zz:encrypted_data_ensure_key_info", kwlist, @@ -599,7 +609,7 @@ static PyObject* PyXmlSec_TemplateEncryptedDataEnsureKeyInfo(PyObject* self, PyO { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplEncDataEnsureKeyInfo(node->_c_node, XSTR(id)); Py_END_ALLOW_THREADS; @@ -627,6 +637,7 @@ static PyObject* PyXmlSec_TemplateEncryptedDataEnsureCipherValue(PyObject* self, static char *kwlist[] = { "node", NULL}; PyXmlSec_LxmlElementPtr node = NULL; + xmlNodePtr res; PYXMLSEC_DEBUG("template encrypted_data_ensure_cipher_value - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:encrypted_data_ensure_cipher_value", kwlist, @@ -634,7 +645,7 @@ static PyObject* PyXmlSec_TemplateEncryptedDataEnsureCipherValue(PyObject* self, { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplEncDataEnsureCipherValue(node->_c_node); Py_END_ALLOW_THREADS; @@ -660,6 +671,10 @@ static PyObject* PyXmlSec_TemplateTransformAddC14NInclNamespaces(PyObject* self, PyXmlSec_LxmlElementPtr node = NULL; PyObject* prefixes = NULL; + PyObject* sep; + int res; + const char* c_prefixes; + // transform_add_c14n_inclusive_namespaces PYXMLSEC_DEBUG("template encrypted_data_ensure_cipher_value - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O:transform_add_c14n_inclusive_namespaces", kwlist, @@ -669,7 +684,7 @@ static PyObject* PyXmlSec_TemplateTransformAddC14NInclNamespaces(PyObject* self, goto ON_FAIL; } if (PyList_Check(prefixes) || PyTuple_Check(prefixes)) { - PyObject* sep = PyString_FromString(" "); + sep = PyString_FromString(" "); prefixes = PyObject_CallMethod(sep, "join", "O", prefixes); Py_DECREF(sep); } else if (PyString_Check(prefixes)) { @@ -683,8 +698,8 @@ static PyObject* PyXmlSec_TemplateTransformAddC14NInclNamespaces(PyObject* self, goto ON_FAIL; } - int res; - const char* c_prefixes = PyString_AsString(prefixes); + + c_prefixes = PyString_AsString(prefixes); Py_BEGIN_ALLOW_THREADS; res = xmlSecTmplTransformAddC14NInclNamespaces(node->_c_node, XSTR(c_prefixes)); Py_END_ALLOW_THREADS; diff --git a/src/tree.c b/src/tree.c index 3d17b329..ac23b53f 100644 --- a/src/tree.c +++ b/src/tree.c @@ -27,6 +27,7 @@ static PyObject* PyXmlSec_TreeFindChild(PyObject* self, PyObject *args, PyObject PyXmlSec_LxmlElementPtr node = NULL; const char* name = NULL; const char* ns = (const char*)xmlSecDSigNs; + xmlNodePtr res; PYXMLSEC_DEBUG("tree find_child - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|s:find_child", kwlist, @@ -34,7 +35,7 @@ static PyObject* PyXmlSec_TreeFindChild(PyObject* self, PyObject *args, PyObject { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecFindChild(node->_c_node, XSTR(name), XSTR(ns)); Py_END_ALLOW_THREADS; @@ -62,6 +63,7 @@ static PyObject* PyXmlSec_TreeFindParent(PyObject* self, PyObject *args, PyObjec PyXmlSec_LxmlElementPtr node = NULL; const char* name = NULL; const char* ns = (const char*)xmlSecDSigNs; + xmlNodePtr res; PYXMLSEC_DEBUG("tree find_parent - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|s:find_parent", kwlist, @@ -69,7 +71,7 @@ static PyObject* PyXmlSec_TreeFindParent(PyObject* self, PyObject *args, PyObjec { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecFindParent(node->_c_node, XSTR(name), XSTR(ns)); Py_END_ALLOW_THREADS; @@ -97,6 +99,7 @@ static PyObject* PyXmlSec_TreeFindNode(PyObject* self, PyObject *args, PyObject PyXmlSec_LxmlElementPtr node = NULL; const char* name = NULL; const char* ns = (const char*)xmlSecDSigNs; + xmlNodePtr res; PYXMLSEC_DEBUG("tree find_node - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|s:find_node", kwlist, @@ -104,7 +107,7 @@ static PyObject* PyXmlSec_TreeFindNode(PyObject* self, PyObject *args, PyObject { goto ON_FAIL; } - xmlNodePtr res; + Py_BEGIN_ALLOW_THREADS; res = xmlSecFindNode(node->_c_node, XSTR(name), XSTR(ns)); Py_END_ALLOW_THREADS; @@ -136,12 +139,17 @@ static PyObject* PyXmlSec_TreeAddIds(PyObject* self, PyObject *args, PyObject *k const xmlChar** list = NULL; + Py_ssize_t n; + PyObject* tmp; + PyObject* key; + Py_ssize_t i; + PYXMLSEC_DEBUG("tree add_ids - start"); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O:add_ids", kwlist, PyXmlSec_LxmlElementConverter, &node, &ids)) { goto ON_FAIL; } - Py_ssize_t n = PyObject_Length(ids); + n = PyObject_Length(ids); if (n < 0) goto ON_FAIL; list = (const xmlChar**)xmlMalloc(sizeof(xmlChar*) * (n + 1)); @@ -150,9 +158,7 @@ static PyObject* PyXmlSec_TreeAddIds(PyObject* self, PyObject *args, PyObject *k goto ON_FAIL; } - PyObject* tmp; - PyObject* key; - for (Py_ssize_t i = 0; i < n; ++i) { + for (i = 0; i < n; ++i) { key = PyLong_FromSsize_t(i); if (key == NULL) goto ON_FAIL; tmp = PyObject_GetItem(ids, key); diff --git a/src/utils.c b/src/utils.c index 679a1b2d..ea6867f3 100644 --- a/src/utils.c +++ b/src/utils.c @@ -10,10 +10,14 @@ #include "utils.h" PyObject* PyXmlSec_GetFilePathOrContent(PyObject* file, int* is_content) { + PyObject* data; + PyObject* utf8; + PyObject* tmp = NULL; + if (PyObject_HasAttrString(file, "read")) { - PyObject* data = PyObject_CallMethod(file, "read", NULL); + data = PyObject_CallMethod(file, "read", NULL); if (data != NULL && PyUnicode_Check(data)) { - PyObject* utf8 = PyUnicode_AsUTF8String(data); + utf8 = PyUnicode_AsUTF8String(data); Py_DECREF(data); data = utf8; } @@ -21,7 +25,6 @@ PyObject* PyXmlSec_GetFilePathOrContent(PyObject* file, int* is_content) { return data; } *is_content = 0; - PyObject* tmp = NULL; if (!PyString_FSConverter(file, &tmp)) { return NULL; } @@ -30,20 +33,24 @@ PyObject* PyXmlSec_GetFilePathOrContent(PyObject* file, int* is_content) { int PyXmlSec_SetStringAttr(PyObject* obj, const char* name, const char* value) { PyObject* tmp = PyString_FromString(value); + int r; + if (tmp == NULL) { return -1; } - int r = PyObject_SetAttrString(obj, name, tmp); + r = PyObject_SetAttrString(obj, name, tmp); Py_DECREF(tmp); return r; } int PyXmlSec_SetLongAttr(PyObject* obj, const char* name, long value) { PyObject* tmp = PyLong_FromLong(value); + int r; + if (tmp == NULL) { return -1; } - int r = PyObject_SetAttrString(obj, name, tmp); + r = PyObject_SetAttrString(obj, name, tmp); Py_DECREF(tmp); return r; } diff --git a/tests/base.py b/tests/base.py index abbe6058..b05de1de 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,6 +1,5 @@ import gc import os -import resource import sys from lxml import etree @@ -8,14 +7,30 @@ import unittest + etype = type(etree.Element("test")) ns = {'dsig': xmlsec.constants.DSigNs, 'enc': xmlsec.constants.EncNs} -def safe_int(s): +try: + import resource + + def get_memory_usage(): + return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss +except ImportError: + resource = None + + def get_memory_usage(): + return 0 + + +def get_iterations(): + if sys.platform in ('win32',): + return 0 + try: - return int(s) + return int(os.getenv("PYXMLSEC_TEST_ITERATIONS", "10")) except ValueError: return 0 @@ -23,7 +38,7 @@ def safe_int(s): class TestMemoryLeaks(unittest.TestCase): maxDiff = None - iterations = safe_int(os.getenv("PYXMLSEC_TEST_ITERATIONS", "10")) + iterations = get_iterations() data_dir = os.path.join(os.path.dirname(__file__), "data") @@ -104,8 +119,8 @@ def assertXmlEqual(self, first, second, msg=None): self.fail('text: %r != %r. %s' % (first.text, second.text, msg)) if not xml_text_compare(first.tail, second.tail): self.fail('tail: %r != %r. %s' % (first.tail, second.tail, msg)) - cl1 = first.getchildren() - cl2 = second.getchildren() + cl1 = sorted(first.getchildren(), key=lambda x: x.tag) + cl2 = sorted(second.getchildren(), key=lambda x: x.tag) if len(cl1) != len(cl2): self.fail('children length differs, %i != %i. %s' % (len(cl1), len(cl2), msg)) i = 0 diff --git a/version.txt b/version.txt new file mode 100644 index 00000000..e7526496 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +1.0.1.dev0