/*
 * Copyright 2002-2005 The Apache Software Foundation.
 *
 * Licensed 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
 *
 * DSIGKeyInfoList := Class for Loading and storing a list of KeyInfo elements
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

// XSEC Includes
#include <xsec/dsig/DSIGKeyInfoList.hpp>
#include <xsec/dsig/DSIGKeyInfoX509.hpp>
#include <xsec/dsig/DSIGKeyInfoName.hpp>
#include <xsec/dsig/DSIGKeyInfoValue.hpp>
#include <xsec/dsig/DSIGKeyInfoPGPData.hpp>
#include <xsec/dsig/DSIGKeyInfoSPKIData.hpp>
#include <xsec/dsig/DSIGKeyInfoMgmtData.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/dsig/DSIGTransformList.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMBase.hpp>

#include "../xenc/impl/XENCEncryptedKeyImpl.hpp"

#include <xercesc/util/Janitor.hpp>

XERCES_CPP_NAMESPACE_USE

DSIGKeyInfoList::DSIGKeyInfoList(const XSECEnv * env) :
mp_env(env),
mp_keyInfoNode(NULL) {}

DSIGKeyInfoList::~DSIGKeyInfoList() {

	empty();

}

// Actions

void DSIGKeyInfoList::addKeyInfo(DSIGKeyInfo * ref) {

	m_keyInfoList.push_back(ref);

}

DSIGKeyInfo * DSIGKeyInfoList::removeKeyInfo(size_type index) {

	if (index < m_keyInfoList.size())
		return m_keyInfoList[index];

	return NULL;

}

size_t DSIGKeyInfoList::getSize() {

	return m_keyInfoList.size();

}


DSIGKeyInfo * DSIGKeyInfoList::item(size_type index) {

	if (index < m_keyInfoList.size())
		return m_keyInfoList[index];
	
	return NULL;

}

void DSIGKeyInfoList::empty() {

	size_type i, s;
	s = getSize();

	for (i = 0; i < s; ++i)
		delete m_keyInfoList[i];

	m_keyInfoList.clear();

}

bool DSIGKeyInfoList::isEmpty() {

		return (m_keyInfoList.size() == 0);

}

// --------------------------------------------------------------------------------
//           Add a KeyInfo based on XML DomNode source
// --------------------------------------------------------------------------------


bool DSIGKeyInfoList::addXMLKeyInfo(DOMNode *ki) {

	// return true if successful - does not throw if the node type is unknown

	if (ki == 0)
		return false;

	DSIGKeyInfo * k;

	if (strEquals(getDSIGLocalName(ki), "X509Data")) {

		// Have a certificate!
		XSECnew(k, DSIGKeyInfoX509(mp_env, ki));
	}

	else if (strEquals(getDSIGLocalName(ki), "KeyName")) {

		XSECnew(k, DSIGKeyInfoName(mp_env, ki));
	}

	else if (strEquals(getDSIGLocalName(ki), "KeyValue")) {

		XSECnew(k, DSIGKeyInfoValue(mp_env, ki));
	}

	else if (strEquals(getDSIGLocalName(ki), "PGPData")) {

		XSECnew(k, DSIGKeyInfoPGPData(mp_env, ki));
	}

	else if (strEquals(getDSIGLocalName(ki), "SPKIData")) {

		XSECnew(k, DSIGKeyInfoSPKIData(mp_env, ki));
		
	}

	else if (strEquals(getDSIGLocalName(ki), "MgmtData")) {

		XSECnew(k, DSIGKeyInfoMgmtData(mp_env, ki));
		
	}

	else if (strEquals(getXENCLocalName(ki), "EncryptedKey")) {

		XSECnew(k, XENCEncryptedKeyImpl(mp_env, (DOMElement *) ki));
		
	}

	else {

		return false;

	}

	// Now we know what the element type is - do the load and save

	try {
		k->load();
	}
	catch (...) {
		delete k;
		throw;
	}

	// Add
	this->addKeyInfo(k);

	return true;

}

// --------------------------------------------------------------------------------
//           Retrieve a complete KeyInfo list
// --------------------------------------------------------------------------------


bool DSIGKeyInfoList::loadListFromXML(DOMNode * node) {

	if (node == NULL || !strEquals(getDSIGLocalName(node), "KeyInfo")) {
		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"DSIGKeyInfoList::loadListFromXML - expected KeyInfo node");
	}

	DOMNode *tmpKI = findFirstChildOfType(node, DOMNode::ELEMENT_NODE);
	
	while (tmpKI != 0) {

		// Find out what kind of KeyInfo child it is

		if (tmpKI != 0 && strEquals(getDSIGLocalName(tmpKI), "RetrievalMethod")) {

			// A reference to key information held elsewhere

			const XMLCh * URI = NULL;
			TXFMBase * currentTxfm;
			bool isRawX509 = false;

			DOMNamedNodeMap *atts = tmpKI->getAttributes();
			const XMLCh * name;
			XMLSize_t size;

			if (atts == 0 || (size = atts->getLength()) == 0)
				return true;

			for (XMLSize_t i = 0; i < size; ++i) {

				name = atts->item(i)->getNodeName();

				if (strEquals(name, "URI")) {
					URI  = atts->item(i)->getNodeValue();
				}

				else if (strEquals(name, "Type")) {

					// Check if this is a raw X509 cert
					if (strEquals(atts->item(i)->getNodeValue(), DSIGConstants::s_unicodeStrURIRawX509)) {
						isRawX509 = true;
					}

				}

				else if (strEquals(name, "Id")) {

					// For now ignore

				}

				else {
					safeBuffer tmp, error;

					error << (*mp_env->getSBFormatter() << name);
					tmp.sbStrcpyIn("Unknown attribute in <RetrievalMethod> Element : ");
					tmp.sbStrcatIn(error);

					throw XSECException(XSECException::UnknownDSIGAttribute, tmp.rawCharBuffer());

				}

			}

			if (isRawX509 == true) {

				if (URI == NULL) {

					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
						"Expected to find a URI attribute in a rawX509RetrievalMethod KeyInfo");

				}

				DSIGKeyInfoX509 * x509;
				XSECnew(x509, DSIGKeyInfoX509(mp_env));
				x509->setRawRetrievalURI(URI);

				addKeyInfo(x509);

			}

			else {

				// Find base transform using the base URI
				currentTxfm = DSIGReference::getURIBaseTXFM(mp_env->getParentDocument(), URI, mp_env);
				TXFMChain * chain;
				XSECnew(chain, TXFMChain(currentTxfm));
				Janitor<TXFMChain> j_chain(chain);

				// Now check for transforms
				tmpKI = tmpKI->getFirstChild();

				while (tmpKI != 0 && (tmpKI->getNodeType() != DOMNode::ELEMENT_NODE))
					// Skip text and comments
					tmpKI = tmpKI->getNextSibling();

				if (tmpKI != 0 && strEquals(getDSIGLocalName(tmpKI), "Transforms")) {


					// Process the transforms using the static function.
					// For the moment we don't really support remote KeyInfos, so
					// Just built the transform list, process it and then destroy it.

					DSIGTransformList * l = DSIGReference::loadTransforms(
						tmpKI,
						mp_env->getSBFormatter(),
						mp_env);

					DSIGTransformList::TransformListVectorType::size_type size, i;
					size = l->getSize();
					for (i = 0; i < size; ++ i) {
						try {
							l->item(i)->appendTransformer(chain);
						}
						catch (...) {
							delete l;
							throw;
						}
					}

					delete l;

				}

				// Find out the type of the final transform and process accordingly
				
				TXFMBase::nodeType type = chain->getLastTxfm()->getNodeType();

				XSECXPathNodeList lst;
				const DOMNode * element;

				switch (type) {

				case TXFMBase::DOM_NODE_DOCUMENT :

					break;

				case TXFMBase::DOM_NODE_DOCUMENT_FRAGMENT :

					element = chain->getLastTxfm()->getFragmentNode();
					if (element != NULL)
						addXMLKeyInfo((DOMNode *) element);

					break;

				case TXFMBase::DOM_NODE_XPATH_NODESET :

					lst = chain->getLastTxfm()->getXPathNodeList();
					element = lst.getFirstNode();

					while (element != NULL) {

						// Try to add each element - just call KeyInfoList add as it will
						// do the check to see if it is a valud KeyInfo

						addXMLKeyInfo((DOMNode *) element);
						element = lst.getNextNode();

					}

					break;

				default :

					throw XSECException(XSECException::XPathError);

				}

				// Delete the transform chain
				chain->getLastTxfm()->deleteExpandedNameSpaces();

				// Janitor will clean up chain
			}

		} /* if getNodeName == Retrieval Method */

		// Now just run through each node type in turn to process "local" KeyInfos

		else if (!addXMLKeyInfo(tmpKI)) {

			throw XSECException(XSECException::KeyInfoError,
				"Unknown KeyInfo element found");

		}

		if (tmpKI != NULL)
			tmpKI = tmpKI->getNextSibling();

		while (tmpKI != NULL && (tmpKI->getNodeType() != DOMNode::ELEMENT_NODE))
			tmpKI = tmpKI->getNextSibling();

	}

	return true;
}

// --------------------------------------------------------------------------------
//           Create new KeyInfo elements
// --------------------------------------------------------------------------------

DOMElement * DSIGKeyInfoList::createKeyInfo(void) {

	// Assume that someone else has looked after the DOM
	empty();

	safeBuffer str;
	DOMDocument * doc = mp_env->getParentDocument();

	makeQName(str, mp_env->getDSIGNSPrefix(), "KeyInfo");

	DOMElement * ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());

	mp_keyInfoNode = ret;
	mp_env->doPrettyPrint(mp_keyInfoNode);

	return ret;	

}


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

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create DSAKeyValue before creating KeyInfo");

	}

	// Create the new element
	DSIGKeyInfoValue * v;
	XSECnew(v, DSIGKeyInfoValue(mp_env));

	mp_keyInfoNode->appendChild(v->createBlankDSAKeyValue(P, Q, G, Y));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	// Add to the list
	addKeyInfo(v);

	return v;

}

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

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create RSAKeyValue before creating KeyInfo");

	}

	// Create the new element
	DSIGKeyInfoValue * v;
	XSECnew(v, DSIGKeyInfoValue(mp_env));

	mp_keyInfoNode->appendChild(v->createBlankRSAKeyValue(modulus, exponent));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	// Add to the list
	addKeyInfo(v);

	return v;

}


DSIGKeyInfoX509 * DSIGKeyInfoList::appendX509Data(void) {

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create X509Data before creating KeyInfo");

	}

	DSIGKeyInfoX509 * x;

	XSECnew(x, DSIGKeyInfoX509(mp_env));

	mp_keyInfoNode->appendChild(x->createBlankX509Data());
	mp_env->doPrettyPrint(mp_keyInfoNode);

	// Add to the list
	addKeyInfo(x);

	return x;

}

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

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create KeyName before creating KeyInfo");

	}

	DSIGKeyInfoName * n;

	XSECnew(n, DSIGKeyInfoName(mp_env));

	mp_keyInfoNode->appendChild(n->createBlankKeyName(name, isDName));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	// Add to the list
	addKeyInfo(n);

	return n;

}

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

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create PGPData before creating KeyInfo");

	}

	DSIGKeyInfoPGPData * p;

	XSECnew(p, DSIGKeyInfoPGPData(mp_env));

	mp_keyInfoNode->appendChild(p->createBlankPGPData(id, packet));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	addKeyInfo(p);

	return p;

}

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

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create SPKIData before creating KeyInfo");

	}

	DSIGKeyInfoSPKIData * s;

	XSECnew(s, DSIGKeyInfoSPKIData(mp_env));

	mp_keyInfoNode->appendChild(s->createBlankSPKIData(sexp));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	addKeyInfo(s);

	return s;

}

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

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create MgmtData before creating KeyInfo");

	}

	DSIGKeyInfoMgmtData * m;

	XSECnew(m, DSIGKeyInfoMgmtData(mp_env));

	mp_keyInfoNode->appendChild(m->createBlankMgmtData(data));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	addKeyInfo(m);

	return m;

}

// --------------------------------------------------------------------------------
//           Some helper functions
// --------------------------------------------------------------------------------

void DSIGKeyInfoList::addAndInsertKeyInfo(DSIGKeyInfo * ref) {

	if (mp_keyInfoNode == NULL) {

		throw XSECException(XSECException::KeyInfoError, 
			"KeyInfoList - Attempt to create MgmtData before creating KeyInfo");

	}

	mp_keyInfoNode->appendChild(ref->getKeyInfoDOMNode());
	mp_env->doPrettyPrint(mp_keyInfoNode);

	addKeyInfo(ref);

}
