/**
 * 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
 *
 * XENCEncryptedTypeImpl := Implementation of the EncryptedType interface
 * element
 *
 * $Id$
 *
 */


#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMSB.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/xenc/XENCEncryptedKey.hpp>

#include "XENCCipherImpl.hpp"
#include "XENCCipherDataImpl.hpp"
#include "XENCEncryptedTypeImpl.hpp"
#include "XENCEncryptionMethodImpl.hpp"
#include "../../utils/XSECAutoPtr.hpp"
#include "../../utils/XSECDOMUtils.hpp"

#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//			UNICODE Strings
// --------------------------------------------------------------------------------

static XMLCh s_EncryptionMethod[] = {

	chLatin_E,
	chLatin_n,
	chLatin_c,
	chLatin_r,
	chLatin_y,
	chLatin_p,
	chLatin_t,
	chLatin_i,
	chLatin_o,
	chLatin_n,
	chLatin_M,
	chLatin_e,
	chLatin_t,
	chLatin_h,
	chLatin_o,
	chLatin_d,
	chNull,
};

static XMLCh s_KeyInfo[] = {

	chLatin_K,
	chLatin_e,
	chLatin_y,
	chLatin_I,
	chLatin_n,
	chLatin_f,
	chLatin_o,
	chNull,
};

static XMLCh s_CipherData[] = {

	chLatin_C,
	chLatin_i,
	chLatin_p,
	chLatin_h,
	chLatin_e,
	chLatin_r,
	chLatin_D,
	chLatin_a,
	chLatin_t,
	chLatin_a,
	chNull,
};

static XMLCh s_Type[] = {
	
	chLatin_T,
	chLatin_y,
	chLatin_p,
	chLatin_e,
	chNull
};

static XMLCh s_MimeType[] = {
	
	chLatin_M,
	chLatin_i,
	chLatin_m,
	chLatin_e,
	chLatin_T,
	chLatin_y,
	chLatin_p,
	chLatin_e,
	chNull
};


static XMLCh s_Encoding[] = {
	
	chLatin_E,
	chLatin_n,
	chLatin_c,
	chLatin_o,
	chLatin_d,
	chLatin_i,
	chLatin_n,
	chLatin_g,
	chNull
};

// --------------------------------------------------------------------------------
//			Constructors and Destructors
// --------------------------------------------------------------------------------

XENCEncryptedTypeImpl::XENCEncryptedTypeImpl(const XSECEnv * env) :
mp_env(env),
mp_encryptedTypeElement(NULL),
mp_keyInfoElement(NULL),
mp_cipherDataElement(NULL),
mp_cipherData(NULL),
mp_encryptionMethod(NULL),
m_keyInfoList(env),
mp_typeAttr(NULL),
mp_mimeTypeAttr(NULL),
mp_encodingAttr(NULL) {

}


XENCEncryptedTypeImpl::XENCEncryptedTypeImpl(const XSECEnv * env, DOMElement * node) :
mp_env(env),
mp_encryptedTypeElement(node),
mp_keyInfoElement(NULL),
mp_cipherDataElement(NULL),
mp_cipherData(NULL),
mp_encryptionMethod(NULL),
m_keyInfoList(env),
mp_typeAttr(NULL),
mp_mimeTypeAttr(NULL),
mp_encodingAttr(NULL) {

}

XENCEncryptedTypeImpl::~XENCEncryptedTypeImpl() {

	if (mp_cipherData != NULL)
		delete mp_cipherData;

	if (mp_encryptionMethod != NULL)
		delete mp_encryptionMethod;

}

// --------------------------------------------------------------------------------
//			Load DOM Structures
// --------------------------------------------------------------------------------

void XENCEncryptedTypeImpl::load() {

	if (mp_encryptedTypeElement == NULL) {

		// Attempt to load an empty encryptedType element
		throw XSECException(XSECException::EncryptedTypeError,
			"XENCEncryptedType::load - called on empty DOM");

	}

	// Type
	mp_typeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Type);
	// MimeType
	mp_mimeTypeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_MimeType);
	// Encoding
	mp_encodingAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Encoding);

	// Don't know what the node name should be (held by super class), 
	// so go straight to the children
	
	DOMElement *tmpElt = (DOMElement *) findFirstChildOfType(mp_encryptedTypeElement, DOMNode::ELEMENT_NODE);

	if (tmpElt != NULL && strEquals(getXENCLocalName(tmpElt), s_EncryptionMethod)) {

		XSECnew(mp_encryptionMethod, XENCEncryptionMethodImpl(mp_env, tmpElt));
		mp_encryptionMethod->load();

		tmpElt = findNextElementChild(tmpElt);

	}

	if (tmpElt != NULL && strEquals(getDSIGLocalName(tmpElt), s_KeyInfo)) {

		// Load
		mp_keyInfoElement = tmpElt;
		m_keyInfoList.loadListFromXML(tmpElt);

		// Find the next node

		tmpElt = findNextElementChild(tmpElt);

	}

	if (tmpElt != NULL && strEquals(getXENCLocalName(tmpElt), s_CipherData)) {

		mp_cipherDataElement = tmpElt;

		XSECnew(mp_cipherData, XENCCipherDataImpl(mp_env, tmpElt));
		mp_cipherData->load();
		tmpElt = findNextElementChild(tmpElt);

	}

	else {

		throw XSECException(XSECException::ExpectedXENCChildNotFound,
			"Expected <CipherData> child of <EncryptedType>");

	}

	// Should check for EncryptionProperties

}

// --------------------------------------------------------------------------------
//			Create a blank structure
// --------------------------------------------------------------------------------

DOMElement * XENCEncryptedTypeImpl::createBlankEncryptedType(
						XMLCh * localName,
						XENCCipherData::XENCCipherDataType type, 
						const XMLCh * algorithm,
						const XMLCh * value) {

	// Reset
	mp_cipherData = NULL;
	mp_encryptionMethod = NULL;

	// Get some setup values
	safeBuffer str;
	DOMDocument *doc = mp_env->getParentDocument();
	const XMLCh * prefix = mp_env->getXENCNSPrefix();

	makeQName(str, prefix, localName);

	mp_encryptedTypeElement = doc->createElementNS(DSIGConstants::s_unicodeStrURIXENC, str.rawXMLChBuffer());

	// Set namespace
	if (prefix[0] == XERCES_CPP_NAMESPACE_QUALIFIER chNull) {
		str.sbTranscodeIn("xmlns");
	}
	else {
		str.sbTranscodeIn("xmlns:");
		str.sbXMLChCat(prefix);
	}

	mp_encryptedTypeElement->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, 
							str.rawXMLChBuffer(), 
							DSIGConstants::s_unicodeStrURIXENC);

	mp_env->doPrettyPrint(mp_encryptedTypeElement);

	// Create the EncryptionMethod
	if (algorithm != NULL) {

		XSECnew(mp_encryptionMethod, XENCEncryptionMethodImpl(mp_env));
		DOMNode * encryptionMethodNode = 
			mp_encryptionMethod->createBlankEncryptionMethod(algorithm);

		mp_encryptedTypeElement->appendChild(encryptionMethodNode);

		mp_env->doPrettyPrint(mp_encryptedTypeElement);

	}

	// Create the cipher Data
	XSECnew(mp_cipherData, XENCCipherDataImpl(mp_env));
	mp_cipherDataElement = mp_cipherData->createBlankCipherData(type, value);

	// Add to EncryptedType
	mp_encryptedTypeElement->appendChild(mp_cipherDataElement);

	mp_env->doPrettyPrint(mp_encryptedTypeElement);

	return mp_encryptedTypeElement;

}

// --------------------------------------------------------------------------------
//			Create a txfm chain for this transform list
// --------------------------------------------------------------------------------

TXFMChain * XENCEncryptedTypeImpl::createCipherTXFMChain(void) {

	if (mp_cipherData->getCipherDataType() == XENCCipherData::VALUE_TYPE) {

		TXFMChain * chain;

		// Given we already have this in memory, we transcode to
		// local code page and then transform

		XSECAutoPtrChar b64(mp_cipherData->getCipherValue()->getCipherString());

		try {
            TXFMSB *sb;
            XSECnew(sb, TXFMSB(mp_env->getParentDocument()));

            safeBuffer temp(b64.get());
            sb->setInput(temp);

            // Create a chain
            XSECnew(chain, TXFMChain(sb));

            // Create a base64 decoder
            TXFMBase64 * tb64;
            XSECnew(tb64, TXFMBase64(mp_env->getParentDocument()));

            chain->appendTxfm(tb64);

            return chain;
		}
        catch (...) {
            throw;
		}
	}

	else if (mp_cipherData->getCipherDataType() == XENCCipherData::REFERENCE_TYPE) {

		TXFMChain * chain;
		TXFMBase * b = DSIGReference::getURIBaseTXFM(mp_env->getParentDocument(), mp_cipherData->getCipherReference()->getURI(), mp_env);

		chain = DSIGReference::createTXFMChainFromList(b, mp_cipherData->getCipherReference()->getTransforms());
		Janitor<TXFMChain> j_chain(chain);

		if (chain->getLastTxfm()->getOutputType() == TXFMBase::DOM_NODES) {

			TXFMC14n * c14n;
			XSECnew(c14n, TXFMC14n(mp_env->getParentDocument()));
			chain->appendTxfm(c14n);

		}

		j_chain.release();
		return chain;

	}

	else {

		throw XSECException(XSECException::EncryptedTypeError,
			"XENCEncryptedType::createDecryptionTXFMChain - Unknown type of CipherData");

	}


}

// --------------------------------------------------------------------------------
//			Get Methods
// --------------------------------------------------------------------------------

XENCCipherData * XENCEncryptedTypeImpl::getCipherData() const {

	return mp_cipherData;

}

XENCEncryptionMethod * XENCEncryptedTypeImpl::getEncryptionMethod() const {
	
	return mp_encryptionMethod;

}

// --------------------------------------------------------------------------------
//			KeyInfo elements
// --------------------------------------------------------------------------------

const DSIGKeyInfoList * XENCEncryptedTypeImpl::getKeyInfoList() const {
    return &m_keyInfoList;
}

DSIGKeyInfoList * XENCEncryptedTypeImpl::getKeyInfoList() {
    return &m_keyInfoList;
}

void XENCEncryptedTypeImpl::clearKeyInfo() {

	if (mp_keyInfoElement == NULL)
		return;

	if (mp_encryptedTypeElement->removeChild(mp_keyInfoElement) != mp_keyInfoElement) {

		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"Attempted to remove KeyInfo node but it is no longer a child of <EncryptedType>");

	}

	mp_keyInfoElement->release();		// No longer required

	mp_keyInfoElement = NULL;

	// Clear out the list
	m_keyInfoList.empty();

}

void XENCEncryptedTypeImpl::createKeyInfoElement() {

	if (mp_keyInfoElement != NULL)
		return;

	safeBuffer str;

	const XMLCh * prefixNS = mp_env->getDSIGNSPrefix();
	makeQName(str, prefixNS, "KeyInfo");

	mp_keyInfoElement = m_keyInfoList.createKeyInfo();

	// Place the node before the CipherData node
	if (mp_cipherDataElement == NULL) {

		throw XSECException(XSECException::EncryptedTypeError,
			"XENCEncryptedTypeImpl::createKeyInfoElement - unable to find CipherData node");

	}

	mp_encryptedTypeElement->insertBefore(mp_keyInfoElement, mp_cipherDataElement);

	if (mp_env->getPrettyPrintFlag() == true)
		mp_encryptedTypeElement->insertBefore(mp_env->getParentDocument()->createTextNode(DSIGConstants::s_unicodeStrNL), mp_cipherDataElement);
	
	// Need to add the DS namespace

	if (prefixNS[0] == '\0') {
		str.sbTranscodeIn("xmlns");
	}
	else {
		str.sbTranscodeIn("xmlns:");
		str.sbXMLChCat(prefixNS);
	}

	mp_keyInfoElement->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, 
							str.rawXMLChBuffer(), 
							DSIGConstants::s_unicodeStrURIDSIG);

}

DSIGKeyInfoValue * XENCEncryptedTypeImpl::appendDSAKeyValue(const XMLCh * P, 
						   const XMLCh * Q, 
						   const XMLCh * G, 
						   const XMLCh * Y) {

	createKeyInfoElement();
	return m_keyInfoList.appendDSAKeyValue(P, Q, G, Y);

}

DSIGKeyInfoValue * XENCEncryptedTypeImpl::appendRSAKeyValue(const XMLCh * modulus, 
						   const XMLCh * exponent) {

	createKeyInfoElement();
	return m_keyInfoList.appendRSAKeyValue(modulus, exponent);

}


DSIGKeyInfoX509 * XENCEncryptedTypeImpl::appendX509Data() {

	createKeyInfoElement();
	return m_keyInfoList.appendX509Data();

}

DSIGKeyInfoName * XENCEncryptedTypeImpl::appendKeyName(const XMLCh * name, bool isDName) {

	createKeyInfoElement();
	return m_keyInfoList.appendKeyName(name, isDName);

}

DSIGKeyInfoPGPData * XENCEncryptedTypeImpl::appendPGPData(const XMLCh * id, const XMLCh * packet) {

    createKeyInfoElement();
    return m_keyInfoList.appendPGPData(id, packet);

}

DSIGKeyInfoSPKIData * XENCEncryptedTypeImpl::appendSPKIData(const XMLCh * sexp) {

    createKeyInfoElement();
    return m_keyInfoList.appendSPKIData(sexp);

}

DSIGKeyInfoMgmtData * XENCEncryptedTypeImpl::appendMgmtData(const XMLCh * data) {

    createKeyInfoElement();
    return m_keyInfoList.appendMgmtData(data);

}

void XENCEncryptedTypeImpl::appendEncryptedKey(XENCEncryptedKey * encryptedKey) {

	createKeyInfoElement();
	m_keyInfoList.addAndInsertKeyInfo(encryptedKey);

}

// --------------------------------------------------------------------------------
//			Type URI handling
// --------------------------------------------------------------------------------

const XMLCh * XENCEncryptedTypeImpl::getType() const {

	if (mp_typeAttr != NULL)
		return mp_typeAttr->getNodeValue();

	return NULL;

}

void XENCEncryptedTypeImpl::setType(const XMLCh * uri) {

	if (mp_typeAttr != NULL) {
		mp_typeAttr->setNodeValue(uri);
	}
	else {

		// Need to create the node
		mp_encryptedTypeElement->setAttributeNS(NULL, s_Type, uri);
		mp_typeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Type);

		if (mp_typeAttr == NULL) {

			throw XSECException(XSECException::InternalError,
				"XENCEncryptedTypeImpl::setTypeURI - Cannot find the attribute I just added");

		}

	}
}

// --------------------------------------------------------------------------------
//			MimeType handling
// --------------------------------------------------------------------------------

const XMLCh * XENCEncryptedTypeImpl::getMimeType() const {

	if (mp_mimeTypeAttr != NULL)
		return mp_mimeTypeAttr->getNodeValue();

	return NULL;

}

void XENCEncryptedTypeImpl::setMimeType(const XMLCh * mimeType) {

	if (mp_mimeTypeAttr != NULL) {
		mp_mimeTypeAttr->setNodeValue(mimeType);
	}
	else {

		// Need to create the node
		mp_encryptedTypeElement->setAttributeNS(NULL, s_MimeType, mimeType);
		mp_mimeTypeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_MimeType);
		if (mp_mimeTypeAttr == NULL) {

			throw XSECException(XSECException::InternalError,
				"XENCEncryptedTypeImpl::setMimeType - Cannot find the attribute I just added");

		}

	}
}

// --------------------------------------------------------------------------------
//			Encoding handling
// --------------------------------------------------------------------------------

const XMLCh * XENCEncryptedTypeImpl::getEncoding() const {

	if (mp_encodingAttr != NULL)
		return mp_encodingAttr->getNodeValue();

	return NULL;

}

void XENCEncryptedTypeImpl::setEncoding(const XMLCh * uri) {

	if (mp_encodingAttr != NULL) {
		mp_encodingAttr->setNodeValue(uri);
	}
	else {

		// Need to create the node
		mp_encryptedTypeElement->setAttributeNS(NULL, s_Encoding, uri);
		mp_encodingAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Encoding);

		if (mp_encodingAttr == NULL) {

			throw XSECException(XSECException::InternalError,
				"XENCEncryptedTypeImpl::setEncodingURI - Cannot find the attribute I just added");

		}

	}
}
