diff --git a/experimental/facho-signer/Makefile b/experimental/facho-signer/Makefile deleted file mode 100644 index d363230..0000000 --- a/experimental/facho-signer/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: facho-signer - -CC = gcc - -CFLAGS = -Wall -Werror -std=gnu11 -CFLAGS += $(shell pkg-config libxml-2.0 --cflags) -CFLAGS += $(shell pkg-config xmlsec1 --cflags) -CFLAGS += $(shell pkg-config xmlsec1-openssl --cflags) -CFLAGS += -Ixades - -LDFLAGS = $(shell pkg-config libxml-2.0 --libs) -LDFLAGS += $(shell pkg-config xmlsec1 --libs) -LDFLAGS += $(shell pkg-config xmlsec1-openssl --libs) -LDFLAGS += xades/templates.c xades/xades.c - -facho-signer: crypto.c facho-signer.c - $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ diff --git a/experimental/facho-signer/Makefile.am b/experimental/facho-signer/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/experimental/facho-signer/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/experimental/facho-signer/boostrap.sh b/experimental/facho-signer/boostrap.sh new file mode 100644 index 0000000..0fb6c4f --- /dev/null +++ b/experimental/facho-signer/boostrap.sh @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf --install diff --git a/experimental/facho-signer/configure.ac b/experimental/facho-signer/configure.ac new file mode 100644 index 0000000..dff6612 --- /dev/null +++ b/experimental/facho-signer/configure.ac @@ -0,0 +1,39 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.71]) +AC_INIT([facho-signer], [0.0.1], [bit4bit@riseup.net]) +AM_INIT_AUTOMAKE +AC_CONFIG_SRCDIR([src/facho_signer.c]) +AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. + +# Checks for header files. +AC_CHECK_HEADERS([sys/time.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([clock_gettime gethrtime gettimeofday memset strdup]) + +PKG_CHECK_MODULES([XMLSEC1], [xmlsec1-openssl]) + +AC_ARG_ENABLE([xmlsec-crypto-dynamic-loading], + AS_HELP_STRING([--enable-xmlsec-crypto-dynamic-loading], + [enable crypto xmlsec dynamic loading]) + ) + +if test "x$enable_xmlsec_crypto_dynamic_loading" == xyes; then + AC_DEFINE([XMLSEC_CRYPTO_DYNAMIC_LOADING], [1], [enable xmlsec crypto dynamic loading]) +else + AC_DEFINE([XMLSEC_NO_CRYPTO_DYNAMIC_LOADING], [1], [disable xmlsec crypto dynamic loading]) +fi + +AC_CONFIG_FILES([Makefile src/Makefile]) +AC_OUTPUT diff --git a/experimental/facho-signer/src/Makefile.am b/experimental/facho-signer/src/Makefile.am new file mode 100644 index 0000000..36a6c79 --- /dev/null +++ b/experimental/facho-signer/src/Makefile.am @@ -0,0 +1,4 @@ +bin_PROGRAMS = facho_signer +facho_signer_SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c +facho_signer_CFLAGS = $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING +facho_signer_LDADD = $(XMLSEC1_LIBS) diff --git a/experimental/facho-signer/src/README.md b/experimental/facho-signer/src/README.md new file mode 100644 index 0000000..b566d7f --- /dev/null +++ b/experimental/facho-signer/src/README.md @@ -0,0 +1,11 @@ +# facho-signer + + +## guia + +- http://xmlsoft.org/html/libxml-tree.html +- http://xmlsoft.org/html/libxml-xpath.html +- http://xmlsoft.org/examples/xpath1.c +- http://xmlsoft.org/tutorial/ar01s05.html +- https://www.aleksey.com/xmlsec/api/xmlsec-reference.html +- https://zakird.com/2013/10/13/certificate-parsing-with-openssl diff --git a/experimental/facho-signer/facho-signer.c b/experimental/facho-signer/src/facho_signer.c similarity index 99% rename from experimental/facho-signer/facho-signer.c rename to experimental/facho-signer/src/facho_signer.c index 1275577..ce063bd 100644 --- a/experimental/facho-signer/facho-signer.c +++ b/experimental/facho-signer/src/facho_signer.c @@ -1,3 +1,4 @@ +#include "config.h" #include "xades/xades.h" #include diff --git a/experimental/facho-signer/politicafirmav2.c b/experimental/facho-signer/src/politicafirmav2.c similarity index 100% rename from experimental/facho-signer/politicafirmav2.c rename to experimental/facho-signer/src/politicafirmav2.c diff --git a/experimental/facho-signer/xades/minunit.h b/experimental/facho-signer/src/xades/minunit.h similarity index 100% rename from experimental/facho-signer/xades/minunit.h rename to experimental/facho-signer/src/xades/minunit.h diff --git a/experimental/facho-signer/xades/minunit_ext.h b/experimental/facho-signer/src/xades/minunit_ext.h similarity index 100% rename from experimental/facho-signer/xades/minunit_ext.h rename to experimental/facho-signer/src/xades/minunit_ext.h diff --git a/experimental/facho-signer/xades/templates.c b/experimental/facho-signer/src/xades/templates.c similarity index 100% rename from experimental/facho-signer/xades/templates.c rename to experimental/facho-signer/src/xades/templates.c diff --git a/experimental/facho-signer/xades/xades.c b/experimental/facho-signer/src/xades/xades.c similarity index 97% rename from experimental/facho-signer/xades/xades.c rename to experimental/facho-signer/src/xades/xades.c index 50030b2..8492a9f 100644 --- a/experimental/facho-signer/xades/xades.c +++ b/experimental/facho-signer/src/xades/xades.c @@ -1,3 +1,4 @@ +#include "config.h" #include "xades.h" #include @@ -9,6 +10,15 @@ #include #include +#include +#include +#include + +#ifndef XMLSEC_CRYPTO_DYNAMIC_LOADING +#include +#include +#endif + #include #include diff --git a/experimental/facho-signer/xades/xades.h b/experimental/facho-signer/src/xades/xades.h similarity index 99% rename from experimental/facho-signer/xades/xades.h rename to experimental/facho-signer/src/xades/xades.h index e8a1459..6dd361f 100644 --- a/experimental/facho-signer/xades/xades.h +++ b/experimental/facho-signer/src/xades/xades.h @@ -5,7 +5,6 @@ #include #include -#include #include #include #include diff --git a/experimental/facho-signer/xades/xades_test.c b/experimental/facho-signer/src/xades/xades_test.c similarity index 100% rename from experimental/facho-signer/xades/xades_test.c rename to experimental/facho-signer/src/xades/xades_test.c diff --git a/experimental/facho-signer/xades/xmlsec1/errors.c b/experimental/facho-signer/src/xades/xmlsec1/errors.c similarity index 100% rename from experimental/facho-signer/xades/xmlsec1/errors.c rename to experimental/facho-signer/src/xades/xmlsec1/errors.c diff --git a/experimental/facho-signer/xades/xmlsec1/errors_helpers.h b/experimental/facho-signer/src/xades/xmlsec1/errors_helpers.h similarity index 100% rename from experimental/facho-signer/xades/xmlsec1/errors_helpers.h rename to experimental/facho-signer/src/xades/xmlsec1/errors_helpers.h diff --git a/experimental/facho-signer/xades/xmlsec1/xmltree.c b/experimental/facho-signer/src/xades/xmlsec1/xmltree.c similarity index 100% rename from experimental/facho-signer/xades/xmlsec1/xmltree.c rename to experimental/facho-signer/src/xades/xmlsec1/xmltree.c diff --git a/experimental/facho-signer/src/xmlsec1/errors.c b/experimental/facho-signer/src/xmlsec1/errors.c new file mode 100644 index 0000000..46d487e --- /dev/null +++ b/experimental/facho-signer/src/xmlsec1/errors.c @@ -0,0 +1,259 @@ +/* + * XML Security Library (http://www.aleksey.com/xmlsec). + * + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2016 Aleksey Sanin . All Rights Reserved. + */ +/** + * SECTION:errors + * @Short_description: Error reporting and logging functions. + * @Stability: Stable + * + */ + +#define XMLSEC_PRIVATE 1 + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* Must be bigger than fatal_error */ +#define XMLSEC_ERRORS_BUFFER_SIZE 1024 + +/* Must fit into xmlChar[XMLSEC_ERRORS_BUFFER_SIZE] */ +static const xmlChar fatal_error[] = "Can not format error message"; + +typedef struct _xmlSecErrorDescription xmlSecErrorDescription, *xmlSecErrorDescriptionPtr; +struct _xmlSecErrorDescription { + int errorCode; + const char* errorMsg; +}; + +static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = { + { XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlsec library function failed" }, + { XMLSEC_ERRORS_R_MALLOC_FAILED, "malloc function failed" }, + { XMLSEC_ERRORS_R_STRDUP_FAILED, "strdup function failed" }, + { XMLSEC_ERRORS_R_CRYPTO_FAILED, "crypto library function failed" }, + { XMLSEC_ERRORS_R_XML_FAILED, "libxml2 library function failed" }, + { XMLSEC_ERRORS_R_XSLT_FAILED, "libxslt library function failed" }, + { XMLSEC_ERRORS_R_IO_FAILED, "io function failed" }, + { XMLSEC_ERRORS_R_DISABLED, "feature is disabled" }, + { XMLSEC_ERRORS_R_NOT_IMPLEMENTED, "feature is not implemented" }, + { XMLSEC_ERRORS_R_INVALID_CONFIG, "invalid configuration" }, + { XMLSEC_ERRORS_R_INVALID_SIZE, "invalid size" }, + { XMLSEC_ERRORS_R_INVALID_DATA, "invalid data" }, + { XMLSEC_ERRORS_R_INVALID_RESULT, "invalid result" }, + { XMLSEC_ERRORS_R_INVALID_TYPE, "invalid type" }, + { XMLSEC_ERRORS_R_INVALID_OPERATION, "invalid operation" }, + { XMLSEC_ERRORS_R_INVALID_STATUS, "invalid status" }, + { XMLSEC_ERRORS_R_INVALID_FORMAT, "invalid format" }, + { XMLSEC_ERRORS_R_DATA_NOT_MATCH, "data do not match" }, + { XMLSEC_ERRORS_R_INVALID_VERSION, "invalid version" }, + { XMLSEC_ERRORS_R_INVALID_NODE, "invalid node" }, + { XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "invalid node content" }, + { XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, "invalid node attribute" }, + { XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE, "missing node attribute" }, + { XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, "node already present" }, + { XMLSEC_ERRORS_R_UNEXPECTED_NODE, "unexpected node" }, + { XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node node found" }, + { XMLSEC_ERRORS_R_INVALID_TRANSFORM, "invalid transform" }, + { XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY, "invalid transform key" }, + { XMLSEC_ERRORS_R_INVALID_URI_TYPE, "invalid URI type" }, + { XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED, "same document is required for transform" }, + { XMLSEC_ERRORS_R_TRANSFORM_DISABLED, "transform is disabled" }, + { XMLSEC_ERRORS_R_INVALID_KEY_DATA, "invalid key data" }, + { XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND, "key data is not found" }, + { XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST, "key data already exist" }, + { XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, "invalid key data size" }, + { XMLSEC_ERRORS_R_KEY_NOT_FOUND, "key is not found" }, + { XMLSEC_ERRORS_R_KEYDATA_DISABLED, "key data is disabled" }, + { XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL, "maximum key retrieval level" }, + { XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" }, + { XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL, "maximum encrypted key level" }, + { XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "certificate verification failed" }, + { XMLSEC_ERRORS_R_CERT_NOT_FOUND, "certificate is not found" }, + { XMLSEC_ERRORS_R_CERT_REVOKED, "certificate is revoked" }, + { XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "certificate issuer check failed" }, + { XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "certificate is not yet valid" }, + { XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "certificate has expired" }, + { XMLSEC_ERRORS_R_DSIG_NO_REFERENCES, "Reference nodes are not found" }, + { XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE, "Reference verification failed" }, + { XMLSEC_ERRORS_R_ASSERTION, "assertion" }, + { 0, NULL} +}; + +static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback; +static int xmlSecPrintErrorMessages = 1; /* whether the error messages will be printed immediately */ + +/** + * xmlSecErrorsInit: + * + * Initializes the errors reporting. It is called from #xmlSecInit function. + * and applications must not call this function directly. + */ +void +xmlSecErrorsInit(void) { +} + +/** + * xmlSecErrorsShutdown: + * + * Cleanups the errors reporting. It is called from #xmlSecShutdown function. + * and applications must not call this function directly. + */ +void +xmlSecErrorsShutdown(void) { +} + +/** + * xmlSecErrorsSetCallback: + * @callback: the new errors callback function. + * + * Sets the errors callback function to @callback that will be called + * every time an error occurs. + */ +void +xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) { + xmlSecErrorsClbk = callback; +} + +/** + * xmlSecErrorsDefaultCallback: + * @file: the error location file name (__FILE__ macro). + * @line: the error location line number (__LINE__ macro). + * @func: the error location function name (__FUNCTION__ macro). + * @errorObject: the error specific error object + * @errorSubject: the error specific error subject. + * @reason: the error code. + * @msg: the additional error message. + * + * The default error reporting callback that utilizes LibXML + * error reporting #xmlGenericError function. + */ +void +xmlSecErrorsDefaultCallback(const char* file, int line, const char* func, + const char* errorObject, const char* errorSubject, + int reason, const char* msg) { + if(xmlSecPrintErrorMessages) { + const char* error_msg = NULL; + xmlSecSize i; + + for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) { + if(xmlSecErrorsGetCode(i) == reason) { + error_msg = xmlSecErrorsGetMsg(i); + break; + } + } + xmlGenericError(xmlGenericErrorContext, + "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n", + (func != NULL) ? func : "unknown", + (file != NULL) ? file : "unknown", + line, + (errorObject != NULL) ? errorObject : "unknown", + (errorSubject != NULL) ? errorSubject : "unknown", + reason, + (error_msg != NULL) ? error_msg : "", + (msg != NULL) ? msg : ""); + } +} + +/** + * xmlSecErrorsDefaultCallbackEnableOutput: + * @enabled: the flag. + * + * Enables or disables calling LibXML2 callback from the default + * errors callback. + */ +void +xmlSecErrorsDefaultCallbackEnableOutput(int enabled) { + xmlSecPrintErrorMessages = enabled; +} + +/** + * xmlSecErrorsGetCode: + * @pos: the error position. + * + * Gets the known error code at position @pos. + * + * Returns: the known error code or 0 if @pos is greater than + * total number of known error codes. + */ +int +xmlSecErrorsGetCode(xmlSecSize pos) { + /* could not use asserts here! */ + if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) { + return(xmlSecErrorsTable[pos].errorCode); + } + return(0); +} + +/** + * xmlSecErrorsGetMsg: + * @pos: the error position. + * + * Gets the known error message at position @pos. + * + * Returns: the known error message or NULL if @pos is greater than + * total number of known error codes. + */ +const char* +xmlSecErrorsGetMsg(xmlSecSize pos) { + /* could not use asserts here! */ + if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) { + return(xmlSecErrorsTable[pos].errorMsg); + } + return(NULL); +} + +/** + * xmlSecError: + * @file: the error location filename (__FILE__). + * @line: the error location line number (__LINE__). + * @func: the error location function (__FUNCTION__). + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @errorSubject: the error specific error subject (e.g. failed function name). + * @reason: the error code. + * @msg: the error message in printf format. + * @...: the parameters for the @msg. + * + * Reports an error to the default (#xmlSecErrorsDefaultCallback) or + * application specific callback installed using #xmlSecErrorsSetCallback + * function. + */ +void +xmlSecError(const char* file, int line, const char* func, + const char* errorObject, const char* errorSubject, + int reason, const char* msg, ...) { + if(xmlSecErrorsClbk != NULL) { + xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE]; + int ret; + + if(msg != NULL) { + va_list va; + + va_start(va, msg); + ret = xmlStrVPrintf(error_msg, sizeof(error_msg), msg, va); + if(ret < 0) { + /* Can't really report an error from an error callback */ + memcpy(error_msg, fatal_error, sizeof(fatal_error)); + } + error_msg[sizeof(error_msg) - 1] = '\0'; /* just in case */ + va_end(va); + } else { + error_msg[0] = '\0'; + } + xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg); + } +} diff --git a/experimental/facho-signer/src/xmlsec1/errors_helpers.h b/experimental/facho-signer/src/xmlsec1/errors_helpers.h new file mode 100644 index 0000000..1781e27 --- /dev/null +++ b/experimental/facho-signer/src/xmlsec1/errors_helpers.h @@ -0,0 +1,869 @@ +/* + * XML Security Library (http://www.aleksey.com/xmlsec). + * + * Internal header only used during the compilation, + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2016 Aleksey Sanin . All Rights Reserved. + */ + +#ifndef __XMLSEC_ERROR_HELPERS_H__ +#define __XMLSEC_ERROR_HELPERS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/********************************************************************** + * + * Error handling macros. + * + **********************************************************************/ + +/** + * xmlSecInternalError: + * @errorFunction: the failed function name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting internal XMLSec errors. + */ +#define xmlSecInternalError(errorFunction, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XMLSEC_FAILED, \ + XMLSEC_ERRORS_NO_MESSAGE \ + ) + +/** + * xmlSecInternalError2: + * @errorFunction: the failed function name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param: the extra message param. + * + * Macro. The XMLSec library macro for reporting internal XMLSec errors. + */ +#define xmlSecInternalError2(errorFunction, errorObject, msg, param) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XMLSEC_FAILED, \ + (msg), (param) \ + ) + +/** + * xmlSecInternalError3: + * @errorFunction: the failed function name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param1: the extra message param1. + * @param2: the extra message param2. + * + * Macro. The XMLSec library macro for reporting internal XMLSec errors. + */ +#define xmlSecInternalError3(errorFunction, errorObject, msg, param1, param2) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XMLSEC_FAILED, \ + (msg), (param1), (param2) \ + ) + +/** + * xmlSecInternalError4: + * @errorFunction: the failed function name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param1: the extra message param1. + * @param2: the extra message param2. + * @param3: the extra message param3. + * + * Macro. The XMLSec library macro for reporting internal XMLSec errors. + */ +#define xmlSecInternalError4(errorFunction, errorObject, msg, param1, param2, param3) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XMLSEC_FAILED, \ + (msg), (param1), (param2), (param3) \ + ) + +/** + * xmlSecMallocError: + * @allocSize: the failed allocation size. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting xmlMalloc() errors. + */ +#define xmlSecMallocError(allocSize, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + "xmlMalloc", \ + XMLSEC_ERRORS_R_MALLOC_FAILED, \ + "size=%lu", (unsigned long)(allocSize) \ + ) + +/** + * xmlSecStrdupError: + * @str: the failed string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting xmlStrdup() errors. + */ +#define xmlSecStrdupError(str, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + "xmlStrdup", \ + XMLSEC_ERRORS_R_STRDUP_FAILED, \ + "size=%lu", (unsigned long)xmlStrlen(str) \ + ) + +/** + * xmlSecXmlError: + * @errorFunction: the failed function. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting generic XML errors. + */ +#define xmlSecXmlError(errorFunction, errorObject) \ + { \ + xmlErrorPtr error = xmlGetLastError(); \ + int code = (error != NULL) ? error->code : 0; \ + const char* message = (error != NULL) ? error->message : NULL; \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XML_FAILED, \ + "xml error: %lu: %s", \ + (unsigned long)code, \ + xmlSecErrorsSafeString(message) \ + ); \ + } + +/** + * xmlSecXmlError2: + * @errorFunction: the failed function. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param: the extra message param. + * + * Macro. The XMLSec library macro for reporting generic XML errors. + */ +#define xmlSecXmlError2(errorFunction, errorObject, msg, param) \ + { \ + xmlErrorPtr error = xmlGetLastError(); \ + int code = (error != NULL) ? error->code : 0; \ + const char* message = (error != NULL) ? error->message : NULL; \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XML_FAILED, \ + msg "; xml error: %lu: %s", \ + (param), \ + (unsigned long)code, \ + xmlSecErrorsSafeString(message) \ + ); \ + } + +/** + * xmlSecXmlParserError: + * @errorFunction: the failed function. + * @ctxt: the parser context. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting XML parser errors. + */ +#define xmlSecXmlParserError(errorFunction, ctxt, errorObject) \ + { \ + xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\ + int code = (error != NULL) ? error->code : 0; \ + const char* message = (error != NULL) ? error->message : NULL; \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XML_FAILED, \ + "xml error: %lu: %s", \ + (unsigned long)code, \ + xmlSecErrorsSafeString(message) \ + ); \ + } + +/** + * xmlSecXmlParserError2: + * @errorFunction: the failed function. + * @ctxt: the parser context. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param: the extra message param. + * + * Macro. The XMLSec library macro for reporting XML parser errors. + */ +#define xmlSecXmlParserError2(errorFunction, ctxt, errorObject, msg, param) \ + { \ + xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\ + int code = (error != NULL) ? error->code : 0; \ + const char* message = (error != NULL) ? error->message : NULL; \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XML_FAILED, \ + msg "; xml error: %lu: %s", \ + (param), \ + (unsigned long)code, \ + xmlSecErrorsSafeString(message) \ + ); \ + } + +/** + * xmlSecXsltError: + * @errorFunction: the failed function. + * @ctxt: the parser context. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting XSLT errors. + */ +#define xmlSecXsltError(errorFunction, ctxt, errorObject) \ + { \ + xmlErrorPtr error = xmlGetLastError(); \ + int code = (error != NULL) ? error->code : 0; \ + const char* message = (error != NULL) ? error->message : NULL; \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_XSLT_FAILED, \ + "xslt error: %lu: %s", \ + (unsigned long)code, \ + xmlSecErrorsSafeString(message) \ + ); \ + } + +/** + * xmlSecIOError: + * @errorFunction: the failed function. + * @name: the filename, function name, uri, etc. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting IO errors. + */ +#define xmlSecIOError(errorFunction, name, errorObject) \ + { \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_IO_FAILED, \ + "name=\"%s\"; errno=%d", \ + xmlSecErrorsSafeString(name), \ + errno \ + ); \ + } + +/** + * xmlSecNotImplementedError: + * @details: the additional details. + * + * Macro. The XMLSec library macro for reporting "not implemented" errors. + */ +#define xmlSecNotImplementedError(details) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + NULL, \ + NULL, \ + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \ + "details=%s", \ + xmlSecErrorsSafeString(details) \ + ) +/** + * xmlSecInvalidSizeError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value. + * @expected: the expected value. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid size" errors when + * we expect exact match. + */ +#define xmlSecInvalidSizeError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_SIZE, \ + "invalid size for '%s': actual=%lu is not equal to expected=%lu", \ + xmlSecErrorsSafeString(name), \ + (unsigned long)(actual), \ + (unsigned long)(expected) \ + ) + +/** + * xmlSecInvalidSizeLessThanError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value. + * @expected: the expected value. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid size" errors when + * we expect at least the expected size. + */ +#define xmlSecInvalidSizeLessThanError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_SIZE, \ + "invalid size for '%s': actual=%lu is less than expected=%lu", \ + xmlSecErrorsSafeString(name), \ + (unsigned long)(actual), \ + (unsigned long)(expected) \ + ) + +/** + * xmlSecInvalidSizeMoreThanError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value. + * @expected: the expected value. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid size" errors when + * we expect at most the expected size. + */ +#define xmlSecInvalidSizeMoreThanError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \ + "invalid size for '%s': actual=%lu is more than expected=%lu", \ + xmlSecErrorsSafeString(name), \ + (unsigned long)(actual), \ + (unsigned long)(expected) \ + ) + +/** + * xmlSecInvalidSizeNotMultipleOfError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value. + * @divider: the expected divider. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid size" errors when + * we expect the size to be a multiple of the divider. + */ +#define xmlSecInvalidSizeNotMultipleOfError(name, actual, divider, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \ + "invalid size for '%s': actual=%lu is not a multiple of %lu", \ + xmlSecErrorsSafeString(name), \ + (unsigned long)(actual), \ + (unsigned long)(divider) \ + ) + +/** + * xmlSecInvalidSizeOtherError: + * @msg: the message about the error. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid size" errors when + * we expect exact match. + */ +#define xmlSecInvalidSizeOtherError(msg, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_SIZE, \ + "invalid size: %s", \ + xmlSecErrorsSafeString(msg) \ + ) + +/** + * xmlSecInvalidDataError: + * @msg: the msg with explanation. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid data" errors. + */ +#define xmlSecInvalidDataError(msg, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_DATA, \ + "%s", \ + xmlSecErrorsSafeString(msg) \ + ) + +/** + * xmlSecInvalidStringDataError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value as a string. + * @expected: the expected value(s) as a string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid data" errors for string. + */ +#define xmlSecInvalidStringDataError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_DATA, \ + "invalid data for '%s': actual='%s' and expected %s", \ + xmlSecErrorsSafeString(name), \ + xmlSecErrorsSafeString(actual), \ + (expected) \ + ) + +/** + * xmlSecInvalidIntegerDataError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value as an integer. + * @expected: the expected value(s) as a string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid data" errors for integers. + */ +#define xmlSecInvalidIntegerDataError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_DATA, \ + "invalid data for '%s': actual=%ld and expected %s", \ + xmlSecErrorsSafeString(name), \ + (unsigned long)(actual), \ + (expected) \ + ) + +/** + * xmlSecInvalidIntegerDataError2: + * @name1: the name of the first variable, parameter, etc. + * @actual1: the actual first value as an integer. + * @name2: the name of the second variable, parameter, etc. + * @actual2: the actual second value as an integer. + * @expected: the expected value(s) as a string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid data" errors for integers. + */ +#define xmlSecInvalidIntegerDataError2(name1, actual1, name2, actual2, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_DATA, \ + "invalid data: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \ + xmlSecErrorsSafeString(name1), \ + (unsigned long)(actual1), \ + xmlSecErrorsSafeString(name2), \ + (unsigned long)(actual2), \ + (expected) \ + ) + +/** + * xmlSecInvalidTypeError: + * @msg: the msg with explanation. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid type" errors. + */ +#define xmlSecInvalidTypeError(msg, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_TYPE, \ + "%s", \ + xmlSecErrorsSafeString(msg) \ + ) + +/** + * xmlSecInvalidStringTypeError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value as a string. + * @expected: the expected value(s) as a string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid type" errors for string. + */ +#define xmlSecInvalidStringTypeError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_TYPE, \ + "invalid type for '%s': actual='%s' and expected %s", \ + xmlSecErrorsSafeString(name), \ + xmlSecErrorsSafeString(actual), \ + (expected) \ + ) + +/** + * xmlSecInvalidIntegerTypeError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value as an integer. + * @expected: the expected value(s) as a string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid type" errors for integers. + */ +#define xmlSecInvalidIntegerTypeError(name, actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_TYPE, \ + "invalid type for '%s': actual=%ld and expected %s", \ + xmlSecErrorsSafeString(name), \ + (unsigned long)(actual), \ + (expected) \ + ) + +/** + * xmlSecInvalidIntegerTypeError2: + * @name1: the name of the first variable, parameter, etc. + * @actual1: the actual first value as an integer. + * @name2: the name of the second variable, parameter, etc. + * @actual2: the actual second value as an integer. + * @expected: the expected value(s) as a string. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid type" errors for integers. + */ +#define xmlSecInvalidIntegerTypeError2(name1, actual1, name2, actual2, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_TYPE, \ + "invalid type: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \ + xmlSecErrorsSafeString(name1), \ + (unsigned long)(actual1), \ + xmlSecErrorsSafeString(name2), \ + (unsigned long)(actual2), \ + (expected) \ + ) + +/** + * xmlSecInvalidNodeError: + * @actualNode: the actual node. + * @expectedNodeName: the expected node name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting an invalid node errors. + */ +#define xmlSecInvalidNodeError(actualNode, expectedNodeName, errorObject) \ + { \ + const char* actualNodeName = xmlSecNodeGetName(actualNode); \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_NODE, \ + "actual=%s; expected=%s", \ + xmlSecErrorsSafeString(actualNodeName), \ + xmlSecErrorsSafeString(expectedNodeName) \ + ); \ + } + +/** + * xmlSecInvalidNodeContentError: + * @node: the node. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @reason: the reason why node content is invalid. + * + * Macro. The XMLSec library macro for reporting an invalid node content errors. + */ +#define xmlSecInvalidNodeContentError(node, errorObject, reason) \ + { \ + const char* nName = xmlSecNodeGetName(node); \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, \ + "node=%s; reason=%s", \ + xmlSecErrorsSafeString(nName), \ + xmlSecErrorsSafeString(reason) \ + ); \ + } + +/** + * xmlSecInvalidNodeAttributeError: + * @node: the node. + * @attrName: the attribute name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @reason: the reason why node content is invalid. + * + * Macro. The XMLSec library macro for reporting an invalid node attribute errors. + */ +#define xmlSecInvalidNodeAttributeError(node, attrName, errorObject, reason) \ + { \ + const char* nName = xmlSecNodeGetName(node); \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, \ + "node=%s; attribute=%s; reason=%s",\ + xmlSecErrorsSafeString(nName), \ + xmlSecErrorsSafeString(attrName), \ + xmlSecErrorsSafeString(reason) \ + ); \ + } + +/** + * xmlSecNodeAlreadyPresentError: + * @parent: the parent node. + * @nodeName: the node name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting node already present errors. + */ +#define xmlSecNodeAlreadyPresentError(parent, nodeName, errorObject) \ + { \ + const char* pName = xmlSecNodeGetName(parent);\ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, \ + "parent=%s; node=%s", \ + xmlSecErrorsSafeString(pName), \ + xmlSecErrorsSafeString(nodeName) \ + ); \ + } + +/** + * xmlSecUnexpectedNodeError: + * @node: the node. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting an invalid node errors. + */ +#define xmlSecUnexpectedNodeError(node, errorObject) \ + { \ + const char* nName = xmlSecNodeGetName(node); \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_UNEXPECTED_NODE, \ + "node=%s", \ + xmlSecErrorsSafeString(nName) \ + ); \ + } + +/** + * xmlSecNodeNotFoundError: + * @errorFunction: the failed function. + * @startNode: the search start node. + * @targetNodeName: the expected child node name. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting node not found errors. + */ +#define xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \ + { \ + const char* startNodeName = xmlSecNodeGetName(startNode); \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + (errorFunction), \ + XMLSEC_ERRORS_R_NODE_NOT_FOUND, \ + "startNode=%s; target=%s", \ + xmlSecErrorsSafeString(startNodeName), \ + xmlSecErrorsSafeString(targetNodeName) \ + ); \ + } + +/** + * xmlSecInvalidTransfromError: + * @transform: the transform. + * + * Macro. The XMLSec library macro for reporting an invalid transform errors. + */ +#define xmlSecInvalidTransfromError(transform) \ + { \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)xmlSecTransformGetName(transform), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_TRANSFORM, \ + XMLSEC_ERRORS_NO_MESSAGE \ + ); \ + } + +/** + * xmlSecInvalidTransfromError2: + * @transform: the transform. + * @msg: the extra message. + * @param: the extra message param. + * + * + * Macro. The XMLSec library macro for reporting an invalid transform errors. + */ +#define xmlSecInvalidTransfromError2(transform, msg, param) \ + { \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)xmlSecTransformGetName(transform), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_TRANSFORM, \ + (msg), (param) \ + ); \ + } + +/** + * xmlSecInvalidTransfromStatusError: + * @transform: the transform. + * + * Macro. The XMLSec library macro for reporting an invalid transform status errors. + */ +#define xmlSecInvalidTransfromStatusError(transform) \ + { \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)xmlSecTransformGetName(transform), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_STATUS, \ + "transformStatus=%d", \ + (int)((transform)->status) \ + ); \ + } + +/** + * xmlSecInvalidTransfromStatusError2: + * @transform: the transform. + * @msg: the extra message. + * + * Macro. The XMLSec library macro for reporting an invalid transform status errors. + */ +#define xmlSecInvalidTransfromStatusError2(transform, msg) \ + { \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)xmlSecTransformGetName(transform), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_STATUS, \ + "transformStatus=%ld, msg=%s", \ + (long int)((transform)->status), \ + msg \ + ); \ + } + +/** + * xmlSecInvalidKeyDataSizeError: + * @name: the name of the variable, parameter, etc. + * @actual: the actual value. + * @expected: the expected value(s). + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid keydata size" errors. + */ +#define xmlSecInvalidKeyDataSizeError(actual, expected, errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, \ + "invalid key data size: actual=%ld and expected=%ld", \ + (unsigned long)(actual), \ + (unsigned long)(expected) \ + ) + +/** + * xmlSecInvalidZeroKeyDataSizeError: + * @name: the name of the variable, parameter, etc. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * + * Macro. The XMLSec library macro for reporting "invalid keydata size" errors. + */ +#define xmlSecInvalidZeroKeyDataSizeError(errorObject) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, \ + "invalid zero key data size" \ + ) + + +/** + * xmlSecOtherError: + * @code: the error code. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @details: the error message. + * + * Macro. The XMLSec library macro for reporting other XMLSec errors. + */ +#define xmlSecOtherError(code, errorObject, details) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + (code), \ + "details=%s", \ + xmlSecErrorsSafeString(details) \ + ) + +/** + * xmlSecOtherError2: + * @code: the error code. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param: the extra message param. + * + * Macro. The XMLSec library macro for reporting other XMLSec errors. + */ +#define xmlSecOtherError2(code, errorObject, msg, param) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + (code), \ + (msg), (param) \ + ) + +/** + * xmlSecOtherError3: + * @code: the error code. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param1: the extra message param. + * @param2: the extra message param. + * + * Macro. The XMLSec library macro for reporting other XMLSec errors. + */ +#define xmlSecOtherError3(code, errorObject, msg, param1, param2) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + (code), \ + (msg), (param1), (param2) \ + ) + +/** + * xmlSecOtherError4: + * @code: the error code. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param1: the extra message param. + * @param2: the extra message param. + * @param3: the extra message param. + * + * Macro. The XMLSec library macro for reporting other XMLSec errors. + */ +#define xmlSecOtherError4(code, errorObject, msg, param1, param2, param3) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + (code), \ + (msg), (param1), (param2), (param3) \ + ) + +/** + * xmlSecOtherError5: + * @code: the error code. + * @errorObject: the error specific error object (e.g. transform, key data, etc). + * @msg: the extra message. + * @param1: the extra message param. + * @param2: the extra message param. + * @param3: the extra message param. + * @param4: the extra message param. + * + * Macro. The XMLSec library macro for reporting other XMLSec errors. + */ +#define xmlSecOtherError5(code, errorObject, msg, param1, param2, param3, param4) \ + xmlSecError(XMLSEC_ERRORS_HERE, \ + (const char*)(errorObject), \ + NULL, \ + (code), \ + (msg), (param1), (param2), (param3), (param4) \ + ) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __XMLSEC_ERROR_HELPERS_H__ */ diff --git a/experimental/facho-signer/src/xmlsec1/xmltree.c b/experimental/facho-signer/src/xmlsec1/xmltree.c new file mode 100644 index 0000000..3056bb5 --- /dev/null +++ b/experimental/facho-signer/src/xmlsec1/xmltree.c @@ -0,0 +1,1950 @@ +/* + * XML Security Library (http://www.aleksey.com/xmlsec). + * + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2016 Aleksey Sanin . All Rights Reserved. + */ +/** + * SECTION:xmltree + * @Short_description: XML tree functions. + * @Stability: Stable + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "errors_helpers.h" + +static const xmlChar* g_xmlsec_xmltree_default_linefeed = xmlSecStringCR; + +/** + * xmlSecGetDefaultLineFeed: + * + * Gets the current default linefeed. + * + * Returns: the current default linefeed. + */ +const xmlChar* +xmlSecGetDefaultLineFeed(void) +{ + return g_xmlsec_xmltree_default_linefeed; +} + +/** + * xmlSecSetDefaultLineFeed: + * @linefeed: default linefeed. + * + * Sets the current default linefeed. The caller must ensure that the linefeed + * string exists for the lifetime of the program or until the new linefeed is set. + */ +void +xmlSecSetDefaultLineFeed(const xmlChar *linefeed) +{ + g_xmlsec_xmltree_default_linefeed = linefeed; +} + +/** + * xmlSecFindSibling: + * @cur: the pointer to XML node. + * @name: the name. + * @ns: the namespace href (may be NULL). + * + * Searches @cur and the next siblings of the @cur node having given name and + * namespace href. + * + * Returns: the pointer to the found node or NULL if an error occurs or + * node is not found. + */ +xmlNodePtr +xmlSecFindSibling(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) { + xmlNodePtr tmp; + xmlSecAssert2(name != NULL, NULL); + + for(tmp = cur; tmp != NULL; tmp = tmp->next) { + if(tmp->type == XML_ELEMENT_NODE) { + if(xmlSecCheckNodeName(tmp, name, ns)) { + return(tmp); + } + } + } + return(NULL); +} + +/** + * xmlSecFindChild: + * @parent: the pointer to XML node. + * @name: the name. + * @ns: the namespace href (may be NULL). + * + * Searches a direct child of the @parent node having given name and + * namespace href. + * + * Returns: the pointer to the found node or NULL if an error occurs or + * node is not found. + */ +xmlNodePtr +xmlSecFindChild(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) { + xmlSecAssert2(parent != NULL, NULL); + xmlSecAssert2(name != NULL, NULL); + + return(xmlSecFindSibling(parent->children, name, ns)); +} + +/** + * xmlSecFindParent: + * @cur: the pointer to an XML node. + * @name: the name. + * @ns: the namespace href (may be NULL). + * + * Searches the ancestors axis of the @cur node for a node having given name + * and namespace href. + * + * Returns: the pointer to the found node or NULL if an error occurs or + * node is not found. + */ +xmlNodePtr +xmlSecFindParent(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) { + xmlSecAssert2(cur != NULL, NULL); + xmlSecAssert2(name != NULL, NULL); + + if(xmlSecCheckNodeName(cur, name, ns)) { + return(cur); + } else if(cur->parent != NULL) { + return(xmlSecFindParent(cur->parent, name, ns)); + } + return(NULL); +} + +/** + * xmlSecFindNode: + * @parent: the pointer to XML node. + * @name: the name. + * @ns: the namespace href (may be NULL). + * + * Searches all children of the @parent node having given name and + * namespace href. + * + * Returns: the pointer to the found node or NULL if an error occurs or + * node is not found. + */ +xmlNodePtr +xmlSecFindNode(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) { + xmlNodePtr cur; + xmlNodePtr ret; + + xmlSecAssert2(name != NULL, NULL); + + cur = parent; + while(cur != NULL) { + if((cur->type == XML_ELEMENT_NODE) && xmlSecCheckNodeName(cur, name, ns)) { + return(cur); + } + if(cur->children != NULL) { + ret = xmlSecFindNode(cur->children, name, ns); + if(ret != NULL) { + return(ret); + } + } + cur = cur->next; + } + return(NULL); +} + +/** + * xmlSecGetNodeNsHref: + * @cur: the pointer to node. + * + * Get's node's namespace href. + * + * Returns: node's namespace href. + */ +const xmlChar* +xmlSecGetNodeNsHref(const xmlNodePtr cur) { + xmlNsPtr ns; + + xmlSecAssert2(cur != NULL, NULL); + + /* do we have a namespace in the node? */ + if(cur->ns != NULL) { + return(cur->ns->href); + } + + /* search for default namespace */ + ns = xmlSearchNs(cur->doc, cur, NULL); + if(ns != NULL) { + return(ns->href); + } + + return(NULL); +} + +/** + * xmlSecCheckNodeName: + * @cur: the pointer to an XML node. + * @name: the name, + * @ns: the namespace href. + * + * Checks that the node has a given name and a given namespace href. + * + * Returns: 1 if the node matches or 0 otherwise. + */ +int +xmlSecCheckNodeName(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) { + xmlSecAssert2(cur != NULL, 0); + + return(xmlStrEqual(cur->name, name) && + xmlStrEqual(xmlSecGetNodeNsHref(cur), ns)); +} + +/** + * xmlSecAddChild: + * @parent: the pointer to an XML node. + * @name: the new node name. + * @ns: the new node namespace. + * + * Adds a child to the node @parent with given @name and namespace @ns. + * + * Returns: pointer to the new node or NULL if an error occurs. + */ +xmlNodePtr +xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) { + xmlNodePtr cur; + xmlNodePtr text; + + xmlSecAssert2(parent != NULL, NULL); + xmlSecAssert2(name != NULL, NULL); + + if(parent->children == NULL) { + /* TODO: add indents */ + text = xmlNewText(xmlSecGetDefaultLineFeed()); + if(text == NULL) { + xmlSecXmlError("xmlNewText", NULL); + return(NULL); + } + xmlAddChild(parent, text); + } + + cur = xmlNewChild(parent, NULL, name, NULL); + if(cur == NULL) { + xmlSecXmlError("xmlNewChild", NULL); + return(NULL); + } + + /* namespaces support */ + if(ns != NULL) { + xmlNsPtr nsPtr; + + /* find namespace by href and check that its prefix is not overwritten */ + nsPtr = xmlSearchNsByHref(cur->doc, cur, ns); + if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) { + nsPtr = xmlNewNs(cur, ns, NULL); + if(nsPtr == NULL) { + xmlSecXmlError("xmlNewNs", NULL); + return(NULL); + } + } + xmlSetNs(cur, nsPtr); + } + + /* TODO: add indents */ + text = xmlNewText(xmlSecGetDefaultLineFeed()); + if(text == NULL) { + xmlSecXmlError("xmlNewText", NULL); + return(NULL); + } + xmlAddChild(parent, text); + + return(cur); +} + +/** + * xmlSecAddChildNode: + * @parent: the pointer to an XML node. + * @child: the new node. + * + * Adds @child node to the @parent node. + * + * Returns: pointer to the new node or NULL if an error occurs. + */ +xmlNodePtr +xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) { + xmlNodePtr text; + + xmlSecAssert2(parent != NULL, NULL); + xmlSecAssert2(child != NULL, NULL); + + if(parent->children == NULL) { + /* TODO: add indents */ + text = xmlNewText(xmlSecGetDefaultLineFeed()); + if(text == NULL) { + xmlSecXmlError("xmlNewText", NULL); + return(NULL); + } + xmlAddChild(parent, text); + } + + xmlAddChild(parent, child); + + /* TODO: add indents */ + text = xmlNewText(xmlSecGetDefaultLineFeed()); + if(text == NULL) { + xmlSecXmlError("xmlNewText", NULL); + return(NULL); + } + xmlAddChild(parent, text); + + return(child); +} + +/** + * xmlSecEnsureEmptyChild: + * @parent: the pointer to XML node. + * @name: the name. + * @ns: the namespace href (may be NULL). + * + * Searches a direct child of the @parent node having given name and + * namespace href. If not found then element node with given name / namespace + * is added. + * + * Returns: the pointer to the found or created node; or NULL if an error occurs. + */ +xmlNodePtr +xmlSecEnsureEmptyChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) { + xmlNodePtr cur = NULL; + xmlNodePtr tmp; + + xmlSecAssert2(parent != NULL, NULL); + xmlSecAssert2(name != NULL, NULL); + + /* try to find an empty node first */ + tmp = xmlSecFindNode(parent, name, ns); + while(tmp != NULL) { + cur = tmp; + if(xmlSecIsEmptyNode(cur) == 1) { + return(cur); + } + tmp = xmlSecFindSibling(cur->next, name, ns); + } + + /* if not found then either add next or add at the end */ + if(cur == NULL) { + cur = xmlSecAddChild(parent, name, ns); + } else if((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE)) { + cur = xmlSecAddNextSibling(cur->next, name, ns); + } else { + cur = xmlSecAddNextSibling(cur, name, ns); + } + if(cur == NULL) { + xmlSecInternalError2("xmlSecAddChild or xmlSecAddNextSibling", NULL, + "node=%s", xmlSecErrorsSafeString(name)); + return(NULL); + } + return(cur); +} + +/** + * xmlSecAddNextSibling + * @node: the pointer to an XML node. + * @name: the new node name. + * @ns: the new node namespace. + * + * Adds next sibling to the node @node with given @name and namespace @ns. + * + * Returns: pointer to the new node or NULL if an error occurs. + */ +xmlNodePtr +xmlSecAddNextSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) { + xmlNodePtr cur; + xmlNodePtr text; + + xmlSecAssert2(node != NULL, NULL); + xmlSecAssert2(name != NULL, NULL); + + cur = xmlNewNode(NULL, name); + if(cur == NULL) { + xmlSecXmlError("xmlNewNode", NULL); + return(NULL); + } + xmlAddNextSibling(node, cur); + + /* namespaces support */ + if(ns != NULL) { + xmlNsPtr nsPtr; + + /* find namespace by href and check that its prefix is not overwritten */ + nsPtr = xmlSearchNsByHref(cur->doc, cur, ns); + if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) { + nsPtr = xmlNewNs(cur, ns, NULL); + } + xmlSetNs(cur, nsPtr); + } + + /* TODO: add indents */ + text = xmlNewText(xmlSecGetDefaultLineFeed()); + if(text == NULL) { + xmlSecXmlError("xmlNewText", NULL); + return(NULL); + } + xmlAddNextSibling(node, text); + + return(cur); +} + +/** + * xmlSecAddPrevSibling + * @node: the pointer to an XML node. + * @name: the new node name. + * @ns: the new node namespace. + * + * Adds prev sibling to the node @node with given @name and namespace @ns. + * + * Returns: pointer to the new node or NULL if an error occurs. + */ +xmlNodePtr +xmlSecAddPrevSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) { + xmlNodePtr cur; + xmlNodePtr text; + + xmlSecAssert2(node != NULL, NULL); + xmlSecAssert2(name != NULL, NULL); + + cur = xmlNewNode(NULL, name); + if(cur == NULL) { + xmlSecXmlError("xmlNewNode", NULL); + return(NULL); + } + xmlAddPrevSibling(node, cur); + + /* namespaces support */ + if(ns != NULL) { + xmlNsPtr nsPtr; + + /* find namespace by href and check that its prefix is not overwritten */ + nsPtr = xmlSearchNsByHref(cur->doc, cur, ns); + if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) { + nsPtr = xmlNewNs(cur, ns, NULL); + } + xmlSetNs(cur, nsPtr); + } + + /* TODO: add indents */ + text = xmlNewText(xmlSecGetDefaultLineFeed()); + if(text == NULL) { + xmlSecXmlError("xmlNewText", NULL); + return(NULL); + } + xmlAddPrevSibling(node, text); + + return(cur); +} + +/** + * xmlSecGetNextElementNode: + * @cur: the pointer to an XML node. + * + * Seraches for the next element node. + * + * Returns: the pointer to next element node or NULL if it is not found. + */ +xmlNodePtr +xmlSecGetNextElementNode(xmlNodePtr cur) { + + while((cur != NULL) && (cur->type != XML_ELEMENT_NODE)) { + cur = cur->next; + } + return(cur); +} + +/** + * xmlSecReplaceNode: + * @node: the current node. + * @newNode: the new node. + * + * Swaps the @node and @newNode in the XML tree. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode) { + return xmlSecReplaceNodeAndReturn(node, newNode, NULL); +} + +/** + * xmlSecReplaceNodeAndReturn: + * @node: the current node. + * @newNode: the new node. + * @replaced: the replaced node, or release it if NULL is given + * + * Swaps the @node and @newNode in the XML tree. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecReplaceNodeAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr* replaced) { + xmlNodePtr oldNode; + int restoreRoot = 0; + + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(newNode != NULL, -1); + + /* fix documents children if necessary first */ + if((node->doc != NULL) && (node->doc->children == node)) { + node->doc->children = node->next; + restoreRoot = 1; + } + if((newNode->doc != NULL) && (newNode->doc->children == newNode)) { + newNode->doc->children = newNode->next; + } + + oldNode = xmlReplaceNode(node, newNode); + if(oldNode == NULL) { + xmlSecXmlError("xmlReplaceNode", NULL); + return(-1); + } + + if(restoreRoot != 0) { + xmlDocSetRootElement(oldNode->doc, newNode); + } + + /* return the old node if requested */ + if(replaced != NULL) { + (*replaced) = oldNode; + } else { + xmlFreeNode(oldNode); + } + + return(0); +} + +/** + * xmlSecReplaceContent + * @node: the current node. + * @newNode: the new node. + * + * Swaps the content of @node and @newNode. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode) { + return xmlSecReplaceContentAndReturn(node, newNode, NULL); +} + +/** + * xmlSecReplaceContentAndReturn + * @node: the current node. + * @newNode: the new node. + * @replaced: the replaced nodes, or release them if NULL is given + * + * Swaps the content of @node and @newNode. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecReplaceContentAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr *replaced) { + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(newNode != NULL, -1); + + /* return the old nodes if requested */ + if(replaced != NULL) { + xmlNodePtr cur, next, tail; + + (*replaced) = tail = NULL; + for(cur = node->children; (cur != NULL); cur = next) { + next = cur->next; + if((*replaced) != NULL) { + /* cur is unlinked in this function */ + xmlAddNextSibling(tail, cur); + tail = cur; + } else { + /* this is the first node, (*replaced) is the head */ + xmlUnlinkNode(cur); + (*replaced) = tail = cur; + } + } + } else { + /* just delete the content */ + xmlNodeSetContent(node, NULL); + } + + /* swap nodes */ + xmlUnlinkNode(newNode); + xmlAddChildList(node, newNode); + + return(0); +} + +/** + * xmlSecReplaceNodeBuffer: + * @node: the current node. + * @buffer: the XML data. + * @size: the XML data size. + * + * Swaps the @node and the parsed XML data from the @buffer in the XML tree. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecReplaceNodeBuffer(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size) { + return xmlSecReplaceNodeBufferAndReturn(node, buffer, size, NULL); +} + +/** + * xmlSecReplaceNodeBufferAndReturn: + * @node: the current node. + * @buffer: the XML data. + * @size: the XML data size. + * @replaced: the replaced nodes, or release them if NULL is given + * + * Swaps the @node and the parsed XML data from the @buffer in the XML tree. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecReplaceNodeBufferAndReturn(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size, xmlNodePtr *replaced) { + xmlNodePtr results = NULL; + xmlNodePtr next = NULL; + int ret; + + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(node->parent != NULL, -1); + + /* parse buffer in the context of node's parent (also see xmlSecParsePrepareCtxt): + * XML_PARSE_NONET to support c14n + * XML_PARSE_NODICT to avoid problems with moving nodes around + * XML_PARSE_HUGE to enable parsing of XML documents with large text nodes + */ + ret = xmlParseInNodeContext(node->parent, (const char*)buffer, size, + XML_PARSE_NONET | XML_PARSE_NODICT | XML_PARSE_HUGE, &results); + if(ret != XML_ERR_OK) { + xmlSecXmlError("xmlParseInNodeContext", NULL); + return(-1); + } + + /* add new nodes */ + while (results != NULL) { + next = results->next; + xmlAddPrevSibling(node, results); + results = next; + } + + /* remove old node */ + xmlUnlinkNode(node); + + /* return the old node if requested */ + if(replaced != NULL) { + (*replaced) = node; + } else { + xmlFreeNode(node); + } + + return(0); +} + +/** + * xmlSecNodeEncodeAndSetContent: + * @node: the pointer to an XML node. + * @buffer: the pointer to the node content. + * + * Encodes "special" characters in the @buffer and sets the result + * as the node content. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecNodeEncodeAndSetContent(xmlNodePtr node, const xmlChar * buffer) { + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(node->doc != NULL, -1); + + if(buffer != NULL) { + xmlChar * tmp; + tmp = xmlEncodeSpecialChars(node->doc, buffer); + if (tmp == NULL) { + xmlSecXmlError("xmlEncodeSpecialChars", NULL); + return(-1); + } + xmlNodeSetContent(node, tmp); + xmlFree(tmp); + } else { + xmlNodeSetContent(node, NULL); + } + return(0); +} + +/** + * xmlSecAddIDs: + * @doc: the pointer to an XML document. + * @cur: the pointer to an XML node. + * @ids: the pointer to a NULL terminated list of ID attributes. + * + * Walks thru all children of the @cur node and adds all attributes + * from the @ids list to the @doc document IDs attributes hash. + */ +void +xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr cur, const xmlChar** ids) { + xmlNodePtr children = NULL; + + xmlSecAssert(doc != NULL); + xmlSecAssert(ids != NULL); + + if((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) { + xmlAttrPtr attr; + xmlAttrPtr tmp; + int i; + xmlChar* name; + + for(attr = cur->properties; attr != NULL; attr = attr->next) { + for(i = 0; ids[i] != NULL; ++i) { + if(xmlStrEqual(attr->name, ids[i])) { + name = xmlNodeListGetString(doc, attr->children, 1); + if(name != NULL) { + tmp = xmlGetID(doc, name); + if(tmp == NULL) { + xmlAddID(NULL, doc, name, attr); + } else if(tmp != attr) { + xmlSecInvalidStringDataError("id", name, "unique id (id already defined)", NULL); + } + xmlFree(name); + } + } + } + } + + children = cur->children; + } else if(cur == NULL) { + children = doc->children; + } + + while(children != NULL) { + if(children->type == XML_ELEMENT_NODE) { + xmlSecAddIDs(doc, children, ids); + } + children = children->next; + } +} + +/** + * xmlSecCreateTree: + * @rootNodeName: the root node name. + * @rootNodeNs: the root node namespace (optional). + * + * Creates a new XML tree with one root node @rootNodeName. + * + * Returns: pointer to the newly created tree or NULL if an error occurs. + */ +xmlDocPtr +xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) { + xmlDocPtr doc; + xmlNodePtr root; + xmlNsPtr ns; + + xmlSecAssert2(rootNodeName != NULL, NULL); + + /* create doc */ + doc = xmlNewDoc(BAD_CAST "1.0"); + if(doc == NULL) { + xmlSecXmlError("xmlNewDoc", NULL); + return(NULL); + } + + /* create root node */ + root = xmlNewDocNode(doc, NULL, rootNodeName, NULL); + if(root == NULL) { + xmlSecXmlError2("xmlNewDocNode", NULL, + "node=%s", rootNodeName); + xmlFreeDoc(doc); + return(NULL); + } + xmlDocSetRootElement(doc, root); + + /* and set root node namespace */ + ns = xmlNewNs(root, rootNodeNs, NULL); + if(ns == NULL) { + xmlSecXmlError2("xmlNewNs", NULL, + "ns=%s", xmlSecErrorsSafeString(rootNodeNs)); + xmlFreeDoc(doc); + return(NULL); + } + xmlSetNs(root, ns); + + return(doc); +} + +/** + * xmlSecIsEmptyNode: + * @node: the node to check + * + * Checks whether the @node is empty (i.e. has only whitespaces children). + * + * Returns: 1 if @node is empty, 0 otherwise or a negative value if an error occurs. + */ +int +xmlSecIsEmptyNode(xmlNodePtr node) { + xmlChar* content; + int res; + + xmlSecAssert2(node != NULL, -1); + + if(xmlSecGetNextElementNode(node->children) != NULL) { + return(0); + } + + content = xmlNodeGetContent(node); + if(content == NULL) { + return(1); + } + + res = xmlSecIsEmptyString(content); + xmlFree(content); + return(res); +} + +/** + * xmlSecIsEmptyString: + * @str: the string to check + * + * Checks whether the @str is empty (i.e. has only whitespaces children). + * + * Returns: 1 if @str is empty, 0 otherwise or a negative value if an error occurs. + */ +int +xmlSecIsEmptyString(const xmlChar* str) { + xmlSecAssert2(str != NULL, -1); + + for( ;*str != '\0'; ++str) { + if(!isspace((int)(*str))) { + return(0); + } + } + return(1); +} + +/** + * xmlSecPrintXmlString: + * @fd: the file descriptor to write the XML string to + * @str: the string + * + * Encodes the @str (e.g. replaces '&' with '&') and writes it to @fd. + * + * Returns: he number of bytes transmitted or a negative value if an error occurs. + */ +int +xmlSecPrintXmlString(FILE * fd, const xmlChar * str) { + int res; + + if(str != NULL) { + xmlChar * encoded_str = NULL; + encoded_str = xmlEncodeSpecialChars(NULL, str); + if(encoded_str == NULL) { + xmlSecXmlError2("xmlEncodeSpecialChars", NULL, + "string=%s", xmlSecErrorsSafeString(str)); + return(-1); + } + + res = fprintf(fd, "%s", (const char*)encoded_str); + xmlFree(encoded_str); + } else { + res = fprintf(fd, "NULL"); + } + + if(res < 0) { + xmlSecIOError("fprintf", NULL, NULL); + return(-1); + } + return(res); +} + +/** + * xmlSecGetQName: + * @node: the context node. + * @href: the QName href (can be NULL). + * @local: the QName local part. + * + * Creates QName (prefix:local) from @href and @local in the context of the @node. + * Caller is responsible for freeing returned string with xmlFree. + * + * Returns: qname or NULL if an error occurs. + */ +xmlChar* +xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) { + xmlChar* qname; + xmlNsPtr ns; + int ret; + + xmlSecAssert2(node != NULL, NULL); + xmlSecAssert2(local != NULL, NULL); + + /* we don't want to create namespace node ourselves because + * it might cause collisions */ + ns = xmlSearchNsByHref(node->doc, node, href); + if((ns == NULL) && (href != NULL)) { + xmlSecXmlError2("xmlSearchNsByHref", NULL, + "node=%s", xmlSecErrorsSafeString(node->name)); + return(NULL); + } + + if((ns != NULL) && (ns->prefix != NULL)) { + xmlSecSize len; + + len = xmlStrlen(local) + xmlStrlen(ns->prefix) + 4; + qname = (xmlChar *)xmlMalloc(len); + if(qname == NULL) { + xmlSecMallocError(len, NULL); + return(NULL); + } + + ret = xmlStrPrintf(qname, len, "%s:%s", ns->prefix, local); + if(ret < 0) { + xmlSecXmlError("xmlStrPrintf", NULL); + xmlFree(qname); + return(NULL); + } + } else { + qname = xmlStrdup(local); + if(qname == NULL) { + xmlSecStrdupError(local, NULL); + return(NULL); + } + } + + + return(qname); +} + + +/************************************************************************* + * + * QName <-> Integer mapping + * + ************************************************************************/ +/** + * xmlSecQName2IntegerGetInfo: + * @info: the qname<->integer mapping information. + * @intValue: the integer value. + * + * Maps integer @intValue to a QName prefix. + * + * Returns: the QName info that is mapped to @intValue or NULL if such value + * is not found. + */ +xmlSecQName2IntegerInfoConstPtr +xmlSecQName2IntegerGetInfo(xmlSecQName2IntegerInfoConstPtr info, int intValue) { + unsigned int ii; + + xmlSecAssert2(info != NULL, NULL); + + for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) { + if(info[ii].intValue == intValue) { + return(&info[ii]); + } + } + + return(NULL); +} + +/** + * xmlSecQName2IntegerGetInteger: + * @info: the qname<->integer mapping information. + * @qnameHref: the qname href value. + * @qnameLocalPart: the qname local part value. + * @intValue: the pointer to result integer value. + * + * Maps qname qname to an integer and returns it in @intValue. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2IntegerGetInteger(xmlSecQName2IntegerInfoConstPtr info, + const xmlChar* qnameHref, const xmlChar* qnameLocalPart, + int* intValue) { + unsigned int ii; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(qnameLocalPart != NULL, -1); + xmlSecAssert2(intValue != NULL, -1); + + for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) { + if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) && + xmlStrEqual(info[ii].qnameHref, qnameHref)) { + (*intValue) = info[ii].intValue; + return(0); + } + } + + return(-1); +} + +/** + * xmlSecQName2IntegerGetIntegerFromString: + * @info: the qname<->integer mapping information. + * @node: the pointer to node. + * @qname: the qname string. + * @intValue: the pointer to result integer value. + * + * Converts @qname into integer in context of @node. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info, + xmlNodePtr node, const xmlChar* qname, + int* intValue) { + const xmlChar* qnameLocalPart = NULL; + xmlChar* qnamePrefix = NULL; + const xmlChar* qnameHref; + xmlNsPtr ns; + int ret; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(qname != NULL, -1); + xmlSecAssert2(intValue != NULL, -1); + + qnameLocalPart = xmlStrchr(qname, ':'); + if(qnameLocalPart != NULL) { + qnamePrefix = xmlStrndup(qname, (int)(qnameLocalPart - qname)); + if(qnamePrefix == NULL) { + xmlSecStrdupError(qname, NULL); + return(-1); + } + qnameLocalPart++; + } else { + qnamePrefix = NULL; + qnameLocalPart = qname; + } + + /* search namespace href */ + ns = xmlSearchNs(node->doc, node, qnamePrefix); + if((ns == NULL) && (qnamePrefix != NULL)) { + xmlSecXmlError2("xmlSearchNs", NULL, + "node=%s", xmlSecErrorsSafeString(node->name)); + if(qnamePrefix != NULL) { + xmlFree(qnamePrefix); + } + return(-1); + } + qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL; + + /* and finally search for integer */ + ret = xmlSecQName2IntegerGetInteger(info, qnameHref, qnameLocalPart, intValue); + if(ret < 0) { + xmlSecInternalError4("xmlSecQName2IntegerGetInteger", NULL, + "node=%s,qnameLocalPart=%s,qnameHref=%s", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(qnameLocalPart), + xmlSecErrorsSafeString(qnameHref)); + if(qnamePrefix != NULL) { + xmlFree(qnamePrefix); + } + return(-1); + } + + if(qnamePrefix != NULL) { + xmlFree(qnamePrefix); + } + return(0); +} + + +/** + * xmlSecQName2IntegerGetStringFromInteger: + * @info: the qname<->integer mapping information. + * @node: the pointer to node. + * @intValue: the integer value. + * + * Creates qname string for @intValue in context of given @node. Caller + * is responsible for freeing returned string with @xmlFree. + * + * Returns: pointer to newly allocated string on success or NULL if an error occurs, + */ +xmlChar* +xmlSecQName2IntegerGetStringFromInteger(xmlSecQName2IntegerInfoConstPtr info, + xmlNodePtr node, int intValue) { + xmlSecQName2IntegerInfoConstPtr qnameInfo; + + xmlSecAssert2(info != NULL, NULL); + xmlSecAssert2(node != NULL, NULL); + + qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue); + if(qnameInfo == NULL) { + xmlSecInternalError3("xmlSecQName2IntegerGetInfo", NULL, + "node=%s,intValue=%d", + xmlSecErrorsSafeString(node->name), + intValue); + return(NULL); + } + + return (xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart)); +} + +/** + * xmlSecQName2IntegerNodeRead: + * @info: the qname<->integer mapping information. + * @node: the pointer to node. + * @intValue: the pointer to result integer value. + * + * Reads the content of @node and converts it to an integer using mapping + * from @info. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2IntegerNodeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, int* intValue) { + xmlChar* content = NULL; + int ret; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(intValue != NULL, -1); + + content = xmlNodeGetContent(node); + if(content == NULL) { + xmlSecXmlError2("xmlNodeGetContent", NULL, + "node=%s", xmlSecErrorsSafeString(node->name)); + return(-1); + } + /* todo: trim content? */ + + ret = xmlSecQName2IntegerGetIntegerFromString(info, node, content, intValue); + if(ret < 0) { + xmlSecInternalError3("xmlSecQName2IntegerGetIntegerFromString", NULL, + "node=%s,value=%s", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(content)); + xmlFree(content); + return(-1); + } + + xmlFree(content); + return(0); +} + +/** + * xmlSecQName2IntegerNodeWrite: + * @info: the qname<->integer mapping information. + * @node: the parent node. + * @nodeName: the child node name. + * @nodeNs: the child node namespace. + * @intValue: the integer value. + * + * Creates new child node in @node and sets its value to @intValue. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2IntegerNodeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, + const xmlChar* nodeName, const xmlChar* nodeNs, int intValue) { + xmlNodePtr cur; + xmlChar* qname = NULL; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(nodeName != NULL, -1); + + /* find and build qname */ + qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue); + if(qname == NULL) { + xmlSecInternalError3("xmlSecQName2IntegerGetStringFromInteger", NULL, + "node=%s,intValue=%d", + xmlSecErrorsSafeString(node->name), + intValue); + return(-1); + } + + cur = xmlSecAddChild(node, nodeName, nodeNs); + if(cur == NULL) { + xmlSecInternalError3("xmlSecAddChild", NULL, + "node=%s,intValue=%d", + xmlSecErrorsSafeString(nodeName), + intValue); + xmlFree(qname); + return(-1); + } + + xmlNodeSetContent(cur, qname); + xmlFree(qname); + return(0); +} + +/** + * xmlSecQName2IntegerAttributeRead: + * @info: the qname<->integer mapping information. + * @node: the element node. + * @attrName: the attribute name. + * @intValue: the pointer to result integer value. + * + * Gets the value of @attrName atrtibute from @node and converts it to integer + * according to @info. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2IntegerAttributeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, + const xmlChar* attrName, int* intValue) { + xmlChar* attrValue; + int ret; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(attrName != NULL, -1); + xmlSecAssert2(intValue != NULL, -1); + + attrValue = xmlGetProp(node, attrName); + if(attrValue == NULL) { + xmlSecXmlError2("xmlGetProp", NULL, + "node=%s", xmlSecErrorsSafeString(node->name)); + return(-1); + } + /* todo: trim value? */ + + ret = xmlSecQName2IntegerGetIntegerFromString(info, node, attrValue, intValue); + if(ret < 0) { + xmlSecInternalError4("xmlSecQName2IntegerGetIntegerFromString", NULL, + "node=%s,attrName=%s,attrValue=%s", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(attrName), + xmlSecErrorsSafeString(attrValue)); + xmlFree(attrValue); + return(-1); + } + + xmlFree(attrValue); + return(0); +} + +/** + * xmlSecQName2IntegerAttributeWrite: + * @info: the qname<->integer mapping information. + * @node: the parent node. + * @attrName: the name of attribute. + * @intValue: the integer value. + * + * Converts @intValue to a qname and sets it to the value of + * attribute @attrName in @node. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2IntegerAttributeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, + const xmlChar* attrName, int intValue) { + xmlChar* qname; + xmlAttrPtr attr; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(attrName != NULL, -1); + + /* find and build qname */ + qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue); + if(qname == NULL) { + xmlSecInternalError4("xmlSecQName2IntegerGetStringFromInteger", NULL, + "node=%s,attrName=%s,intValue=%d", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(attrName), + intValue); + return(-1); + } + + attr = xmlSetProp(node, attrName, qname); + if(attr == NULL) { + xmlSecInternalError4("xmlSetProp", NULL, + "node=%s,attrName=%s,intValue=%d", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(attrName), + intValue); + xmlFree(qname); + return(-1); + } + + xmlFree(qname); + return(0); +} + +/** + * xmlSecQName2IntegerDebugDump: + * @info: the qname<->integer mapping information. + * @intValue: the integer value. + * @name: the value name to print. + * @output: the pointer to output FILE. + * + * Prints @intValue into @output. + */ +void +xmlSecQName2IntegerDebugDump(xmlSecQName2IntegerInfoConstPtr info, int intValue, + const xmlChar* name, FILE* output) { + xmlSecQName2IntegerInfoConstPtr qnameInfo; + + xmlSecAssert(info != NULL); + xmlSecAssert(name != NULL); + xmlSecAssert(output != NULL); + + qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue); + if(qnameInfo != NULL) { + fprintf(output, "== %s: %d (name=\"%s\", href=\"%s\")\n", name, intValue, + (qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL, + (qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL); + } +} + +/** + * xmlSecQName2IntegerDebugXmlDump: + * @info: the qname<->integer mapping information. + * @intValue: the integer value. + * @name: the value name to print. + * @output: the pointer to output FILE. + * + * Prints @intValue into @output in XML format. + */ +void +xmlSecQName2IntegerDebugXmlDump(xmlSecQName2IntegerInfoConstPtr info, int intValue, + const xmlChar* name, FILE* output) { + xmlSecQName2IntegerInfoConstPtr qnameInfo; + + xmlSecAssert(info != NULL); + xmlSecAssert(name != NULL); + xmlSecAssert(output != NULL); + + qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue); + if(qnameInfo != NULL) { + fprintf(output, "<%s value=\"%d\" href=\"%s\">%s<%s>\n", name, intValue, + (qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL, + (qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL, + name); + } +} + + +/************************************************************************* + * + * QName <-> Bits mask mapping + * + ************************************************************************/ +/** + * xmlSecQName2BitMaskGetInfo: + * @info: the qname<->bit mask mapping information. + * @mask: the bit mask. + * + * Converts @mask to qname. + * + * Returns: pointer to the qname info for @mask or NULL if mask is unknown. + */ +xmlSecQName2BitMaskInfoConstPtr +xmlSecQName2BitMaskGetInfo(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask) { + unsigned int ii; + + xmlSecAssert2(info != NULL, NULL); + + for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) { + xmlSecAssert2(info[ii].mask != 0, NULL); + if(info[ii].mask == mask) { + return(&info[ii]); + } + } + + return(NULL); +} + +/** + * xmlSecQName2BitMaskGetBitMask: + * @info: the qname<->bit mask mapping information. + * @qnameHref: the qname Href value. + * @qnameLocalPart: the qname LocalPart value. + * @mask: the pointer to result mask. + * + * Converts @qnameLocalPart to @mask. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2BitMaskGetBitMask(xmlSecQName2BitMaskInfoConstPtr info, + const xmlChar* qnameHref, const xmlChar* qnameLocalPart, + xmlSecBitMask* mask) { + unsigned int ii; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(qnameLocalPart != NULL, -1); + xmlSecAssert2(mask != NULL, -1); + + for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) { + xmlSecAssert2(info[ii].mask != 0, -1); + if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) && + xmlStrEqual(info[ii].qnameHref, qnameHref)) { + + (*mask) = info[ii].mask; + return(0); + } + } + + return(-1); +} + +/** + * xmlSecQName2BitMaskGetBitMaskFromString: + * @info: the qname<->integer mapping information. + * @node: the pointer to node. + * @qname: the qname string. + * @mask: the pointer to result msk value. + * + * Converts @qname into integer in context of @node. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info, + xmlNodePtr node, const xmlChar* qname, + xmlSecBitMask* mask) { + const xmlChar* qnameLocalPart = NULL; + xmlChar* qnamePrefix = NULL; + const xmlChar* qnameHref; + xmlNsPtr ns; + int ret; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(qname != NULL, -1); + xmlSecAssert2(mask != NULL, -1); + + qnameLocalPart = xmlStrchr(qname, ':'); + if(qnameLocalPart != NULL) { + qnamePrefix = xmlStrndup(qname, (int)(qnameLocalPart - qname)); + if(qnamePrefix == NULL) { + xmlSecStrdupError(qname, NULL); + return(-1); + } + qnameLocalPart++; + } else { + qnamePrefix = NULL; + qnameLocalPart = qname; + } + + /* search namespace href */ + ns = xmlSearchNs(node->doc, node, qnamePrefix); + if((ns == NULL) && (qnamePrefix != NULL)) { + xmlSecXmlError2("xmlSearchNs", NULL, + "node=%s", xmlSecErrorsSafeString(node->name)); + if(qnamePrefix != NULL) { + xmlFree(qnamePrefix); + } + return(-1); + } + qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL; + + /* and finally search for integer */ + ret = xmlSecQName2BitMaskGetBitMask(info, qnameHref, qnameLocalPart, mask); + if(ret < 0) { + xmlSecInternalError4("xmlSecQName2BitMaskGetBitMask", NULL, + "node=%s,qnameLocalPart=%s,qnameHref=%s", + xmlSecErrorsSafeString(node->name), + xmlSecErrorsSafeString(qnameLocalPart), + xmlSecErrorsSafeString(qnameHref)); + if(qnamePrefix != NULL) { + xmlFree(qnamePrefix); + } + return(-1); + } + + if(qnamePrefix != NULL) { + xmlFree(qnamePrefix); + } + return(0); +} + + +/** + * xmlSecQName2BitMaskGetStringFromBitMask: + * @info: the qname<->integer mapping information. + * @node: the pointer to node. + * @mask: the mask. + * + * Creates qname string for @mask in context of given @node. Caller + * is responsible for freeing returned string with @xmlFree. + * + * Returns: pointer to newly allocated string on success or NULL if an error occurs, + */ +xmlChar* +xmlSecQName2BitMaskGetStringFromBitMask(xmlSecQName2BitMaskInfoConstPtr info, + xmlNodePtr node, xmlSecBitMask mask) { + xmlSecQName2BitMaskInfoConstPtr qnameInfo; + + xmlSecAssert2(info != NULL, NULL); + xmlSecAssert2(node != NULL, NULL); + + qnameInfo = xmlSecQName2BitMaskGetInfo(info, mask); + if(qnameInfo == NULL) { + xmlSecInternalError3("xmlSecQName2BitMaskGetInfo", NULL, + "node=%s,mask=%d", + xmlSecErrorsSafeString(node->name), + mask); + return(NULL); + } + + return(xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart)); +} + +/** + * xmlSecQName2BitMaskNodesRead: + * @info: the qname<->bit mask mapping information. + * @node: the start. + * @nodeName: the mask nodes name. + * @nodeNs: the mask nodes namespace. + * @stopOnUnknown: if this flag is set then function exits if unknown + * value was found. + * @mask: the pointer to result mask. + * + * Reads <@nodeNs:@nodeName> elements and puts the result bit mask + * into @mask. When function exits, @node points to the first element node + * after all the <@nodeNs:@nodeName> elements. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2BitMaskNodesRead(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr* node, + const xmlChar* nodeName, const xmlChar* nodeNs, + int stopOnUnknown, xmlSecBitMask* mask) { + xmlNodePtr cur; + xmlChar* content; + xmlSecBitMask tmp; + int ret; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(mask != NULL, -1); + + (*mask) = 0; + cur = (*node); + while((cur != NULL) && (xmlSecCheckNodeName(cur, nodeName, nodeNs))) { + content = xmlNodeGetContent(cur); + if(content == NULL) { + xmlSecXmlError2("xmlNodeGetContent", NULL, + "node=%s", xmlSecErrorsSafeString(cur->name)); + return(-1); + } + + ret = xmlSecQName2BitMaskGetBitMaskFromString(info, cur, content, &tmp); + if(ret < 0) { + xmlSecInternalError2("xmlSecQName2BitMaskGetBitMaskFromString", NULL, + "value=%s", xmlSecErrorsSafeString(content)); + xmlFree(content); + return(-1); + } + xmlFree(content); + + if((stopOnUnknown != 0) && (tmp == 0)) { + /* todo: better error */ + xmlSecInternalError2("xmlSecQName2BitMaskGetBitMaskFromString", NULL, + "value=%s", xmlSecErrorsSafeString(content)); + return(-1); + } + + (*mask) |= tmp; + cur = xmlSecGetNextElementNode(cur->next); + } + + (*node) = cur; + return(0); +} + +/** + * xmlSecQName2BitMaskNodesWrite: + * @info: the qname<->bit mask mapping information. + * @node: the parent element for mask nodes. + * @nodeName: the mask nodes name. + * @nodeNs: the mask nodes namespace. + * @mask: the bit mask. + * + * Writes <@nodeNs:@nodeName> elemnts with values from @mask to @node. + * + * Returns: 0 on success or a negative value if an error occurs, + */ +int +xmlSecQName2BitMaskNodesWrite(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr node, + const xmlChar* nodeName, const xmlChar* nodeNs, + xmlSecBitMask mask) { + unsigned int ii; + + xmlSecAssert2(info != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(nodeName != NULL, -1); + + for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) { + xmlSecAssert2(info[ii].mask != 0, -1); + + if((mask & info[ii].mask) != 0) { + xmlNodePtr cur; + xmlChar* qname; + + qname = xmlSecGetQName(node, info[ii].qnameHref, info[ii].qnameLocalPart); + if(qname == NULL) { + xmlSecXmlError2("xmlSecGetQName", NULL, + "node=%s", xmlSecErrorsSafeString(nodeName)); + return(-1); + } + + cur = xmlSecAddChild(node, nodeName, nodeNs); + if(cur == NULL) { + xmlSecXmlError2("xmlSecAddChild", NULL, + "node=%s", xmlSecErrorsSafeString(nodeName)); + xmlFree(qname); + return(-1); + } + + xmlNodeSetContent(cur, qname); + xmlFree(qname); + } + } + return(0); +} + +/** + * xmlSecQName2BitMaskDebugDump: + * @info: the qname<->bit mask mapping information. + * @mask: the bit mask. + * @name: the value name to print. + * @output: the pointer to output FILE. + * + * Prints debug information about @mask to @output. + */ +void +xmlSecQName2BitMaskDebugDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask, + const xmlChar* name, FILE* output) { + unsigned int ii; + + xmlSecAssert(info != NULL); + xmlSecAssert(name != NULL); + xmlSecAssert(output != NULL); + + if(mask == 0) { + return; + } + + fprintf(output, "== %s (0x%08x): ", name, mask); + for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) { + xmlSecAssert(info[ii].mask != 0); + + if((mask & info[ii].mask) != 0) { + fprintf(output, "name=\"%s\" (href=\"%s\"),", info[ii].qnameLocalPart, info[ii].qnameHref); + } + } + fprintf(output, "\n"); +} + +/** + * xmlSecQName2BitMaskDebugXmlDump: + * @info: the qname<->bit mask mapping information. + * @mask: the bit mask. + * @name: the value name to print. + * @output: the pointer to output FILE. + * + * Prints debug information about @mask to @output in XML format. + */ +void +xmlSecQName2BitMaskDebugXmlDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask, + const xmlChar* name, FILE* output) { + unsigned int ii; + + xmlSecAssert(info != NULL); + xmlSecAssert(name != NULL); + xmlSecAssert(output != NULL); + + if(mask == 0) { + return; + } + + fprintf(output, "<%sList>\n", name); + for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) { + xmlSecAssert(info[ii].mask != 0); + + if((mask & info[ii].mask) != 0) { + fprintf(output, "<%s href=\"%s\">%s\n", name, + info[ii].qnameHref, info[ii].qnameLocalPart, name); + } + } + fprintf(output, "\n", name); +} + +/************************************************************************* + * + * Windows string conversions + * + ************************************************************************/ +#ifdef WIN32 + +/** + * xmlSecWin32ConvertUtf8ToUnicode: + * @str: the string to convert. + * + * Converts input string from UTF8 to Unicode. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +LPWSTR +xmlSecWin32ConvertUtf8ToUnicode(const xmlChar* str) { + LPWSTR res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + /* call MultiByteToWideChar first to get the buffer size */ + ret = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, NULL, 0); + if(ret <= 0) { + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len); + if(res == NULL) { + xmlSecMallocError(sizeof(WCHAR) * len, NULL); + return(NULL); + } + + /* convert */ + ret = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, res, len); + if(ret <= 0) { + xmlFree(res); + return(NULL); + } + + /* done */ + return(res); +} + +/** + * xmlSecWin32ConvertUnicodeToUtf8: + * @str: the string to convert. + * + * Converts input string from Unicode to UTF8. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +xmlChar* +xmlSecWin32ConvertUnicodeToUtf8(LPCWSTR str) { + xmlChar * res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + /* call WideCharToMultiByte first to get the buffer size */ + ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); + if(ret <= 0) { + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len); + if(res == NULL) { + xmlSecMallocError(sizeof(xmlChar) * len, NULL); + return(NULL); + } + + /* convert */ + ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, (LPSTR)res, len, NULL, NULL); + if(ret <= 0) { + xmlFree(res); + return(NULL); + } + + /* done */ + return(res); +} + +/** + * xmlSecWin32ConvertLocaleToUnicode: + * @str: the string to convert. + * + * Converts input string from current system locale to Unicode. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +LPWSTR +xmlSecWin32ConvertLocaleToUnicode(const char* str) { + LPWSTR res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + /* call MultiByteToWideChar first to get the buffer size */ + ret = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + if(ret <= 0) { + return(NULL); + } + len = ret; + + /* allocate buffer */ + res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len); + if(res == NULL) { + xmlSecMallocError(sizeof(WCHAR) * len, NULL); + return(NULL); + } + + /* convert */ + ret = MultiByteToWideChar(CP_ACP, 0, str, -1, res, len); + if(ret <= 0) { + xmlFree(res); + return(NULL); + } + + /* done */ + return(res); +} + +/** + * xmlSecWin32ConvertLocaleToUtf8: + * @str: the string to convert. + * + * Converts input string from locale to UTF8. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +xmlChar* +xmlSecWin32ConvertLocaleToUtf8(const char * str) { + LPWSTR strW = NULL; + xmlChar * res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + strW = xmlSecWin32ConvertLocaleToUnicode(str); + if(strW == NULL) { + return(NULL); + } + + /* call WideCharToMultiByte first to get the buffer size */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len); + if(res == NULL) { + xmlSecMallocError(sizeof(xmlChar) * len, NULL); + xmlFree(strW); + return(NULL); + } + + /* convert */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, (LPSTR)res, len, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + xmlFree(res); + return(NULL); + } + + /* done */ + xmlFree(strW); + return(res); +} + +/** + * xmlSecWin32ConvertUtf8ToLocale: + * @str: the string to convert. + * + * Converts input string from UTF8 to locale. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +char * +xmlSecWin32ConvertUtf8ToLocale(const xmlChar* str) { + LPWSTR strW = NULL; + char * res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + strW = xmlSecWin32ConvertUtf8ToUnicode(str); + if(strW == NULL) { + return(NULL); + } + + /* call WideCharToMultiByte first to get the buffer size */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (char*)xmlMalloc(sizeof(char) * len); + if(res == NULL) { + xmlSecMallocError(sizeof(char) * len, NULL); + xmlFree(strW); + return(NULL); + } + + /* convert */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, res, len, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + xmlFree(res); + return(NULL); + } + + /* done */ + xmlFree(strW); + return(res); +} + +/** + * xmlSecWin32ConvertTstrToUtf8: + * @str: the string to convert. + * + * Converts input string from TSTR (locale or Unicode) to UTF8. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +xmlChar* +xmlSecWin32ConvertTstrToUtf8(LPCTSTR str) { +#ifdef UNICODE + return xmlSecWin32ConvertUnicodeToUtf8(str); +#else /* UNICODE */ + return xmlSecWin32ConvertLocaleToUtf8(str); +#endif /* UNICODE */ +} + +/** + * xmlSecWin32ConvertUtf8ToTstr: + * @str: the string to convert. + * + * Converts input string from UTF8 to TSTR (locale or Unicode). + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +LPTSTR +xmlSecWin32ConvertUtf8ToTstr(const xmlChar* str) { +#ifdef UNICODE + return xmlSecWin32ConvertUtf8ToUnicode(str); +#else /* UNICODE */ + return xmlSecWin32ConvertUtf8ToLocale(str); +#endif /* UNICODE */ +} + +#endif /* WIN32 */ + + + diff --git a/experimental/facho-signer/src/xmlusigned.xml b/experimental/facho-signer/src/xmlusigned.xml new file mode 100644 index 0000000..23ead39 --- /dev/null +++ b/experimental/facho-signer/src/xmlusigned.xml @@ -0,0 +1,200 @@ + + + + + + + 2bd9a18f23cf1188d36888d218e9b0c31df77aa00bc036eaeaa1619184054237eee56d2d8db4ecab0173f65f8dab7753 + + 800197268 + + + 900579212 + 01ab9caa-6838-461e-82fb-da44da36a084 + + + CO + + + fc8eac422eba16e22ffd8c6f94b3f40a6e38162c + + 2019-01-19 + 2030-01-19 + + + SETP + 990000000 + 995000000 + + + + + + + UBL 2.1 + 10 + DIAN 2.1 + 2 + SETP990000001 + 50578625ce1fb2f6bb2bc57b22180d2763c8a868c4e62da72e0e43001f9c7f3459c81e2bf9324830175b1225af37e435 + COP + 2020-09-05 + 22:38:53-05:00 + 01 + 1 + + 2020-09-05 + 2020-09-05 + + + 1 + + + NEUROTEC TECNOLOGIA S.A.S + + + + + + + + + + 900579212 + NEUROTEC TECNOLOGIA S.A.S + + + + + + + CO + COLOMBIA + + + + + NEUROTEC TECNOLOGIA S.A.S + 900579212 + O-07;O-09;O-14;O-48 + + + + sdds@sd.com + + + + + 2 + + + facho-customer + + + + + + + + + + 43851425 + facho-customer + ZZ + + + + facho-customer + + + + + + + CO + COLOMBIA + + + + + + + 100.00 + 100.00 + 119.00 + 19.00 + 119.00 + + + + + + + 01 + + + + 19.00 + + + + + + 04 + + + + 0.00 + + + + + + 03 + + + + 0.00 + + + 1 + 1 + 100.0 + + 19.0 + + 100.0 + 19.0 + + 19.0 + + 01 + IVA + + + + + + + 100.0 + 01 + x + + + + test + + 9999 + + + + 100.0 + + + + 1 + 10 + 2020-09-05 + 1 + + diff --git a/experimental/facho-signer/xades/Makefile b/experimental/facho-signer/xades/Makefile deleted file mode 100644 index d017580..0000000 --- a/experimental/facho-signer/xades/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -.PHONY: test - -CC=gcc - -test: xmlsec1/errors.c xmlsec1/xmltree.c templates.c xades_test.c - $(CC) -o $@ -Wall -Werror -std=gnu11 $(shell pkg-config libxml-2.0 --cflags --libs) $(shell pkg-config xmlsec1 --cflags --libs) $^ - ./test