2 * XML Security Library (http://www.aleksey.com/xmlsec).
4 * The Transforms Element (http://www.w3.org/TR/xmldsig-core/#sec-Transforms)
6 * The optional Transforms element contains an ordered list of Transform
7 * elements; these describe how the signer obtained the data object that
12 * <element name="Transforms" type="ds:TransformsType"/>
13 * <complexType name="TransformsType">
15 * <element ref="ds:Transform" maxOccurs="unbounded"/>
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"/>
26 * <attribute name="Algorithm" type="anyURI" use="required"/>
31 * <!ELEMENT Transforms (Transform+)>
32 * <!ELEMENT Transform (#PCDATA|XPath %Transform.ANY;)* >
33 * <!ATTLIST Transform Algorithm CDATA #REQUIRED >
34 * <!ELEMENT XPath (#PCDATA) >
36 * This is free software; see Copyright file in the source
37 * distribution for preciese wording.
39 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
47 #include <libxml/tree.h>
48 #include <libxml/xpath.h>
49 #include <libxml/xpointer.h>
51 #include <xmlsec/xmlsec.h>
52 #include <xmlsec/buffer.h>
53 #include <xmlsec/xmltree.h>
54 #include <xmlsec/keysdata.h>
55 #include <xmlsec/keys.h>
56 #include <xmlsec/keyinfo.h>
57 #include <xmlsec/transforms.h>
58 #include <xmlsec/base64.h>
59 #include <xmlsec/io.h>
60 #include <xmlsec/membuf.h>
61 #include <xmlsec/parser.h>
62 #include <xmlsec/errors.h>
64 /**************************************************************************
66 * Global xmlSecTransformIds list functions
68 *************************************************************************/
69 static xmlSecPtrList xmlSecAllTransformIds;
73 * xmlSecTransformIdsGet:
75 * Gets global registered transform klasses list.
77 * Returns: the pointer to list of all registered transform klasses.
80 xmlSecTransformIdsGet(void) {
81 return(&xmlSecAllTransformIds);
85 * xmlSecTransformIdsInit:
87 * Initializes the transform klasses. This function is called from the
88 * #xmlSecInit function and the application should not call it directly.
90 * Returns: 0 on success or a negative value if an error occurs.
93 xmlSecTransformIdsInit(void) {
96 ret = xmlSecPtrListInitialize(xmlSecTransformIdsGet(), xmlSecTransformIdListId);
98 xmlSecError(XMLSEC_ERRORS_HERE,
100 "xmlSecPtrListPtrInitialize",
101 XMLSEC_ERRORS_R_XMLSEC_FAILED,
102 "xmlSecTransformIdListId");
106 ret = xmlSecTransformIdsRegisterDefault();
108 xmlSecError(XMLSEC_ERRORS_HERE,
110 "xmlSecTransformIdsRegisterDefault",
111 XMLSEC_ERRORS_R_XMLSEC_FAILED,
112 XMLSEC_ERRORS_NO_MESSAGE);
120 * xmlSecTransformIdsShutdown:
122 * Shuts down the keys data klasses. This function is called from the
123 * #xmlSecShutdown function and the application should not call it directly.
126 xmlSecTransformIdsShutdown(void) {
127 xmlSecPtrListFinalize(xmlSecTransformIdsGet());
131 * xmlSecTransformIdsRegister:
132 * @id: the transform klass.
134 * Registers @id in the global list of transform klasses.
136 * Returns: 0 on success or a negative value if an error occurs.
139 xmlSecTransformIdsRegister(xmlSecTransformId id) {
142 xmlSecAssert2(id != xmlSecTransformIdUnknown, -1);
144 ret = xmlSecPtrListAdd(xmlSecTransformIdsGet(), (xmlSecPtr)id);
146 xmlSecError(XMLSEC_ERRORS_HERE,
149 XMLSEC_ERRORS_R_XMLSEC_FAILED,
151 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
159 * xmlSecTransformIdsRegisterDefault:
161 * Registers default (implemented by XML Security Library)
162 * transform klasses: XPath transform, Base64 transform, ...
164 * Returns: 0 on success or a negative value if an error occurs.
167 xmlSecTransformIdsRegisterDefault(void) {
168 if(xmlSecTransformIdsRegister(xmlSecTransformBase64Id) < 0) {
169 xmlSecError(XMLSEC_ERRORS_HERE,
171 "xmlSecTransformIdsRegister",
172 XMLSEC_ERRORS_R_XMLSEC_FAILED,
174 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformBase64Id)));
178 if(xmlSecTransformIdsRegister(xmlSecTransformEnvelopedId) < 0) {
179 xmlSecError(XMLSEC_ERRORS_HERE,
181 "xmlSecTransformIdsRegister",
182 XMLSEC_ERRORS_R_XMLSEC_FAILED,
184 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformEnvelopedId)));
189 if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NId) < 0) {
190 xmlSecError(XMLSEC_ERRORS_HERE,
192 "xmlSecTransformIdsRegister",
193 XMLSEC_ERRORS_R_XMLSEC_FAILED,
195 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId)));
198 if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NWithCommentsId) < 0) {
199 xmlSecError(XMLSEC_ERRORS_HERE,
201 "xmlSecTransformIdsRegister",
202 XMLSEC_ERRORS_R_XMLSEC_FAILED,
204 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NWithCommentsId)));
207 if(xmlSecTransformIdsRegister(xmlSecTransformInclC14N11Id) < 0) {
208 xmlSecError(XMLSEC_ERRORS_HERE,
210 "xmlSecTransformIdsRegister",
211 XMLSEC_ERRORS_R_XMLSEC_FAILED,
213 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14N11Id)));
216 if(xmlSecTransformIdsRegister(xmlSecTransformInclC14N11WithCommentsId) < 0) {
217 xmlSecError(XMLSEC_ERRORS_HERE,
219 "xmlSecTransformIdsRegister",
220 XMLSEC_ERRORS_R_XMLSEC_FAILED,
222 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14N11WithCommentsId)));
225 if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NId) < 0) {
226 xmlSecError(XMLSEC_ERRORS_HERE,
228 "xmlSecTransformIdsRegister",
229 XMLSEC_ERRORS_R_XMLSEC_FAILED,
231 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NId)));
234 if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NWithCommentsId) < 0) {
235 xmlSecError(XMLSEC_ERRORS_HERE,
237 "xmlSecTransformIdsRegister",
238 XMLSEC_ERRORS_R_XMLSEC_FAILED,
240 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NWithCommentsId)));
244 if(xmlSecTransformIdsRegister(xmlSecTransformXPathId) < 0) {
245 xmlSecError(XMLSEC_ERRORS_HERE,
247 "xmlSecTransformIdsRegister",
248 XMLSEC_ERRORS_R_XMLSEC_FAILED,
250 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPathId)));
254 if(xmlSecTransformIdsRegister(xmlSecTransformXPath2Id) < 0) {
255 xmlSecError(XMLSEC_ERRORS_HERE,
257 "xmlSecTransformIdsRegister",
258 XMLSEC_ERRORS_R_XMLSEC_FAILED,
260 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPath2Id)));
264 if(xmlSecTransformIdsRegister(xmlSecTransformXPointerId) < 0) {
265 xmlSecError(XMLSEC_ERRORS_HERE,
267 "xmlSecTransformIdsRegister",
268 XMLSEC_ERRORS_R_XMLSEC_FAILED,
270 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId)));
274 #ifndef XMLSEC_NO_XSLT
275 if(xmlSecTransformIdsRegister(xmlSecTransformXsltId) < 0) {
276 xmlSecError(XMLSEC_ERRORS_HERE,
278 "xmlSecTransformIdsRegister",
279 XMLSEC_ERRORS_R_XMLSEC_FAILED,
281 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXsltId)));
284 #endif /* XMLSEC_NO_XSLT */
289 /**************************************************************************
293 *************************************************************************/
295 * xmlSecTransformUriTypeCheck:
296 * @type: the expected URI type.
297 * @uri: the uri for checking.
299 * Checks if @uri matches expected type @type.
301 * Returns: 1 if @uri matches @type, 0 if not or a negative value
302 * if an error occurs.
305 xmlSecTransformUriTypeCheck(xmlSecTransformUriType type, const xmlChar* uri) {
306 xmlSecTransformUriType uriType = 0;
308 if((uri == NULL) || (xmlStrlen(uri) == 0)) {
309 uriType = xmlSecTransformUriTypeEmpty;
310 } else if(uri[0] == '#') {
311 uriType = xmlSecTransformUriTypeSameDocument;
312 } else if(xmlStrncmp(uri, BAD_CAST "file://", 7) == 0) {
313 uriType = xmlSecTransformUriTypeLocal;
315 uriType = xmlSecTransformUriTypeRemote;
317 return(((uriType & type) != 0) ? 1 : 0);
320 /**************************************************************************
324 *************************************************************************/
327 * xmlSecTransformCtxCreate:
329 * Creates transforms chain processing context.
330 * The caller is responsible for destroying returend object by calling
331 * #xmlSecTransformCtxDestroy function.
333 * Returns: pointer to newly allocated context object or NULL if an error
336 xmlSecTransformCtxPtr
337 xmlSecTransformCtxCreate(void) {
338 xmlSecTransformCtxPtr ctx;
341 /* Allocate a new xmlSecTransform and fill the fields. */
342 ctx = (xmlSecTransformCtxPtr)xmlMalloc(sizeof(xmlSecTransformCtx));
344 xmlSecError(XMLSEC_ERRORS_HERE,
347 XMLSEC_ERRORS_R_MALLOC_FAILED,
348 "size=%d", sizeof(xmlSecTransformCtx));
352 ret = xmlSecTransformCtxInitialize(ctx);
354 xmlSecError(XMLSEC_ERRORS_HERE,
356 "xmlSecTransformCtxInitialize",
357 XMLSEC_ERRORS_R_XMLSEC_FAILED,
358 XMLSEC_ERRORS_NO_MESSAGE);
359 xmlSecTransformCtxDestroy(ctx);
367 * xmlSecTransformCtxDestroy:
368 * @ctx: the pointer to transforms chain processing context.
370 * Destroy context object created with #xmlSecTransformCtxCreate function.
373 xmlSecTransformCtxDestroy(xmlSecTransformCtxPtr ctx) {
374 xmlSecAssert(ctx != NULL);
376 xmlSecTransformCtxFinalize(ctx);
381 * xmlSecTransformCtxInitialize:
382 * @ctx: the pointer to transforms chain processing context.
384 * Initializes transforms chain processing context.
385 * The caller is responsible for cleaing up returend object by calling
386 * #xmlSecTransformCtxFinalize function.
388 * Returns: 0 on success or a negative value if an error occurs.
391 xmlSecTransformCtxInitialize(xmlSecTransformCtxPtr ctx) {
394 xmlSecAssert2(ctx != NULL, -1);
396 memset(ctx, 0, sizeof(xmlSecTransformCtx));
398 ret = xmlSecPtrListInitialize(&(ctx->enabledTransforms), xmlSecTransformIdListId);
400 xmlSecError(XMLSEC_ERRORS_HERE,
402 "xmlSecPtrListInitialize",
403 XMLSEC_ERRORS_R_XMLSEC_FAILED,
404 XMLSEC_ERRORS_NO_MESSAGE);
408 ctx->enabledUris = xmlSecTransformUriTypeAny;
413 * xmlSecTransformCtxFinalize:
414 * @ctx: the pointer to transforms chain processing context.
416 * Cleans up @ctx object initialized with #xmlSecTransformCtxInitialize function.
419 xmlSecTransformCtxFinalize(xmlSecTransformCtxPtr ctx) {
420 xmlSecAssert(ctx != NULL);
422 xmlSecTransformCtxReset(ctx);
423 xmlSecPtrListFinalize(&(ctx->enabledTransforms));
424 memset(ctx, 0, sizeof(xmlSecTransformCtx));
428 * xmlSecTransformCtxReset:
429 * @ctx: the pointer to transforms chain processing context.
431 * Resets transfroms context for new processing.
434 xmlSecTransformCtxReset(xmlSecTransformCtxPtr ctx) {
435 xmlSecTransformPtr transform, tmp;
437 xmlSecAssert(ctx != NULL);
440 ctx->status = xmlSecTransformStatusNone;
443 if(ctx->uri != NULL) {
447 if(ctx->xptrExpr != NULL) {
448 xmlFree(ctx->xptrExpr);
449 ctx->xptrExpr = NULL;
452 /* destroy transforms chain */
453 for(transform = ctx->first; transform != NULL; transform = tmp) {
454 tmp = transform->next;
455 xmlSecTransformDestroy(transform);
457 ctx->first = ctx->last = NULL;
461 * xmlSecTransformCtxCopyUserPref:
462 * @dst: the pointer to destination transforms chain processing context.
463 * @src: the pointer to source transforms chain processing context.
465 * Copies user settings from @src context to @dst.
467 * Returns: 0 on success or a negative value otherwise.
470 xmlSecTransformCtxCopyUserPref(xmlSecTransformCtxPtr dst, xmlSecTransformCtxPtr src) {
473 xmlSecAssert2(dst != NULL, -1);
474 xmlSecAssert2(src != NULL, -1);
476 dst->userData = src->userData;
477 dst->flags = src->flags;
478 dst->flags2 = src->flags2;
479 dst->enabledUris = src->enabledUris;
480 dst->preExecCallback = src->preExecCallback;
482 ret = xmlSecPtrListCopy(&(dst->enabledTransforms), &(src->enabledTransforms));
484 xmlSecError(XMLSEC_ERRORS_HERE,
487 XMLSEC_ERRORS_R_XMLSEC_FAILED,
488 XMLSEC_ERRORS_NO_MESSAGE);
496 * xmlSecTransformCtxAppend:
497 * @ctx: the pointer to transforms chain processing context.
498 * @transform: the pointer to new transform.
500 * Connects the @transform to the end of the chain of transforms in the @ctx
501 * (see #xmlSecTransformConnect function for details).
503 * Returns: 0 on success or a negative value otherwise.
506 xmlSecTransformCtxAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) {
509 xmlSecAssert2(ctx != NULL, -1);
510 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
511 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
513 if(ctx->last != NULL) {
514 ret = xmlSecTransformConnect(ctx->last, transform, ctx);
516 xmlSecError(XMLSEC_ERRORS_HERE,
518 "xmlSecTransformConnect",
519 XMLSEC_ERRORS_R_XMLSEC_FAILED,
521 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
525 xmlSecAssert2(ctx->first == NULL, -1);
526 ctx->first = transform;
528 ctx->last = transform;
534 * xmlSecTransformCtxPrepend:
535 * @ctx: the pointer to transforms chain processing context.
536 * @transform: the pointer to new transform.
538 * Connects the @transform to the beggining of the chain of transforms in the @ctx
539 * (see #xmlSecTransformConnect function for details).
541 * Returns: 0 on success or a negative value otherwise.
544 xmlSecTransformCtxPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) {
547 xmlSecAssert2(ctx != NULL, -1);
548 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
549 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
551 if(ctx->first != NULL) {
552 ret = xmlSecTransformConnect(transform, ctx->first, ctx);
554 xmlSecError(XMLSEC_ERRORS_HERE,
556 "xmlSecTransformConnect",
557 XMLSEC_ERRORS_R_XMLSEC_FAILED,
559 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
563 xmlSecAssert2(ctx->last == NULL, -1);
564 ctx->last = transform;
566 ctx->first = transform;
572 * xmlSecTransformCtxCreateAndAppend:
573 * @ctx: the pointer to transforms chain processing context.
574 * @id: the new transform klass.
576 * Creaeates new transform and connects it to the end of the chain of
577 * transforms in the @ctx (see #xmlSecTransformConnect function for details).
579 * Returns: pointer to newly created transform or NULL if an error occurs.
582 xmlSecTransformCtxCreateAndAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) {
583 xmlSecTransformPtr transform;
586 xmlSecAssert2(ctx != NULL, NULL);
587 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
588 xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL);
590 transform = xmlSecTransformCreate(id);
591 if(!xmlSecTransformIsValid(transform)) {
592 xmlSecError(XMLSEC_ERRORS_HERE,
594 "xmlSecTransformCreate",
595 XMLSEC_ERRORS_R_XMLSEC_FAILED,
597 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
601 ret = xmlSecTransformCtxAppend(ctx, transform);
603 xmlSecError(XMLSEC_ERRORS_HERE,
605 "xmlSecTransformCtxAppend",
606 XMLSEC_ERRORS_R_XMLSEC_FAILED,
608 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
609 xmlSecTransformDestroy(transform);
617 * xmlSecTransformCtxCreateAndPrepend:
618 * @ctx: the pointer to transforms chain processing context.
619 * @id: the new transform klass.
621 * Creaeates new transform and connects it to the end of the chain of
622 * transforms in the @ctx (see #xmlSecTransformConnect function for details).
624 * Returns: pointer to newly created transform or NULL if an error occurs.
627 xmlSecTransformCtxCreateAndPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) {
628 xmlSecTransformPtr transform;
631 xmlSecAssert2(ctx != NULL, NULL);
632 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
633 xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL);
635 transform = xmlSecTransformCreate(id);
636 if(!xmlSecTransformIsValid(transform)) {
637 xmlSecError(XMLSEC_ERRORS_HERE,
639 "xmlSecTransformCreate",
640 XMLSEC_ERRORS_R_XMLSEC_FAILED,
642 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
646 ret = xmlSecTransformCtxPrepend(ctx, transform);
648 xmlSecError(XMLSEC_ERRORS_HERE,
650 "xmlSecTransformCtxPrepend",
651 XMLSEC_ERRORS_R_XMLSEC_FAILED,
653 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
654 xmlSecTransformDestroy(transform);
662 * xmlSecTransformCtxNodeRead:
663 * @ctx: the pointer to transforms chain processing context.
664 * @node: the pointer to transform's node.
665 * @usage: the transform's usage (signature, encryption, etc.).
667 * Reads the transform from the @node and appends it to the current chain
668 * of transforms in @ctx.
670 * Returns: pointer to newly created transform or NULL if an error occurs.
673 xmlSecTransformCtxNodeRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node,
674 xmlSecTransformUsage usage) {
675 xmlSecTransformPtr transform;
678 xmlSecAssert2(ctx != NULL, NULL);
679 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
680 xmlSecAssert2(node != NULL, NULL);
682 transform = xmlSecTransformNodeRead(node, usage, ctx);
683 if(transform == NULL) {
684 xmlSecError(XMLSEC_ERRORS_HERE,
686 "xmlSecTransformNodeRead",
687 XMLSEC_ERRORS_R_XMLSEC_FAILED,
689 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
693 ret = xmlSecTransformCtxAppend(ctx, transform);
695 xmlSecError(XMLSEC_ERRORS_HERE,
697 "xmlSecTransformCtxAppend",
698 XMLSEC_ERRORS_R_XMLSEC_FAILED,
700 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
701 xmlSecTransformDestroy(transform);
709 * xmlSecTransformCtxNodesListRead:
710 * @ctx: the pointer to transforms chain processing context.
711 * @node: the pointer to <dsig:Transform/> nodes parent node.
712 * @usage: the transform's usage (signature, encryption, etc.).
714 * Reads transforms from the <dsig:Transform/> children of the @node and
715 * appends them to the current transforms chain in @ctx object.
717 * Returns: 0 on success or a negative value otherwise.
720 xmlSecTransformCtxNodesListRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node, xmlSecTransformUsage usage) {
721 xmlSecTransformPtr transform;
725 xmlSecAssert2(ctx != NULL, -1);
726 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
727 xmlSecAssert2(node != NULL, -1);
729 cur = xmlSecGetNextElementNode(node->children);
730 while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTransform, xmlSecDSigNs)) {
731 transform = xmlSecTransformNodeRead(cur, usage, ctx);
732 if(transform == NULL) {
733 xmlSecError(XMLSEC_ERRORS_HERE,
735 "xmlSecTransformNodeRead",
736 XMLSEC_ERRORS_R_XMLSEC_FAILED,
738 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
742 ret = xmlSecTransformCtxAppend(ctx, transform);
744 xmlSecError(XMLSEC_ERRORS_HERE,
746 "xmlSecTransformCtxAppend",
747 XMLSEC_ERRORS_R_XMLSEC_FAILED,
749 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
750 xmlSecTransformDestroy(transform);
753 cur = xmlSecGetNextElementNode(cur->next);
757 xmlSecError(XMLSEC_ERRORS_HERE,
759 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
760 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
761 XMLSEC_ERRORS_NO_MESSAGE);
768 * xmlSecTransformCtxSetUri:
769 * @ctx: the pointer to transforms chain processing context.
771 * @hereNode: the pointer to "here" node required by some
772 * XML transforms (may be NULL).
774 * Parses uri and adds xpointer transforms if required.
776 * The following examples demonstrate what the URI attribute identifies and
777 * how it is dereferenced
778 * (http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel):
780 * - URI="http://example.com/bar.xml"
781 * identifies the octets that represent the external resource
782 * 'http://example.com/bar.xml', that is probably an XML document given
783 * its file extension.
785 * - URI="http://example.com/bar.xml#chapter1"
786 * identifies the element with ID attribute value 'chapter1' of the
787 * external XML resource 'http://example.com/bar.xml', provided as an
788 * octet stream. Again, for the sake of interoperability, the element
789 * identified as 'chapter1' should be obtained using an XPath transform
790 * rather than a URI fragment (barename XPointer resolution in external
791 * resources is not REQUIRED in this specification).
794 * identifies the node-set (minus any comment nodes) of the XML resource
795 * containing the signature
798 * identifies a node-set containing the element with ID attribute value
799 * 'chapter1' of the XML resource containing the signature. XML Signature
800 * (and its applications) modify this node-set to include the element plus
801 * all descendents including namespaces and attributes -- but not comments.
803 * Returns: 0 on success or a negative value otherwise.
806 xmlSecTransformCtxSetUri(xmlSecTransformCtxPtr ctx, const xmlChar* uri, xmlNodePtr hereNode) {
807 xmlSecNodeSetType nodeSetType = xmlSecNodeSetTree;
810 int useVisa3DHack = 0;
813 xmlSecAssert2(ctx != NULL, -1);
814 xmlSecAssert2(ctx->uri == NULL, -1);
815 xmlSecAssert2(ctx->xptrExpr == NULL, -1);
816 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
817 xmlSecAssert2(hereNode != NULL, -1);
820 if(xmlSecTransformUriTypeCheck(ctx->enabledUris, uri) != 1) {
821 xmlSecError(XMLSEC_ERRORS_HERE,
824 XMLSEC_ERRORS_R_INVALID_URI_TYPE,
826 xmlSecErrorsSafeString(uri));
830 /* is it an empty uri? */
831 if((uri == NULL) || (xmlStrlen(uri) == 0)) {
835 /* do we have barename or full xpointer? */
836 xptr = xmlStrchr(uri, '#');
838 ctx->uri = xmlStrdup(uri);
839 if(ctx->uri == NULL) {
840 xmlSecError(XMLSEC_ERRORS_HERE,
843 XMLSEC_ERRORS_R_STRDUP_FAILED,
844 "size=%d", xmlStrlen(uri));
849 } else if(xmlStrcmp(uri, BAD_CAST "#xpointer(/)") == 0) {
850 ctx->xptrExpr = xmlStrdup(uri);
851 if(ctx->xptrExpr == NULL) {
852 xmlSecError(XMLSEC_ERRORS_HERE,
855 XMLSEC_ERRORS_R_STRDUP_FAILED,
856 "size=%d", xmlStrlen(uri));
863 ctx->uri = xmlStrndup(uri, xptr - uri);
864 if(ctx->uri == NULL) {
865 xmlSecError(XMLSEC_ERRORS_HERE,
868 XMLSEC_ERRORS_R_STRDUP_FAILED,
869 "size=%d", xptr - uri);
873 ctx->xptrExpr = xmlStrdup(xptr);
874 if(ctx->xptrExpr == NULL) {
875 xmlSecError(XMLSEC_ERRORS_HERE,
878 XMLSEC_ERRORS_R_STRDUP_FAILED,
879 "size=%d", xmlStrlen(xptr));
883 /* do we have barename or full xpointer? */
884 xmlSecAssert2(xptr != NULL, -1);
885 if((xmlStrncmp(xptr, BAD_CAST "#xpointer(", 10) == 0) || (xmlStrncmp(xptr, BAD_CAST "#xmlns(", 7) == 0)) {
887 nodeSetType = xmlSecNodeSetTree;
888 } else if((ctx->flags & XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK) != 0) {
890 nodeSetType = xmlSecNodeSetTreeWithoutComments;
893 static const char tmpl[] = "xpointer(id(\'%s\'))";
896 /* we need to add "xpointer(id('..')) because otherwise we have
897 * problems with numeric ("111" and so on) and other "strange" ids */
898 size = xmlStrlen(BAD_CAST tmpl) + xmlStrlen(xptr) + 2;
899 buf = (xmlChar*)xmlMalloc(size * sizeof(xmlChar));
901 xmlSecError(XMLSEC_ERRORS_HERE,
904 XMLSEC_ERRORS_R_MALLOC_FAILED,
908 sprintf((char*)buf, tmpl, xptr + 1);
910 nodeSetType = xmlSecNodeSetTreeWithoutComments;
913 if(useVisa3DHack == 0) {
914 xmlSecTransformPtr transform;
916 /* we need to create XPonter transform to execute expr */
917 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXPointerId);
918 if(!xmlSecTransformIsValid(transform)) {
919 xmlSecError(XMLSEC_ERRORS_HERE,
921 "xmlSecTransformCtxCreateAndPrepend",
922 XMLSEC_ERRORS_R_XMLSEC_FAILED,
924 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId)));
928 ret = xmlSecTransformXPointerSetExpr(transform, xptr, nodeSetType, hereNode);
930 xmlSecError(XMLSEC_ERRORS_HERE,
932 "xmlSecTransformXPointerSetExpr",
933 XMLSEC_ERRORS_R_XMLSEC_FAILED,
935 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
942 /* Visa3D protocol doesn't follow XML/XPointer/XMLDSig specs
943 * and allows invalid XPointer expressions (e.g. "#12345") in
945 * Since we couldn't evaluate such expressions thru XPath/XPointer
946 * engine, we need to have this hack here
948 xmlSecTransformPtr transform;
950 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformVisa3DHackId);
951 if(!xmlSecTransformIsValid(transform)) {
952 xmlSecError(XMLSEC_ERRORS_HERE,
954 "xmlSecTransformCtxCreateAndPrepend",
955 XMLSEC_ERRORS_R_XMLSEC_FAILED,
957 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformVisa3DHackId)));
961 ret = xmlSecTransformVisa3DHackSetID(transform, xptr);
963 xmlSecError(XMLSEC_ERRORS_HERE,
965 "xmlSecTransformVisa3DHackSetID",
966 XMLSEC_ERRORS_R_XMLSEC_FAILED,
968 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
983 * xmlSecTransformCtxPrepare:
984 * @ctx: the pointer to transforms chain processing context.
985 * @inputDataType: the expected input type.
987 * Prepares the transform context for processing data of @inputDataType.
989 * Returns: 0 on success or a negative value otherwise.
992 xmlSecTransformCtxPrepare(xmlSecTransformCtxPtr ctx, xmlSecTransformDataType inputDataType) {
993 xmlSecTransformDataType firstType;
994 xmlSecTransformPtr transform;
997 xmlSecAssert2(ctx != NULL, -1);
998 xmlSecAssert2(ctx->result == NULL, -1);
999 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
1001 /* add binary buffer to store result */
1002 transform = xmlSecTransformCtxCreateAndAppend(ctx, xmlSecTransformMemBufId);
1003 if(!xmlSecTransformIsValid(transform)) {
1004 xmlSecError(XMLSEC_ERRORS_HERE,
1006 "xmlSecTransformCreate",
1007 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1009 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
1012 ctx->result = xmlSecTransformMemBufGetBuffer(transform);
1013 if(ctx->result == NULL) {
1014 xmlSecError(XMLSEC_ERRORS_HERE,
1016 "xmlSecTransformMemBufGetBuffer",
1017 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1019 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
1023 firstType = xmlSecTransformGetDataType(ctx->first, xmlSecTransformModePush, ctx);
1024 if(((firstType & xmlSecTransformDataTypeBin) == 0) &&
1025 ((inputDataType & xmlSecTransformDataTypeBin) != 0)) {
1027 /* need to add parser transform */
1028 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXmlParserId);
1029 if(transform == NULL) {
1030 xmlSecError(XMLSEC_ERRORS_HERE,
1032 "xmlSecTransformCtxCreateAndPrepend",
1033 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1035 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXmlParserId)));
1038 } else if(((firstType & xmlSecTransformDataTypeXml) == 0) &&
1039 ((inputDataType & xmlSecTransformDataTypeXml) != 0)) {
1041 /* need to add c14n transform */
1042 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInclC14NId);
1043 if(transform == NULL) {
1044 xmlSecError(XMLSEC_ERRORS_HERE,
1046 "xmlSecTransformCtxCreateAndPrepend",
1047 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1049 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId)));
1054 /* finally let application a chance to verify that it's ok to execte
1055 * this transforms chain */
1056 if(ctx->preExecCallback != NULL) {
1057 ret = (ctx->preExecCallback)(ctx);
1059 xmlSecError(XMLSEC_ERRORS_HERE,
1061 "ctx->preExecCallback",
1062 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1063 XMLSEC_ERRORS_NO_MESSAGE);
1068 ctx->status = xmlSecTransformStatusWorking;
1073 * xmlSecTransformCtxBinaryExecute:
1074 * @ctx: the pointer to transforms chain processing context.
1075 * @data: the input binary data buffer.
1076 * @dataSize: the input data size.
1078 * Processes binary data using transforms chain in the @ctx.
1080 * Returns: 0 on success or a negative value otherwise.
1083 xmlSecTransformCtxBinaryExecute(xmlSecTransformCtxPtr ctx,
1084 const xmlSecByte* data, xmlSecSize dataSize) {
1087 xmlSecAssert2(ctx != NULL, -1);
1088 xmlSecAssert2(ctx->result == NULL, -1);
1089 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
1090 xmlSecAssert2(data != NULL, -1);
1091 xmlSecAssert2(dataSize > 0, -1);
1093 /* we should not have uri stored in ctx */
1094 xmlSecAssert2(ctx->uri == NULL, -1);
1096 ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeBin);
1098 xmlSecError(XMLSEC_ERRORS_HERE,
1100 "xmlSecTransformCtxPrepare",
1101 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1106 ret = xmlSecTransformPushBin(ctx->first, data, dataSize, 1, ctx);
1108 xmlSecError(XMLSEC_ERRORS_HERE,
1110 "xmlSecTransformCtxPushBin",
1111 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1112 "dataSize=%d", dataSize);
1116 ctx->status = xmlSecTransformStatusFinished;
1121 * xmlSecTransformCtxUriExecute:
1122 * @ctx: the pointer to transforms chain processing context.
1125 * Process binary data from the URI using transforms chain in @ctx.
1127 * Returns: 0 on success or a negative value otherwise.
1130 xmlSecTransformCtxUriExecute(xmlSecTransformCtxPtr ctx, const xmlChar* uri) {
1131 xmlSecTransformPtr uriTransform;
1134 xmlSecAssert2(ctx != NULL, -1);
1135 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
1136 xmlSecAssert2(uri != NULL, -1);
1138 /* we should not execute transform for a different uri */
1139 xmlSecAssert2((ctx->uri == NULL) || (uri == ctx->uri) || xmlStrEqual(uri, ctx->uri), -1);
1141 uriTransform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInputURIId);
1142 if(uriTransform == NULL) {
1143 xmlSecError(XMLSEC_ERRORS_HERE,
1145 "xmlSecTransformCtxCreateAndPrepend",
1146 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1148 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInputURIId)));
1152 ret = xmlSecTransformInputURIOpen(uriTransform, uri);
1154 xmlSecError(XMLSEC_ERRORS_HERE,
1156 "xmlSecTransformInputURIOpen",
1157 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1159 xmlSecErrorsSafeString(uri));
1163 /* we do not need to do something special for this transform */
1164 ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeUnknown);
1166 xmlSecError(XMLSEC_ERRORS_HERE,
1168 "xmlSecTransformCtxPrepare",
1169 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1174 /* Now we have a choice: we either can push from first transform or pop
1175 * from last. Our C14N transforms prefers push, so push data!
1177 ret = xmlSecTransformPump(uriTransform, uriTransform->next, ctx);
1179 xmlSecError(XMLSEC_ERRORS_HERE,
1181 "xmlSecTransformPump",
1182 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1184 xmlSecErrorsSafeString(uri));
1188 ctx->status = xmlSecTransformStatusFinished;
1193 * xmlSecTransformCtxXmlExecute:
1194 * @ctx: the pointer to transforms chain processing context.
1195 * @nodes: the input node set.
1197 * Process @nodes using transforms in the transforms chain in @ctx.
1199 * Returns: 0 on success or a negative value otherwise.
1202 xmlSecTransformCtxXmlExecute(xmlSecTransformCtxPtr ctx, xmlSecNodeSetPtr nodes) {
1205 xmlSecAssert2(ctx != NULL, -1);
1206 xmlSecAssert2(ctx->result == NULL, -1);
1207 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
1208 xmlSecAssert2(nodes != NULL, -1);
1210 xmlSecAssert2((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0), -1);
1212 ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeXml);
1214 xmlSecError(XMLSEC_ERRORS_HERE,
1216 "xmlSecTransformCtxPrepare",
1217 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1222 /* it's better to do push than pop because all XML transform
1223 * just don't care and c14n likes push more than pop */
1224 ret = xmlSecTransformPushXml(ctx->first, nodes, ctx);
1226 xmlSecError(XMLSEC_ERRORS_HERE,
1228 "xmlSecTransformPushXml",
1229 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1231 xmlSecErrorsSafeString(xmlSecTransformGetName(ctx->first)));
1235 ctx->status = xmlSecTransformStatusFinished;
1240 * xmlSecTransformCtxExecute:
1241 * @ctx: the pointer to transforms chain processing context.
1242 * @doc: the pointer to input document.
1244 * Executes transforms chain in @ctx.
1246 * Returns: 0 on success or a negative value otherwise.
1249 xmlSecTransformCtxExecute(xmlSecTransformCtxPtr ctx, xmlDocPtr doc) {
1252 xmlSecAssert2(ctx != NULL, -1);
1253 xmlSecAssert2(ctx->result == NULL, -1);
1254 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
1255 xmlSecAssert2(doc != NULL, -1);
1257 if((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0)) {
1258 xmlSecNodeSetPtr nodes;
1260 if((ctx->xptrExpr != NULL) && (xmlStrlen(ctx->xptrExpr) > 0)){
1261 /* our xpointer transform takes care of providing correct nodes set */
1262 nodes = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetNormal);
1264 xmlSecError(XMLSEC_ERRORS_HERE,
1266 "xmlSecNodeSetCreate",
1267 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1268 XMLSEC_ERRORS_NO_MESSAGE);
1273 /* we do not want to have comments for empty URI */
1274 nodes = xmlSecNodeSetGetChildren(doc, NULL, 0, 0);
1276 xmlSecError(XMLSEC_ERRORS_HERE,
1278 "xmlSecNodeSetGetChildren",
1279 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1280 XMLSEC_ERRORS_NO_MESSAGE);
1284 ret = xmlSecTransformCtxXmlExecute(ctx, nodes);
1286 xmlSecError(XMLSEC_ERRORS_HERE,
1288 "xmlSecTransformCtxXmlExecute",
1289 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1290 XMLSEC_ERRORS_NO_MESSAGE);
1291 xmlSecNodeSetDestroy(nodes);
1294 /* TODO: don't destroy nodes here */
1295 xmlSecNodeSetDestroy(nodes);
1297 ret = xmlSecTransformCtxUriExecute(ctx, ctx->uri);
1299 xmlSecError(XMLSEC_ERRORS_HERE,
1301 "xmlSecTransformCtxUriExecute",
1302 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1303 XMLSEC_ERRORS_NO_MESSAGE);
1312 * xmlSecTransformCtxDebugDump:
1313 * @ctx: the pointer to transforms chain processing context.
1314 * @output: the pointer to output FILE.
1316 * Prints transforms context debug information to @output.
1319 xmlSecTransformCtxDebugDump(xmlSecTransformCtxPtr ctx, FILE* output) {
1320 xmlSecTransformPtr transform;
1322 xmlSecAssert(ctx != NULL);
1323 xmlSecAssert(output != NULL);
1325 fprintf(output, "== TRANSFORMS CTX (status=%d)\n", ctx->status);
1327 fprintf(output, "== flags: 0x%08x\n", ctx->flags);
1328 fprintf(output, "== flags2: 0x%08x\n", ctx->flags2);
1329 if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) {
1330 fprintf(output, "== enabled transforms: ");
1331 xmlSecTransformIdListDebugDump(&(ctx->enabledTransforms), output);
1333 fprintf(output, "== enabled transforms: all\n");
1336 fprintf(output, "=== uri: %s\n",
1337 (ctx->uri != NULL) ? ctx->uri : BAD_CAST "NULL");
1338 fprintf(output, "=== uri xpointer expr: %s\n",
1339 (ctx->xptrExpr != NULL) ? ctx->xptrExpr : BAD_CAST "NULL");
1340 for(transform = ctx->first; transform != NULL; transform = transform->next) {
1341 xmlSecTransformDebugDump(transform, output);
1346 * xmlSecTransformCtxDebugXmlDump:
1347 * @ctx: the pointer to transforms chain processing context.
1348 * @output: the pointer to output FILE.
1350 * Prints transforms context debug information to @output in XML format.
1353 xmlSecTransformCtxDebugXmlDump(xmlSecTransformCtxPtr ctx, FILE* output) {
1354 xmlSecTransformPtr transform;
1356 xmlSecAssert(ctx != NULL);
1357 xmlSecAssert(output != NULL);
1359 fprintf(output, "<TransformCtx status=\"%d\">\n", ctx->status);
1361 fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags);
1362 fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2);
1363 if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) {
1364 fprintf(output, "<EnabledTransforms>\n");
1365 xmlSecTransformIdListDebugXmlDump(&(ctx->enabledTransforms), output);
1366 fprintf(output, "</EnabledTransforms>\n");
1368 fprintf(output, "<EnabledTransforms>all</EnabledTransforms>\n");
1372 fprintf(output, "<Uri>");
1373 xmlSecPrintXmlString(output, ctx->uri);
1374 fprintf(output, "</Uri>\n");
1376 fprintf(output, "<UriXPointer>");
1377 xmlSecPrintXmlString(output, ctx->xptrExpr);
1378 fprintf(output, "</UriXPointer>\n");
1380 for(transform = ctx->first; transform != NULL; transform = transform->next) {
1381 xmlSecTransformDebugXmlDump(transform, output);
1383 fprintf(output, "</TransformCtx>\n");
1386 /**************************************************************************
1390 *************************************************************************/
1392 * xmlSecTransformCreate:
1393 * @id: the transform id to create.
1395 * Creates new transform of the @id klass. The caller is responsible for
1396 * destroying returned tansform using #xmlSecTransformDestroy function.
1398 * Returns: pointer to newly created transform or NULL if an error occurs.
1401 xmlSecTransformCreate(xmlSecTransformId id) {
1402 xmlSecTransformPtr transform;
1405 xmlSecAssert2(id != NULL, NULL);
1406 xmlSecAssert2(id->klassSize >= sizeof(xmlSecTransformKlass), NULL);
1407 xmlSecAssert2(id->objSize >= sizeof(xmlSecTransform), NULL);
1408 xmlSecAssert2(id->name != NULL, NULL);
1410 /* Allocate a new xmlSecTransform and fill the fields. */
1411 transform = (xmlSecTransformPtr)xmlMalloc(id->objSize);
1412 if(transform == NULL) {
1413 xmlSecError(XMLSEC_ERRORS_HERE,
1416 XMLSEC_ERRORS_R_MALLOC_FAILED,
1417 "size=%d", id->objSize);
1420 memset(transform, 0, id->objSize);
1423 if(id->initialize != NULL) {
1424 ret = (id->initialize)(transform);
1426 xmlSecError(XMLSEC_ERRORS_HERE,
1427 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
1429 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1430 XMLSEC_ERRORS_NO_MESSAGE);
1431 xmlSecTransformDestroy(transform);
1436 ret = xmlSecBufferInitialize(&(transform->inBuf), 0);
1438 xmlSecError(XMLSEC_ERRORS_HERE,
1439 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
1440 "xmlSecBufferInitialize",
1441 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1443 xmlSecTransformDestroy(transform);
1447 ret = xmlSecBufferInitialize(&(transform->outBuf), 0);
1449 xmlSecError(XMLSEC_ERRORS_HERE,
1450 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
1451 "xmlSecBufferInitialize",
1452 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1454 xmlSecTransformDestroy(transform);
1462 * xmlSecTransformDestroy:
1463 * @transform: the pointer to transform.
1465 * Destroys transform created with #xmlSecTransformCreate function.
1468 xmlSecTransformDestroy(xmlSecTransformPtr transform) {
1469 xmlSecAssert(xmlSecTransformIsValid(transform));
1470 xmlSecAssert(transform->id->objSize > 0);
1472 /* first need to remove ourselves from chain */
1473 xmlSecTransformRemove(transform);
1475 xmlSecBufferFinalize(&(transform->inBuf));
1476 xmlSecBufferFinalize(&(transform->outBuf));
1478 /* we never destroy input nodes, output nodes
1479 * are destroyed if and only if they are different
1482 if((transform->outNodes != NULL) && (transform->outNodes != transform->inNodes)) {
1483 xmlSecNodeSetDestroy(transform->outNodes);
1485 if(transform->id->finalize != NULL) {
1486 (transform->id->finalize)(transform);
1488 memset(transform, 0, transform->id->objSize);
1493 * xmlSecTransformNodeRead:
1494 * @node: the pointer to the transform's node.
1495 * @usage: the transform usage (signature, encryption, ...).
1496 * @transformCtx: the transform's chaing processing context.
1498 * Reads transform from the @node as follows:
1500 * 1) reads "Algorithm" attribute;
1502 * 2) checks the lists of known and allowed transforms;
1504 * 3) calls transform's create method;
1506 * 4) calls transform's read transform node method.
1508 * Returns: pointer to newly created transform or NULL if an error occurs.
1511 xmlSecTransformNodeRead(xmlNodePtr node, xmlSecTransformUsage usage, xmlSecTransformCtxPtr transformCtx) {
1512 xmlSecTransformPtr transform;
1513 xmlSecTransformId id;
1517 xmlSecAssert2(node != NULL, NULL);
1518 xmlSecAssert2(transformCtx != NULL, NULL);
1520 href = xmlGetProp(node, xmlSecAttrAlgorithm);
1522 xmlSecError(XMLSEC_ERRORS_HERE,
1524 xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
1525 XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
1527 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
1531 id = xmlSecTransformIdListFindByHref(xmlSecTransformIdsGet(), href, usage);
1532 if(id == xmlSecTransformIdUnknown) {
1533 xmlSecError(XMLSEC_ERRORS_HERE,
1535 "xmlSecTransformIdListFindByHref",
1536 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1538 xmlSecErrorsSafeString(href));
1543 /* check with enabled transforms list */
1544 if((xmlSecPtrListGetSize(&(transformCtx->enabledTransforms)) > 0) &&
1545 (xmlSecTransformIdListFind(&(transformCtx->enabledTransforms), id) != 1)) {
1546 xmlSecError(XMLSEC_ERRORS_HERE,
1548 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)),
1549 XMLSEC_ERRORS_R_TRANSFORM_DISABLED,
1551 xmlSecErrorsSafeString(href));
1556 transform = xmlSecTransformCreate(id);
1557 if(!xmlSecTransformIsValid(transform)) {
1558 xmlSecError(XMLSEC_ERRORS_HERE,
1560 "xmlSecTransformCreate",
1561 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1563 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
1568 if(transform->id->readNode != NULL) {
1569 ret = transform->id->readNode(transform, node, transformCtx);
1571 xmlSecError(XMLSEC_ERRORS_HERE,
1574 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1576 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
1577 xmlSecTransformDestroy(transform);
1583 /* finally remember the transform node */
1584 transform->hereNode = node;
1590 * xmlSecTransformPump:
1591 * @left: the source pumping transform.
1592 * @right: the destination pumping transform.
1593 * @transformCtx: the transform's chaing processing context.
1595 * Pops data from @left transform and pushes to @right transform until
1596 * no more data is available.
1598 * Returns: 0 on success or a negative value if an error occurs.
1601 xmlSecTransformPump(xmlSecTransformPtr left, xmlSecTransformPtr right, xmlSecTransformCtxPtr transformCtx) {
1602 xmlSecTransformDataType leftType;
1603 xmlSecTransformDataType rightType;
1606 xmlSecAssert2(xmlSecTransformIsValid(left), -1);
1607 xmlSecAssert2(xmlSecTransformIsValid(right), -1);
1608 xmlSecAssert2(transformCtx != NULL, -1);
1610 leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx);
1611 rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx);
1613 if(((leftType & xmlSecTransformDataTypeXml) != 0) &&
1614 ((rightType & xmlSecTransformDataTypeXml) != 0)) {
1616 xmlSecNodeSetPtr nodes = NULL;
1618 ret = xmlSecTransformPopXml(left, &nodes, transformCtx);
1620 xmlSecError(XMLSEC_ERRORS_HERE,
1621 xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
1622 "xmlSecTransformPopXml",
1623 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1624 XMLSEC_ERRORS_NO_MESSAGE);
1628 ret = xmlSecTransformPushXml(right, nodes, transformCtx);
1630 xmlSecError(XMLSEC_ERRORS_HERE,
1631 xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
1632 "xmlSecTransformPushXml",
1633 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1634 XMLSEC_ERRORS_NO_MESSAGE);
1637 } else if(((leftType & xmlSecTransformDataTypeBin) != 0) &&
1638 ((rightType & xmlSecTransformDataTypeBin) != 0)) {
1639 xmlSecByte buf[XMLSEC_TRANSFORM_BINARY_CHUNK];
1644 ret = xmlSecTransformPopBin(left, buf, sizeof(buf), &bufSize, transformCtx);
1646 xmlSecError(XMLSEC_ERRORS_HERE,
1647 xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
1648 "xmlSecTransformPopBin",
1649 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1650 XMLSEC_ERRORS_NO_MESSAGE);
1653 final = (bufSize == 0) ? 1 : 0;
1654 ret = xmlSecTransformPushBin(right, buf, bufSize, final, transformCtx);
1656 xmlSecError(XMLSEC_ERRORS_HERE,
1657 xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
1658 "xmlSecTransformPushBin",
1659 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1660 XMLSEC_ERRORS_NO_MESSAGE);
1663 } while(final == 0);
1665 xmlSecError(XMLSEC_ERRORS_HERE,
1666 xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
1667 xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
1668 XMLSEC_ERRORS_R_INVALID_TRANSFORM,
1669 "transforms input/output data formats do not match");
1676 * xmlSecTransformSetKey:
1677 * @transform: the pointer to transform.
1678 * @key: the pointer to key.
1680 * Sets the transform's key.
1682 * Returns: 0 on success or a negative value otherwise.
1685 xmlSecTransformSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
1686 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1687 xmlSecAssert2(key != NULL, -1);
1689 if(transform->id->setKey != NULL) {
1690 return((transform->id->setKey)(transform, key));
1696 * xmlSecTransformSetKeyReq:
1697 * @transform: the pointer to transform.
1698 * @keyReq: the pointer to keys requirements object.
1700 * Sets the key requirements for @transform in the @keyReq.
1702 * Returns: 0 on success or a negative value otherwise.
1705 xmlSecTransformSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
1706 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1707 xmlSecAssert2(keyReq != NULL, -1);
1709 keyReq->keyId = xmlSecKeyDataIdUnknown;
1710 keyReq->keyType = xmlSecKeyDataTypeUnknown;
1711 keyReq->keyUsage = xmlSecKeyUsageAny;
1712 keyReq->keyBitsSize = 0;
1714 if(transform->id->setKeyReq != NULL) {
1715 return((transform->id->setKeyReq)(transform, keyReq));
1721 * xmlSecTransformVerify:
1722 * @transform: the pointer to transform.
1723 * @data: the binary data for verification.
1724 * @dataSize: the data size.
1725 * @transformCtx: the transform's chaing processing context.
1727 * Verifies the data with transform's processing results
1728 * (for digest, HMAC and signature transforms). The verification
1729 * result is stored in the #status member of #xmlSecTransform object.
1731 * Returns: 0 on success or a negative value if an error occurs.
1734 xmlSecTransformVerify(xmlSecTransformPtr transform, const xmlSecByte* data,
1735 xmlSecSize dataSize, xmlSecTransformCtxPtr transformCtx) {
1736 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1737 xmlSecAssert2(transform->id->verify != NULL, -1);
1738 xmlSecAssert2(transformCtx != NULL, -1);
1740 return((transform->id->verify)(transform, data, dataSize, transformCtx));
1744 * xmlSecTransformVerifyNodeContent:
1745 * @transform: the pointer to transform.
1746 * @node: the pointer to node.
1747 * @transformCtx: the transform's chaing processing context.
1749 * Gets the @node content, base64 decodes it and calls #xmlSecTransformVerify
1750 * function to verify binary results.
1752 * Returns: 0 on success or a negative value if an error occurs.
1755 xmlSecTransformVerifyNodeContent(xmlSecTransformPtr transform, xmlNodePtr node,
1756 xmlSecTransformCtxPtr transformCtx) {
1757 xmlSecBuffer buffer;
1760 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1761 xmlSecAssert2(node != NULL, -1);
1762 xmlSecAssert2(transformCtx != NULL, -1);
1764 ret = xmlSecBufferInitialize(&buffer, 0);
1766 xmlSecError(XMLSEC_ERRORS_HERE,
1767 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
1768 "xmlSecBufferInitialize",
1769 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1770 XMLSEC_ERRORS_NO_MESSAGE);
1774 ret = xmlSecBufferBase64NodeContentRead(&buffer, node);
1775 if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL)) {
1776 xmlSecError(XMLSEC_ERRORS_HERE,
1777 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
1778 "xmlSecBufferBase64NodeContentRead",
1779 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1780 XMLSEC_ERRORS_NO_MESSAGE);
1781 xmlSecBufferFinalize(&buffer);
1785 ret = xmlSecTransformVerify(transform, xmlSecBufferGetData(&buffer),
1786 xmlSecBufferGetSize(&buffer), transformCtx);
1788 xmlSecError(XMLSEC_ERRORS_HERE,
1789 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
1790 "xmlSecTransformVerify",
1791 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1792 XMLSEC_ERRORS_NO_MESSAGE);
1793 xmlSecBufferFinalize(&buffer);
1797 xmlSecBufferFinalize(&buffer);
1802 * xmlSecTransformGetDataType:
1803 * @transform: the pointer to transform.
1804 * @mode: the data mode (push or pop).
1805 * @transformCtx: the transform's chaing processing context.
1807 * Gets transform input (@mode is "push") or output (@mode is "pop") data
1808 * type (binary or XML).
1810 * Returns: the transform's data type for the @mode operation.
1812 xmlSecTransformDataType
1813 xmlSecTransformGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode,
1814 xmlSecTransformCtxPtr transformCtx) {
1815 xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown);
1816 xmlSecAssert2(transform->id->getDataType != NULL, xmlSecTransformDataTypeUnknown);
1818 return((transform->id->getDataType)(transform, mode, transformCtx));
1822 * xmlSecTransformPushBin:
1823 * @transform: the pointer to transform object.
1824 * @data: the input binary data,
1825 * @dataSize: the input data size.
1826 * @final: the flag: if set to 1 then it's the last
1828 * @transformCtx: the pointer to transform context object.
1830 * Process binary @data and pushes results to next transform.
1832 * Returns: 0 on success or a negative value if an error occurs.
1835 xmlSecTransformPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
1836 xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
1837 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1838 xmlSecAssert2(transform->id->pushBin != NULL, -1);
1839 xmlSecAssert2(transformCtx != NULL, -1);
1841 return((transform->id->pushBin)(transform, data, dataSize, final, transformCtx));
1845 * xmlSecTransformPopBin:
1846 * @transform: the pointer to transform object.
1847 * @data: the buffer to store result data.
1848 * @maxDataSize: the size of the buffer #data.
1849 * @dataSize: the pointer to returned data size.
1850 * @transformCtx: the pointer to transform context object.
1852 * Pops data from previous transform in the chain, processes data and
1853 * returns result in the @data buffer. The size of returned data is
1854 * placed in the @dataSize.
1856 * Returns: 0 on success or a negative value if an error occurs.
1859 xmlSecTransformPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
1860 xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) {
1861 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1862 xmlSecAssert2(transform->id->popBin != NULL, -1);
1863 xmlSecAssert2(data != NULL, -1);
1864 xmlSecAssert2(dataSize != NULL, -1);
1865 xmlSecAssert2(transformCtx != NULL, -1);
1867 return((transform->id->popBin)(transform, data, maxDataSize, dataSize, transformCtx));
1871 * xmlSecTransformPushXml:
1872 * @transform: the pointer to transform object.
1873 * @nodes: the input nodes.
1874 * @transformCtx: the pointer to transform context object.
1876 * Processes @nodes and pushes result to the next transform in the chain.
1878 * Returns: 0 on success or a negative value if an error occurs.
1881 xmlSecTransformPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes,
1882 xmlSecTransformCtxPtr transformCtx) {
1883 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1884 xmlSecAssert2(transform->id->pushXml != NULL, -1);
1885 xmlSecAssert2(transformCtx != NULL, -1);
1887 return((transform->id->pushXml)(transform, nodes, transformCtx));
1891 * xmlSecTransformPopXml:
1892 * @transform: the pointer to transform object.
1893 * @nodes: the pointer to store popinter to result nodes.
1894 * @transformCtx: the pointer to transform context object.
1896 * Pops data from previous transform in the chain, processes the data and
1897 * returns result in @nodes.
1899 * Returns: 0 on success or a negative value if an error occurs.
1902 xmlSecTransformPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
1903 xmlSecTransformCtxPtr transformCtx) {
1904 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1905 xmlSecAssert2(transform->id->popXml != NULL, -1);
1906 xmlSecAssert2(transformCtx != NULL, -1);
1908 return((transform->id->popXml)(transform, nodes, transformCtx));
1912 * xmlSecTransformExecute:
1913 * @transform: the pointer to transform.
1914 * @last: the flag: if set to 1 then it's the last data chunk.
1915 * @transformCtx: the transform's chaing processing context.
1917 * Executes transform (used by default popBin/pushBin/popXml/pushXml methods).
1919 * Returns: 0 on success or a negative value if an error occurs.
1922 xmlSecTransformExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
1923 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
1924 xmlSecAssert2(transform->id->execute != NULL, -1);
1925 xmlSecAssert2(transformCtx != NULL, -1);
1927 return((transform->id->execute)(transform, last, transformCtx));
1931 * xmlSecTransformDebugDump:
1932 * @transform: the pointer to transform.
1933 * @output: the pointer to output FILE.
1935 * Prints transform's debug information to @output.
1938 xmlSecTransformDebugDump(xmlSecTransformPtr transform, FILE* output) {
1939 xmlSecAssert(xmlSecTransformIsValid(transform));
1940 xmlSecAssert(output != NULL);
1942 fprintf(output, "=== Transform: %s (href=%s)\n",
1943 xmlSecErrorsSafeString(transform->id->name),
1944 xmlSecErrorsSafeString(transform->id->href));
1948 * xmlSecTransformDebugXmlDump:
1949 * @transform: the pointer to transform.
1950 * @output: the pointer to output FILE.
1952 * Prints transform's debug information to @output in XML format.
1955 xmlSecTransformDebugXmlDump(xmlSecTransformPtr transform, FILE* output) {
1956 xmlSecAssert(xmlSecTransformIsValid(transform));
1957 xmlSecAssert(output != NULL);
1959 fprintf(output, "<Transform name=\"");
1960 xmlSecPrintXmlString(output,transform->id->name);
1961 fprintf(output, "\" href=\"");
1962 xmlSecPrintXmlString(output, transform->id->href);
1963 fprintf(output, "\" />\n");
1966 /************************************************************************
1968 * Operations on transforms chain
1970 ************************************************************************/
1972 * xmlSecTransformConnect:
1973 * @left: the pointer to left (prev) transform.
1974 * @right: the pointer to right (next) transform.
1975 * @transformCtx: the transform's chaing processing context.
1977 * If the data object is a node-set and the next transform requires octets,
1978 * the signature application MUST attempt to convert the node-set to an octet
1979 * stream using Canonical XML [XML-C14N].
1981 * The story is different if the right transform is base64 decode
1982 * (http://www.w3.org/TR/xmldsig-core/#sec-Base-64):
1984 * This transform requires an octet stream for input. If an XPath node-set
1985 * (or sufficiently functional alternative) is given as input, then it is
1986 * converted to an octet stream by performing operations logically equivalent
1987 * to 1) applying an XPath transform with expression self::text(), then 2)
1988 * taking the string-value of the node-set. Thus, if an XML element is
1989 * identified by a barename XPointer in the Reference URI, and its content
1990 * consists solely of base64 encoded character data, then this transform
1991 * automatically strips away the start and end tags of the identified element
1992 * and any of its descendant elements as well as any descendant comments and
1993 * processing instructions. The output of this transform is an octet stream.
1995 * Returns: 0 on success or a negative value if an error occurs.
1998 xmlSecTransformConnect(xmlSecTransformPtr left, xmlSecTransformPtr right,
1999 xmlSecTransformCtxPtr transformCtx) {
2000 xmlSecTransformDataType leftType;
2001 xmlSecTransformDataType rightType;
2002 xmlSecTransformId middleId;
2003 xmlSecTransformPtr middle;
2005 xmlSecAssert2(xmlSecTransformIsValid(left), -1);
2006 xmlSecAssert2(xmlSecTransformIsValid(right), -1);
2007 xmlSecAssert2(transformCtx != NULL, -1);
2009 leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx);
2010 rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx);
2012 /* happy case first: nothing need to be done */
2013 if((((leftType & xmlSecTransformDataTypeBin) != 0) &&
2014 ((rightType & xmlSecTransformDataTypeBin) != 0)) ||
2015 (((leftType & xmlSecTransformDataTypeXml) != 0) &&
2016 ((rightType & xmlSecTransformDataTypeXml) != 0))) {
2023 if(((leftType & xmlSecTransformDataTypeBin) != 0) &&
2024 ((rightType & xmlSecTransformDataTypeXml) != 0)) {
2026 /* need to insert parser */
2027 middleId = xmlSecTransformXmlParserId;
2028 } else if(((leftType & xmlSecTransformDataTypeXml) != 0) &&
2029 ((rightType & xmlSecTransformDataTypeBin) != 0)) {
2031 /* need to insert c14n or special pre-base64 transform */
2032 if(xmlSecTransformCheckId(right, xmlSecTransformBase64Id)) {
2033 middleId = xmlSecTransformRemoveXmlTagsC14NId;
2035 middleId = xmlSecTransformInclC14NId;
2038 xmlSecError(XMLSEC_ERRORS_HERE,
2039 xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
2040 xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
2041 XMLSEC_ERRORS_R_INVALID_TRANSFORM,
2042 "leftType=%d;rightType=%d",
2043 leftType, rightType);
2047 /* insert transform */
2048 middle = xmlSecTransformCreate(middleId);
2049 if(middle == NULL) {
2050 xmlSecError(XMLSEC_ERRORS_HERE,
2051 xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
2052 "xmlSecTransformCreate",
2053 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2055 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(middleId)));
2058 left->next = middle;
2059 middle->prev = left;
2060 middle->next = right;
2061 right->prev = middle;
2066 * xmlSecTransformRemove:
2067 * @transform: the pointer to #xmlSecTransform structure.
2069 * Removes @transform from the chain.
2072 xmlSecTransformRemove(xmlSecTransformPtr transform) {
2073 xmlSecAssert(xmlSecTransformIsValid(transform));
2075 if(transform->next != NULL) {
2076 transform->next->prev = transform->prev;
2078 if(transform->prev != NULL) {
2079 transform->prev->next = transform->next;
2081 transform->next = transform->prev = NULL;
2085 /************************************************************************
2087 * Default callbacks, most of the transforms can use them
2089 ************************************************************************/
2091 * xmlSecTransformDefaultGetDataType:
2092 * @transform: the pointer to transform.
2093 * @mode: the data mode (push or pop).
2094 * @transformCtx: the transform's chaing processing context.
2096 * Gets transform input (@mode is "push") or output (@mode is "pop") data
2097 * type (binary or XML) by analyzing available pushBin/popBin/pushXml/popXml
2100 * Returns: the transform's data type for the @mode operation.
2102 xmlSecTransformDataType
2103 xmlSecTransformDefaultGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode,
2104 xmlSecTransformCtxPtr transformCtx) {
2105 xmlSecTransformDataType type = xmlSecTransformDataTypeUnknown;
2107 xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown);
2108 xmlSecAssert2(transformCtx != NULL, xmlSecTransformDataTypeUnknown);
2110 /* we'll try to guess the data type based on the handlers we have */
2112 case xmlSecTransformModePush:
2113 if(transform->id->pushBin != NULL) {
2114 type |= xmlSecTransformDataTypeBin;
2116 if(transform->id->pushXml != NULL) {
2117 type |= xmlSecTransformDataTypeXml;
2120 case xmlSecTransformModePop:
2121 if(transform->id->popBin != NULL) {
2122 type |= xmlSecTransformDataTypeBin;
2124 if(transform->id->popXml != NULL) {
2125 type |= xmlSecTransformDataTypeXml;
2129 xmlSecError(XMLSEC_ERRORS_HERE,
2130 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2132 XMLSEC_ERRORS_R_INVALID_DATA,
2134 return(xmlSecTransformDataTypeUnknown);
2141 * xmlSecTransformDefaultPushBin:
2142 * @transform: the pointer to transform object.
2143 * @data: the input binary data,
2144 * @dataSize: the input data size.
2145 * @final: the flag: if set to 1 then it's the last
2147 * @transformCtx: the pointer to transform context object.
2149 * Process binary @data by calling transform's execute method and pushes
2150 * results to next transform.
2152 * Returns: 0 on success or a negative value if an error occurs.
2155 xmlSecTransformDefaultPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
2156 xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
2157 xmlSecSize inSize = 0;
2158 xmlSecSize outSize = 0;
2162 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
2163 xmlSecAssert2(transformCtx != NULL, -1);
2166 /* append data to input buffer */
2168 xmlSecSize chunkSize;
2170 xmlSecAssert2(data != NULL, -1);
2172 chunkSize = dataSize;
2173 if(chunkSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
2174 chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
2177 ret = xmlSecBufferAppend(&(transform->inBuf), data, chunkSize);
2179 xmlSecError(XMLSEC_ERRORS_HERE,
2180 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2181 "xmlSecBufferAppend",
2182 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2183 "size=%d", chunkSize);
2187 dataSize -= chunkSize;
2192 inSize = xmlSecBufferGetSize(&(transform->inBuf));
2193 outSize = xmlSecBufferGetSize(&(transform->outBuf));
2194 finalData = (((dataSize == 0) && (final != 0)) ? 1 : 0);
2195 ret = xmlSecTransformExecute(transform, finalData, transformCtx);
2197 xmlSecError(XMLSEC_ERRORS_HERE,
2198 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2199 "xmlSecTransformExecute",
2200 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2205 /* push data to the next transform */
2206 inSize = xmlSecBufferGetSize(&(transform->inBuf));
2207 outSize = xmlSecBufferGetSize(&(transform->outBuf));
2212 /* we don't want to puch too much */
2213 if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
2214 outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
2217 if((transform->next != NULL) && ((outSize > 0) || (finalData != 0))) {
2218 ret = xmlSecTransformPushBin(transform->next,
2219 xmlSecBufferGetData(&(transform->outBuf)),
2224 xmlSecError(XMLSEC_ERRORS_HERE,
2225 xmlSecErrorsSafeString(xmlSecTransformGetName(transform->next)),
2226 "xmlSecTransformPushBin",
2227 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2228 "final=%d;outSize=%d", final, outSize);
2233 /* remove data anyway */
2235 ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
2237 xmlSecError(XMLSEC_ERRORS_HERE,
2238 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2239 "xmlSecBufferAppend",
2240 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2241 "size=%d", outSize);
2245 } while((dataSize > 0) || (outSize > 0));
2251 * xmlSecTransformDefaultPopBin:
2252 * @transform: the pointer to transform object.
2253 * @data: the buffer to store result data.
2254 * @maxDataSize: the size of the buffer #data.
2255 * @dataSize: the pointer to returned data size.
2256 * @transformCtx: the pointer to transform context object.
2258 * Pops data from previous transform in the chain, processes data by calling
2259 * transform's execute method and returns result in the @data buffer. The
2260 * size of returned data is placed in the @dataSize.
2262 * Returns: 0 on success or a negative value if an error occurs.
2265 xmlSecTransformDefaultPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
2266 xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) {
2271 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
2272 xmlSecAssert2(data != NULL, -1);
2273 xmlSecAssert2(dataSize != NULL, -1);
2274 xmlSecAssert2(transformCtx != NULL, -1);
2276 while((xmlSecBufferGetSize(&(transform->outBuf)) == 0) && (final == 0)) {
2277 /* read data from previous transform if exist */
2278 if(transform->prev != NULL) {
2279 xmlSecSize inSize, chunkSize;
2281 inSize = xmlSecBufferGetSize(&(transform->inBuf));
2282 chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
2284 /* ensure that we have space for at least one data chunk */
2285 ret = xmlSecBufferSetMaxSize(&(transform->inBuf), inSize + chunkSize);
2287 xmlSecError(XMLSEC_ERRORS_HERE,
2288 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2289 "xmlSecBufferSetMaxSize",
2290 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2291 "size=%d", inSize + chunkSize);
2295 /* get data from previous transform */
2296 ret = xmlSecTransformPopBin(transform->prev,
2297 xmlSecBufferGetData(&(transform->inBuf)) + inSize,
2298 chunkSize, &chunkSize, transformCtx);
2300 xmlSecError(XMLSEC_ERRORS_HERE,
2301 xmlSecErrorsSafeString(xmlSecTransformGetName(transform->prev)),
2302 "xmlSecTransformPopBin",
2303 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2304 XMLSEC_ERRORS_NO_MESSAGE);
2308 /* adjust our size if needed */
2310 ret = xmlSecBufferSetSize(&(transform->inBuf), inSize + chunkSize);
2312 xmlSecError(XMLSEC_ERRORS_HERE,
2313 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2314 "xmlSecBufferSetSize",
2315 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2316 "size=%d", inSize + chunkSize);
2319 final = 0; /* the previous transform returned some data..*/
2321 final = 1; /* no data returned from previous transform, we are done */
2324 final = 1; /* no previous transform, we are "permanently final" */
2327 /* execute our transform */
2328 ret = xmlSecTransformExecute(transform, final, transformCtx);
2330 xmlSecError(XMLSEC_ERRORS_HERE,
2331 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2332 "xmlSecTransformExecute",
2333 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2334 XMLSEC_ERRORS_NO_MESSAGE);
2339 /* copy result (if any) */
2340 outSize = xmlSecBufferGetSize(&(transform->outBuf));
2341 if(outSize > maxDataSize) {
2342 outSize = maxDataSize;
2345 /* we don't want to put too much */
2346 if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
2347 outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
2350 xmlSecAssert2(xmlSecBufferGetData(&(transform->outBuf)), -1);
2352 memcpy(data, xmlSecBufferGetData(&(transform->outBuf)), outSize);
2354 ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
2356 xmlSecError(XMLSEC_ERRORS_HERE,
2357 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2358 "xmlSecBufferRemoveHead",
2359 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2360 "size=%d", outSize);
2365 /* set the result size */
2366 (*dataSize) = outSize;
2371 * xmlSecTransformDefaultPushXml:
2372 * @transform: the pointer to transform object.
2373 * @nodes: the input nodes.
2374 * @transformCtx: the pointer to transform context object.
2376 * Processes @nodes by calling transform's execute method and pushes
2377 * result to the next transform in the chain.
2379 * Returns: 0 on success or a negative value if an error occurs.
2382 xmlSecTransformDefaultPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes,
2383 xmlSecTransformCtxPtr transformCtx) {
2386 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
2387 xmlSecAssert2(transform->inNodes == NULL, -1);
2388 xmlSecAssert2(transform->outNodes == NULL, -1);
2389 xmlSecAssert2(transformCtx != NULL, -1);
2391 /* execute our transform */
2392 transform->inNodes = nodes;
2393 ret = xmlSecTransformExecute(transform, 1, transformCtx);
2395 xmlSecError(XMLSEC_ERRORS_HERE,
2396 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2397 "xmlSecTransformExecute",
2398 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2399 XMLSEC_ERRORS_NO_MESSAGE);
2403 /* push result to the next transform (if exist) */
2404 if(transform->next != NULL) {
2405 ret = xmlSecTransformPushXml(transform->next, transform->outNodes, transformCtx);
2407 xmlSecError(XMLSEC_ERRORS_HERE,
2408 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2409 "xmlSecTransformPushXml",
2410 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2411 XMLSEC_ERRORS_NO_MESSAGE);
2419 * xmlSecTransformDefaultPopXml:
2420 * @transform: the pointer to transform object.
2421 * @nodes: the pointer to store popinter to result nodes.
2422 * @transformCtx: the pointer to transform context object.
2424 * Pops data from previous transform in the chain, processes the data
2425 * by calling transform's execute method and returns result in @nodes.
2427 * Returns: 0 on success or a negative value if an error occurs.
2430 xmlSecTransformDefaultPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
2431 xmlSecTransformCtxPtr transformCtx) {
2434 xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
2435 xmlSecAssert2(transform->inNodes == NULL, -1);
2436 xmlSecAssert2(transform->outNodes == NULL, -1);
2437 xmlSecAssert2(transformCtx != NULL, -1);
2439 /* pop result from the prev transform (if exist) */
2440 if(transform->prev != NULL) {
2441 ret = xmlSecTransformPopXml(transform->prev, &(transform->inNodes), transformCtx);
2443 xmlSecError(XMLSEC_ERRORS_HERE,
2444 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2445 "xmlSecTransformPopXml",
2446 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2447 XMLSEC_ERRORS_NO_MESSAGE);
2452 /* execute our transform */
2453 ret = xmlSecTransformExecute(transform, 1, transformCtx);
2455 xmlSecError(XMLSEC_ERRORS_HERE,
2456 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2457 "xmlSecTransformExecute",
2458 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2459 XMLSEC_ERRORS_NO_MESSAGE);
2463 /* return result if requested */
2465 (*nodes) = transform->outNodes;
2471 /***********************************************************************
2473 * Transform Ids list
2475 **********************************************************************/
2476 static xmlSecPtrListKlass xmlSecTransformIdListKlass = {
2477 BAD_CAST "transform-ids-list",
2478 NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
2479 NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */
2480 NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
2481 NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
2485 * xmlSecTransformIdListGetKlass:
2487 * The transform id list klass.
2489 * Returns: pointer to the transform id list klass.
2492 xmlSecTransformIdListGetKlass(void) {
2493 return(&xmlSecTransformIdListKlass);
2497 * xmlSecTransformIdListFind:
2498 * @list: the pointer to transform ids list.
2499 * @transformId: the transform klass.
2501 * Lookups @dataId in @list.
2503 * Returns: 1 if @dataId is found in the @list, 0 if not and a negative
2504 * value if an error occurs.
2507 xmlSecTransformIdListFind(xmlSecPtrListPtr list, xmlSecTransformId transformId) {
2510 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), -1);
2511 xmlSecAssert2(transformId != NULL, -1);
2513 size = xmlSecPtrListGetSize(list);
2514 for(i = 0; i < size; ++i) {
2515 if((xmlSecTransformId)xmlSecPtrListGetItem(list, i) == transformId) {
2523 * xmlSecTransformIdListFindByHref:
2524 * @list: the pointer to transform ids list.
2525 * @href: the desired transform klass href.
2526 * @usage: the desired transform usage.
2528 * Lookups data klass in the list with given @href and @usage in @list.
2530 * Returns: transform klass is found and NULL otherwise.
2533 xmlSecTransformIdListFindByHref(xmlSecPtrListPtr list, const xmlChar* href,
2534 xmlSecTransformUsage usage) {
2535 xmlSecTransformId transformId;
2538 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown);
2539 xmlSecAssert2(href != NULL, xmlSecTransformIdUnknown);
2541 size = xmlSecPtrListGetSize(list);
2542 for(i = 0; i < size; ++i) {
2543 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
2544 xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown);
2546 if(((usage & transformId->usage) != 0) && (transformId->href != NULL) &&
2547 xmlStrEqual(href, transformId->href)) {
2548 return(transformId);
2551 return(xmlSecTransformIdUnknown);
2555 * xmlSecTransformIdListFindByName:
2556 * @list: the pointer to transform ids list.
2557 * @name: the desired transform klass name.
2558 * @usage: the desired transform usage.
2560 * Lookups data klass in the list with given @name and @usage in @list.
2562 * Returns: transform klass is found and NULL otherwise.
2565 xmlSecTransformIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name,
2566 xmlSecTransformUsage usage) {
2567 xmlSecTransformId transformId;
2570 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown);
2571 xmlSecAssert2(name != NULL, xmlSecTransformIdUnknown);
2573 size = xmlSecPtrListGetSize(list);
2574 for(i = 0; i < size; ++i) {
2575 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
2576 xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown);
2578 if(((usage & transformId->usage) != 0) && (transformId->name != NULL) &&
2579 xmlStrEqual(name, BAD_CAST transformId->name)) {
2581 return(transformId);
2584 return(xmlSecTransformIdUnknown);
2588 * xmlSecTransformIdListDebugDump:
2589 * @list: the pointer to transform ids list.
2590 * @output: the pointer to output FILE.
2592 * Prints binary transform debug information to @output.
2595 xmlSecTransformIdListDebugDump(xmlSecPtrListPtr list, FILE* output) {
2596 xmlSecTransformId transformId;
2599 xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId));
2600 xmlSecAssert(output != NULL);
2602 size = xmlSecPtrListGetSize(list);
2603 for(i = 0; i < size; ++i) {
2604 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
2605 xmlSecAssert(transformId != NULL);
2606 xmlSecAssert(transformId->name != NULL);
2609 fprintf(output, ",\"%s\"", transformId->name);
2611 fprintf(output, "\"%s\"", transformId->name);
2614 fprintf(output, "\n");
2618 * xmlSecTransformIdListDebugXmlDump:
2619 * @list: the pointer to transform ids list.
2620 * @output: the pointer to output FILE.
2622 * Prints binary transform debug information to @output in XML format.
2625 xmlSecTransformIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
2626 xmlSecTransformId transformId;
2629 xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId));
2630 xmlSecAssert(output != NULL);
2632 fprintf(output, "<TransformIdsList>\n");
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);
2639 fprintf(output, "<TransformId name=\"");
2640 xmlSecPrintXmlString(output, transformId->name);
2641 fprintf(output, "\" />");
2643 fprintf(output, "</TransformIdsList>\n");
2646 /************************************************************************
2648 * IO buffers for transforms
2650 ************************************************************************/
2651 typedef struct _xmlSecTransformIOBuffer xmlSecTransformIOBuffer,
2652 *xmlSecTransformIOBufferPtr;
2654 xmlSecTransformIOBufferModeRead,
2655 xmlSecTransformIOBufferModeWrite
2656 } xmlSecTransformIOBufferMode;
2658 struct _xmlSecTransformIOBuffer {
2659 xmlSecTransformIOBufferMode mode;
2660 xmlSecTransformPtr transform;
2661 xmlSecTransformCtxPtr transformCtx;
2664 static xmlSecTransformIOBufferPtr xmlSecTransformIOBufferCreate (xmlSecTransformIOBufferMode mode,
2665 xmlSecTransformPtr transform,
2666 xmlSecTransformCtxPtr transformCtx);
2667 static void xmlSecTransformIOBufferDestroy (xmlSecTransformIOBufferPtr buffer);
2668 static int xmlSecTransformIOBufferRead (xmlSecTransformIOBufferPtr buffer,
2671 static int xmlSecTransformIOBufferWrite (xmlSecTransformIOBufferPtr buffer,
2672 const xmlSecByte *buf,
2674 static int xmlSecTransformIOBufferClose (xmlSecTransformIOBufferPtr buffer);
2678 * xmlSecTransformCreateOutputBuffer:
2679 * @transform: the pointer to transform.
2680 * @transformCtx: the pointer to transform context object.
2682 * Creates output buffer to write data to @transform.
2684 * Returns: pointer to new output buffer or NULL if an error occurs.
2687 xmlSecTransformCreateOutputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
2688 xmlSecTransformIOBufferPtr buffer;
2689 xmlSecTransformDataType type;
2690 xmlOutputBufferPtr output;
2692 xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
2693 xmlSecAssert2(transformCtx != NULL, NULL);
2695 /* check that we have binary push method for this transform */
2696 type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePush, transformCtx);
2697 if((type & xmlSecTransformDataTypeBin) == 0) {
2698 xmlSecError(XMLSEC_ERRORS_HERE,
2699 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2701 XMLSEC_ERRORS_R_INVALID_TRANSFORM,
2702 "push binary data not supported");
2706 buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeWrite, transform, transformCtx);
2707 if(buffer == NULL) {
2708 xmlSecError(XMLSEC_ERRORS_HERE,
2709 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2710 "xmlSecTransformIOBufferCreate",
2711 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2712 XMLSEC_ERRORS_NO_MESSAGE);
2716 output = xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecTransformIOBufferWrite,
2717 (xmlOutputCloseCallback)xmlSecTransformIOBufferClose,
2720 if(output == NULL) {
2721 xmlSecError(XMLSEC_ERRORS_HERE,
2722 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2723 "xmlOutputBufferCreateIO",
2724 XMLSEC_ERRORS_R_XML_FAILED,
2725 XMLSEC_ERRORS_NO_MESSAGE);
2726 xmlSecTransformIOBufferDestroy(buffer);
2734 * xmlSecTransformCreateInputBuffer:
2735 * @transform: the pointer to transform.
2736 * @transformCtx: the pointer to transform context object.
2738 * Creates input buffer to read data from @transform.
2740 * Returns: pointer to new input buffer or NULL if an error occurs.
2742 xmlParserInputBufferPtr
2743 xmlSecTransformCreateInputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
2744 xmlSecTransformIOBufferPtr buffer;
2745 xmlSecTransformDataType type;
2746 xmlParserInputBufferPtr input;
2748 xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
2749 xmlSecAssert2(transformCtx != NULL, NULL);
2751 /* check that we have binary pop method for this transform */
2752 type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePop, transformCtx);
2753 if((type & xmlSecTransformDataTypeBin) == 0) {
2754 xmlSecError(XMLSEC_ERRORS_HERE,
2755 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2757 XMLSEC_ERRORS_R_INVALID_TRANSFORM,
2758 "pop binary data not supported");
2762 buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeRead, transform, transformCtx);
2763 if(buffer == NULL) {
2764 xmlSecError(XMLSEC_ERRORS_HERE,
2765 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2766 "xmlSecTransformIOBufferCreate",
2767 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2768 XMLSEC_ERRORS_NO_MESSAGE);
2772 input = xmlParserInputBufferCreateIO((xmlInputReadCallback)xmlSecTransformIOBufferRead,
2773 (xmlInputCloseCallback)xmlSecTransformIOBufferClose,
2775 XML_CHAR_ENCODING_NONE);
2777 xmlSecError(XMLSEC_ERRORS_HERE,
2778 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
2779 "xmlParserInputBufferCreateIO",
2780 XMLSEC_ERRORS_R_XML_FAILED,
2781 XMLSEC_ERRORS_NO_MESSAGE);
2782 xmlSecTransformIOBufferDestroy(buffer);
2789 static xmlSecTransformIOBufferPtr
2790 xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferMode mode, xmlSecTransformPtr transform,
2791 xmlSecTransformCtxPtr transformCtx) {
2792 xmlSecTransformIOBufferPtr buffer;
2794 xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
2795 xmlSecAssert2(transformCtx != NULL, NULL);
2797 buffer = (xmlSecTransformIOBufferPtr)xmlMalloc(sizeof(xmlSecTransformIOBuffer));
2798 if(buffer == NULL) {
2799 xmlSecError(XMLSEC_ERRORS_HERE,
2802 XMLSEC_ERRORS_R_MALLOC_FAILED,
2803 "size=%d", sizeof(xmlSecTransformIOBuffer));
2806 memset(buffer, 0, sizeof(xmlSecTransformIOBuffer));
2808 buffer->mode = mode;
2809 buffer->transform = transform;
2810 buffer->transformCtx = transformCtx;
2816 xmlSecTransformIOBufferDestroy(xmlSecTransformIOBufferPtr buffer) {
2817 xmlSecAssert(buffer != NULL);
2819 memset(buffer, 0, sizeof(xmlSecTransformIOBuffer));
2824 xmlSecTransformIOBufferRead(xmlSecTransformIOBufferPtr buffer,
2825 xmlSecByte *buf, xmlSecSize size) {
2828 xmlSecAssert2(buffer != NULL, -1);
2829 xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeRead, -1);
2830 xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
2831 xmlSecAssert2(buffer->transformCtx != NULL, -1);
2832 xmlSecAssert2(buf != NULL, -1);
2834 ret = xmlSecTransformPopBin(buffer->transform, buf, size, &size, buffer->transformCtx);
2836 xmlSecError(XMLSEC_ERRORS_HERE,
2837 xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
2838 "xmlSecTransformPopBin",
2839 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2840 XMLSEC_ERRORS_NO_MESSAGE);
2847 xmlSecTransformIOBufferWrite(xmlSecTransformIOBufferPtr buffer,
2848 const xmlSecByte *buf, xmlSecSize size) {
2851 xmlSecAssert2(buffer != NULL, -1);
2852 xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeWrite, -1);
2853 xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
2854 xmlSecAssert2(buffer->transformCtx != NULL, -1);
2855 xmlSecAssert2(buf != NULL, -1);
2857 ret = xmlSecTransformPushBin(buffer->transform, buf, size, 0, buffer->transformCtx);
2859 xmlSecError(XMLSEC_ERRORS_HERE,
2860 xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
2861 "xmlSecTransformPushBin",
2862 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2863 XMLSEC_ERRORS_NO_MESSAGE);
2870 xmlSecTransformIOBufferClose(xmlSecTransformIOBufferPtr buffer) {
2873 xmlSecAssert2(buffer != NULL, -1);
2874 xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
2875 xmlSecAssert2(buffer->transformCtx != NULL, -1);
2877 /* need to flush write buffer before destroing */
2878 if(buffer->mode == xmlSecTransformIOBufferModeWrite) {
2879 ret = xmlSecTransformPushBin(buffer->transform, NULL, 0, 1, buffer->transformCtx);
2881 xmlSecError(XMLSEC_ERRORS_HERE,
2882 xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
2883 "xmlSecTransformPushBin",
2884 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2885 XMLSEC_ERRORS_NO_MESSAGE);
2890 xmlSecTransformIOBufferDestroy(buffer);