xmlsecurityengine/xmlsec/src/xmlsec_buffer.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlsec/src/xmlsec_buffer.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,709 @@
+/** 
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Memory buffer.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ * 
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
+ */
+#include "xmlsec_globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <libxml2_tree.h>
+#include <libxml2_globals.h>
+
+#include "xmlsec_xmlsec.h"
+#include "xmlsec_xmltree.h"
+#include "xmlsec_base64.h"
+#include "xmlsec_buffer.h"
+#include "xmlsec_errors.h"
+
+#include "xmlsec_error_flag.h"
+
+//added for symbian port
+#include "xmlsec_io.h"
+
+/*****************************************************************************
+ *
+ * xmlSecBuffer
+ *
+ ****************************************************************************/
+static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble;
+static xmlSecSize gInitialSize = 1024;
+
+/**
+ * xmlSecBufferSetDefaultAllocMode:
+ * @defAllocMode:	the new default buffer allocation mode.
+ * @defInitialSize:	the new default buffer minimal intial size.
+ * 
+ * Sets new global default allocation mode and minimal intial size.
+ */
+EXPORT_C
+void 
+xmlSecBufferSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) {
+    xmlSecAssert(defInitialSize > 0);
+    
+    gAllocMode = defAllocMode;
+    gInitialSize = defInitialSize;
+}
+
+/**
+ * xmlSecBufferCreate:
+ * @size: 		the intial size.
+ *
+ * Allocates and initalizes new memory buffer with given size.
+ * Caller is responsible for calling #xmlSecBufferDestroy function
+ * to free the buffer.
+ *
+ * Returns pointer to newly allocated buffer or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecBufferPtr 
+xmlSecBufferCreate(xmlSecSize size) {
+    xmlSecBufferPtr buf;
+    int ret;
+    
+    buf = (xmlSecBufferPtr)xmlMalloc(sizeof(xmlSecBuffer));
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "sizeof(xmlSecBuffer)=%d", sizeof(xmlSecBuffer));
+	return(NULL);
+    }
+    
+    ret = xmlSecBufferInitialize(buf, size);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBufferInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", size);
+	xmlSecBufferDestroy(buf);
+	return(NULL);
+    }
+    return(buf);
+}
+
+/**
+ * xmlSecBufferDestroy:
+ * @buf:		the pointer to buffer object.
+ *
+ * Desrtoys buffer object created with #xmlSecBufferCreate function.
+ */
+EXPORT_C
+void 
+xmlSecBufferDestroy(xmlSecBufferPtr buf) {
+    xmlSecAssert(buf != NULL);
+    
+    xmlSecBufferFinalize(buf);
+    xmlFree(buf);
+}
+
+/**
+ * xmlSecBufferInitialize:
+ * @buf:		the pointer to buffer object.
+ * @size:		the initial buffer size.
+ *
+ * Initializes buffer object @buf. Caller is responsible for calling
+ * #xmlSecBufferFinalize function to free allocated resources.
+ * 
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferInitialize(xmlSecBufferPtr buf, xmlSecSize size) {
+    xmlSecAssert2(buf != NULL, -1);
+
+    buf->data = NULL;
+    buf->size = buf->maxSize = 0;
+    buf->allocMode = gAllocMode;
+        
+    return(xmlSecBufferSetMaxSize(buf, size));
+}
+
+/**
+ * xmlSecBufferFinalize:
+ * @buf:		the pointer to buffer object.
+ *
+ * Frees allocated resource for a buffer intialized with #xmlSecBufferInitialize
+ * function.
+ */
+EXPORT_C
+void 
+xmlSecBufferFinalize(xmlSecBufferPtr buf) {
+    xmlSecAssert(buf != NULL);
+
+    xmlSecBufferEmpty(buf);    
+    if(buf->data != 0) {
+	xmlFree(buf->data);
+    }
+    buf->data = NULL;
+    buf->size = buf->maxSize = 0;
+}
+
+/**
+ * xmlSecBufferEmpty:
+ * @buf:		the pointer to buffer object.
+ *
+ * Empties the buffer.
+ */
+EXPORT_C
+void
+xmlSecBufferEmpty(xmlSecBufferPtr buf) {
+    xmlSecAssert(buf != NULL);
+    
+    if(buf->data != 0) {
+	xmlSecAssert(buf->maxSize > 0);
+
+	memset(buf->data, 0, buf->maxSize);
+    }
+    buf->size = 0;
+}
+
+/**
+ * xmlSecBufferGetData:
+ * @buf:		the pointer to buffer object.
+ *
+ * Gets pointer to buffer's data.
+ *
+ * Returns pointer to buffer's data.
+ */
+EXPORT_C
+xmlSecByte* 
+xmlSecBufferGetData(xmlSecBufferPtr buf) {
+    xmlSecAssert2(buf != NULL, NULL);
+    
+    return(buf->data);
+}
+
+/**
+ * xmlSecBufferSetData:
+ * @buf:		the pointer to buffer object.
+ * @data:		the data.
+ * @size:		the data size.
+ *
+ * Sets the value of the buffer to @data.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferSetData(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
+    int ret;
+    
+    xmlSecAssert2(buf != NULL, -1);
+
+    xmlSecBufferEmpty(buf);
+    if(size > 0) {
+	xmlSecAssert2(data != NULL, -1);
+    
+	ret = xmlSecBufferSetMaxSize(buf, size);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferSetMaxSize",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"size=%d", size);
+	    return(-1);
+        }
+	
+	memcpy(buf->data, data, size);
+    }
+    
+    buf->size = size;    
+    return(0);
+}
+
+/**
+ * xmlSecBufferGetSize:
+ * @buf:		the pointer to buffer object.
+ *
+ * Gets the current buffer data size.
+ *
+ * Returns the current data size.
+ */
+EXPORT_C
+xmlSecSize 
+xmlSecBufferGetSize(xmlSecBufferPtr buf) {
+    xmlSecAssert2(buf != NULL, 0);
+
+    return(buf->size);
+}
+
+/**
+ * xmlSecBufferSetSize:
+ * @buf:		the pointer to buffer object.
+ * @size:		the new data size.
+ *
+ * Sets new buffer data size. If necessary, buffer grows to 
+ * have at least @size bytes. 
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferSetSize(xmlSecBufferPtr buf, xmlSecSize size) {
+    int ret;
+    
+    xmlSecAssert2(buf != NULL, -1);
+
+    ret = xmlSecBufferSetMaxSize(buf, size);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBufferSetMaxSize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", size);
+	return(-1);
+    }
+    
+    
+    buf->size = size;
+    return(0);
+}
+
+/**
+ * xmlSecBufferGetMaxSize:
+ * @buf:		the pointer to buffer object.
+ *
+ * Gets the maximum (allocated) buffer size.
+ *
+ * Returns the maximum (allocated) buffer size.
+ */
+EXPORT_C
+xmlSecSize 
+xmlSecBufferGetMaxSize(xmlSecBufferPtr buf) {
+    xmlSecAssert2(buf != NULL, 0);
+
+    return(buf->maxSize);
+}
+
+/**
+ * xmlSecBufferSetMaxSize:
+ * @buf:		the pointer to buffer object.
+ * @size:		the new maximum size.
+ *
+ * Sets new buffer maximum size. If necessary, buffer grows to 
+ * have at least @size bytes. 
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferSetMaxSize(xmlSecBufferPtr buf, xmlSecSize size) {
+    xmlSecByte* newData;
+    xmlSecSize newSize = 0;
+    
+    xmlSecAssert2(buf != NULL, -1);
+    if(size <= buf->maxSize) {
+	return(0);
+    }
+    
+    switch(buf->allocMode) {
+	case xmlSecAllocModeExact:
+	    newSize = size + 8;
+	    break;
+	case xmlSecAllocModeDouble:
+	    newSize = 2 * size + 32;
+	    break;
+    }
+
+    if(newSize < gInitialSize) {
+	newSize = gInitialSize;
+    }
+    
+
+    if(buf->data != NULL) {
+    	newData = (xmlSecByte*)xmlRealloc(buf->data, newSize);
+    } else {
+    	newData = (xmlSecByte*)xmlMalloc(newSize);
+    }
+    if(newData == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "size=%d", newSize);
+	return(-1);
+    }
+    
+    buf->data = newData;
+    buf->maxSize = newSize;
+
+    if(buf->size < buf->maxSize) {
+	xmlSecAssert2(buf->data != NULL, -1);
+	memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecBufferAppend:
+ * @buf:		the pointer to buffer object.
+ * @data:		the data.
+ * @size:		the data size.
+ *
+ * Appends the @data after the current data stored in the buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferAppend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
+    int ret;
+    
+    xmlSecAssert2(buf != NULL, -1);
+
+    if(size > 0) {
+	xmlSecAssert2(data != NULL, -1);
+    
+        ret = xmlSecBufferSetMaxSize(buf, buf->size + size);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferSetMaxSize",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"size=%d", buf->size + size);
+	    return(-1);
+	}
+	
+	memcpy(buf->data + buf->size, data, size);
+	buf->size += size;    
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecBufferPrepend:
+ * @buf:		the pointer to buffer object.
+ * @data:		the data.
+ * @size:		the data size.
+ *
+ * Prepends the @data before the current data stored in the buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int
+xmlSecBufferPrepend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
+    int ret;
+    
+    xmlSecAssert2(buf != NULL, -1);
+
+    if(size > 0) {
+	xmlSecAssert2(data != NULL, -1);
+    
+	ret = xmlSecBufferSetMaxSize(buf, buf->size + size);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferSetMaxSize",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"size=%d", buf->size + size);
+	    return(-1);
+	}
+
+	memmove(buf->data + size, buf->data, buf->size);	
+	memcpy(buf->data, data, size);
+	buf->size += size;    
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecBufferRemoveHead:
+ * @buf:		the pointer to buffer object.
+ * @size:		the number of bytes to be removed.
+ *
+ * Removes @size bytes from the beginning of the current buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferRemoveHead(xmlSecBufferPtr buf, xmlSecSize size) {
+    xmlSecAssert2(buf != NULL, -1);
+    
+    if(size < buf->size) {
+	xmlSecAssert2(buf->data != NULL, -1);
+	
+	buf->size -= size;
+	memmove(buf->data, buf->data + size, buf->size);
+    } else {
+	buf->size = 0;
+    }
+    if(buf->size < buf->maxSize) {
+	xmlSecAssert2(buf->data != NULL, -1);
+	memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
+    }
+    return(0);
+}
+
+/**
+ * xmlSecBufferRemoveTail:
+ * @buf:		the pointer to buffer object.
+ * @size:		the number of bytes to be removed.
+ *
+ * Removes @size bytes from the end of current buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferRemoveTail(xmlSecBufferPtr buf, xmlSecSize size) {
+    xmlSecAssert2(buf != NULL, -1);
+
+    if(size < buf->size) {
+	buf->size -= size;
+    } else {
+	buf->size = 0;
+    }
+    if(buf->size < buf->maxSize) {
+	xmlSecAssert2(buf->data != NULL, -1);
+	memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
+    }
+    return(0);
+}
+
+/**
+ * xmlSecBufferReadFile:
+ * @buf:		the pointer to buffer object.
+ * @filename:		the filename.
+ *
+ * Reads the content of the file @filename in the buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferReadFile(xmlSecBufferPtr buf, const char* filename) {
+    xmlSecByte buffer[1024];
+    FILE* f;
+    int ret, len;
+
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(filename != NULL, -1);
+
+    f = fopen(filename, "rb");
+    if(f == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "fopen",
+		    XMLSEC_ERRORS_R_IO_FAILED,
+		    "filename=%s;errno=%d", 
+		    xmlSecErrorsSafeString(filename),
+		    errno);
+    if ( errno == ENOMEM )
+        {
+        xmlSecSetErrorFlag( -4 ); //KErrNoMemory
+        }
+	return(-1);
+    }
+
+    while(1) {
+        len = fread(buffer, 1, sizeof(buffer), f);
+	if(len == 0 && !errno) {
+            break;
+        }else if( errno ) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "fread",
+                        XMLSEC_ERRORS_R_IO_FAILED,
+                        "filename=%s;errno=%d", 
+                        xmlSecErrorsSafeString(filename),
+			errno);
+			if ( errno == ENOMEM )
+                {
+                xmlSecSetErrorFlag( -4 ); //KErrNoMemory
+                }
+            fclose(f);
+            return(-1);
+        }
+
+	ret = xmlSecBufferAppend(buf, buffer, len);
+	if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecBufferAppend",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "size=%d", 
+                        len);
+            fclose(f);
+            return(-1);
+        }     
+    }
+
+    fclose(f);
+    return(0);
+}
+
+/**
+ * xmlSecBufferBase64NodeContentRead:
+ * @buf:		the pointer to buffer object.
+ * @node:		the pointer to node.
+ *
+ * Reads the content of the @node, base64 decodes it and stores the
+ * result in the buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferBase64NodeContentRead(xmlSecBufferPtr buf, xmlNodePtr node) {
+    xmlChar* content;
+    xmlSecSize size;
+    int ret;
+    
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    content = xmlNodeGetContent(node);
+    if(content == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);		
+    }
+    
+    /* base64 decode size is less than input size */
+    ret = xmlSecBufferSetMaxSize(buf, xmlStrlen(content));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBufferSetMaxSize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlFree(content);
+	return(-1);
+    }
+    
+    ret = xmlSecBase64Decode(content, xmlSecBufferGetData(buf), xmlSecBufferGetMaxSize(buf));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBase64Decode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlFree(content);
+	return(-1);
+    }
+    size = ret;
+
+    ret = xmlSecBufferSetSize(buf, size);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBufferSetSize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", size);
+	xmlFree(content);
+	return(-1);
+    }
+    xmlFree(content);
+    
+    return(0);
+}
+
+/**
+ * xmlSecBufferBase64NodeContentWrite:
+ * @buf:		the pointer to buffer object.
+ * @node:		the pointer to a node.
+ * @columns:		the max line size fro base64 encoded data.
+ *
+ * Sets the content of the @node to the base64 encoded buffer data.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBufferBase64NodeContentWrite(xmlSecBufferPtr buf, xmlNodePtr node, int columns) {
+    xmlChar* content;
+    
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    content = xmlSecBase64Encode(xmlSecBufferGetData(buf), xmlSecBufferGetSize(buf), columns);
+    if(content == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBase64Encode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    xmlNodeAddContent(node, content);
+    xmlFree(content);
+    
+    return(0);
+}
+
+/************************************************************************
+ *
+ * IO buffer
+ *
+ ************************************************************************/ 
+static int	xmlSecBufferIOWrite				(xmlSecBufferPtr buf,
+								 const xmlSecByte *data,
+								 xmlSecSize size);		
+static int	xmlSecBufferIOClose				(xmlSecBufferPtr buf);
+
+/**
+ * xmlSecBufferCreateOutputBuffer:
+ * @buf:		the pointer to buffer.
+ *
+ * Creates new LibXML output buffer to store data in the @buf. Caller is 
+ * responsible for destroying @buf when processing is done. 
+ *
+ * Returns pointer to newly allocated output buffer or NULL if an error
+ * occurs.
+ */
+EXPORT_C
+xmlOutputBufferPtr 
+xmlSecBufferCreateOutputBuffer(xmlSecBufferPtr buf) {
+    return(xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecBufferIOWrite,
+				     (xmlOutputCloseCallback)xmlSecBufferIOClose,
+				     buf,
+				     NULL)); 
+}
+
+static int 
+xmlSecBufferIOWrite(xmlSecBufferPtr buf, const xmlSecByte *data, xmlSecSize size) {
+    int ret;
+    
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(data != NULL, -1);
+    
+    ret = xmlSecBufferAppend(buf, data, size);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBufferAppend",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", size);
+	return(-1);
+    }
+    
+    return(size);    
+}
+
+static int 
+xmlSecBufferIOClose(xmlSecBufferPtr buf) {
+    xmlSecAssert2(buf != NULL, -1);
+    
+    /* just do nothing */
+    return(0);
+}