/**
 * 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
 *
 * 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/DSIGKeyInfoDEREncoded.hpp>
#include <xsec/dsig/DSIGKeyInfoPGPData.hpp>
#include <xsec/dsig/DSIGKeyInfoSPKIData.hpp>
#include <xsec/dsig/DSIGKeyInfoMgmtData.hpp>
#include <xsec/dsig/DSIGKeyInfoExt.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() const {

	return m_keyInfoList.size();

}


DSIGKeyInfo * DSIGKeyInfoList::item(size_type index) {

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

	return NULL;

}

const DSIGKeyInfo * DSIGKeyInfoList::item(size_type index) const {

	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() const {

		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(getDSIG11LocalName(ki), "DEREncodedKeyValue")) {

		XSECnew(k, DSIGKeyInfoDEREncoded(mp_env, ki));

	}

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

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

	}

	else {

	    XSECnew(k, DSIGKeyInfoExt(mp_env, ki));

	}

	// 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
				DOMNode * tmpTran = tmpKI->getFirstChild();

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

				if (tmpTran != 0 && strEquals(getDSIGLocalName(tmpTran), "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(
					    tmpTran,
						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 valid 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 {
            // This used to check the return value, and throw if the child was unknown.
            // Now, should handle all cases.
            addXMLKeyInfo(tmpKI);
		}

		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;

}

DSIGKeyInfoDEREncoded * DSIGKeyInfoList::appendDEREncoded(const XMLCh * data) {

	if (mp_keyInfoNode == NULL) {

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

	}

	DSIGKeyInfoDEREncoded * d;

	XSECnew(d, DSIGKeyInfoDEREncoded(mp_env));

	mp_keyInfoNode->appendChild(d->createBlankDEREncoded(data));
	mp_env->doPrettyPrint(mp_keyInfoNode);

	addKeyInfo(d);

	return d;

}

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

void DSIGKeyInfoList::addAndInsertKeyInfo(DSIGKeyInfo * ref) {

	if (mp_keyInfoNode == NULL) {

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

	}

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

	addKeyInfo(ref);

}
