xmlsecurityengine/xmlsec/src/xmlsec_transforms.c
changeset 0 e35f40988205
child 16 d10d750052f0
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * The Transforms Element (http://www.w3.org/TR/xmldsig-core/#sec-Transforms)
       
     5  * 
       
     6  * The optional Transforms element contains an ordered list of Transform 
       
     7  * elements; these describe how the signer obtained the data object that 
       
     8  * was digested.
       
     9  *
       
    10  * Schema Definition:
       
    11  * 
       
    12  *  <element name="Transforms" type="ds:TransformsType"/>
       
    13  *  <complexType name="TransformsType">
       
    14  *    <sequence>
       
    15  *      <element ref="ds:Transform" maxOccurs="unbounded"/> 
       
    16  *    </sequence>
       
    17  *   </complexType>
       
    18  *
       
    19  *  <element name="Transform" type="ds:TransformType"/>
       
    20  *  <complexType name="TransformType" mixed="true">
       
    21  *    <choice minOccurs="0" maxOccurs="unbounded"> 
       
    22  *      <any namespace="##other" processContents="lax"/>
       
    23  *      <!-- (1,1) elements from (0,unbounded) namespaces -->
       
    24  *      <element name="XPath" type="string"/> 
       
    25  *    </choice>
       
    26  *    <attribute name="Algorithm" type="anyURI" use="required"/> 
       
    27  *  </complexType>
       
    28  *    
       
    29  * DTD:
       
    30  *    
       
    31  *  <!ELEMENT Transforms (Transform+)>
       
    32  *  <!ELEMENT Transform (#PCDATA|XPath %Transform.ANY;)* >
       
    33  *  <!ATTLIST Transform Algorithm    CDATA    #REQUIRED >
       
    34  *  <!ELEMENT XPath (#PCDATA) >
       
    35  * 
       
    36  * This is free software; see Copyright file in the source
       
    37  * distribution for preciese wording.
       
    38  * 
       
    39  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    40  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    41  */
       
    42 
       
    43 #include "xmlsec_globals.h"
       
    44 
       
    45 #include <stdlib.h>
       
    46 #include <stdio.h>
       
    47 #include <string.h>
       
    48 
       
    49 #include <libxml2_tree.h>
       
    50 #include <libxml2_xpath.h>
       
    51 #include <libxml2_xpointer.h>
       
    52 #include <libxml2_globals.h>
       
    53 
       
    54 #include "xmlsec_xmlsec.h"
       
    55 #include "xmlsec_buffer.h"
       
    56 #include "xmlsec_xmltree.h"
       
    57 #include "xmlsec_keysdata.h"
       
    58 #include "xmlsec_keys.h"
       
    59 #include "xmlsec_keyinfo.h"
       
    60 #include "xmlsec_transforms.h"
       
    61 #include "xmlsec_base64.h"
       
    62 #include "xmlsec_io.h"
       
    63 #include "xmlsec_membuf.h"
       
    64 #include "xmlsec_parser.h"
       
    65 #include "xmlsec_errors.h"
       
    66 
       
    67 /**************************************************************************
       
    68  *
       
    69  * Global xmlSecTransformIds list functions
       
    70  *
       
    71  *************************************************************************/
       
    72 static xmlSecPtrList xmlSecAllTransformIds;
       
    73 
       
    74 
       
    75 /** 
       
    76  * xmlSecTransformIdsGet:
       
    77  *
       
    78  * Gets global registered transform klasses list.
       
    79  * 
       
    80  * Returns the pointer to list of all registered transform klasses.
       
    81  */
       
    82 EXPORT_C
       
    83 xmlSecPtrListPtr
       
    84 xmlSecTransformIdsGet(void) {
       
    85     return(&xmlSecAllTransformIds);
       
    86 }
       
    87 
       
    88 /** 
       
    89  * xmlSecTransformIdsInit:
       
    90  *
       
    91  * Initializes the transform klasses. This function is called from the 
       
    92  * #xmlSecInit function and the application should not call it directly.
       
    93  *
       
    94  * Returns 0 on success or a negative value if an error occurs.
       
    95  */
       
    96 EXPORT_C
       
    97 int 
       
    98 xmlSecTransformIdsInit(void) {
       
    99     int ret;       
       
   100     
       
   101     ret = xmlSecPtrListInitialize(xmlSecTransformIdsGet(), xmlSecTransformIdListId);
       
   102     if(ret < 0) {
       
   103 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   104 		    NULL,
       
   105 		    "xmlSecPtrListPtrInitialize",
       
   106 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   107 		    "xmlSecTransformIdListId");
       
   108         return(-1);
       
   109     }
       
   110     
       
   111     ret = xmlSecTransformIdsRegisterDefault();
       
   112     if(ret < 0) {
       
   113 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   114 		    NULL,
       
   115 		    "xmlSecTransformIdsRegisterDefault",
       
   116 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   117 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   118         return(-1);
       
   119     }
       
   120     
       
   121     return(0);
       
   122 }
       
   123 
       
   124 /**
       
   125  * xmlSecTransformIdsShutdown:
       
   126  * 
       
   127  * Shuts down the keys data klasses. This function is called from the 
       
   128  * #xmlSecShutdown function and the application should not call it directly.
       
   129  */
       
   130 EXPORT_C
       
   131 void
       
   132 xmlSecTransformIdsShutdown(void) {
       
   133     xmlSecPtrListFinalize(xmlSecTransformIdsGet());
       
   134 }
       
   135 
       
   136 /** 
       
   137  * xmlSecTransformIdsRegister:
       
   138  * @id:			the transform klass.
       
   139  *
       
   140  * Registers @id in the global list of transform klasses.
       
   141  *
       
   142  * Returns 0 on success or a negative value if an error occurs.
       
   143  */
       
   144 EXPORT_C
       
   145 int 
       
   146 xmlSecTransformIdsRegister(xmlSecTransformId id) {
       
   147     int ret;
       
   148         
       
   149     xmlSecAssert2(id != xmlSecTransformIdUnknown, -1);
       
   150     
       
   151     ret = xmlSecPtrListAdd(xmlSecTransformIdsGet(), (xmlSecPtr)id);
       
   152     if(ret < 0) {
       
   153 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   154 		    NULL,
       
   155 		    "xmlSecPtrListAdd",
       
   156 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   157 		    "transform=%s",
       
   158 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
       
   159         return(-1);
       
   160     }
       
   161     
       
   162     return(0);    
       
   163 }
       
   164 
       
   165 /**
       
   166  * xmlSecTransformIdsRegisterDefault:
       
   167  *
       
   168  * Registers default (implemented by XML Security Library)
       
   169  * transform klasses: XPath transform, Base64 transform, ...
       
   170  *
       
   171  * Returns 0 on success or a negative value if an error occurs.
       
   172  */
       
   173 EXPORT_C
       
   174 int 
       
   175 xmlSecTransformIdsRegisterDefault(void) {
       
   176     if(xmlSecTransformIdsRegister(xmlSecTransformBase64Id) < 0) {
       
   177 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   178 		    NULL,
       
   179 		    "xmlSecTransformIdsRegister",	    
       
   180 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   181 		    "name=%s",
       
   182 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformBase64Id)));
       
   183 	return(-1);
       
   184     }
       
   185 
       
   186     if(xmlSecTransformIdsRegister(xmlSecTransformEnvelopedId) < 0) {
       
   187 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   188 		    NULL,
       
   189 		    "xmlSecTransformIdsRegister",	    
       
   190 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   191 		    "name=%s",
       
   192 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformEnvelopedId)));
       
   193 	return(-1);
       
   194     }
       
   195 
       
   196     /* c14n methods */
       
   197     if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NId) < 0) {
       
   198 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   199 		    NULL,
       
   200 		    "xmlSecTransformIdsRegister",	    
       
   201 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   202 		    "name=%s",
       
   203 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId)));
       
   204 	return(-1);
       
   205     }
       
   206     if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NWithCommentsId) < 0) {
       
   207 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   208 		    NULL,
       
   209 		    "xmlSecTransformIdsRegister",	    
       
   210 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   211 		    "name=%s",
       
   212 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NWithCommentsId)));
       
   213 	return(-1);
       
   214     }
       
   215     if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NId) < 0) {
       
   216 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   217 		    NULL,
       
   218 		    "xmlSecTransformIdsRegister",	    
       
   219 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   220 		    "name=%s",
       
   221 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NId)));
       
   222 	return(-1);
       
   223     }
       
   224     if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NWithCommentsId) < 0) {
       
   225 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   226 		    NULL,
       
   227 		    "xmlSecTransformIdsRegister",	    
       
   228 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   229 		    "name=%s",
       
   230 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NWithCommentsId)));
       
   231 	return(-1);
       
   232     }
       
   233 
       
   234     if(xmlSecTransformIdsRegister(xmlSecTransformXPathId) < 0) {
       
   235 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   236 		    NULL,
       
   237 		    "xmlSecTransformIdsRegister",	    
       
   238 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   239 		    "name=%s",
       
   240 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPathId)));
       
   241 	return(-1);
       
   242     }
       
   243 
       
   244     if(xmlSecTransformIdsRegister(xmlSecTransformXPath2Id) < 0) {
       
   245 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   246 		    NULL,
       
   247 		    "xmlSecTransformIdsRegister",	    
       
   248 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   249 		    "name=%s",
       
   250 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPath2Id)));
       
   251 	return(-1);
       
   252     }
       
   253 
       
   254     if(xmlSecTransformIdsRegister(xmlSecTransformXPointerId) < 0) {
       
   255 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   256 		    NULL,
       
   257 		    "xmlSecTransformIdsRegister",	    
       
   258 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   259 		    "name=%s",
       
   260 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId)));
       
   261 	return(-1);
       
   262     }
       
   263 
       
   264 #ifndef XMLSEC_NO_XSLT
       
   265     if(xmlSecTransformIdsRegister(xmlSecTransformXsltId) < 0) {
       
   266 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   267 		    NULL,
       
   268 		    "xmlSecTransformIdsRegister",	    
       
   269 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   270 		    "name=%s",
       
   271 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXsltId)));
       
   272 	return(-1);
       
   273     }
       
   274 #endif /* XMLSEC_NO_XSLT */    
       
   275     
       
   276     return(0);
       
   277 }
       
   278 
       
   279 /**************************************************************************
       
   280  *
       
   281  * utils
       
   282  *
       
   283  *************************************************************************/
       
   284 /**
       
   285  * xmlSecTransformUriTypeCheck:
       
   286  * @type:		the expected URI type.
       
   287  * @uri:		the uri for checking.
       
   288  *
       
   289  * Checks if @uri matches expected type @type.
       
   290  *
       
   291  * Returns 1 if @uri matches @type, 0 if not or a negative value
       
   292  * if an error occurs.
       
   293  */
       
   294 EXPORT_C
       
   295 int 
       
   296 xmlSecTransformUriTypeCheck(xmlSecTransformUriType type, const xmlChar* uri) {
       
   297     xmlSecTransformUriType uriType = 0;
       
   298 
       
   299     if((uri == NULL) || (xmlStrlen(uri) == 0)) {
       
   300 	uriType = xmlSecTransformUriTypeEmpty;
       
   301     } else if(uri[0] == '#') {
       
   302 	uriType = xmlSecTransformUriTypeSameDocument;
       
   303     } else if(xmlStrncmp(uri, BAD_CAST "file://", 7) == 0) {
       
   304 	uriType = xmlSecTransformUriTypeLocal;
       
   305     } else {
       
   306 	uriType = xmlSecTransformUriTypeRemote;
       
   307     }    
       
   308     return(((uriType & type) != 0) ? 1 : 0);
       
   309 }
       
   310 
       
   311 /**************************************************************************
       
   312  *
       
   313  * xmlSecTransformCtx
       
   314  *
       
   315  *************************************************************************/
       
   316 
       
   317 /**
       
   318  * xmlSecTransformCtxCreate:
       
   319  *
       
   320  * Creates transforms chain processing context.
       
   321  * The caller is responsible for destroying returend object by calling 
       
   322  * #xmlSecTransformCtxDestroy function.
       
   323  *
       
   324  * Returns pointer to newly allocated context object or NULL if an error
       
   325  * occurs.
       
   326  */
       
   327 EXPORT_C
       
   328 xmlSecTransformCtxPtr 
       
   329 xmlSecTransformCtxCreate(void) {
       
   330     xmlSecTransformCtxPtr ctx;
       
   331     int ret;
       
   332     
       
   333     /* Allocate a new xmlSecTransform and fill the fields. */
       
   334     ctx = (xmlSecTransformCtxPtr)xmlMalloc(sizeof(xmlSecTransformCtx));
       
   335     if(ctx == NULL) {
       
   336 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   337 		    NULL,
       
   338 		    NULL,
       
   339 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   340 		    "size=%d", sizeof(xmlSecTransformCtx)); 
       
   341 	return(NULL);
       
   342     }
       
   343     
       
   344     ret = xmlSecTransformCtxInitialize(ctx);
       
   345     if(ret < 0) {
       
   346 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   347 		    NULL,
       
   348 		    "xmlSecTransformCtxInitialize",
       
   349 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   350 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   351 	xmlSecTransformCtxDestroy(ctx);
       
   352 	return(NULL);
       
   353     }
       
   354     
       
   355     return(ctx);
       
   356 }
       
   357 
       
   358 /**
       
   359  * xmlSecTransformCtxDestroy:
       
   360  * @ctx:		the pointer to transforms chain processing context.
       
   361  *
       
   362  * Destroy context object created with #xmlSecTransformCtxCreate function.
       
   363  */
       
   364 EXPORT_C
       
   365 void
       
   366 xmlSecTransformCtxDestroy(xmlSecTransformCtxPtr ctx) {
       
   367     xmlSecAssert(ctx != NULL);
       
   368     
       
   369     xmlSecTransformCtxFinalize(ctx);
       
   370     xmlFree(ctx);
       
   371 }
       
   372 
       
   373 /**
       
   374  * xmlSecTransformCtxInitialize:
       
   375  * @ctx:		the pointer to transforms chain processing context.
       
   376  *
       
   377  * Initializes transforms chain processing context.
       
   378  * The caller is responsible for cleaing up returend object by calling 
       
   379  * #xmlSecTransformCtxFinalize function.
       
   380  *
       
   381  * Returns 0 on success or a negative value if an error occurs.
       
   382  */
       
   383 EXPORT_C
       
   384 int 
       
   385 xmlSecTransformCtxInitialize(xmlSecTransformCtxPtr ctx) {
       
   386     int ret;
       
   387     
       
   388     xmlSecAssert2(ctx != NULL, -1);
       
   389     
       
   390     memset(ctx, 0, sizeof(xmlSecTransformCtx));
       
   391 
       
   392     ret = xmlSecPtrListInitialize(&(ctx->enabledTransforms), xmlSecTransformIdListId);
       
   393     if(ret < 0) { 
       
   394 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   395 		    NULL,
       
   396 		    "xmlSecPtrListInitialize",
       
   397 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   398 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   399 	return(-1);
       
   400     }
       
   401 
       
   402     ctx->enabledUris = xmlSecTransformUriTypeAny;
       
   403     return(0);
       
   404 }
       
   405 
       
   406 /**
       
   407  * xmlSecTransformCtxFinalize:
       
   408  * @ctx:		the pointer to transforms chain processing context.
       
   409  *
       
   410  * Cleans up @ctx object initialized with #xmlSecTransformCtxInitialize function.
       
   411  */
       
   412 EXPORT_C
       
   413 void 
       
   414 xmlSecTransformCtxFinalize(xmlSecTransformCtxPtr ctx) {
       
   415     xmlSecAssert(ctx != NULL);
       
   416     
       
   417     xmlSecTransformCtxReset(ctx);
       
   418     xmlSecPtrListFinalize(&(ctx->enabledTransforms));
       
   419     memset(ctx, 0, sizeof(xmlSecTransformCtx));
       
   420 }
       
   421 
       
   422 /**
       
   423  * xmlSecTransformCtxReset:
       
   424  * @ctx:		the pointer to transforms chain processing context.
       
   425  *
       
   426  * Resets transfroms context for new processing.
       
   427  */
       
   428 EXPORT_C
       
   429 void 
       
   430 xmlSecTransformCtxReset(xmlSecTransformCtxPtr ctx) {
       
   431     xmlSecTransformPtr transform, tmp;    
       
   432     
       
   433     xmlSecAssert(ctx != NULL);
       
   434 
       
   435     ctx->result = NULL;
       
   436     ctx->status = xmlSecTransformStatusNone;
       
   437     
       
   438     /* destroy uri */
       
   439     if(ctx->uri != NULL) {
       
   440 	xmlFree(ctx->uri);
       
   441 	ctx->uri = NULL;
       
   442     }
       
   443     if(ctx->xptrExpr != NULL) {
       
   444 	xmlFree(ctx->xptrExpr);
       
   445 	ctx->xptrExpr = NULL;
       
   446     }
       
   447     
       
   448     /* destroy transforms chain */
       
   449     for(transform = ctx->first; transform != NULL; transform = tmp) {
       
   450 	tmp = transform->next;
       
   451 	xmlSecTransformDestroy(transform);
       
   452     }
       
   453     ctx->first = ctx->last = NULL;
       
   454 }
       
   455 
       
   456 /**
       
   457  * xmlSecTransformCtxCopyUserPref: 
       
   458  * @dst:		the pointer to destination transforms chain processing context.
       
   459  * @src:		the pointer to source transforms chain processing context.
       
   460  *
       
   461  * Copies user settings from @src context to @dst.
       
   462  *
       
   463  * Returns 0 on success or a negative value otherwise.
       
   464  */
       
   465 EXPORT_C
       
   466 int 
       
   467 xmlSecTransformCtxCopyUserPref(xmlSecTransformCtxPtr dst, xmlSecTransformCtxPtr src) {
       
   468     int ret;
       
   469     
       
   470     xmlSecAssert2(dst != NULL, -1);
       
   471     xmlSecAssert2(src != NULL, -1);
       
   472     
       
   473     dst->userData 	 = src->userData;  
       
   474     dst->flags		 = src->flags;  
       
   475     dst->flags2		 = src->flags2;  
       
   476     dst->enabledUris	 = src->enabledUris;
       
   477     dst->preExecCallback = src->preExecCallback;
       
   478     
       
   479     ret = xmlSecPtrListCopy(&(dst->enabledTransforms), &(src->enabledTransforms));
       
   480     if(ret < 0) { 
       
   481 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   482 		    NULL,
       
   483 		    "xmlSecPtrListCopy",
       
   484 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   485 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   486 	return(-1);
       
   487     }
       
   488     
       
   489     return(0);
       
   490 }
       
   491 
       
   492 /**
       
   493  * xmlSecTransformCtxAppend: 
       
   494  * @ctx:		the pointer to transforms chain processing context.
       
   495  * @transform:		the pointer to new transform.
       
   496  *
       
   497  * Connects the @transform to the end of the chain of transforms in the @ctx 
       
   498  * (see #xmlSecTransformConnect function for details).
       
   499  *
       
   500  * Returns 0 on success or a negative value otherwise.
       
   501  */
       
   502 EXPORT_C
       
   503 int 
       
   504 xmlSecTransformCtxAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) {
       
   505     int ret;
       
   506     
       
   507     xmlSecAssert2(ctx != NULL, -1);    
       
   508     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
   509     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
   510 
       
   511     if(ctx->last != NULL) {
       
   512 	ret = xmlSecTransformConnect(ctx->last, transform, ctx);
       
   513 	if(ret < 0) {
       
   514 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   515 			NULL,
       
   516 			"xmlSecTransformConnect",	    
       
   517 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   518 			"name=%s",
       
   519 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   520 	    return(-1);
       
   521 	}
       
   522     } else {
       
   523 	xmlSecAssert2(ctx->first == NULL, -1);
       
   524 	ctx->first = transform;
       
   525     }
       
   526     ctx->last = transform;
       
   527 
       
   528     return(0);
       
   529 }
       
   530 
       
   531 /**
       
   532  * xmlSecTransformCtxPrepend: 
       
   533  * @ctx:		the pointer to transforms chain processing context.
       
   534  * @transform:		the pointer to new transform.
       
   535  *
       
   536  * Connects the @transform to the beggining of the chain of transforms in the @ctx 
       
   537  * (see #xmlSecTransformConnect function for details).
       
   538  *
       
   539  * Returns 0 on success or a negative value otherwise.
       
   540  */
       
   541 EXPORT_C
       
   542 int 
       
   543 xmlSecTransformCtxPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) {
       
   544     int ret;
       
   545     
       
   546     xmlSecAssert2(ctx != NULL, -1);
       
   547     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
   548     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
   549 
       
   550     if(ctx->first != NULL) {
       
   551 	ret = xmlSecTransformConnect(transform, ctx->first, ctx);
       
   552 	if(ret < 0) {
       
   553 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   554 			NULL,
       
   555 			"xmlSecTransformConnect",	    
       
   556 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   557 			"name=%s",
       
   558 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   559 	    return(-1);
       
   560 	}
       
   561     } else {
       
   562 	xmlSecAssert2(ctx->last == NULL, -1);
       
   563 	ctx->last = transform;
       
   564     }
       
   565     ctx->first = transform;
       
   566 
       
   567     return(0);
       
   568 }
       
   569 
       
   570 /**
       
   571  * xmlSecTransformCtxCreateAndAppend: 
       
   572  * @ctx:		the pointer to transforms chain processing context.
       
   573  * @id:			the new transform klass.
       
   574  *
       
   575  * Creaeates new transform and connects it to the end of the chain of 
       
   576  * transforms in the @ctx (see #xmlSecTransformConnect function for details).
       
   577  *
       
   578  * Returns pointer to newly created transform or NULL if an error occurs.
       
   579  */
       
   580 EXPORT_C
       
   581 xmlSecTransformPtr 
       
   582 xmlSecTransformCtxCreateAndAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) {
       
   583     xmlSecTransformPtr transform;
       
   584     int ret;
       
   585     
       
   586     xmlSecAssert2(ctx != NULL, NULL);
       
   587     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
       
   588     xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL);
       
   589 
       
   590     transform = xmlSecTransformCreate(id);
       
   591     if(!xmlSecTransformIsValid(transform)) {
       
   592 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   593 		    NULL,
       
   594 		    "xmlSecTransformCreate",		    
       
   595 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   596 		    "transform=%s",
       
   597 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
       
   598 	return(NULL);
       
   599     }
       
   600 
       
   601     ret = xmlSecTransformCtxAppend(ctx, transform);
       
   602     if(ret < 0) {
       
   603 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   604 		    NULL,
       
   605 		    "xmlSecTransformCtxAppend",	    
       
   606 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   607 		    "name=%s",
       
   608 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   609 	xmlSecTransformDestroy(transform);
       
   610 	return(NULL);
       
   611     }
       
   612 
       
   613     return(transform);
       
   614 }
       
   615 
       
   616 /**
       
   617  * xmlSecTransformCtxCreateAndPrepend: 
       
   618  * @ctx:		the pointer to transforms chain processing context.
       
   619  * @id:			the new transform klass.
       
   620  *
       
   621  * Creaeates new transform and connects it to the end of the chain of 
       
   622  * transforms in the @ctx (see #xmlSecTransformConnect function for details).
       
   623  *
       
   624  * Returns pointer to newly created transform or NULL if an error occurs.
       
   625  */
       
   626 EXPORT_C
       
   627 xmlSecTransformPtr 
       
   628 xmlSecTransformCtxCreateAndPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) {
       
   629     xmlSecTransformPtr transform;
       
   630     int ret;
       
   631     
       
   632     xmlSecAssert2(ctx != NULL, NULL);
       
   633     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
       
   634     xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL);
       
   635 
       
   636     transform = xmlSecTransformCreate(id);
       
   637     if(!xmlSecTransformIsValid(transform)) {
       
   638 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   639 		    NULL,
       
   640 		    "xmlSecTransformCreate",		    
       
   641 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   642 		    "transform=%s",
       
   643 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
       
   644 	return(NULL);
       
   645     }
       
   646 
       
   647     ret = xmlSecTransformCtxPrepend(ctx, transform);
       
   648     if(ret < 0) {
       
   649 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   650 		    NULL,
       
   651 		    "xmlSecTransformCtxPrepend",	    
       
   652 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   653 		    "name=%s",
       
   654 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   655 	xmlSecTransformDestroy(transform);
       
   656 	return(NULL);
       
   657     }
       
   658 
       
   659     return(transform);
       
   660 }
       
   661 
       
   662 /**
       
   663  * xmlSecTransformCtxNodeRead: 
       
   664  * @ctx:		the pointer to transforms chain processing context.
       
   665  * @node:		the pointer to transform's node.
       
   666  * @usage:		the transform's usage (signature, encryption, etc.).
       
   667  *
       
   668  * Reads the transform from the @node and appends it to the current chain 
       
   669  * of transforms in @ctx.
       
   670  *
       
   671  * Returns pointer to newly created transform or NULL if an error occurs.
       
   672  */
       
   673 EXPORT_C
       
   674 xmlSecTransformPtr
       
   675 xmlSecTransformCtxNodeRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node, 
       
   676 			   xmlSecTransformUsage usage) {
       
   677     xmlSecTransformPtr transform;
       
   678     int ret;
       
   679     
       
   680     xmlSecAssert2(ctx != NULL, NULL);
       
   681     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
       
   682     xmlSecAssert2(node != NULL, NULL);
       
   683     
       
   684     transform = xmlSecTransformNodeRead(node, usage, ctx);
       
   685     if(transform == NULL) {
       
   686 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   687 		    NULL,
       
   688 		    "xmlSecTransformNodeRead",
       
   689 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   690 		    "name=%s",
       
   691 		    xmlSecErrorsSafeString(xmlSecNodeGetName(node))); 
       
   692 	return(NULL);
       
   693     }
       
   694     
       
   695     ret = xmlSecTransformCtxAppend(ctx, transform);
       
   696     if(ret < 0) {
       
   697 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   698 		    NULL,
       
   699 		    "xmlSecTransformCtxAppend",	    
       
   700 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   701 		    "name=%s",
       
   702 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   703 	xmlSecTransformDestroy(transform);
       
   704 	return(NULL);
       
   705     }
       
   706     
       
   707     return(transform);
       
   708 }
       
   709 
       
   710 /**
       
   711  * xmlSecTransformCtxNodesListRead: 
       
   712  * @ctx:		the pointer to transforms chain processing context.
       
   713  * @node:		the pointer to <dsig:Transform/> nodes parent node.
       
   714  * @usage:		the transform's usage (signature, encryption, etc.).
       
   715  *
       
   716  * Reads transforms from the <dsig:Transform/> children of the @node and 
       
   717  * appends them to the current transforms chain in @ctx object.
       
   718  *
       
   719  * Returns 0 on success or a negative value otherwise.
       
   720  */
       
   721 EXPORT_C
       
   722 int 
       
   723 xmlSecTransformCtxNodesListRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node, xmlSecTransformUsage usage) {
       
   724     xmlSecTransformPtr transform;
       
   725     xmlNodePtr cur;
       
   726     int ret;
       
   727         
       
   728     xmlSecAssert2(ctx != NULL, -1);
       
   729     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
   730     xmlSecAssert2(node != NULL, -1);
       
   731     
       
   732     cur = xmlSecGetNextElementNode(node->children);
       
   733     while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTransform, xmlSecDSigNs)) {
       
   734 	transform = xmlSecTransformNodeRead(cur, usage, ctx);
       
   735 	if(transform == NULL) {
       
   736 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   737 			NULL,
       
   738 			"xmlSecTransformNodeRead",
       
   739 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   740 			"node=%s",
       
   741 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   742 	    return(-1);
       
   743 	}
       
   744 	
       
   745 	ret = xmlSecTransformCtxAppend(ctx, transform); 
       
   746 	if(ret < 0) {
       
   747 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   748 			NULL,
       
   749 			"xmlSecTransformCtxAppend",
       
   750 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   751 			"node=%s",
       
   752 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   753 	    xmlSecTransformDestroy(transform);
       
   754 	    return(-1);
       
   755 	}	
       
   756 	cur = xmlSecGetNextElementNode(cur->next);
       
   757     }
       
   758 
       
   759     if(cur != NULL) {
       
   760 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   761 		    NULL,
       
   762 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   763 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   764 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   765 	return(-1);
       
   766     }    
       
   767     return(0);
       
   768 }
       
   769 
       
   770 /**
       
   771  * xmlSecTransformCtxSetUri: 
       
   772  * @ctx:		the pointer to transforms chain processing context.
       
   773  * @uri:		the URI.
       
   774  * @hereNode:		the pointer to "here" node required by some 
       
   775  *			XML transforms (may be NULL).
       
   776  *
       
   777  * Parses uri and adds xpointer transforms if required.
       
   778  *
       
   779  * The following examples demonstrate what the URI attribute identifies and
       
   780  * how it is dereferenced 
       
   781  * (http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel):
       
   782  *
       
   783  * - URI="http://example.com/bar.xml"
       
   784  * identifies the octets that represent the external resource 
       
   785  * 'http://example.com/bar.xml', that is probably an XML document given 
       
   786  * its file extension. 
       
   787  *
       
   788  * - URI="http://example.com/bar.xml#chapter1"
       
   789  * identifies the element with ID attribute value 'chapter1' of the 
       
   790  * external XML resource 'http://example.com/bar.xml', provided as an 
       
   791  * octet stream. Again, for the sake of interoperability, the element 
       
   792  * identified as 'chapter1' should be obtained using an XPath transform 
       
   793  * rather than a URI fragment (barename XPointer resolution in external 
       
   794  * resources is not REQUIRED in this specification). 
       
   795  *
       
   796  * - URI=""
       
   797  * identifies the node-set (minus any comment nodes) of the XML resource 
       
   798  * containing the signature 
       
   799  *
       
   800  * - URI="#chapter1"
       
   801  * identifies a node-set containing the element with ID attribute value 
       
   802  * 'chapter1' of the XML resource containing the signature. XML Signature 
       
   803  * (and its applications) modify this node-set to include the element plus 
       
   804  * all descendents including namespaces and attributes -- but not comments.
       
   805  *
       
   806  * Returns 0 on success or a negative value otherwise.
       
   807  */
       
   808 EXPORT_C
       
   809 int
       
   810 xmlSecTransformCtxSetUri(xmlSecTransformCtxPtr ctx, const xmlChar* uri, xmlNodePtr hereNode) {
       
   811     xmlSecNodeSetType nodeSetType = xmlSecNodeSetTree;
       
   812     const xmlChar* xptr;
       
   813     xmlChar* buf = NULL;
       
   814     int useVisa3DHack = 0;
       
   815     int ret;
       
   816     
       
   817     xmlSecAssert2(ctx != NULL, -1);
       
   818     xmlSecAssert2(ctx->uri == NULL, -1);
       
   819     xmlSecAssert2(ctx->xptrExpr == NULL, -1);
       
   820     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
   821     xmlSecAssert2(hereNode != NULL, -1);
       
   822 
       
   823     /* check uri */
       
   824     if(xmlSecTransformUriTypeCheck(ctx->enabledUris, uri) != 1) {
       
   825 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   826 		    NULL,
       
   827 		    NULL,
       
   828 		    XMLSEC_ERRORS_R_INVALID_URI_TYPE,
       
   829 		    "uri=%s", 
       
   830 		    xmlSecErrorsSafeString(uri));
       
   831 	return(-1);
       
   832     }
       
   833 
       
   834     /* is it an empty uri? */    
       
   835     if((uri == NULL) || (xmlStrlen(uri) == 0)) {
       
   836 	return(0);
       
   837     }
       
   838 
       
   839     /* do we have barename or full xpointer? */
       
   840     xptr = xmlStrchr(uri, '#');
       
   841     if(xptr == NULL){
       
   842         ctx->uri = xmlStrdup(uri);
       
   843 	if(ctx->uri == NULL) {
       
   844 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   845 			NULL,
       
   846 			NULL,
       
   847 			XMLSEC_ERRORS_R_STRDUP_FAILED,
       
   848 			"size=%d", xmlStrlen(uri)); 
       
   849 	    return(-1);
       
   850 	}
       
   851 	/* we are done */
       
   852 	return(0);
       
   853     } else if(xmlStrcmp(uri, BAD_CAST "#xpointer(/)") == 0) {
       
   854         ctx->xptrExpr = xmlStrdup(uri);
       
   855 	if(ctx->xptrExpr == NULL) {
       
   856 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   857 			NULL,
       
   858 			NULL,
       
   859 			XMLSEC_ERRORS_R_STRDUP_FAILED,
       
   860 			"size=%d", xmlStrlen(uri)); 
       
   861 	    return(-1);
       
   862 	}
       
   863 	/* we are done */
       
   864 	return(0);	
       
   865     }
       
   866     
       
   867     ctx->uri = xmlStrndup(uri, xptr - uri);
       
   868     if(ctx->uri == NULL) {
       
   869 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   870 		    NULL,
       
   871 		    NULL,
       
   872 		    XMLSEC_ERRORS_R_STRDUP_FAILED,
       
   873 		    "size=%d", xptr - uri); 
       
   874 	return(-1);
       
   875     }
       
   876 
       
   877     ctx->xptrExpr = xmlStrdup(xptr);
       
   878     if(ctx->xptrExpr == NULL) {
       
   879         xmlSecError(XMLSEC_ERRORS_HERE,
       
   880 		    NULL,
       
   881 		    NULL,
       
   882 		    XMLSEC_ERRORS_R_STRDUP_FAILED,
       
   883 		    "size=%d", xmlStrlen(xptr)); 
       
   884 	return(-1);
       
   885     }
       
   886 
       
   887     /* do we have barename or full xpointer? */
       
   888     xmlSecAssert2(xptr != NULL, -1);
       
   889     if((xmlStrncmp(xptr, BAD_CAST "#xpointer(", 10) == 0) || (xmlStrncmp(xptr, BAD_CAST "#xmlns(", 7) == 0)) {
       
   890 	++xptr;
       
   891 	nodeSetType = xmlSecNodeSetTree;
       
   892     } else if((ctx->flags & XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK) != 0) {
       
   893 	++xptr;
       
   894 	nodeSetType = xmlSecNodeSetTreeWithoutComments;
       
   895 	useVisa3DHack = 1;
       
   896     } else {
       
   897 	static const char tmpl[] = "xpointer(id(\'%s\'))";
       
   898 	xmlSecSize size;
       
   899 	
       
   900 	/* we need to add "xpointer(id('..')) because otherwise we have 
       
   901 	 * problems with numeric ("111" and so on) and other "strange" ids */
       
   902 	size = xmlStrlen(BAD_CAST tmpl) + xmlStrlen(xptr) + 2;
       
   903 	buf = (xmlChar*)xmlMalloc(size * sizeof(xmlChar));
       
   904 	if(buf == NULL) {
       
   905 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   906 			NULL,
       
   907 			NULL,
       
   908 			XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   909 			"size=%d", size);
       
   910 	    return(-1);	    
       
   911 	}
       
   912 	sprintf((char*)buf, tmpl, xptr + 1);
       
   913 	xptr = buf;
       
   914 	nodeSetType = xmlSecNodeSetTreeWithoutComments;
       
   915     }
       
   916 
       
   917     if(useVisa3DHack == 0) {    
       
   918 	xmlSecTransformPtr transform;
       
   919         
       
   920 	/* we need to create XPonter transform to execute expr */
       
   921 	transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXPointerId);
       
   922 	if(!xmlSecTransformIsValid(transform)) {
       
   923 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   924 		        NULL,
       
   925 			"xmlSecTransformCtxCreateAndPrepend", 
       
   926 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   927 			"transform=%s",
       
   928 			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId)));
       
   929 	        xmlFree( buf ); //buf == xptr
       
   930 	    return(-1);
       
   931 	}
       
   932     
       
   933         ret = xmlSecTransformXPointerSetExpr(transform, xptr, nodeSetType, hereNode);
       
   934 	if(ret < 0) {
       
   935 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   936 		        NULL,
       
   937 			"xmlSecTransformXPointerSetExpr",  
       
   938 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   939 			"name=%s",
       
   940 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   941 	        if( buf != NULL) {
       
   942 		        xmlFree( buf ); //buf == xptr
       
   943 	        }
       
   944 	    return(-1);
       
   945 	}
       
   946     } else {
       
   947 	/* Visa3D protocol doesn't follow XML/XPointer/XMLDSig specs
       
   948 	 * and allows something like "#12345" in the URI attribute.
       
   949 	 */
       
   950 	xmlSecTransformPtr transform;
       
   951         
       
   952 	transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformVisa3DHackId);
       
   953 	if(!xmlSecTransformIsValid(transform)) {
       
   954 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   955 		        NULL,
       
   956 			"xmlSecTransformCtxCreateAndPrepend", 
       
   957 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   958 			"transform=%s",
       
   959 			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformVisa3DHackId)));
       
   960 	    return(-1);
       
   961 	}
       
   962     
       
   963         ret = xmlSecTransformVisa3DHackSetID(transform, xptr);
       
   964 	if(ret < 0) {
       
   965 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   966 		        NULL,
       
   967 			"xmlSecTransformVisa3DHackSetID",  
       
   968 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   969 			"name=%s",
       
   970 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
   971 	    if(buf != NULL) {
       
   972 		xmlFree(buf);
       
   973 	    }
       
   974 	    return(-1);
       
   975 	}
       
   976     }
       
   977     if(buf != NULL) {
       
   978 	xmlFree(buf);
       
   979     }
       
   980     
       
   981     return(0);
       
   982 }
       
   983 
       
   984 /**
       
   985  * xmlSecTransformCtxPrepare: 
       
   986  * @ctx:		the pointer to transforms chain processing context.
       
   987  * @inputDataType:	the expected input type.
       
   988  *
       
   989  * Prepares the transform context for processing data of @inputDataType.
       
   990  *
       
   991  * Returns 0 on success or a negative value otherwise.
       
   992  */
       
   993 EXPORT_C
       
   994 int 
       
   995 xmlSecTransformCtxPrepare(xmlSecTransformCtxPtr ctx, xmlSecTransformDataType inputDataType) {
       
   996     xmlSecTransformDataType firstType;
       
   997     xmlSecTransformPtr transform;
       
   998     int ret;
       
   999     
       
  1000     xmlSecAssert2(ctx != NULL, -1);
       
  1001     xmlSecAssert2(ctx->result == NULL, -1);
       
  1002     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
  1003     
       
  1004     /* add binary buffer to store result */
       
  1005     transform = xmlSecTransformCtxCreateAndAppend(ctx, xmlSecTransformMemBufId);
       
  1006     if(!xmlSecTransformIsValid(transform)) {
       
  1007 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1008 		    NULL,
       
  1009 		    "xmlSecTransformCreate",		    
       
  1010 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1011 		    "transform=%s",
       
  1012 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
       
  1013 	return(-1);
       
  1014     }
       
  1015     ctx->result = xmlSecTransformMemBufGetBuffer(transform);
       
  1016     if(ctx->result == NULL) {
       
  1017 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1018 		    NULL,
       
  1019 		    "xmlSecTransformMemBufGetBuffer",  
       
  1020 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1021 		    "transform=%s",
       
  1022 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
       
  1023 	return(-1);
       
  1024     }    
       
  1025 
       
  1026     firstType = xmlSecTransformGetDataType(ctx->first, xmlSecTransformModePush, ctx);
       
  1027     if(((firstType & xmlSecTransformDataTypeBin) == 0) &&
       
  1028        ((inputDataType & xmlSecTransformDataTypeBin) != 0)) {
       
  1029 	
       
  1030         /* need to add parser transform */
       
  1031 	transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXmlParserId);
       
  1032 	if(transform == NULL) {
       
  1033 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1034 			NULL,
       
  1035 			"xmlSecTransformCtxCreateAndPrepend",
       
  1036 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1037 			"transform=%s",
       
  1038 			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXmlParserId)));
       
  1039 	    return(-1);
       
  1040 	}
       
  1041     } else if(((firstType & xmlSecTransformDataTypeXml) == 0) &&
       
  1042        ((inputDataType & xmlSecTransformDataTypeXml) != 0)) {
       
  1043 
       
  1044 	/* need to add c14n transform */
       
  1045 	transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInclC14NId);
       
  1046 	if(transform == NULL) {
       
  1047 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1048 			NULL,
       
  1049 			"xmlSecTransformCtxCreateAndPrepend",
       
  1050 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1051 			"transform=%s",
       
  1052 			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId)));
       
  1053 	    return(-1);
       
  1054 	}
       
  1055     }
       
  1056 
       
  1057     /* finally let application a chance to verify that it's ok to execte
       
  1058      * this transforms chain */
       
  1059     if(ctx->preExecCallback != NULL) {
       
  1060 	ret = (ctx->preExecCallback)(ctx);
       
  1061 	if(ret < 0) {
       
  1062     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1063 			NULL,
       
  1064 			"ctx->preExecCallback", 
       
  1065 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1066 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1067     	    return(-1);
       
  1068 	}	
       
  1069     }
       
  1070 
       
  1071     ctx->status = xmlSecTransformStatusWorking;    
       
  1072     return(0);
       
  1073 }
       
  1074 
       
  1075 /**
       
  1076  * xmlSecTransformCtxBinaryExecute: 
       
  1077  * @ctx:		the pointer to transforms chain processing context.
       
  1078  * @data:		the input binary data buffer.
       
  1079  * @dataSize:		the input data size.
       
  1080  *
       
  1081  * Processes binary data using transforms chain in the @ctx.
       
  1082  *
       
  1083  * Returns 0 on success or a negative value otherwise.
       
  1084  */
       
  1085 EXPORT_C
       
  1086 int
       
  1087 xmlSecTransformCtxBinaryExecute(xmlSecTransformCtxPtr ctx, 
       
  1088 				const xmlSecByte* data, xmlSecSize dataSize) {
       
  1089     int ret;
       
  1090         
       
  1091     xmlSecAssert2(ctx != NULL, -1);
       
  1092     xmlSecAssert2(ctx->result == NULL, -1);
       
  1093     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
  1094     xmlSecAssert2(data != NULL, -1);
       
  1095     xmlSecAssert2(dataSize > 0, -1);
       
  1096 
       
  1097     /* we should not have uri stored in ctx */
       
  1098     xmlSecAssert2(ctx->uri == NULL, -1);
       
  1099     
       
  1100     ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeBin);
       
  1101     if(ret < 0) {
       
  1102         xmlSecError(XMLSEC_ERRORS_HERE,
       
  1103 		    NULL,
       
  1104 		    "xmlSecTransformCtxPrepare", 
       
  1105 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1106 		    "type=bin");
       
  1107     	return(-1);
       
  1108     }	
       
  1109     
       
  1110     ret = xmlSecTransformPushBin(ctx->first, data, dataSize, 1, ctx);
       
  1111     if(ret < 0) {
       
  1112     	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1113 		    NULL,
       
  1114 		    "xmlSecTransformCtxPushBin", 
       
  1115 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1116 		    "dataSize=%d", dataSize);
       
  1117     	return(-1);
       
  1118     }
       
  1119 
       
  1120     ctx->status = xmlSecTransformStatusFinished;
       
  1121     return(0);    
       
  1122 }
       
  1123 
       
  1124 /**
       
  1125  * xmlSecTransformCtxUriExecute: 
       
  1126  * @ctx:		the pointer to transforms chain processing context.
       
  1127  * @uri:		the URI.
       
  1128  *
       
  1129  * Process binary data from the URI using transforms chain in @ctx.
       
  1130  *
       
  1131  * Returns 0 on success or a negative value otherwise.
       
  1132  */
       
  1133 EXPORT_C
       
  1134 int 
       
  1135 xmlSecTransformCtxUriExecute(xmlSecTransformCtxPtr ctx, const xmlChar* uri) {
       
  1136     xmlSecTransformPtr uriTransform;
       
  1137     int ret;
       
  1138         
       
  1139     xmlSecAssert2(ctx != NULL, -1);
       
  1140     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
  1141     xmlSecAssert2(uri != NULL, -1);
       
  1142 
       
  1143     /* we should not execute transform for a different uri */
       
  1144     xmlSecAssert2((ctx->uri == NULL) || (uri == ctx->uri) || xmlStrEqual(uri, ctx->uri), -1);
       
  1145     
       
  1146     uriTransform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInputURIId);
       
  1147     if(uriTransform == NULL) {
       
  1148 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1149 		    NULL,
       
  1150 		    "xmlSecTransformCtxCreateAndPrepend",
       
  1151 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1152 		    "transform=%s",
       
  1153 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInputURIId)));
       
  1154 	return(-1);
       
  1155     }
       
  1156     
       
  1157     ret = xmlSecTransformInputURIOpen(uriTransform, uri);
       
  1158     if(ret < 0) {
       
  1159 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1160 		    NULL,
       
  1161 		    "xmlSecTransformInputURIOpen",
       
  1162 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1163 		    "uri=%s",
       
  1164 		    xmlSecErrorsSafeString(uri));
       
  1165 	return(-1);
       
  1166     }
       
  1167 
       
  1168     /* we do not need to do something special for this transform */
       
  1169     ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeUnknown);
       
  1170     if(ret < 0) {
       
  1171         xmlSecError(XMLSEC_ERRORS_HERE,
       
  1172 		    NULL,
       
  1173 		    "xmlSecTransformCtxPrepare", 
       
  1174 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1175 		    "type=bin");
       
  1176     	return(-1);
       
  1177     }	
       
  1178     
       
  1179     /* Now we have a choice: we either can push from first transform or pop 
       
  1180      * from last. Our C14N transforms prefers push, so push data!
       
  1181      */
       
  1182     ret = xmlSecTransformPump(uriTransform, uriTransform->next, ctx);     
       
  1183     if(ret < 0) {
       
  1184 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1185 		    NULL,
       
  1186 		    "xmlSecTransformPump",
       
  1187 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1188 		    "uri=%s",
       
  1189 		    xmlSecErrorsSafeString(uri));
       
  1190 	return(-1);
       
  1191     }
       
  1192      
       
  1193     ctx->status = xmlSecTransformStatusFinished;
       
  1194     return(0);
       
  1195 }
       
  1196 
       
  1197 /**
       
  1198  * xmlSecTransformCtxXmlExecute: 
       
  1199  * @ctx:		the pointer to transforms chain processing context.
       
  1200  * @nodes:		the input node set.
       
  1201  *
       
  1202  * Process @nodes using transforms in the transforms chain in @ctx.
       
  1203  *
       
  1204  * Returns 0 on success or a negative value otherwise.
       
  1205  */
       
  1206 EXPORT_C
       
  1207 int
       
  1208 xmlSecTransformCtxXmlExecute(xmlSecTransformCtxPtr ctx, xmlSecNodeSetPtr nodes) {
       
  1209     int ret;
       
  1210         
       
  1211     xmlSecAssert2(ctx != NULL, -1);
       
  1212     xmlSecAssert2(ctx->result == NULL, -1);
       
  1213     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
  1214     xmlSecAssert2(nodes != NULL, -1);
       
  1215     
       
  1216     xmlSecAssert2((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0), -1); 
       
  1217 
       
  1218     ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeXml);
       
  1219     if(ret < 0) {
       
  1220     	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1221 		    NULL,
       
  1222 		    "xmlSecTransformCtxPrepare", 
       
  1223 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1224 		    "type=xml");
       
  1225     	return(-1);
       
  1226     }	
       
  1227 
       
  1228     /* it's better to do push than pop because all XML transform
       
  1229      * just don't care and c14n likes push more than pop */
       
  1230     ret = xmlSecTransformPushXml(ctx->first, nodes, ctx);
       
  1231     if(ret < 0) {
       
  1232 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1233 		    NULL,
       
  1234 		    "xmlSecTransformPushXml", 
       
  1235 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1236 		    "transform=%s",
       
  1237 		    xmlSecErrorsSafeString(xmlSecTransformGetName(ctx->first)));
       
  1238 	return(-1);
       
  1239     }
       
  1240 
       
  1241     ctx->status = xmlSecTransformStatusFinished;
       
  1242     return(0);
       
  1243 }
       
  1244 
       
  1245 /**
       
  1246  * xmlSecTransformCtxExecute: 
       
  1247  * @ctx:		the pointer to transforms chain processing context.
       
  1248  * @doc:		the pointer to input document.
       
  1249  *
       
  1250  * Executes transforms chain in @ctx.
       
  1251  *
       
  1252  * Returns 0 on success or a negative value otherwise.
       
  1253  */
       
  1254 EXPORT_C
       
  1255 int
       
  1256 xmlSecTransformCtxExecute(xmlSecTransformCtxPtr ctx, xmlDocPtr doc) {
       
  1257     int ret;
       
  1258         
       
  1259     xmlSecAssert2(ctx != NULL, -1);
       
  1260     xmlSecAssert2(ctx->result == NULL, -1);
       
  1261     xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
       
  1262     xmlSecAssert2(doc != NULL, -1);
       
  1263     
       
  1264     if((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0)) {
       
  1265 	xmlSecNodeSetPtr nodes;
       
  1266         
       
  1267 	if((ctx->xptrExpr != NULL) && (xmlStrlen(ctx->xptrExpr) > 0)){
       
  1268 	    /* our xpointer transform takes care of providing correct nodes set */
       
  1269 	    nodes = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetNormal);
       
  1270 	    if(nodes == NULL) {
       
  1271 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  1272 			    NULL,
       
  1273 			    "xmlSecNodeSetCreate", 
       
  1274 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1275 			    XMLSEC_ERRORS_NO_MESSAGE);
       
  1276 	        return(-1);
       
  1277 	    }
       
  1278 	
       
  1279 	} else {
       
  1280 	    /* we do not want to have comments for empty URI */
       
  1281 	    nodes = xmlSecNodeSetGetChildren(doc, NULL, 0, 0);
       
  1282 	    if(nodes == NULL) {
       
  1283 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  1284 			    NULL,
       
  1285 			    "xmlSecNodeSetGetChildren", 
       
  1286 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1287 			    XMLSEC_ERRORS_NO_MESSAGE);
       
  1288 	        return(-1);
       
  1289 	    }
       
  1290 	}
       
  1291 	ret = xmlSecTransformCtxXmlExecute(ctx, nodes);
       
  1292 	if(ret < 0) {
       
  1293 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1294 			NULL,
       
  1295 			"xmlSecTransformCtxXmlExecute", 
       
  1296 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1297 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1298 	    xmlSecNodeSetDestroy(nodes);
       
  1299 	    return(-1);
       
  1300 	}
       
  1301 	xmlSecNodeSetDestroy(nodes);
       
  1302     } else {
       
  1303 	ret = xmlSecTransformCtxUriExecute(ctx, ctx->uri);
       
  1304 	if(ret < 0) {
       
  1305 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1306 			NULL,
       
  1307 			"xmlSecTransformCtxUriExecute", 
       
  1308 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1309 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1310 	    return(-1);
       
  1311 	}
       
  1312     } 
       
  1313     
       
  1314     return(0);
       
  1315 }
       
  1316 
       
  1317 /**
       
  1318  * xmlSecTransformCtxDebugDump:
       
  1319  * @ctx:		the pointer to transforms chain processing context.
       
  1320  * @output:		the pointer to output FILE.
       
  1321  * 
       
  1322  * Prints transforms context debug information to @output.
       
  1323  */
       
  1324 EXPORT_C
       
  1325 void 
       
  1326 xmlSecTransformCtxDebugDump(xmlSecTransformCtxPtr ctx, FILE* output) {
       
  1327     xmlSecTransformPtr transform;    
       
  1328     
       
  1329     xmlSecAssert(ctx != NULL);
       
  1330     xmlSecAssert(output != NULL);
       
  1331 
       
  1332     fprintf(output, "== TRANSFORMS CTX (status=%d)\n", ctx->status);    
       
  1333 
       
  1334     fprintf(output, "== flags: 0x%08x\n", ctx->flags);
       
  1335     fprintf(output, "== flags2: 0x%08x\n", ctx->flags2);
       
  1336     if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) {
       
  1337 	fprintf(output, "== enabled transforms: ");
       
  1338 	xmlSecTransformIdListDebugDump(&(ctx->enabledTransforms), output);
       
  1339     } else {
       
  1340 	fprintf(output, "== enabled transforms: all\n");
       
  1341     }
       
  1342     
       
  1343     fprintf(output, "=== uri: %s\n", 
       
  1344 	    (ctx->uri != NULL) ? ctx->uri : BAD_CAST "NULL");    
       
  1345     fprintf(output, "=== uri xpointer expr: %s\n", 
       
  1346 	    (ctx->xptrExpr != NULL) ? ctx->xptrExpr : BAD_CAST "NULL");    
       
  1347     for(transform = ctx->first; transform != NULL; transform = transform->next) {
       
  1348 	xmlSecTransformDebugDump(transform, output);
       
  1349     }
       
  1350 }
       
  1351 
       
  1352 /**
       
  1353  * xmlSecTransformCtxDebugXmlDump:
       
  1354  * @ctx:		the pointer to transforms chain processing context.
       
  1355  * @output:		the pointer to output FILE.
       
  1356  * 
       
  1357  * Prints transforms context debug information to @output in XML format.
       
  1358  */
       
  1359 EXPORT_C
       
  1360 void 
       
  1361 xmlSecTransformCtxDebugXmlDump(xmlSecTransformCtxPtr ctx, FILE* output) {
       
  1362     xmlSecTransformPtr transform;    
       
  1363     
       
  1364     xmlSecAssert(ctx != NULL);
       
  1365     xmlSecAssert(output != NULL);
       
  1366  
       
  1367     fprintf(output, "<TransformCtx status=\"%d\">\n", ctx->status);
       
  1368 
       
  1369     fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags);
       
  1370     fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2);
       
  1371     if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) {
       
  1372 	fprintf(output, "<EnabledTransforms>\n");
       
  1373 	xmlSecTransformIdListDebugXmlDump(&(ctx->enabledTransforms), output);
       
  1374 	fprintf(output, "</EnabledTransforms>\n");
       
  1375     } else {
       
  1376 	fprintf(output, "<EnabledTransforms>all</EnabledTransforms>\n");
       
  1377     }
       
  1378 
       
  1379 
       
  1380     fprintf(output, "<Uri>%s</Uri>\n", 
       
  1381 		(ctx->uri != NULL) ? ctx->uri : BAD_CAST "NULL");
       
  1382     fprintf(output, "<UriXPointer>%s</UriXPointer>\n", 
       
  1383 		(ctx->xptrExpr != NULL) ? ctx->xptrExpr : BAD_CAST "NULL");    
       
  1384 
       
  1385     for(transform = ctx->first; transform != NULL; transform = transform->next) {
       
  1386 	xmlSecTransformDebugXmlDump(transform, output);
       
  1387     }
       
  1388     fprintf(output, "</TransformCtx>\n");    
       
  1389 }
       
  1390 
       
  1391 /**************************************************************************
       
  1392  *
       
  1393  * xmlSecTransform
       
  1394  *
       
  1395  *************************************************************************/
       
  1396 /**
       
  1397  * xmlSecTransformCreate:
       
  1398  * @id: 		the transform id to create.
       
  1399  *
       
  1400  * Creates new transform of the @id klass. The caller is responsible for
       
  1401  * destroying returned tansform using #xmlSecTransformDestroy function.
       
  1402  *
       
  1403  * Returns pointer to newly created transform or NULL if an error occurs.
       
  1404  */
       
  1405 EXPORT_C 
       
  1406 xmlSecTransformPtr	
       
  1407 xmlSecTransformCreate(xmlSecTransformId id) {
       
  1408     xmlSecTransformPtr transform;
       
  1409     int ret;
       
  1410     
       
  1411     xmlSecAssert2(id != NULL, NULL);
       
  1412     xmlSecAssert2(id->klassSize >= sizeof(xmlSecTransformKlass), NULL);
       
  1413     xmlSecAssert2(id->objSize >= sizeof(xmlSecTransform), NULL);
       
  1414     xmlSecAssert2(id->name != NULL, NULL);
       
  1415         
       
  1416     /* Allocate a new xmlSecTransform and fill the fields. */
       
  1417     transform = (xmlSecTransformPtr)xmlMalloc(id->objSize);
       
  1418     if(transform == NULL) {
       
  1419 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1420 		    NULL,
       
  1421 		    NULL,
       
  1422 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
  1423 		    "size=%d", id->objSize); 
       
  1424 	return(NULL);
       
  1425     }
       
  1426     memset(transform, 0, id->objSize);    
       
  1427     transform->id = id;
       
  1428     
       
  1429     if(id->initialize != NULL) {
       
  1430 	ret = (id->initialize)(transform);
       
  1431         if(ret < 0) {
       
  1432 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1433 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1434 			"id->initialize",
       
  1435 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1436 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1437 	    xmlSecTransformDestroy(transform);
       
  1438 	    return(NULL);
       
  1439 	}
       
  1440     }
       
  1441 
       
  1442     ret = xmlSecBufferInitialize(&(transform->inBuf), 0);
       
  1443     if(ret < 0) {
       
  1444 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1445 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1446 		    "xmlSecBufferInitialize",
       
  1447 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1448 		    "size=%d", 0);
       
  1449 	xmlSecTransformDestroy(transform);
       
  1450 	return(NULL);	
       
  1451     }
       
  1452 
       
  1453     ret = xmlSecBufferInitialize(&(transform->outBuf), 0);
       
  1454     if(ret < 0) {
       
  1455 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1456 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1457 		    "xmlSecBufferInitialize",
       
  1458 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1459 		    "size=%d", 0);
       
  1460 	xmlSecTransformDestroy(transform);
       
  1461 	return(NULL);	
       
  1462     }
       
  1463     
       
  1464     return(transform);
       
  1465 }
       
  1466 
       
  1467 /**
       
  1468  * xmlSecTransformDestroy:
       
  1469  * @transform: 		the pointer to transform.
       
  1470  *
       
  1471  * Destroys transform created with #xmlSecTransformCreate function.
       
  1472  */
       
  1473 EXPORT_C
       
  1474 void
       
  1475 xmlSecTransformDestroy(xmlSecTransformPtr transform) {
       
  1476     xmlSecAssert(xmlSecTransformIsValid(transform));
       
  1477     xmlSecAssert(transform->id->objSize > 0);
       
  1478     
       
  1479     /* first need to remove ourselves from chain */
       
  1480     xmlSecTransformRemove(transform);
       
  1481 
       
  1482     xmlSecBufferFinalize(&(transform->inBuf));
       
  1483     xmlSecBufferFinalize(&(transform->outBuf));
       
  1484 
       
  1485     /* we never destroy input nodes, output nodes
       
  1486      * are destroyed if and only if they are different
       
  1487      * from input nodes 
       
  1488      */
       
  1489     if((transform->outNodes != NULL) && (transform->outNodes != transform->inNodes)) {
       
  1490 	xmlSecNodeSetDestroy(transform->outNodes);
       
  1491     }
       
  1492     if(transform->id->finalize != NULL) { 
       
  1493 	(transform->id->finalize)(transform);
       
  1494     }
       
  1495     memset(transform, 0, transform->id->objSize);
       
  1496     xmlFree(transform);
       
  1497 }
       
  1498 
       
  1499 /** 
       
  1500  * xmlSecTransformNodeRead:
       
  1501  * @node: 		the pointer to the transform's node.
       
  1502  * @usage:		the transform usage (signature, encryption, ...).
       
  1503  * @transformCtx:	the transform's chaing processing context.
       
  1504  *
       
  1505  * Reads transform from the @node as follows:
       
  1506  *
       
  1507  *    1) reads "Algorithm" attribute;
       
  1508  *
       
  1509  *    2) checks the lists of known and allowed transforms;
       
  1510  *
       
  1511  *    3) calls transform's create method;
       
  1512  *
       
  1513  *    4) calls transform's read transform node method.
       
  1514  *
       
  1515  * Returns pointer to newly created transform or NULL if an error occurs.
       
  1516  */
       
  1517 EXPORT_C
       
  1518 xmlSecTransformPtr
       
  1519 xmlSecTransformNodeRead(xmlNodePtr node, xmlSecTransformUsage usage, xmlSecTransformCtxPtr transformCtx) {
       
  1520     xmlSecTransformPtr transform;
       
  1521     xmlSecTransformId id;
       
  1522     xmlChar *href;
       
  1523     int ret;
       
  1524 
       
  1525     xmlSecAssert2(node != NULL, NULL);
       
  1526     xmlSecAssert2(transformCtx != NULL, NULL);
       
  1527 
       
  1528     href = xmlGetProp(node, xmlSecAttrAlgorithm);
       
  1529     if(href == NULL) {
       
  1530 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1531 		    NULL,
       
  1532 		    xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
       
  1533 		    XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
       
  1534 		    "node=%s",
       
  1535 		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
       
  1536 	return(NULL);		
       
  1537     }
       
  1538     
       
  1539     id = xmlSecTransformIdListFindByHref(xmlSecTransformIdsGet(), href, usage);    
       
  1540     if(id == xmlSecTransformIdUnknown) {
       
  1541 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1542 		    NULL,
       
  1543 		    "xmlSecTransformIdsListFindByHref",
       
  1544 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1545 		    "href=%s", 
       
  1546 		    xmlSecErrorsSafeString(href));
       
  1547 	xmlFree(href);
       
  1548 	return(NULL);		
       
  1549     }
       
  1550 
       
  1551     /* check with enabled transforms list */
       
  1552     if((xmlSecPtrListGetSize(&(transformCtx->enabledTransforms)) > 0) &&
       
  1553        (xmlSecTransformIdListFind(&(transformCtx->enabledTransforms), id) != 1)) {
       
  1554 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1555 		    NULL,
       
  1556 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)),
       
  1557 		    XMLSEC_ERRORS_R_TRANSFORM_DISABLED,
       
  1558 		    "href=%s",
       
  1559 		    xmlSecErrorsSafeString(href));
       
  1560 	xmlFree(href);
       
  1561 	return(NULL);
       
  1562     }
       
  1563         
       
  1564     transform = xmlSecTransformCreate(id);
       
  1565     if(!xmlSecTransformIsValid(transform)) {
       
  1566 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1567 		    NULL,
       
  1568 		    "xmlSecTransformCreate",		    
       
  1569 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1570 		    "transform=%s",
       
  1571 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
       
  1572 	xmlFree(href);
       
  1573 	return(NULL);		
       
  1574     }
       
  1575 
       
  1576     if(transform->id->readNode != NULL) {
       
  1577 	ret = transform->id->readNode(transform, node, transformCtx);
       
  1578         if(ret < 0) {
       
  1579     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1580 			NULL,
       
  1581 			"id->readNode",
       
  1582 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1583 			"transform=%s",
       
  1584 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
       
  1585 	    xmlSecTransformDestroy(transform);
       
  1586 	    xmlFree(href);
       
  1587 	    return(NULL);		
       
  1588 	}
       
  1589     }
       
  1590 
       
  1591     /* finally remember the transform node */    
       
  1592     transform->hereNode = node;
       
  1593     xmlFree(href);   
       
  1594     return(transform);
       
  1595 }
       
  1596 
       
  1597 /**
       
  1598  * xmlSecTransformPump:
       
  1599  * @left:		the source pumping transform.
       
  1600  * @right:		the destination pumping transform.
       
  1601  * @transformCtx:	the transform's chaing processing context.
       
  1602  *
       
  1603  * Pops data from @left transform and pushes to @right transform until
       
  1604  * no more data is available.
       
  1605  *
       
  1606  * Returns 0 on success or a negative value if an error occurs.
       
  1607  */
       
  1608 EXPORT_C
       
  1609 int 
       
  1610 xmlSecTransformPump(xmlSecTransformPtr left, xmlSecTransformPtr right, xmlSecTransformCtxPtr transformCtx) {
       
  1611     xmlSecTransformDataType leftType;
       
  1612     xmlSecTransformDataType rightType;
       
  1613     int ret;
       
  1614     
       
  1615     xmlSecAssert2(xmlSecTransformIsValid(left), -1);
       
  1616     xmlSecAssert2(xmlSecTransformIsValid(right), -1);
       
  1617     xmlSecAssert2(transformCtx != NULL, -1);
       
  1618     
       
  1619     leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx);
       
  1620     rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx);
       
  1621 
       
  1622     if(((leftType & xmlSecTransformDataTypeXml) != 0) && 
       
  1623        ((rightType & xmlSecTransformDataTypeXml) != 0)) {
       
  1624        
       
  1625        xmlSecNodeSetPtr nodes = NULL;
       
  1626 
       
  1627        ret = xmlSecTransformPopXml(left, &nodes, transformCtx);
       
  1628        if(ret < 0) {
       
  1629 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1630 			xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
       
  1631 			"xmlSecTransformPopXml",
       
  1632 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1633 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1634 	    return(-1);
       
  1635        }
       
  1636 
       
  1637        ret = xmlSecTransformPushXml(right, nodes, transformCtx);
       
  1638        if(ret < 0) {
       
  1639 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1640 			xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
       
  1641 			"xmlSecTransformPushXml",
       
  1642 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1643 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1644 	    return(-1);
       
  1645        }
       
  1646     }  else if(((leftType & xmlSecTransformDataTypeBin) != 0) && 
       
  1647     	       ((rightType & xmlSecTransformDataTypeBin) != 0)) {	
       
  1648 	xmlSecByte buf[XMLSEC_TRANSFORM_BINARY_CHUNK];
       
  1649 	xmlSecSize bufSize;
       
  1650 	int final;
       
  1651 	
       
  1652 	do {
       
  1653 	    ret = xmlSecTransformPopBin(left, buf, sizeof(buf), &bufSize, transformCtx);
       
  1654     	    if(ret < 0) {
       
  1655 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  1656 			    xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
       
  1657 			    "xmlSecTransformPopBin",
       
  1658 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1659 			    XMLSEC_ERRORS_NO_MESSAGE);
       
  1660 		return(-1);
       
  1661 	    }
       
  1662 	    final = (bufSize == 0) ? 1 : 0;
       
  1663 	    ret = xmlSecTransformPushBin(right, buf, bufSize, final, transformCtx);
       
  1664     	    if(ret < 0) {
       
  1665 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  1666 			    xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
       
  1667 			    "xmlSecTransformPushBin",
       
  1668 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1669 			    XMLSEC_ERRORS_NO_MESSAGE);
       
  1670 		return(-1);
       
  1671 	    }
       
  1672 	} while(final == 0);
       
  1673     } else {
       
  1674 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1675 		    xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
       
  1676 		    xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
       
  1677 		    XMLSEC_ERRORS_R_INVALID_TRANSFORM,
       
  1678 		    "transforms input/output data formats do not match");
       
  1679     }
       
  1680     return(0);
       
  1681 }
       
  1682 
       
  1683 
       
  1684 /**
       
  1685  * xmlSecTransformSetKey:
       
  1686  * @transform: 		the pointer to transform.
       
  1687  * @key: 		the pointer to key. 
       
  1688  *
       
  1689  * Sets the transform's key.
       
  1690  *
       
  1691  * Returns 0 on success or a negative value otherwise.
       
  1692  */
       
  1693 EXPORT_C
       
  1694 int
       
  1695 xmlSecTransformSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
       
  1696     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1697     xmlSecAssert2(key != NULL, -1);
       
  1698         
       
  1699     if(transform->id->setKey != NULL) {
       
  1700 	return((transform->id->setKey)(transform, key));
       
  1701     }
       
  1702     return(0);
       
  1703 }
       
  1704 
       
  1705 /**
       
  1706  * xmlSecTransformSetKeyReq:
       
  1707  * @transform: 		the pointer to transform.
       
  1708  * @keyReq: 		the pointer to keys requirements object. 
       
  1709  *
       
  1710  * Sets the key requirements for @transform in the @keyReq.
       
  1711  *
       
  1712  * Returns 0 on success or a negative value otherwise.
       
  1713  */
       
  1714 EXPORT_C
       
  1715 int
       
  1716 xmlSecTransformSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
       
  1717     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1718     xmlSecAssert2(keyReq != NULL, -1);
       
  1719         
       
  1720     keyReq->keyId   	= xmlSecKeyDataIdUnknown;
       
  1721     keyReq->keyType 	= xmlSecKeyDataTypeUnknown;
       
  1722     keyReq->keyUsage	= xmlSecKeyUsageAny;
       
  1723     keyReq->keyBitsSize	= 0;
       
  1724         
       
  1725     if(transform->id->setKeyReq != NULL) {
       
  1726 	return((transform->id->setKeyReq)(transform, keyReq));
       
  1727     }
       
  1728     return(0);
       
  1729 }
       
  1730 
       
  1731 /**
       
  1732  * xmlSecTransformVerify:
       
  1733  * @transform:		the pointer to transform.
       
  1734  * @data:		the binary data for verification.
       
  1735  * @dataSize:		the data size.
       
  1736  * @transformCtx:	the transform's chaing processing context.
       
  1737  *
       
  1738  * Verifies the data with transform's processing results
       
  1739  * (for digest, HMAC and signature transforms). The verification
       
  1740  * result is stored in the #status member of #xmlSecTransform object.
       
  1741  *
       
  1742  * Returns 0 on success or a negative value if an error occurs.
       
  1743  */
       
  1744 EXPORT_C
       
  1745 int 
       
  1746 xmlSecTransformVerify(xmlSecTransformPtr transform, const xmlSecByte* data,
       
  1747 		    xmlSecSize dataSize, xmlSecTransformCtxPtr transformCtx) {
       
  1748     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1749     xmlSecAssert2(transform->id->verify != NULL, -1);
       
  1750     xmlSecAssert2(transformCtx != NULL, -1);
       
  1751 
       
  1752     return((transform->id->verify)(transform, data, dataSize, transformCtx));
       
  1753 }
       
  1754 
       
  1755 /**
       
  1756  * xmlSecTransformVerifyNodeContent:
       
  1757  * @transform:		the pointer to transform.
       
  1758  * @node:		the pointer to node.
       
  1759  * @transformCtx:	the transform's chaing processing context.
       
  1760  *
       
  1761  * Gets the @node content, base64 decodes it and calls #xmlSecTransformVerify
       
  1762  * function to verify binary results.
       
  1763  *
       
  1764  * Returns 0 on success or a negative value if an error occurs.
       
  1765  */
       
  1766 EXPORT_C
       
  1767 int 
       
  1768 xmlSecTransformVerifyNodeContent(xmlSecTransformPtr transform, xmlNodePtr node,
       
  1769 				 xmlSecTransformCtxPtr transformCtx) {
       
  1770     xmlSecBuffer buffer;
       
  1771     int ret;
       
  1772     
       
  1773     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1774     xmlSecAssert2(node != NULL, -1);
       
  1775     xmlSecAssert2(transformCtx != NULL, -1);
       
  1776     
       
  1777     ret = xmlSecBufferInitialize(&buffer, 0);
       
  1778     if(ret < 0) {
       
  1779 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1780 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1781 		    "xmlSecBufferInitialize",
       
  1782 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1783 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1784 	return(-1);
       
  1785     }
       
  1786     
       
  1787     ret = xmlSecBufferBase64NodeContentRead(&buffer, node);
       
  1788     if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL)) {
       
  1789 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1790 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1791 		    "xmlSecBufferBase64NodeContentRead",
       
  1792 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1793 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1794 	xmlSecBufferFinalize(&buffer);
       
  1795 	return(-1);
       
  1796     }
       
  1797     
       
  1798     ret = xmlSecTransformVerify(transform, xmlSecBufferGetData(&buffer),
       
  1799 				xmlSecBufferGetSize(&buffer), transformCtx);
       
  1800     if(ret < 0) {
       
  1801 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1802 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1803 		    "xmlSecTransformVerify",
       
  1804 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1805 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1806 	xmlSecBufferFinalize(&buffer);
       
  1807 	return(-1);
       
  1808     }
       
  1809 
       
  1810     xmlSecBufferFinalize(&buffer);
       
  1811     return(0);
       
  1812 }
       
  1813 
       
  1814 /**
       
  1815  * xmlSecTransformGetDataType:
       
  1816  * @transform:		the pointer to transform.
       
  1817  * @mode:		the data mode (push or pop).
       
  1818  * @transformCtx:	the transform's chaing processing context.
       
  1819  *
       
  1820  * Gets transform input (@mode is "push") or output (@mode is "pop") data 
       
  1821  * type (binary or XML).
       
  1822  *
       
  1823  * Returns the transform's data type for the @mode operation.
       
  1824  */
       
  1825 EXPORT_C
       
  1826 xmlSecTransformDataType	
       
  1827 xmlSecTransformGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode, 
       
  1828 		    xmlSecTransformCtxPtr transformCtx) {
       
  1829     xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown);
       
  1830     xmlSecAssert2(transform->id->getDataType != NULL, xmlSecTransformDataTypeUnknown);
       
  1831     
       
  1832     return((transform->id->getDataType)(transform, mode, transformCtx));    
       
  1833 }
       
  1834 
       
  1835 /**
       
  1836  * xmlSecTransformPushBin:
       
  1837  * @transform:		the pointer to transform object.
       
  1838  * @data:		the input binary data,
       
  1839  * @dataSize:		the input data size.
       
  1840  * @final:		the flag: if set to 1 then it's the last
       
  1841  *			data chunk.
       
  1842  * @transformCtx:	the pointer to transform context object.
       
  1843  *
       
  1844  * Process binary @data and pushes results to next transform.
       
  1845  * 
       
  1846  * Returns 0 on success or a negative value if an error occurs.
       
  1847  */
       
  1848 EXPORT_C
       
  1849 int 
       
  1850 xmlSecTransformPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
       
  1851 		    xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
       
  1852     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1853     xmlSecAssert2(transform->id->pushBin != NULL, -1);
       
  1854     xmlSecAssert2(transformCtx != NULL, -1);
       
  1855     
       
  1856     return((transform->id->pushBin)(transform, data, dataSize, final, transformCtx));    
       
  1857 }
       
  1858 
       
  1859 /**
       
  1860  * xmlSecTransformPopBin:
       
  1861  * @transform:		the pointer to transform object.
       
  1862  * @data:		the buffer to store result data.
       
  1863  * @maxDataSize:	the size of the buffer #data.
       
  1864  * @dataSize:		the pointer to returned data size.
       
  1865  * @transformCtx:	the pointer to transform context object.
       
  1866  *
       
  1867  * Pops data from previous transform in the chain, processes data and 
       
  1868  * returns result in the @data buffer. The size of returned data is 
       
  1869  * placed in the @dataSize.
       
  1870  *
       
  1871  * Returns 0 on success or a negative value if an error occurs.
       
  1872  */
       
  1873 EXPORT_C
       
  1874 int 
       
  1875 xmlSecTransformPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
       
  1876 		    xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) {
       
  1877     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1878     xmlSecAssert2(transform->id->popBin != NULL, -1);
       
  1879     xmlSecAssert2(data != NULL, -1);
       
  1880     xmlSecAssert2(dataSize != NULL, -1);
       
  1881     xmlSecAssert2(transformCtx != NULL, -1);
       
  1882 
       
  1883     return((transform->id->popBin)(transform, data, maxDataSize, dataSize, transformCtx));    
       
  1884 }
       
  1885 
       
  1886 /**
       
  1887  * xmlSecTransformPushXml:
       
  1888  * @transform:		the pointer to transform object.
       
  1889  * @nodes:		the input nodes.
       
  1890  * @transformCtx:	the pointer to transform context object.
       
  1891  *
       
  1892  * Processes @nodes and pushes result to the next transform in the chain.
       
  1893  *
       
  1894  * Returns 0 on success or a negative value if an error occurs.
       
  1895  */
       
  1896 EXPORT_C
       
  1897 int 
       
  1898 xmlSecTransformPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes,
       
  1899 		    xmlSecTransformCtxPtr transformCtx) {
       
  1900     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1901     xmlSecAssert2(transform->id->pushXml != NULL, -1);
       
  1902     xmlSecAssert2(transformCtx != NULL, -1);
       
  1903 
       
  1904     return((transform->id->pushXml)(transform, nodes, transformCtx));    
       
  1905 }
       
  1906 
       
  1907 /**
       
  1908  * xmlSecTransformPopXml:
       
  1909  * @transform:		the pointer to transform object.
       
  1910  * @nodes:		the pointer to store popinter to result nodes.
       
  1911  * @transformCtx:	the pointer to transform context object.
       
  1912  *
       
  1913  * Pops data from previous transform in the chain, processes the data and 
       
  1914  * returns result in @nodes.
       
  1915  *
       
  1916  * Returns 0 on success or a negative value if an error occurs.
       
  1917  */
       
  1918 EXPORT_C
       
  1919 int 
       
  1920 xmlSecTransformPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
       
  1921 		    xmlSecTransformCtxPtr transformCtx) {
       
  1922     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1923     xmlSecAssert2(transform->id->popXml != NULL, -1);
       
  1924     xmlSecAssert2(transformCtx != NULL, -1);
       
  1925 
       
  1926     return((transform->id->popXml)(transform, nodes, transformCtx));    
       
  1927 }
       
  1928 
       
  1929 /**
       
  1930  * xmlSecTransformExecute:
       
  1931  * @transform:		the pointer to transform.
       
  1932  * @last:		the flag: if set to 1 then it's the last data chunk.
       
  1933  * @transformCtx:	the transform's chaing processing context.
       
  1934  *
       
  1935  * Executes transform (used by default popBin/pushBin/popXml/pushXml methods).
       
  1936  *
       
  1937  * Returns 0 on success or a negative value if an error occurs.
       
  1938  */
       
  1939 EXPORT_C
       
  1940 int 
       
  1941 xmlSecTransformExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
       
  1942     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  1943     xmlSecAssert2(transform->id->execute != NULL, -1);
       
  1944     xmlSecAssert2(transformCtx != NULL, -1);
       
  1945 
       
  1946     return((transform->id->execute)(transform, last, transformCtx));
       
  1947 }
       
  1948 
       
  1949 /**
       
  1950  * xmlSecTransformDebugDump:
       
  1951  * @transform:		the pointer to transform.
       
  1952  * @output:		the pointer to output FILE.
       
  1953  *
       
  1954  * Prints transform's debug information to @output.
       
  1955  */
       
  1956 EXPORT_C
       
  1957 void 
       
  1958 xmlSecTransformDebugDump(xmlSecTransformPtr transform, FILE* output) {
       
  1959     xmlSecAssert(xmlSecTransformIsValid(transform));
       
  1960     xmlSecAssert(output != NULL);
       
  1961     
       
  1962     fprintf(output, "=== Transform: %s (href=%s)\n",
       
  1963 		xmlSecErrorsSafeString(transform->id->name),
       
  1964 		xmlSecErrorsSafeString(transform->id->href));
       
  1965 }
       
  1966 
       
  1967 /**
       
  1968  * xmlSecTransformDebugXmlDump:
       
  1969  * @transform:		the pointer to transform.
       
  1970  * @output:		the pointer to output FILE.
       
  1971  *
       
  1972  * Prints transform's debug information to @output in XML format.
       
  1973  */
       
  1974 EXPORT_C
       
  1975 void 
       
  1976 xmlSecTransformDebugXmlDump(xmlSecTransformPtr transform, FILE* output) {
       
  1977     xmlSecAssert(xmlSecTransformIsValid(transform));
       
  1978     xmlSecAssert(output != NULL);
       
  1979 
       
  1980     fprintf(output, "<Transform name=\"%s\" href=\"%s\" />\n",
       
  1981 		xmlSecErrorsSafeString(transform->id->name),
       
  1982 		xmlSecErrorsSafeString(transform->id->href));
       
  1983 }
       
  1984 
       
  1985 /************************************************************************
       
  1986  *
       
  1987  * Operations on transforms chain
       
  1988  *
       
  1989  ************************************************************************/ 
       
  1990 /**
       
  1991  * xmlSecTransformConnect:
       
  1992  * @left:		the pointer to left (prev) transform.
       
  1993  * @right:		the pointer to right (next) transform.
       
  1994  * @transformCtx:	the transform's chaing processing context.
       
  1995  *
       
  1996  * If the data object is a node-set and the next transform requires octets, 
       
  1997  * the signature application MUST attempt to convert the node-set to an octet 
       
  1998  * stream using Canonical XML [XML-C14N].  
       
  1999  *
       
  2000  * The story is different if the right transform is base64 decode
       
  2001  * (http://www.w3.org/TR/xmldsig-core/#sec-Base-64):
       
  2002  *
       
  2003  * This transform requires an octet stream for input. If an XPath node-set 
       
  2004  * (or sufficiently functional alternative) is given as input, then it is 
       
  2005  * converted to an octet stream by performing operations logically equivalent 
       
  2006  * to 1) applying an XPath transform with expression self::text(), then 2) 
       
  2007  * taking the string-value of the node-set. Thus, if an XML element is 
       
  2008  * identified by a barename XPointer in the Reference URI, and its content 
       
  2009  * consists solely of base64 encoded character data, then this transform 
       
  2010  * automatically strips away the start and end tags of the identified element 
       
  2011  * and any of its descendant elements as well as any descendant comments and 
       
  2012  * processing instructions. The output of this transform is an octet stream.
       
  2013  *
       
  2014  * Returns 0 on success or a negative value if an error occurs. 
       
  2015  */
       
  2016 EXPORT_C
       
  2017 int 
       
  2018 xmlSecTransformConnect(xmlSecTransformPtr left, xmlSecTransformPtr right, 
       
  2019 		       xmlSecTransformCtxPtr transformCtx) {
       
  2020     xmlSecTransformDataType leftType;
       
  2021     xmlSecTransformDataType rightType;
       
  2022     xmlSecTransformId middleId;
       
  2023     xmlSecTransformPtr middle;
       
  2024         
       
  2025     xmlSecAssert2(xmlSecTransformIsValid(left), -1);
       
  2026     xmlSecAssert2(xmlSecTransformIsValid(right), -1);
       
  2027     xmlSecAssert2(transformCtx != NULL, -1);
       
  2028 
       
  2029     leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx);
       
  2030     rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx);
       
  2031 
       
  2032     if((((leftType & xmlSecTransformDataTypeBin) != 0) && 
       
  2033         ((rightType & xmlSecTransformDataTypeBin) != 0)) || 
       
  2034        (((leftType & xmlSecTransformDataTypeXml) != 0) && 
       
  2035         ((rightType & xmlSecTransformDataTypeXml) != 0))) {
       
  2036 	
       
  2037 	left->next = right;
       
  2038 	right->prev = left;
       
  2039 	return(0);
       
  2040     } 
       
  2041     
       
  2042     if(((leftType & xmlSecTransformDataTypeBin) != 0) && 
       
  2043         ((rightType & xmlSecTransformDataTypeXml) != 0)) {
       
  2044 	    
       
  2045 	/* need to insert parser */
       
  2046 	middleId = xmlSecTransformXmlParserId;
       
  2047     } else if(((leftType & xmlSecTransformDataTypeXml) != 0) && 
       
  2048         ((rightType & xmlSecTransformDataTypeBin) != 0)) {
       
  2049 	
       
  2050 	/* need to insert c14n or special pre-base64 transform */
       
  2051 	if(xmlSecTransformCheckId(right, xmlSecTransformBase64Id)) {
       
  2052 	    middleId = xmlSecTransformRemoveXmlTagsC14NId;
       
  2053 	} else {
       
  2054 	    middleId = xmlSecTransformInclC14NId;
       
  2055 	}
       
  2056     } else {
       
  2057 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2058 		    xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
       
  2059 		    xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
       
  2060 		    XMLSEC_ERRORS_R_INVALID_TRANSFORM,
       
  2061 		    "leftType=%d;rightType=%d", 
       
  2062 		    leftType, rightType);
       
  2063 	return(-1);	
       
  2064     }
       
  2065     
       
  2066     /* insert transform */
       
  2067     middle = xmlSecTransformCreate(middleId);
       
  2068     if(middle == NULL) {
       
  2069 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2070 		    xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
       
  2071 		    "xmlSecTransformCreate",
       
  2072 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2073 		    "transform=%s",
       
  2074 		    xmlSecErrorsSafeString(xmlSecTransformKlassGetName(middleId)));
       
  2075 	return(-1);
       
  2076     }	
       
  2077     left->next = middle;
       
  2078     middle->prev = left;
       
  2079     middle->next = right;
       
  2080     right->prev = middle;
       
  2081     return(0);
       
  2082 }
       
  2083 
       
  2084 /**
       
  2085  * xmlSecTransformRemove:
       
  2086  * @transform: the pointer to #xmlSecTransform structure.
       
  2087  *
       
  2088  * Removes @transform from the chain. 
       
  2089  */
       
  2090 EXPORT_C
       
  2091 void
       
  2092 xmlSecTransformRemove(xmlSecTransformPtr transform) {
       
  2093     xmlSecAssert(xmlSecTransformIsValid(transform));
       
  2094 
       
  2095     if(transform->next != NULL) {
       
  2096 	transform->next->prev = transform->prev;
       
  2097     }
       
  2098     if(transform->prev != NULL) {
       
  2099 	transform->prev->next = transform->next;
       
  2100     }
       
  2101     transform->next = transform->prev = NULL;
       
  2102 }
       
  2103 
       
  2104 
       
  2105 /************************************************************************
       
  2106  *
       
  2107  * Default callbacks, most of the transforms can use them
       
  2108  *
       
  2109  ************************************************************************/ 
       
  2110 /**
       
  2111  * xmlSecTransformDefaultGetDataType:
       
  2112  * @transform:		the pointer to transform.
       
  2113  * @mode:		the data mode (push or pop).
       
  2114  * @transformCtx:	the transform's chaing processing context.
       
  2115  *
       
  2116  * Gets transform input (@mode is "push") or output (@mode is "pop") data 
       
  2117  * type (binary or XML) by analyzing available pushBin/popBin/pushXml/popXml
       
  2118  * methods.
       
  2119  *
       
  2120  * Returns the transform's data type for the @mode operation.
       
  2121  */
       
  2122 EXPORT_C
       
  2123 xmlSecTransformDataType 
       
  2124 xmlSecTransformDefaultGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode,
       
  2125 				  xmlSecTransformCtxPtr transformCtx) {
       
  2126     xmlSecTransformDataType type = xmlSecTransformDataTypeUnknown;
       
  2127     
       
  2128     xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown);
       
  2129     xmlSecAssert2(transformCtx != NULL, xmlSecTransformDataTypeUnknown);
       
  2130 
       
  2131     /* we'll try to guess the data type based on the handlers we have */
       
  2132     switch(mode) {
       
  2133 	case xmlSecTransformModePush:
       
  2134 	    if(transform->id->pushBin != NULL) {
       
  2135 		type |= xmlSecTransformDataTypeBin;
       
  2136 	    } 
       
  2137 	    if(transform->id->pushXml != NULL) {
       
  2138 		type |= xmlSecTransformDataTypeXml;
       
  2139 	    } 
       
  2140 	    break;
       
  2141 	case xmlSecTransformModePop:
       
  2142 	    if(transform->id->popBin != NULL) {
       
  2143 		type |= xmlSecTransformDataTypeBin;
       
  2144 	    } 
       
  2145 	    if(transform->id->popXml != NULL) {
       
  2146 		type |= xmlSecTransformDataTypeXml;
       
  2147 	    } 
       
  2148 	    break;
       
  2149 	default:
       
  2150 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2151 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2152 			NULL,
       
  2153 		        XMLSEC_ERRORS_R_INVALID_DATA,
       
  2154 			"mode=%d", mode);
       
  2155 	    return(xmlSecTransformDataTypeUnknown);
       
  2156     }
       
  2157     
       
  2158     return(type);
       
  2159 }
       
  2160 
       
  2161 /**
       
  2162  * xmlSecTransformDefaultPushBin:
       
  2163  * @transform:		the pointer to transform object.
       
  2164  * @data:		the input binary data,
       
  2165  * @dataSize:		the input data size.
       
  2166  * @final:		the flag: if set to 1 then it's the last
       
  2167  *			data chunk.
       
  2168  * @transformCtx:	the pointer to transform context object.
       
  2169  *
       
  2170  * Process binary @data by calling transform's execute method and pushes 
       
  2171  * results to next transform.
       
  2172  * 
       
  2173  * Returns 0 on success or a negative value if an error occurs.
       
  2174  */
       
  2175 EXPORT_C
       
  2176 int 
       
  2177 xmlSecTransformDefaultPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
       
  2178 			xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
       
  2179     xmlSecSize inSize = 0;
       
  2180     xmlSecSize outSize = 0;
       
  2181     int finalData = 0;
       
  2182     int ret;
       
  2183     
       
  2184     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  2185     xmlSecAssert2(transformCtx != NULL, -1);
       
  2186     
       
  2187     do {
       
  2188         /* append data to input buffer */    
       
  2189 	if(dataSize > 0) {
       
  2190 	    xmlSecSize chunkSize;
       
  2191 	    
       
  2192 	    xmlSecAssert2(data != NULL, -1);
       
  2193 
       
  2194 	    chunkSize = dataSize;
       
  2195 	    if(chunkSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
       
  2196 		chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
       
  2197 	    }
       
  2198 	    
       
  2199 	    ret = xmlSecBufferAppend(&(transform->inBuf), data, chunkSize);
       
  2200 	    if(ret < 0) {
       
  2201 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  2202 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2203 			    "xmlSecBufferAppend",
       
  2204 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2205 			    "size=%d", chunkSize);
       
  2206 		return(-1);
       
  2207 	    }	
       
  2208 
       
  2209 	    dataSize -= chunkSize;
       
  2210 	    data += chunkSize;
       
  2211 	}
       
  2212 
       
  2213 	/* process data */
       
  2214 	inSize = xmlSecBufferGetSize(&(transform->inBuf));
       
  2215 	outSize = xmlSecBufferGetSize(&(transform->outBuf));
       
  2216 	finalData = (((dataSize == 0) && (final != 0)) ? 1 : 0);
       
  2217 	ret = xmlSecTransformExecute(transform, finalData, transformCtx);
       
  2218 	if(ret < 0) {
       
  2219 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2220 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2221 			"xmlSecTransformExecute",
       
  2222 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2223 			"final=%d", final);
       
  2224 	    return(-1);
       
  2225 	}
       
  2226 
       
  2227 	/* push data to the next transform */
       
  2228 	inSize = xmlSecBufferGetSize(&(transform->inBuf));
       
  2229 	outSize = xmlSecBufferGetSize(&(transform->outBuf));
       
  2230 	if(inSize > 0) {
       
  2231 	    finalData = 0;
       
  2232 	}
       
  2233 
       
  2234 	/* we don't want to puch too much */
       
  2235 	if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
       
  2236 	    outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
       
  2237 	    finalData = 0;
       
  2238 	}
       
  2239 	if((transform->next != NULL) && ((outSize > 0) || (finalData != 0))) {
       
  2240 	    ret = xmlSecTransformPushBin(transform->next, 
       
  2241 			    xmlSecBufferGetData(&(transform->outBuf)),
       
  2242 			    outSize,
       
  2243 			    finalData,
       
  2244 			    transformCtx);
       
  2245 	    if(ret < 0) {
       
  2246 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  2247 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform->next)),
       
  2248 			    "xmlSecTransformPushBin",
       
  2249 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2250 			    "final=%d;outSize=%d", final, outSize);
       
  2251 		return(-1);
       
  2252 	    }
       
  2253 	}
       
  2254 	
       
  2255 	/* remove data anyway */
       
  2256 	if(outSize > 0) {
       
  2257 	    ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
       
  2258 	    if(ret < 0) {
       
  2259 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  2260 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2261 			    "xmlSecBufferAppend",
       
  2262 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2263 			    "size=%d", outSize);
       
  2264 		return(-1);
       
  2265 	    }
       
  2266 	}
       
  2267     } while((dataSize > 0) || (outSize > 0));
       
  2268     
       
  2269     return(0);
       
  2270 }
       
  2271 
       
  2272 /**
       
  2273  * xmlSecTransformDefaultPopBin:
       
  2274  * @transform:		the pointer to transform object.
       
  2275  * @data:		the buffer to store result data.
       
  2276  * @maxDataSize:	the size of the buffer #data.
       
  2277  * @dataSize:		the pointer to returned data size.
       
  2278  * @transformCtx:	the pointer to transform context object.
       
  2279  *
       
  2280  * Pops data from previous transform in the chain, processes data by calling
       
  2281  * transform's execute method and returns result in the @data buffer. The 
       
  2282  * size of returned data is placed in the @dataSize.
       
  2283  *
       
  2284  * Returns 0 on success or a negative value if an error occurs.
       
  2285  */
       
  2286 EXPORT_C
       
  2287 int 
       
  2288 xmlSecTransformDefaultPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
       
  2289 			    xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) {
       
  2290     xmlSecSize outSize;
       
  2291     int final = 0;
       
  2292     int ret;
       
  2293 
       
  2294     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  2295     xmlSecAssert2(data != NULL, -1);
       
  2296     xmlSecAssert2(dataSize != NULL, -1);
       
  2297     xmlSecAssert2(transformCtx != NULL, -1);
       
  2298 
       
  2299     while((xmlSecBufferGetSize(&(transform->outBuf)) == 0) && (final == 0)) {
       
  2300 	/* read data from previous transform if exist */
       
  2301 	if(transform->prev != NULL) {    
       
  2302     	    xmlSecSize inSize, chunkSize;
       
  2303 
       
  2304 	    inSize = xmlSecBufferGetSize(&(transform->inBuf));
       
  2305 	    chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
       
  2306 
       
  2307 	    /* ensure that we have space for at least one data chunk */
       
  2308     	    ret = xmlSecBufferSetMaxSize(&(transform->inBuf), inSize + chunkSize);
       
  2309     	    if(ret < 0) {
       
  2310 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  2311 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2312 			    "xmlSecBufferSetMaxSize",
       
  2313 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2314 			    "size=%d", inSize + chunkSize);
       
  2315 		return(-1);
       
  2316 	    }	
       
  2317 
       
  2318 	    /* get data from previous transform */
       
  2319 	    ret = xmlSecTransformPopBin(transform->prev, 
       
  2320 			    xmlSecBufferGetData(&(transform->inBuf)) + inSize,
       
  2321 			    chunkSize, &chunkSize, transformCtx);
       
  2322 	    if(ret < 0) {
       
  2323 		xmlSecError(XMLSEC_ERRORS_HERE,
       
  2324 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform->prev)),
       
  2325 			    "xmlSecTransformPopBin",
       
  2326 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2327 			    XMLSEC_ERRORS_NO_MESSAGE);
       
  2328 		return(-1);
       
  2329 	    }
       
  2330 	
       
  2331 	    /* adjust our size if needed */
       
  2332 	    if(chunkSize > 0) {
       
  2333 		ret = xmlSecBufferSetSize(&(transform->inBuf), inSize + chunkSize);
       
  2334 		if(ret < 0) {
       
  2335 		    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2336 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2337 				"xmlSecBufferSetSize",
       
  2338 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2339 				"size=%d", inSize + chunkSize);
       
  2340 		    return(-1);
       
  2341 	        }
       
  2342 		final = 0; /* the previous transform returned some data..*/
       
  2343 	    } else {
       
  2344 		final = 1; /* no data returned from previous transform, we are done */
       
  2345 	    }
       
  2346 	} else {
       
  2347 	    final = 1; /* no previous transform, we are "permanently final" */
       
  2348 	}	
       
  2349 
       
  2350 	/* execute our transform */
       
  2351     	ret = xmlSecTransformExecute(transform, final, transformCtx);
       
  2352 	if(ret < 0) {
       
  2353 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2354 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2355 			"xmlSecTransformExecute",
       
  2356 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2357 			XMLSEC_ERRORS_NO_MESSAGE);
       
  2358 	    return(-1);
       
  2359 	}
       
  2360     }
       
  2361     
       
  2362     /* copy result (if any) */
       
  2363     outSize = xmlSecBufferGetSize(&(transform->outBuf)); 
       
  2364     if(outSize > maxDataSize) {
       
  2365 	outSize = maxDataSize;
       
  2366     }
       
  2367     
       
  2368     /* we don't want to put too much */
       
  2369     if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
       
  2370 	outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
       
  2371     }
       
  2372     if(outSize > 0) {
       
  2373 	xmlSecAssert2(xmlSecBufferGetData(&(transform->outBuf)), -1);
       
  2374 	
       
  2375 	memcpy(data, xmlSecBufferGetData(&(transform->outBuf)), outSize);
       
  2376 
       
  2377 	ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
       
  2378     	if(ret < 0) {
       
  2379 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2380 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2381 			"xmlSecBufferRemoveHead",
       
  2382 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2383 			"size=%d", outSize);
       
  2384 	    return(-1);
       
  2385 	}	
       
  2386     }
       
  2387     
       
  2388     /* set the result size */
       
  2389     (*dataSize) = outSize;
       
  2390     return(0);
       
  2391 }
       
  2392 
       
  2393 /**
       
  2394  * xmlSecTransformDefaultPushXml:
       
  2395  * @transform:		the pointer to transform object.
       
  2396  * @nodes:		the input nodes.
       
  2397  * @transformCtx:	the pointer to transform context object.
       
  2398  *
       
  2399  * Processes @nodes by calling transform's execute method and pushes 
       
  2400  * result to the next transform in the chain.
       
  2401  *
       
  2402  * Returns 0 on success or a negative value if an error occurs.
       
  2403  */
       
  2404 EXPORT_C
       
  2405 int 
       
  2406 xmlSecTransformDefaultPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes, 
       
  2407 			    xmlSecTransformCtxPtr transformCtx) {
       
  2408     int ret;
       
  2409 
       
  2410     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  2411     xmlSecAssert2(transform->inNodes == NULL, -1);
       
  2412     xmlSecAssert2(transform->outNodes == NULL, -1);
       
  2413     xmlSecAssert2(transformCtx != NULL, -1);
       
  2414 
       
  2415     /* execute our transform */
       
  2416     transform->inNodes = nodes;
       
  2417     ret = xmlSecTransformExecute(transform, 1, transformCtx);
       
  2418     if(ret < 0) {
       
  2419 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2420 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2421 		    "xmlSecTransformExecute",
       
  2422 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2423 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2424 	return(-1);
       
  2425     }
       
  2426 
       
  2427     /* push result to the next transform (if exist) */
       
  2428     if(transform->next != NULL) {
       
  2429 	ret = xmlSecTransformPushXml(transform->next, transform->outNodes, transformCtx);
       
  2430 	if(ret < 0) {
       
  2431 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2432 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2433 			"xmlSecTransformPushXml",
       
  2434 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2435 			XMLSEC_ERRORS_NO_MESSAGE);
       
  2436 	    return(-1);
       
  2437 	}
       
  2438     }        
       
  2439     return(0);
       
  2440 }
       
  2441 
       
  2442 /**
       
  2443  * xmlSecTransformDefaultPopXml:
       
  2444  * @transform:		the pointer to transform object.
       
  2445  * @nodes:		the pointer to store popinter to result nodes.
       
  2446  * @transformCtx:	the pointer to transform context object.
       
  2447  *
       
  2448  * Pops data from previous transform in the chain, processes the data 
       
  2449  * by calling transform's execute method and returns result in @nodes.
       
  2450  *
       
  2451  * Returns 0 on success or a negative value if an error occurs.
       
  2452  */
       
  2453 EXPORT_C
       
  2454 int 
       
  2455 xmlSecTransformDefaultPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes, 
       
  2456 			    xmlSecTransformCtxPtr transformCtx) {
       
  2457     int ret;
       
  2458     
       
  2459     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
       
  2460     xmlSecAssert2(transform->inNodes == NULL, -1);
       
  2461     xmlSecAssert2(transform->outNodes == NULL, -1);
       
  2462     xmlSecAssert2(transformCtx != NULL, -1);
       
  2463     
       
  2464     /* pop result from the prev transform (if exist) */
       
  2465     if(transform->prev != NULL) {
       
  2466 	ret = xmlSecTransformPopXml(transform->prev, &(transform->inNodes), transformCtx);
       
  2467 	if(ret < 0) {
       
  2468 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2469 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2470 			"xmlSecTransformPopXml",
       
  2471 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2472 			XMLSEC_ERRORS_NO_MESSAGE);
       
  2473 	    return(-1);
       
  2474 	}
       
  2475     }        
       
  2476 
       
  2477     /* execute our transform */
       
  2478     ret = xmlSecTransformExecute(transform, 1, transformCtx);
       
  2479     if(ret < 0) {
       
  2480 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2481 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2482 		    "xmlSecTransformExecute",
       
  2483 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2484 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2485 	return(-1);
       
  2486     }
       
  2487 
       
  2488     /* return result if requested */
       
  2489     if(nodes != NULL) {
       
  2490 	(*nodes) = transform->outNodes;
       
  2491     }
       
  2492     
       
  2493     return(0);
       
  2494 }
       
  2495 
       
  2496 /***********************************************************************
       
  2497  *
       
  2498  * Transform Ids list
       
  2499  *
       
  2500  **********************************************************************/
       
  2501 static xmlSecPtrListKlass xmlSecTransformIdListKlass = {
       
  2502     BAD_CAST "transform-ids-list",
       
  2503     NULL, 							/* xmlSecPtrDuplicateItemMethod duplicateItem; */
       
  2504     NULL,							/* xmlSecPtrDestroyItemMethod destroyItem; */
       
  2505     NULL,							/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
       
  2506     NULL,							/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
       
  2507 };
       
  2508 
       
  2509 /**
       
  2510  * xmlSecTransformIdListGetKlass:
       
  2511  * 
       
  2512  * The transform id list klass.
       
  2513  *
       
  2514  * Returns pointer to the transform id list klass.
       
  2515  */
       
  2516 EXPORT_C
       
  2517 xmlSecPtrListId 
       
  2518 xmlSecTransformIdListGetKlass(void) {
       
  2519     return(&xmlSecTransformIdListKlass);
       
  2520 }
       
  2521 
       
  2522 /**
       
  2523  * xmlSecTransformIdListFind:
       
  2524  * @list:		the pointer to transform ids list.
       
  2525  * @transformId:	the transform klass.
       
  2526  *
       
  2527  * Lookups @dataId in @list.
       
  2528  *
       
  2529  * Returns 1 if @dataId is found in the @list, 0 if not and a negative
       
  2530  * value if an error occurs.
       
  2531  */
       
  2532 EXPORT_C
       
  2533 int 
       
  2534 xmlSecTransformIdListFind(xmlSecPtrListPtr list, xmlSecTransformId transformId) {
       
  2535     xmlSecSize i, size;
       
  2536     
       
  2537     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), -1);
       
  2538     xmlSecAssert2(transformId != NULL, -1);
       
  2539     
       
  2540     size = xmlSecPtrListGetSize(list);
       
  2541     for(i = 0; i < size; ++i) {
       
  2542 	if((xmlSecTransformId)xmlSecPtrListGetItem(list, i) == transformId) {
       
  2543 	    return(1);
       
  2544 	}
       
  2545     }
       
  2546     return(0);
       
  2547 }
       
  2548 
       
  2549 /** 
       
  2550  * xmlSecTransformIdListFindByHref:
       
  2551  * @list:		the pointer to transform ids list.
       
  2552  * @href:		the desired transform klass href.
       
  2553  * @usage:		the desired transform usage.
       
  2554  *
       
  2555  * Lookups data klass in the list with given @href and @usage in @list.
       
  2556  *
       
  2557  * Returns transform klass is found and NULL otherwise.
       
  2558  */
       
  2559 EXPORT_C 
       
  2560 xmlSecTransformId	
       
  2561 xmlSecTransformIdListFindByHref(xmlSecPtrListPtr list, const xmlChar* href,
       
  2562 			    xmlSecTransformUsage usage) {
       
  2563     xmlSecTransformId transformId;
       
  2564     xmlSecSize i, size;
       
  2565     
       
  2566     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown);
       
  2567     xmlSecAssert2(href != NULL, xmlSecTransformIdUnknown);
       
  2568     
       
  2569     size = xmlSecPtrListGetSize(list);
       
  2570     for(i = 0; i < size; ++i) {
       
  2571 	transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
       
  2572 	xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown);
       
  2573 
       
  2574 	if(((usage & transformId->usage) != 0) && (transformId->href != NULL) && 
       
  2575 	   xmlStrEqual(href, transformId->href)) {
       
  2576 	   
       
  2577 	   return(transformId);	   
       
  2578 	}
       
  2579     }
       
  2580     return(xmlSecTransformIdUnknown);
       
  2581 }
       
  2582 
       
  2583 /** 
       
  2584  * xmlSecTransformIdListFindByName:
       
  2585  * @list:		the pointer to transform ids list.
       
  2586  * @name:		the desired transform klass name.
       
  2587  * @usage:		the desired transform usage.
       
  2588  *
       
  2589  * Lookups data klass in the list with given @name and @usage in @list.
       
  2590  *
       
  2591  * Returns transform klass is found and NULL otherwise.
       
  2592  */
       
  2593 EXPORT_C 
       
  2594 xmlSecTransformId	
       
  2595 xmlSecTransformIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name, 
       
  2596 			    xmlSecTransformUsage usage) {
       
  2597     xmlSecTransformId transformId;
       
  2598     xmlSecSize i, size;
       
  2599     
       
  2600     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown);
       
  2601     xmlSecAssert2(name != NULL, xmlSecTransformIdUnknown);
       
  2602 
       
  2603     size = xmlSecPtrListGetSize(list);
       
  2604     for(i = 0; i < size; ++i) {
       
  2605 	transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
       
  2606 	xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown);
       
  2607 
       
  2608 	if(((usage & transformId->usage) != 0) && (transformId->name != NULL) &&
       
  2609 	   xmlStrEqual(name, BAD_CAST transformId->name)) {
       
  2610 	   
       
  2611 	   return(transformId);	   
       
  2612 	}
       
  2613     }
       
  2614     return(xmlSecTransformIdUnknown);
       
  2615 }
       
  2616 
       
  2617 /** 
       
  2618  * xmlSecTransformIdListDebugDump:
       
  2619  * @list:		the pointer to transform ids list.
       
  2620  * @output:		the pointer to output FILE.
       
  2621  * 
       
  2622  * Prints binary transform debug information to @output.
       
  2623  */
       
  2624 EXPORT_C
       
  2625 void 
       
  2626 xmlSecTransformIdListDebugDump(xmlSecPtrListPtr list, FILE* output) {
       
  2627     xmlSecTransformId transformId;
       
  2628     xmlSecSize i, size;
       
  2629     
       
  2630     xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId));
       
  2631     xmlSecAssert(output != NULL);
       
  2632 
       
  2633     size = xmlSecPtrListGetSize(list);
       
  2634     for(i = 0; i < size; ++i) {
       
  2635 	transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
       
  2636 	xmlSecAssert(transformId != NULL);
       
  2637 	xmlSecAssert(transformId->name != NULL);
       
  2638 	    
       
  2639 	if(i > 0) {
       
  2640 	    fprintf(output, ",\"%s\"", transformId->name);
       
  2641 	} else {
       
  2642 	    fprintf(output, "\"%s\"", transformId->name);
       
  2643 	}	    
       
  2644     }
       
  2645     fprintf(output, "\n");
       
  2646 }
       
  2647 
       
  2648 /** 
       
  2649  * xmlSecTransformIdListDebugXmlDump:
       
  2650  * @list:		the pointer to transform ids list.
       
  2651  * @output:		the pointer to output FILE.
       
  2652  * 
       
  2653  * Prints binary transform debug information to @output in XML format.
       
  2654  */
       
  2655 EXPORT_C
       
  2656 void 
       
  2657 xmlSecTransformIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
       
  2658     xmlSecTransformId transformId;
       
  2659     xmlSecSize i, size;
       
  2660 
       
  2661     xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId));
       
  2662     xmlSecAssert(output != NULL);
       
  2663 
       
  2664     fprintf(output, "<TransformIdsList>\n");
       
  2665     size = xmlSecPtrListGetSize(list);
       
  2666     for(i = 0; i < size; ++i) {
       
  2667 	transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
       
  2668 	xmlSecAssert(transformId != NULL);
       
  2669 	xmlSecAssert(transformId->name != NULL);
       
  2670 	    
       
  2671 	fprintf(output, "<TransformId name=\"%s\" />", transformId->name);
       
  2672     }
       
  2673     fprintf(output, "</TransformIdsList>\n");
       
  2674 }
       
  2675 
       
  2676 /************************************************************************
       
  2677  *
       
  2678  * IO buffers for transforms
       
  2679  *
       
  2680  ************************************************************************/ 
       
  2681 typedef struct _xmlSecTransformIOBuffer			xmlSecTransformIOBuffer,
       
  2682 							*xmlSecTransformIOBufferPtr;
       
  2683 typedef enum {
       
  2684     xmlSecTransformIOBufferModeRead,
       
  2685     xmlSecTransformIOBufferModeWrite
       
  2686 } xmlSecTransformIOBufferMode;
       
  2687 
       
  2688 struct _xmlSecTransformIOBuffer {
       
  2689     xmlSecTransformIOBufferMode		mode;
       
  2690     xmlSecTransformPtr			transform;
       
  2691     xmlSecTransformCtxPtr		transformCtx;
       
  2692 };
       
  2693 
       
  2694 static xmlSecTransformIOBufferPtr xmlSecTransformIOBufferCreate	(xmlSecTransformIOBufferMode mode,
       
  2695 								 xmlSecTransformPtr transform,
       
  2696 								 xmlSecTransformCtxPtr transformCtx);
       
  2697 static void	xmlSecTransformIOBufferDestroy			(xmlSecTransformIOBufferPtr buffer);
       
  2698 static int	xmlSecTransformIOBufferRead			(xmlSecTransformIOBufferPtr buffer,
       
  2699 								 xmlSecByte *buf,
       
  2700 								 xmlSecSize size);		
       
  2701 static int	xmlSecTransformIOBufferWrite			(xmlSecTransformIOBufferPtr buffer,
       
  2702 								 const xmlSecByte *buf,
       
  2703 								 xmlSecSize size);		
       
  2704 static int	xmlSecTransformIOBufferClose			(xmlSecTransformIOBufferPtr buffer);
       
  2705 
       
  2706 
       
  2707 /**
       
  2708  * xmlSecTransformCreateOutputBuffer:
       
  2709  * @transform:		the pointer to transform.
       
  2710  * @transformCtx:	the pointer to transform context object.
       
  2711  *
       
  2712  * Creates output buffer to write data to @transform.
       
  2713  *
       
  2714  * Returns pointer to new output buffer or NULL if an error occurs.
       
  2715  */
       
  2716 EXPORT_C
       
  2717 xmlOutputBufferPtr 
       
  2718 xmlSecTransformCreateOutputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
       
  2719     xmlSecTransformIOBufferPtr buffer; 
       
  2720     xmlSecTransformDataType type;
       
  2721     xmlOutputBufferPtr output;
       
  2722     
       
  2723     xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
       
  2724     xmlSecAssert2(transformCtx != NULL, NULL);
       
  2725     
       
  2726     /* check that we have binary push method for this transform */
       
  2727     type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePush, transformCtx);
       
  2728     if((type & xmlSecTransformDataTypeBin) == 0) {
       
  2729 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2730 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2731 		    NULL,
       
  2732 		    XMLSEC_ERRORS_R_INVALID_TRANSFORM,
       
  2733 		    "push binary data not supported");
       
  2734 	return(NULL);
       
  2735     }
       
  2736     
       
  2737     buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeWrite, transform, transformCtx);
       
  2738     if(buffer == NULL) {
       
  2739 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2740 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2741 		    "xmlSecTransformIOBufferCreate",
       
  2742 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2743 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2744 	return(NULL);
       
  2745     }
       
  2746     
       
  2747     output = xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecTransformIOBufferWrite,
       
  2748 				     (xmlOutputCloseCallback)xmlSecTransformIOBufferClose,
       
  2749 				     buffer,
       
  2750 				     NULL); 
       
  2751     if(output == NULL) {
       
  2752 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2753 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2754 		    "xmlOutputBufferCreateIO",
       
  2755 		    XMLSEC_ERRORS_R_XML_FAILED,
       
  2756 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2757 	xmlSecTransformIOBufferDestroy(buffer);
       
  2758 	return(NULL);
       
  2759     }
       
  2760     
       
  2761     return(output);
       
  2762 }
       
  2763 
       
  2764 /**
       
  2765  * xmlSecTransformCreateInputBuffer:
       
  2766  * @transform:		the pointer to transform.
       
  2767  * @transformCtx:	the pointer to transform context object.
       
  2768  *
       
  2769  * Creates input buffer to read data from @transform.
       
  2770  *
       
  2771  * Returns pointer to new input buffer or NULL if an error occurs.
       
  2772  */
       
  2773 EXPORT_C
       
  2774 xmlParserInputBufferPtr 
       
  2775 xmlSecTransformCreateInputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
       
  2776     xmlSecTransformIOBufferPtr buffer;    
       
  2777     xmlSecTransformDataType type;
       
  2778     xmlParserInputBufferPtr input;
       
  2779     
       
  2780     xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
       
  2781     xmlSecAssert2(transformCtx != NULL, NULL);
       
  2782 
       
  2783     /* check that we have binary pop method for this transform */
       
  2784     type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePop, transformCtx);
       
  2785     if((type & xmlSecTransformDataTypeBin) == 0) {
       
  2786 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2787 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2788 		    NULL,
       
  2789 		    XMLSEC_ERRORS_R_INVALID_TRANSFORM,
       
  2790 		    "pop binary data not supported");
       
  2791 	return(NULL);
       
  2792     }    
       
  2793 
       
  2794     buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeRead, transform, transformCtx);
       
  2795     if(buffer == NULL) {
       
  2796 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2797 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2798 		    "xmlSecTransformIOBufferCreate",
       
  2799 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2800 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2801 	return(NULL);
       
  2802     }
       
  2803     
       
  2804     input = xmlParserInputBufferCreateIO((xmlInputReadCallback)xmlSecTransformIOBufferRead,
       
  2805 				     (xmlInputCloseCallback)xmlSecTransformIOBufferClose,
       
  2806 				     buffer,
       
  2807 				     XML_CHAR_ENCODING_NONE); 
       
  2808     if(input == NULL) {
       
  2809 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2810 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  2811 		    "xmlParserInputBufferCreateIO",
       
  2812 		    XMLSEC_ERRORS_R_XML_FAILED,
       
  2813 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2814 	xmlSecTransformIOBufferDestroy(buffer);
       
  2815 	return(NULL);
       
  2816     }
       
  2817     
       
  2818     return(input);
       
  2819 }
       
  2820 
       
  2821 static xmlSecTransformIOBufferPtr 
       
  2822 xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferMode mode, xmlSecTransformPtr transform,
       
  2823 			      xmlSecTransformCtxPtr transformCtx) {
       
  2824     xmlSecTransformIOBufferPtr buffer;
       
  2825     
       
  2826     xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
       
  2827     xmlSecAssert2(transformCtx != NULL, NULL);
       
  2828     
       
  2829     buffer = (xmlSecTransformIOBufferPtr)xmlMalloc(sizeof(xmlSecTransformIOBuffer));
       
  2830     if(buffer == NULL) {
       
  2831 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2832 		    NULL,
       
  2833 		    NULL,
       
  2834 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
  2835 		    "size=%d", sizeof(xmlSecTransformIOBuffer)); 
       
  2836 	return(NULL);
       
  2837     }
       
  2838     memset(buffer, 0, sizeof(xmlSecTransformIOBuffer));
       
  2839     
       
  2840     buffer->mode = mode;
       
  2841     buffer->transform = transform;
       
  2842     buffer->transformCtx = transformCtx;
       
  2843     
       
  2844     return(buffer);
       
  2845 }
       
  2846 
       
  2847 static void 
       
  2848 xmlSecTransformIOBufferDestroy(xmlSecTransformIOBufferPtr buffer) {
       
  2849     xmlSecAssert(buffer != NULL);
       
  2850 
       
  2851     memset(buffer, 0, sizeof(xmlSecTransformIOBuffer));
       
  2852     xmlFree(buffer);
       
  2853 }
       
  2854 
       
  2855 static int 
       
  2856 xmlSecTransformIOBufferRead(xmlSecTransformIOBufferPtr buffer, 
       
  2857 			    xmlSecByte *buf, xmlSecSize size) {
       
  2858     int ret;
       
  2859     
       
  2860     xmlSecAssert2(buffer != NULL, -1);
       
  2861     xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeRead, -1);
       
  2862     xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
       
  2863     xmlSecAssert2(buffer->transformCtx != NULL, -1);
       
  2864     xmlSecAssert2(buf != NULL, -1);
       
  2865     
       
  2866     ret = xmlSecTransformPopBin(buffer->transform, buf, size, &size, buffer->transformCtx);
       
  2867     if(ret < 0) {
       
  2868 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2869 		    xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
       
  2870 		    "xmlSecTransformPopBin",
       
  2871 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2872 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2873 	return(-1);
       
  2874     }
       
  2875     return(size);
       
  2876 }
       
  2877 
       
  2878 static int 
       
  2879 xmlSecTransformIOBufferWrite(xmlSecTransformIOBufferPtr buffer, 
       
  2880 			    const xmlSecByte *buf, xmlSecSize size) {
       
  2881     int ret;
       
  2882     
       
  2883     xmlSecAssert2(buffer != NULL, -1);
       
  2884     xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeWrite, -1);
       
  2885     xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
       
  2886     xmlSecAssert2(buffer->transformCtx != NULL, -1);
       
  2887     xmlSecAssert2(buf != NULL, -1);
       
  2888 
       
  2889     ret = xmlSecTransformPushBin(buffer->transform, buf, size, 0, buffer->transformCtx);
       
  2890     if(ret < 0) {
       
  2891 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  2892 		    xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
       
  2893 		    "xmlSecTransformPushBin",
       
  2894 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2895 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  2896 	return(-1);
       
  2897     }
       
  2898     return(size);
       
  2899 }
       
  2900 
       
  2901 static int 
       
  2902 xmlSecTransformIOBufferClose(xmlSecTransformIOBufferPtr buffer) {
       
  2903     int ret;
       
  2904     
       
  2905     xmlSecAssert2(buffer != NULL, -1);
       
  2906     xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
       
  2907     xmlSecAssert2(buffer->transformCtx != NULL, -1);
       
  2908     
       
  2909     /* need to flush write buffer before destroing */
       
  2910     if(buffer->mode == xmlSecTransformIOBufferModeWrite) {
       
  2911         ret = xmlSecTransformPushBin(buffer->transform, NULL, 0, 1, buffer->transformCtx);
       
  2912 	if(ret < 0) {
       
  2913 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  2914 			xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
       
  2915 			"xmlSecTransformPushBin",
       
  2916 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  2917 			XMLSEC_ERRORS_NO_MESSAGE);
       
  2918 		xmlSecTransformIOBufferDestroy(buffer);	
       
  2919 	    return(-1);
       
  2920 	}
       
  2921     }
       
  2922     
       
  2923     xmlSecTransformIOBufferDestroy(buffer);
       
  2924     return(0);
       
  2925 }