/**
 * 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/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 "../utils/XSECDOMUtils.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);

}
