/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * XSEC
 *
 * XSECSafeBuffer := a class for storing expanding amounts of information.
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

// XSEC includes

#include <xsec/utils/XSECSafeBuffer.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/transformers/TXFMBase.hpp>

#include <xercesc/util/XMLUniDefs.hpp>

XSEC_USING_XERCES(XMLString);

// Standard includes

#include <stdlib.h>
#include <string.h>

size_t safeBuffer::size_XMLCh;

#if defined (_MSC_VER)
#pragma warning(disable: 4311)
#endif

void safeBuffer::checkAndExpand(XMLSize_t size) {

	// For a given size, check it will fit (with one byte spare)
	// and expand if necessary

	if (bufferSize >= 2 && size < bufferSize - 2) {
		return;
	}

	if (size > XERCES_SIZE_MAX - DEFAULT_SAFE_BUFFER_SIZE) {
		/* We've got a string that's too big to deal with */
		throw XSECException(XSECException::SafeBufferError,
			"Buffer has grown too large");
	}

	// Resize and add 1K for further growth
	XMLSize_t newBufferSize = size + DEFAULT_SAFE_BUFFER_SIZE;

	unsigned char * newBuffer = new unsigned char[newBufferSize];
	if (newBuffer == NULL)
	{
		/* Ran out of memory */
		throw XSECException(XSECException::MemoryAllocationFail,
			"Error allocating memory for Buffer");
	}

	memset((void *) newBuffer, 0, newBufferSize);
	memcpy(newBuffer, buffer, bufferSize);

	// If we are sensitive, clean the old buffer
	if (m_isSensitive == true)
		cleanseBuffer();

	// clean up
	bufferSize = newBufferSize;
	delete[] buffer;
	buffer = newBuffer;
}

void safeBuffer::checkBufferType(bufferType bt) const {

	if (bt != m_bufferType) {

		throw XSECException(XSECException::SafeBufferError,
			"Attempt to perform an operation on a buffer of incorrect type");
	}

}


void safeBuffer::setBufferType(bufferType bt) {

	m_bufferType = bt;

}

void safeBuffer::resize(XMLSize_t sz) {

	checkAndExpand(sz);

}

safeBuffer::safeBuffer(XMLSize_t initialSize) {

	// Initialise the buffer with a set size string

	bufferSize = initialSize;
	buffer = new unsigned char[initialSize];
	memset((void *) buffer, 0, bufferSize);
	mp_XMLCh = NULL;
	m_bufferType = BUFFER_UNKNOWN;
	m_isSensitive = false;

}

safeBuffer::safeBuffer() {

	bufferSize = DEFAULT_SAFE_BUFFER_SIZE;
	buffer = new unsigned char[bufferSize];
	memset((void *) buffer, 0, bufferSize);
	mp_XMLCh = NULL;
	m_bufferType = BUFFER_UNKNOWN;
	m_isSensitive = false;

}

safeBuffer::safeBuffer(const char * inStr, XMLSize_t initialSize) {
    // Initialise with a string
    bufferSize = ((XMLSize_t) strlen(inStr) > initialSize ? (XMLSize_t) (strlen(inStr) * 2) : initialSize);

	buffer = new unsigned char[bufferSize];
	memset((void *) buffer, 0, bufferSize);
	strcpy((char *) buffer, inStr);
	mp_XMLCh = NULL;
	m_bufferType = BUFFER_CHAR;
	m_isSensitive = false;

}

safeBuffer::safeBuffer(const safeBuffer & other) {

	// Copy constructor

	bufferSize = other.bufferSize;
	buffer = new unsigned char [bufferSize];

	memcpy(buffer, other.buffer, bufferSize);

	if (other.mp_XMLCh != NULL) {

		mp_XMLCh = XMLString::replicate(other.mp_XMLCh);

	}
	else {

		mp_XMLCh = NULL;

	}

	m_bufferType = other.m_bufferType;
	m_isSensitive = other.m_isSensitive;

}

safeBuffer::~safeBuffer() {


	if (buffer != NULL) {
		if (m_isSensitive == true)
			cleanseBuffer();
		delete[] buffer;
	}

	if (mp_XMLCh != NULL)
		XSEC_RELEASE_XMLCH(mp_XMLCh);

}

void safeBuffer::init (void) {

	size_XMLCh = sizeof(XMLCh);

}

// "IN" functions - these read in information to the buffer

void safeBuffer::sbStrcpyIn(const char * inStr) {

	// Copy a string into the safe buffer
    checkAndExpand((XMLSize_t) strlen(inStr));
	strcpy((char *) buffer, inStr);
	m_bufferType = BUFFER_CHAR;

}

void safeBuffer::sbStrcpyIn(const safeBuffer & inStr) {

	inStr.checkBufferType(BUFFER_CHAR);
    checkAndExpand((XMLSize_t) strlen((char *) inStr.buffer));
	strcpy((char *) buffer, (char *) inStr.buffer);
	m_bufferType = BUFFER_CHAR;

}


void safeBuffer::sbStrncpyIn(const char * inStr, XMLSize_t n) {
    XMLSize_t len = (XMLSize_t) strlen(inStr);
	checkAndExpand((n < len) ? n : len);
	strncpy((char *) buffer, inStr, n);
	buffer[n] = '\0';
	m_bufferType = BUFFER_CHAR;

}

void safeBuffer::sbStrncpyIn(const safeBuffer & inStr, XMLSize_t n) {

	inStr.checkBufferType(BUFFER_CHAR);
	checkAndExpand(n);
	strncpy((char *) buffer, (char *) inStr.buffer, n);
	buffer[n] = '\0';
	m_bufferType = BUFFER_CHAR;


}


void safeBuffer::sbStrcatIn(const char * inStr) {

	checkBufferType(BUFFER_CHAR);
    checkAndExpand((XMLSize_t) (strlen((char *) buffer) + strlen(inStr) + 1));
	strcat((char *) buffer, inStr);

}

void safeBuffer::sbStrcatIn(const safeBuffer & inStr) {

	checkBufferType(BUFFER_CHAR);
    checkAndExpand((XMLSize_t) (strlen((char *) buffer) + strlen((char *) inStr.buffer) + 2));
	strcat((char *) buffer, (char *) inStr.buffer);

}

void safeBuffer::sbStrncatIn(const char * inStr, XMLSize_t n) {
    checkBufferType(BUFFER_CHAR);
    XMLSize_t len = (XMLSize_t) strlen(inStr);
	XMLSize_t totalLen = ((n < len) ? n : len) + (XMLSize_t)strlen((char *)buffer);
    checkAndExpand(totalLen + 2);
	strncat((char *) buffer, inStr, n);
	buffer[totalLen] = '\0';

}

void safeBuffer::sbMemcpyIn(const void * inBuf, XMLSize_t n) {

	checkAndExpand(n);
	memcpy(buffer, inBuf, n);
	m_bufferType = BUFFER_UNKNOWN;

}

void safeBuffer::sbMemcpyIn(XMLSize_t offset, const void * inBuf, XMLSize_t n) {

	checkAndExpand(n + offset);
	memcpy(&buffer[offset], inBuf, n);
	m_bufferType = BUFFER_UNKNOWN;
}

void safeBuffer::sbStrinsIn(const char * inStr, XMLSize_t offset) {

    checkBufferType(BUFFER_CHAR);

    XMLSize_t bl = (XMLSize_t) strlen((char *) buffer);
    XMLSize_t il = (XMLSize_t) strlen((char *) inStr);

	if (offset > bl) {
		throw XSECException(XSECException::SafeBufferError,
			"Attempt to insert string after termination point");
	}

	checkAndExpand(bl + il + 1);

	memmove(&buffer[offset + il], &buffer[offset], bl - offset + 1);
	memcpy(&buffer[offset], inStr, il);

}

void safeBuffer::sbMemcpyOut(void *outBuf, XMLSize_t n) const {

	// WARNING - JUST ASSUMES OUTPUT BUFFER LONG ENOUGH
	// ALSO MAKES NO ASSUMPTION OF THE BUFFER TYPE

	if (n > bufferSize) {
		throw XSECException(XSECException::SafeBufferError,
			"safeBuffer::sbMemcpyOut Attempt to copy more data than buffer can hold");
	}

	memcpy(outBuf, buffer, n);

}

void safeBuffer::sbMemshift(XMLSize_t toOffset, XMLSize_t fromOffset, XMLSize_t len) {

	// Move data in the buffer around
	checkAndExpand(len + (toOffset > fromOffset ? toOffset : fromOffset));

	memmove(&buffer[toOffset], &buffer[fromOffset], len);

}


// Comparisons

int safeBuffer::sbStrncmp(const char *inStr, XMLSize_t n) const {

	checkBufferType(BUFFER_CHAR);
	return (strncmp((char *) buffer, inStr, n));

}

int safeBuffer::sbStrcmp(const char *inStr) const {

	checkBufferType(BUFFER_CHAR);
	return (strcmp((char *) buffer, inStr));

}

int safeBuffer::sbStrcmp(const safeBuffer & inStr) const {

	checkBufferType(BUFFER_CHAR);
	return (strcmp((char *) buffer, (char *) inStr.buffer));

}

int safeBuffer::sbOffsetStrcmp(const char * inStr, XMLSize_t offset) const {

    checkBufferType(BUFFER_CHAR);
    XMLSize_t bl = (XMLSize_t) strlen((char *) buffer);

	if (offset > bl)
		return -1;

	return (strcmp((char *) &buffer[offset], inStr));

}

XMLSSize_t safeBuffer::sbStrstr(const char * inStr) const {

	checkBufferType(BUFFER_CHAR);
	const char* p = strstr((char *) buffer, inStr);

	if (p == NULL)
		return -1;

	XMLSSize_t d = p - (char*) buffer;
	if (d > bufferSize || d < 0)
		return -1;

	return d;

}

XMLSSize_t safeBuffer::sbOffsetStrstr(const char * inStr, XMLSize_t offset) const {

	checkBufferType(BUFFER_CHAR);
	XMLSize_t bl = strlen((char *) buffer);

	if (offset > bl)
		return -1;

	const char* p = strstr((char *) &buffer[offset], inStr);

	if (p == NULL)
		return -1;

	XMLSSize_t d = p - (char*) buffer;
	if (d > bufferSize || d < 0)
		return -1;

	return d;

}

// XMLCh and char common functions

void safeBuffer::sbStrlwr(void) {

	if (m_bufferType == BUFFER_UNKNOWN) {

		throw XSECException(XSECException::SafeBufferError,
			"Attempt to perform an operation on a buffer of incorrect type");

	}

	if (m_bufferType == BUFFER_CHAR) {

	    XMLSize_t i, l = (XMLSize_t) strlen((char *) buffer);

		for (i = 0; i < l; ++i) {
			if (buffer[i] >= 'A' && buffer[i] <= 'Z')
				buffer[i] = (buffer[i] - 'A') + 'a';
		}

	}

	else {

		XMLCh * b = (XMLCh *) buffer;
		XMLSize_t i, l = XMLString::stringLen(b);

		for (i = 0; i < l; ++i) {
			if (b[i] >= XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A && b[i] <= XERCES_CPP_NAMESPACE_QUALIFIER chLatin_Z)
				b[i] = (b[i] - XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A) + XERCES_CPP_NAMESPACE_QUALIFIER chLatin_a;
		}

	}

}
// Operators

unsigned char & safeBuffer::operator[](XMLSize_t n) {

	// If the character is outside our range (but +ve), then simply increase
	// the buffer size - NOTE: it is not our problem if the caller does
	// not realise they are outside the buffer, we are simply trying to ensure
	// the call is "safe"

	checkAndExpand(n);

	return buffer[n];

}

safeBuffer & safeBuffer::operator= (const safeBuffer & cpy) {

	if (bufferSize != cpy.bufferSize) {

		if (bufferSize != 0) {

			if (m_isSensitive == true)
				cleanseBuffer();

			delete [] buffer;
		}

		buffer = new unsigned char [cpy.bufferSize];
		bufferSize = cpy.bufferSize;

	}

	memcpy(buffer, cpy.buffer, bufferSize);
	m_bufferType = cpy.m_bufferType;
	// Once we are sensitive, we are always sensitive
	m_isSensitive = m_isSensitive || cpy.m_isSensitive;

	return *this;
}

safeBuffer & safeBuffer::operator= (const XMLCh * inStr) {

	checkAndExpand(XMLString::stringLen(inStr) * size_XMLCh);
	XMLString::copyString((XMLCh *) buffer, inStr);
	m_bufferType = BUFFER_UNICODE;
	return *this;

}

safeBuffer & safeBuffer::operator << (TXFMBase * t) {

	// Read into buffer the output of the transform
	XMLSize_t offset = 0;
	unsigned char inBuf[2048];
	XMLSize_t bytesRead;

	while ((bytesRead = t->readBytes(inBuf, 2000)) > 0) {

		checkAndExpand(offset + bytesRead + 1);
		memcpy(&buffer[offset], inBuf, bytesRead);
		offset += bytesRead;

	}

	m_bufferType = BUFFER_CHAR;
	buffer[offset] = '\0';

	return *this;
}


// Unicode Functions

const XMLCh * safeBuffer::sbStrToXMLCh(void) const {

	checkBufferType(BUFFER_CHAR);
	if (mp_XMLCh != NULL)
		XSEC_RELEASE_XMLCH(mp_XMLCh);

	mp_XMLCh = XMLString::transcode((char *) buffer);

	return mp_XMLCh;

}

void safeBuffer::sbTranscodeIn(const XMLCh * inStr) {

	// Transcode the string to the local code page and store in the buffer
	char * t;

	t = XMLString::transcode(inStr);

	assert (t != 0);


	// Now copy into our local buffer - a bit inefficient but better in the long run
	// as a buffer that is the exact size is likely to be deleted anyway during a
	// concat operation

	XMLSize_t len = (XMLSize_t) strlen(t) + 1;
	checkAndExpand(len);
	strcpy((char *) buffer, t);
	m_bufferType = BUFFER_CHAR;

	XSEC_RELEASE_XMLCH(t);

}

void safeBuffer::sbTranscodeIn(const char * inStr) {

	// Transcode the string to the local code page and store in the buffer
	XMLCh * t;

	t = XMLString::transcode(inStr);

	assert (t != 0);

	// Copy into local buffer

	XMLSize_t len = XMLString::stringLen(t) + 1;
    len *= (XMLSize_t) size_XMLCh;
	checkAndExpand(len);

	XMLString::copyString((XMLCh *) buffer, t);
	m_bufferType = BUFFER_UNICODE;

	XSEC_RELEASE_XMLCH(t);

}


void safeBuffer::sbXMLChIn(const XMLCh * in) {

	checkAndExpand((XMLString::stringLen(in) + 1) * size_XMLCh);

	XMLString::copyString((XMLCh *) buffer, in);
	m_bufferType = BUFFER_UNICODE;

}

void safeBuffer::sbXMLChAppendCh(const XMLCh c) {

	checkBufferType(BUFFER_UNICODE);
	XMLSize_t len = XMLString::stringLen((XMLCh *) buffer);

	checkAndExpand((len + 2) * size_XMLCh);

	((XMLCh *) buffer)[len++] = c;
	((XMLCh *) buffer)[len] = 0;

}

void safeBuffer::sbXMLChCat(const XMLCh *str) {

	checkBufferType(BUFFER_UNICODE);
	XMLSize_t len = XMLString::stringLen((XMLCh *) buffer) * size_XMLCh;
	len += XMLString::stringLen(str) * size_XMLCh;
	len += (2 * ((XMLSize_t) size_XMLCh));

	checkAndExpand(len);

	XMLString::catString((XMLCh *) buffer, str);

}

void safeBuffer::sbXMLChCat(const char * str) {

	checkBufferType(BUFFER_UNICODE);
	XMLSize_t len = XMLString::stringLen((XMLCh *) buffer) * size_XMLCh;

	XMLCh * t = XMLString::transcode(str);

	assert (t != NULL);

	len += XMLString::stringLen(t) * size_XMLCh;
	len += (XMLSize_t) (2 * size_XMLCh);

	checkAndExpand(len);

	XMLString::catString((XMLCh *) buffer, t);

	XSEC_RELEASE_XMLCH(t);
}

void safeBuffer::sbXMLChCat8(const char * str) {

	checkBufferType(BUFFER_UNICODE);

	XMLCh * toAdd = transcodeFromUTF8((const unsigned char *) str);
	sbXMLChCat(toAdd);
	XSEC_RELEASE_XMLCH(toAdd);

}

// Get functions

XMLSize_t safeBuffer::sbStrlen(void) const {

    checkBufferType(BUFFER_CHAR);
    return (XMLSize_t) (strlen ((char *) buffer));

}

XMLSize_t safeBuffer::sbRawBufferSize(void) const {

    return bufferSize;

}


// raw buffer manipulation

const unsigned char * safeBuffer::rawBuffer() const {

	return buffer;

}

const char * safeBuffer::rawCharBuffer() const {

	return (char *) buffer;

}

const XMLCh * safeBuffer::rawXMLChBuffer() const {

	return (XMLCh *) buffer;

}

// Sensitive data functions

void safeBuffer::isSensitive(void) {

	m_isSensitive = true;

}

void safeBuffer::cleanseBuffer(void) {

	// Cleanse the main buffer
	for (XMLSize_t i = 0; i < bufferSize; ++i)
		buffer[i] = 0;

}
