xmlsecurityengine/xmlsec/src/xmlsec_io.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlsec/src/xmlsec_io.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,506 @@
+/** 
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Input uri transform and utility functions.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ * 
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "xmlsec_globals.h"
+
+#include <stdlib.h>
+#include <string.h> 
+#include <errno.h>
+
+#include <stdio.h> //added for symbian
+
+#include <libxml2_tree.h>
+#include <libxml2_uri.h>
+#include <libxml2_xmlio.h>
+#include <libxml2_globals.h>
+
+#ifdef LIBXML_HTTP_ENABLED
+#include <libxml2_nanohttp.h>
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+#include <libxml2_nanoftp.h>
+#endif /* LIBXML_FTP_ENABLED */
+
+#include "xmlsec_xmlsec.h"
+#include "xmlsec_keys.h"
+#include "xmlsec_transforms.h"
+#include "xmlsec_keys.h"
+#include "xmlsec_io.h"
+#include "xmlsec_errors.h"
+
+/*******************************************************************
+ *
+ * Input I/O callback sets
+ *
+ ******************************************************************/
+typedef struct _xmlSecIOCallback {
+    xmlInputMatchCallback matchcallback;
+    xmlInputOpenCallback opencallback;
+    xmlInputReadCallback readcallback;
+    xmlInputCloseCallback closecallback;
+} xmlSecIOCallback, *xmlSecIOCallbackPtr;
+
+static xmlSecIOCallbackPtr	xmlSecIOCallbackCreate	(xmlInputMatchCallback matchFunc,
+							 xmlInputOpenCallback openFunc, 
+							 xmlInputReadCallback readFunc,
+							 xmlInputCloseCallback closeFunc);
+static void			xmlSecIOCallbackDestroy	(xmlSecIOCallbackPtr callbacks);
+
+static xmlSecIOCallbackPtr 
+xmlSecIOCallbackCreate(xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc, 
+		       xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc) {
+    xmlSecIOCallbackPtr callbacks;
+    
+    xmlSecAssert2(matchFunc != NULL, NULL);
+    
+    /* Allocate a new xmlSecIOCallback and fill the fields. */
+    callbacks = (xmlSecIOCallbackPtr)xmlMalloc(sizeof(xmlSecIOCallback));
+    if(callbacks == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "sizeof(xmlSecIOCallback)=%d", 
+		    sizeof(xmlSecIOCallback));
+	return(NULL);
+    }
+    memset(callbacks, 0, sizeof(xmlSecIOCallback));    
+
+    callbacks->matchcallback = matchFunc;
+    callbacks->opencallback  = openFunc;
+    callbacks->readcallback  = readFunc;
+    callbacks->closecallback = closeFunc;
+    
+    return(callbacks);
+}
+
+static void 
+xmlSecIOCallbackDestroy(xmlSecIOCallbackPtr callbacks) {
+    xmlSecAssert(callbacks != NULL);
+
+    memset(callbacks, 0, sizeof(xmlSecIOCallback));    
+    xmlFree(callbacks);    
+}
+
+/*******************************************************************
+ *
+ * Input I/O callback list
+ *
+ ******************************************************************/
+static xmlSecPtrListKlass xmlSecIOCallbackPtrListKlass = {
+    BAD_CAST "io-callbacks-list",
+    NULL, 						/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    (xmlSecPtrDestroyItemMethod)xmlSecIOCallbackDestroy,/* xmlSecPtrDestroyItemMethod destroyItem; */
+    NULL,  					  	/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    NULL						/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+#define xmlSecIOCallbackPtrListId	xmlSecIOCallbackPtrListGetKlass	()
+static xmlSecPtrListId 			xmlSecIOCallbackPtrListGetKlass	(void);
+static xmlSecIOCallbackPtr		xmlSecIOCallbackPtrListFind	(xmlSecPtrListPtr list,
+									 const char* uri);
+
+/**
+ * xmlSecIOCallbackPtrListGetKlass: 
+ *
+ * The keys list klass.
+ *
+ * Returns keys list id.
+ */
+static xmlSecPtrListId 
+xmlSecIOCallbackPtrListGetKlass(void) {
+    return(&xmlSecIOCallbackPtrListKlass);
+}
+
+static xmlSecIOCallbackPtr 
+xmlSecIOCallbackPtrListFind(xmlSecPtrListPtr list, const char* uri) {
+    xmlSecIOCallbackPtr callbacks;
+    xmlSecSize i, size;
+
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecIOCallbackPtrListId), NULL);
+    xmlSecAssert2(uri != NULL, NULL);
+
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	callbacks = (xmlSecIOCallbackPtr)xmlSecPtrListGetItem(list, i);
+	xmlSecAssert2(callbacks != NULL, NULL);	
+	xmlSecAssert2(callbacks->matchcallback != NULL, NULL);	
+	
+	if((callbacks->matchcallback(uri)) != 0) {
+	    return(callbacks);
+	}
+    }
+    return(NULL);
+}
+
+static xmlSecPtrList xmlSecAllIOCallbacks;
+
+/**
+ * xmlSecIOInit:
+ *
+ * The IO initialization (called from #xmlSecInit function).
+ * Applications should not call this function directly.
+ *
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C 
+int
+xmlSecIOInit(void) {    
+    int ret;
+    
+    ret = xmlSecPtrListInitialize(&xmlSecAllIOCallbacks, xmlSecIOCallbackPtrListId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListPtrInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+#ifdef LIBXML_HTTP_ENABLED
+    xmlNanoHTTPInit();
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED       
+    xmlNanoFTPInit();
+#endif /* LIBXML_FTP_ENABLED */ 
+
+    return(xmlSecIORegisterDefaultCallbacks());
+}
+
+/**
+ * xmlSecIOShutdown:
+ *
+ * The IO clenaup (called from #xmlSecShutdown function).
+ * Applications should not call this function directly.
+ */
+EXPORT_C 
+void
+xmlSecIOShutdown(void) {
+
+#ifdef LIBXML_HTTP_ENABLED
+    xmlNanoHTTPCleanup();
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED       
+    xmlNanoFTPCleanup();
+#endif /* LIBXML_FTP_ENABLED */ 
+
+    xmlSecPtrListFinalize(&xmlSecAllIOCallbacks);
+}
+
+/**
+ * xmlSecIOCleanupCallbacks:
+ *
+ * Clears the entire input callback table. this includes the
+ * compiled-in I/O. 
+ */
+EXPORT_C
+void
+xmlSecIOCleanupCallbacks(void) {
+    xmlSecPtrListEmpty(&xmlSecAllIOCallbacks);
+}
+
+/**
+ * xmlSecIORegisterCallbacks:
+ * @matchFunc:  	the protocol match callback.
+ * @openFunc:  		the open stream callback.
+ * @readFunc:  		the read from stream callback.
+ * @closeFunc:  	the close stream callback.
+ *
+ * Register a new set of I/O callback for handling parser input.
+ *
+ * Returns the 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int
+xmlSecIORegisterCallbacks(xmlInputMatchCallback matchFunc,
+	xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
+	xmlInputCloseCallback closeFunc) {
+    xmlSecIOCallbackPtr callbacks;
+    int ret;
+    
+    xmlSecAssert2(matchFunc != NULL, -1);
+    
+    callbacks = xmlSecIOCallbackCreate(matchFunc, openFunc, readFunc, closeFunc);
+    if(callbacks == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecIOCallbackCreate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    ret = xmlSecPtrListAdd(&xmlSecAllIOCallbacks, callbacks);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecIOCallbackDestroy(callbacks);
+	return(-1);
+    }
+    return(0);
+}
+
+
+/**
+ * xmlSecIORegisterDefaultCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ *
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecIORegisterDefaultCallbacks(void) {
+    int ret;
+    
+#ifdef LIBXML_HTTP_ENABLED
+    ret = xmlSecIORegisterCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
+	                      xmlIOHTTPRead, xmlIOHTTPClose);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecIORegisterCallbacks",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "http");
+	return(-1);
+    }
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+    ret = xmlSecIORegisterCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
+	                      xmlIOFTPRead, xmlIOFTPClose);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecIORegisterCallbacks",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "ftp");
+	return(-1);
+    }
+#endif /* LIBXML_FTP_ENABLED */
+
+    ret = xmlSecIORegisterCallbacks(xmlFileMatch, xmlFileOpen,
+	                      xmlFileRead, xmlFileClose);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecIORegisterCallbacks",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "file");
+	return(-1);
+    }
+
+    return(0);
+}
+
+
+
+								
+/**************************************************************
+ *
+ * Input URI Transform
+ *
+ * xmlSecInputURICtx is located after xmlSecTransform
+ * 
+ **************************************************************/
+typedef struct _xmlSecInputURICtx				xmlSecInputURICtx,
+								*xmlSecInputURICtxPtr;
+struct _xmlSecInputURICtx {
+    xmlSecIOCallbackPtr		clbks;
+    void*			clbksCtx;
+};
+#define xmlSecTransformInputUriSize \
+	(sizeof(xmlSecTransform) + sizeof(xmlSecInputURICtx))
+#define xmlSecTransformInputUriGetCtx(transform) \
+    ((xmlSecTransformCheckSize((transform), xmlSecTransformInputUriSize)) ? \
+	(xmlSecInputURICtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+	(xmlSecInputURICtxPtr)NULL)
+
+static int		xmlSecTransformInputURIInitialize	(xmlSecTransformPtr transform);
+static void		xmlSecTransformInputURIFinalize		(xmlSecTransformPtr transform);
+static int		xmlSecTransformInputURIPopBin		(xmlSecTransformPtr transform, 
+								 xmlSecByte* data,
+								 xmlSecSize maxDataSize,
+								 xmlSecSize* dataSize,
+								 xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecTransformInputURIKlass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
+    xmlSecTransformInputUriSize,		/* xmlSecSize objSize */
+
+    BAD_CAST "input-uri",			/* const xmlChar* name; */
+    NULL,					/* const xmlChar* href; */
+    0,						/* xmlSecAlgorithmUsage usage; */
+
+    xmlSecTransformInputURIInitialize, 		/* xmlSecTransformInitializeMethod initialize; */
+    xmlSecTransformInputURIFinalize,		/* xmlSecTransformFinalizeMethod finalize; */
+    NULL,					/* xmlSecTransformNodeReadMethod readNode; */
+    NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
+    NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    NULL,					/* xmlSecTransformSetKeyMethod setKey; */
+    NULL,					/* xmlSecTransformValidateMethod validate; */
+    xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
+    NULL,					/* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformInputURIPopBin,		/* xmlSecTransformPopBinMethod popBin; */
+    NULL,					/* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,					/* xmlSecTransformPopXmlMethod popXml; */
+    NULL,					/* xmlSecTransformExecuteMethod execute; */
+    
+    NULL,					/* void* reserved0; */
+    NULL,					/* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformInputURIGetKlass:
+ *
+ * The input uri transform klass. Reads binary data from an uri.
+ *
+ * Returns input URI transform id.
+ */
+EXPORT_C
+xmlSecTransformId 
+xmlSecTransformInputURIGetKlass(void) {
+    return(&xmlSecTransformInputURIKlass);
+}
+
+/** 
+ * xmlSecTransformInputURIOpen:
+ * @transform: 		the pointer to IO transform.
+ * @uri: 		the URL to open.
+ *
+ * Opens the given @uri for reading.
+ *
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecTransformInputURIOpen(xmlSecTransformPtr transform, const xmlChar *uri) {
+    xmlSecInputURICtxPtr ctx;
+        
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
+    xmlSecAssert2(uri != NULL, -1);
+
+    ctx = xmlSecTransformInputUriGetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->clbks == NULL, -1);
+    xmlSecAssert2(ctx->clbksCtx == NULL, -1);
+
+    /*
+     * Try to find one of the input accept method accepting that scheme
+     * Go in reverse to give precedence to user defined handlers.
+     * try with an unescaped version of the uri
+     */
+    if(ctx->clbks == NULL) {
+	char *unescaped;
+    
+        unescaped = xmlURIUnescapeString((char*)uri, 0, NULL);
+	if (unescaped != NULL) {
+	    ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, unescaped);
+	    if(ctx->clbks != NULL) {
+		ctx->clbksCtx = ctx->clbks->opencallback(unescaped);
+	    }
+	    xmlFree(unescaped);
+	}
+    }
+
+    /*
+     * If this failed try with a non-escaped uri this may be a strange
+     * filename
+     */
+    if (ctx->clbks == NULL) {
+	ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, (char*)uri);
+	if(ctx->clbks != NULL) {
+	    ctx->clbksCtx = ctx->clbks->opencallback((char*)uri);
+	}
+    }
+
+    if((ctx->clbks == NULL) || (ctx->clbksCtx == NULL)) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+		    "opencallback",
+		    XMLSEC_ERRORS_R_IO_FAILED,
+		    "uri=%s;errno=%d", 
+		    xmlSecErrorsSafeString(uri),
+		    errno);
+	return(-1);
+    }
+    
+    return(0);
+}
+
+static int
+xmlSecTransformInputURIInitialize(xmlSecTransformPtr transform) {
+    xmlSecInputURICtxPtr ctx;
+
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
+
+    ctx = xmlSecTransformInputUriGetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+    
+    memset(ctx, 0, sizeof(xmlSecInputURICtx));
+    return(0);
+}
+
+static void
+xmlSecTransformInputURIFinalize(xmlSecTransformPtr transform) {
+    xmlSecInputURICtxPtr ctx;
+
+    xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId));
+
+    ctx = xmlSecTransformInputUriGetCtx(transform);
+    xmlSecAssert(ctx != NULL);
+
+    if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->closecallback != NULL)) {
+	(ctx->clbks->closecallback)(ctx->clbksCtx);
+    }
+    memset(ctx, 0, sizeof(xmlSecInputURICtx));
+}
+
+static int 
+xmlSecTransformInputURIPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
+			      xmlSecSize maxDataSize, xmlSecSize* dataSize, 
+			      xmlSecTransformCtxPtr transformCtx) {
+    xmlSecInputURICtxPtr ctx;
+
+    int ret;
+    			    
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
+    xmlSecAssert2(data != NULL, -1);
+    xmlSecAssert2(dataSize != NULL, -1);
+    xmlSecAssert2(transformCtx != NULL, -1);
+
+    ctx = xmlSecTransformInputUriGetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+    
+    if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->readcallback != NULL)) {
+        ret = (ctx->clbks->readcallback)(ctx->clbksCtx, (char*)data, (int)maxDataSize);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+			"readcallback",
+			XMLSEC_ERRORS_R_IO_FAILED,
+			"errno=%d", errno);
+	    return(-1);
+	}
+	(*dataSize) = ret;
+    } else {
+	(*dataSize) = 0;
+    }
+    return(0);
+}
+