/**
 * 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
 *
 * DSIGKeyInfoValue := A value setting
 *
 * $Id$
 *
 */

#include <xsec/dsig/DSIGKeyInfoValue.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/framework/XSECEnv.hpp>

XERCES_CPP_NAMESPACE_USE

DSIGKeyInfoValue::DSIGKeyInfoValue(const XSECEnv * env, DOMNode *valueNode) :
DSIGKeyInfo(env),
mp_PTextNode(0),
mp_QTextNode(0),
mp_GTextNode(0),
mp_YTextNode(0),
mp_modulusTextNode(0),
mp_exponentTextNode(0),
mp_namedCurveElementNode(0),
mp_ecPublicKeyTextNode(0),
m_keyInfoType(KEYINFO_NOTSET) {

		mp_keyInfoDOMNode = valueNode;
}

DSIGKeyInfoValue::DSIGKeyInfoValue(const XSECEnv * env) :
DSIGKeyInfo(env),
mp_PTextNode(0),
mp_QTextNode(0),
mp_GTextNode(0),
mp_YTextNode(0),
mp_modulusTextNode(0),
mp_exponentTextNode(0),
mp_namedCurveElementNode(0),
mp_ecPublicKeyTextNode(0),
m_keyInfoType(KEYINFO_NOTSET) {

	mp_keyInfoDOMNode = NULL;
}

DSIGKeyInfoValue::~DSIGKeyInfoValue() {


}

// --------------------------------------------------------------------------------
//           Load from XML
// --------------------------------------------------------------------------------

void DSIGKeyInfoValue::load(void) {

	if (mp_keyInfoDOMNode == NULL || !strEquals(getDSIGLocalName(mp_keyInfoDOMNode), "KeyValue")) {

		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"Empty or incorrect node passed to DSIGKeyInfoValue");

	}

	DOMNode *child, *p, *val;

	child = mp_keyInfoDOMNode->getFirstChild();
	while (child != NULL && child->getNodeType() != DOMNode::ELEMENT_NODE)
		child = child->getNextSibling();
	//child = findFirstChildOfType(mp_valueNode, DOMNode::ELEMENT_NODE);

	if (child == 0) {
		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"Empty Expected value node beneath <KeyValue>");
	}

	if (strEquals(getDSIGLocalName(child), "DSAKeyValue")) {

		m_keyInfoType = KEYINFO_VALUE_DSA;

		p = findFirstChildOfType(child, DOMNode::ELEMENT_NODE);

		while (p != NULL) {

			if (strEquals(getDSIGLocalName(p), "P")) {
				val = findFirstChildOfType(p, DOMNode::TEXT_NODE);
				if (val != NULL) {
					mp_PTextNode = val;
				}
			}
			if (strEquals(getDSIGLocalName(p), "Q")) {
				val = findFirstChildOfType(p, DOMNode::TEXT_NODE);
				if (val != NULL) {
					mp_QTextNode = val;
				}
			}
			if (strEquals(getDSIGLocalName(p), "G")) {
				val = findFirstChildOfType(p, DOMNode::TEXT_NODE);
				if (val != NULL) {
					mp_GTextNode = val;
				}
			}
			if (strEquals(getDSIGLocalName(p), "Y")) {
				val = findFirstChildOfType(p, DOMNode::TEXT_NODE);
				if (val != NULL) {
					mp_YTextNode = val;
				}
			}

			p = p->getNextSibling();

		}
	}

	else if (strEquals(getDSIGLocalName(child), "RSAKeyValue")) {

		m_keyInfoType = KEYINFO_VALUE_RSA;

		p = findFirstChildOfType(child, DOMNode::ELEMENT_NODE);

		if (p == 0 || !strEquals(getDSIGLocalName(p), "Modulus")) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <Modulus> node beneath <RSAKeyValue>");

		}

		val = findFirstChildOfType(p, DOMNode::TEXT_NODE);

		if (val == 0) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected a text node beneath <Modulus>");

		}
		
		mp_modulusTextNode = val;

		// Find the Exponent

		p = p->getNextSibling();

		while (p != 0 && p->getNodeType() != DOMNode::ELEMENT_NODE)
			p = p->getNextSibling();

		if (p == 0 || !strEquals(getDSIGLocalName(p), "Exponent")) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <Exponent> node beneath <RSAKeyValue>");

		}

		val = findFirstChildOfType(p, DOMNode::TEXT_NODE);

		if (val == 0) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected a text node beneath <Exponent>");

		}
		
		mp_exponentTextNode = val;

	}

    else if (strEquals(getDSIG11LocalName(child), "ECKeyValue")) {

        m_keyInfoType = KEYINFO_VALUE_EC;

        p = findFirstChildOfType(child, DOMNode::ELEMENT_NODE);
        if (p == 0 || !strEquals(getDSIG11LocalName(p), "NamedCurve")) {
			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <NamedCurve> node beneath <ECKeyValue> (<ECParameters> not supported)");
        }

        mp_namedCurveElementNode = p;

		p = p->getNextSibling();

		while (p != 0 && p->getNodeType() != DOMNode::ELEMENT_NODE)
			p = p->getNextSibling();

        if (p == 0 || !strEquals(getDSIG11LocalName(p), "PublicKey")) {
			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <PublicKey> node beneath <ECKeyValue>");
        }

		val = findFirstChildOfType(p, DOMNode::TEXT_NODE);

		if (val == 0) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected a text node beneath <PublicKey>");

		}
		
		mp_ecPublicKeyTextNode = val;

    }

	else {

		throw XSECException(XSECException::UnknownKeyValue);

	}

}

// --------------------------------------------------------------------------------
//           Get RSA Values
// --------------------------------------------------------------------------------

const XMLCh* DSIGKeyInfoValue::getRSAModulus(void) const {

	if (m_keyInfoType != KEYINFO_VALUE_RSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to Get an RSA Modulus from a non-RSAValue KeyValue node");

	}

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

	return NULL;

}

const XMLCh * DSIGKeyInfoValue::getRSAExponent(void) const {

	if (m_keyInfoType != KEYINFO_VALUE_RSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to Get an RSA Exponent from a non-RSAValue KeyValue node");

	}

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

	return NULL;

}

// --------------------------------------------------------------------------------
//           Get EC Values
// --------------------------------------------------------------------------------

const XMLCh* DSIGKeyInfoValue::getECNamedCurve(void) const {

	if (m_keyInfoType != KEYINFO_VALUE_EC) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to Get an EC NamedCurve from a non-ECValue KeyValue node");

	}

	if (mp_namedCurveElementNode != NULL)
        return static_cast<DOMElement*>(mp_namedCurveElementNode)->getAttributeNS(NULL, DSIGConstants::s_unicodeStrURI);

	return NULL;

}

const XMLCh * DSIGKeyInfoValue::getECPublicKey(void) const {

	if (m_keyInfoType != KEYINFO_VALUE_EC) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to Get an EC PublicKey from a non-ECValue KeyValue node");

	}

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

	return NULL;

}

// --------------------------------------------------------------------------------
//           Create and manipulate DSA Values
// --------------------------------------------------------------------------------

DOMElement * DSIGKeyInfoValue::createBlankDSAKeyValue(const XMLCh * P,
	const XMLCh * Q,
	const XMLCh * G,
	const XMLCh * Y) {

	// Set our type
	
	m_keyInfoType = KEYINFO_VALUE_DSA;

	// Create the DOM Structure

	safeBuffer str;
	DOMDocument *doc = mp_env->getParentDocument();
	const XMLCh * prefix = mp_env->getDSIGNSPrefix();

	makeQName(str, prefix, "KeyValue");

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

	makeQName(str, prefix, "DSAKeyValue");
	DOMElement * dsa = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_env->doPrettyPrint(ret);
	ret->appendChild(dsa);
	mp_env->doPrettyPrint(dsa);
	mp_env->doPrettyPrint(ret);

	// Now create the value children

	makeQName(str, prefix, "P");
	DOMElement * v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_PTextNode = doc->createTextNode(P);
	dsa->appendChild(v);
	mp_env->doPrettyPrint(dsa);
	v->appendChild(mp_PTextNode);

	makeQName(str, prefix, "Q");
	v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_PTextNode = doc->createTextNode(Q);
	dsa->appendChild(v);
	mp_env->doPrettyPrint(dsa);
	v->appendChild(mp_PTextNode);

	makeQName(str, prefix, "G");
	v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_PTextNode = doc->createTextNode(G);
	dsa->appendChild(v);
	mp_env->doPrettyPrint(dsa);
	v->appendChild(mp_PTextNode);

	makeQName(str, prefix, "Y");
	v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_PTextNode = doc->createTextNode(Y);
	dsa->appendChild(v);
	mp_env->doPrettyPrint(dsa);
	v->appendChild(mp_PTextNode);

	return ret;

}

void DSIGKeyInfoValue::setDSAP(const XMLCh * P) {

	if (m_keyInfoType != KEYINFO_VALUE_DSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set a DSA value in a non-DSA KeyValue node");

	}

	mp_PTextNode->setNodeValue(P);

}

void DSIGKeyInfoValue::setDSAQ(const XMLCh * Q) {

	if (m_keyInfoType != KEYINFO_VALUE_DSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set a DSA value in a non-DSA KeyValue node");

	}

	mp_QTextNode->setNodeValue(Q);

}

void DSIGKeyInfoValue::setDSAG(const XMLCh * G) {

	if (m_keyInfoType != KEYINFO_VALUE_DSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set a DSA value in a non-DSA KeyValue node");

	}

	mp_GTextNode->setNodeValue(G);

}

void DSIGKeyInfoValue::setDSAY(const XMLCh * Y) {

	if (m_keyInfoType != KEYINFO_VALUE_DSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set a DSA value in a non-DSA KeyValue node");

	}

	mp_YTextNode->setNodeValue(Y);

}

// --------------------------------------------------------------------------------
//           Create and manipulate RSA Values
// --------------------------------------------------------------------------------

DOMElement * DSIGKeyInfoValue::createBlankRSAKeyValue(const XMLCh * modulus,
													  const XMLCh * exponent) {

	// Set our type
	
	m_keyInfoType = KEYINFO_VALUE_RSA;

	// Create the DOM Structure

	safeBuffer str;
	DOMDocument *doc = mp_env->getParentDocument();
	const XMLCh * prefix = mp_env->getDSIGNSPrefix();

	makeQName(str, prefix, "KeyValue");

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

	makeQName(str, prefix, "RSAKeyValue");
	DOMElement * rsa = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_env->doPrettyPrint(ret);
	ret->appendChild(rsa);
	mp_env->doPrettyPrint(rsa);
	mp_env->doPrettyPrint(ret);

	// Now create the value children

	makeQName(str, prefix, "Modulus");
	DOMElement * v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_modulusTextNode = doc->createTextNode(modulus);
	rsa->appendChild(v);
	mp_env->doPrettyPrint(rsa);
	v->appendChild(mp_modulusTextNode);

	makeQName(str, prefix, "Exponent");
	v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_exponentTextNode = doc->createTextNode(exponent);
	rsa->appendChild(v);
	mp_env->doPrettyPrint(rsa);
	v->appendChild(mp_exponentTextNode);

	return ret;

}

void DSIGKeyInfoValue::setRSAModulus(const XMLCh * modulus) {

	if (m_keyInfoType != KEYINFO_VALUE_RSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set an RSA Modulus from a non-RSA KeyValue node");

	}

	mp_modulusTextNode->setNodeValue(modulus);

}

void DSIGKeyInfoValue::setRSAExponent(const XMLCh * exponent) {

	if (m_keyInfoType != KEYINFO_VALUE_RSA) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set an RSA Exponent from a non-RSA KeyValue node");

	}

	mp_exponentTextNode->setNodeValue(exponent);

}

DOMElement* DSIGKeyInfoValue::createBlankECKeyValue(const XMLCh * curveName, const XMLCh * publicKey) {

	// Set our type
	
	m_keyInfoType = KEYINFO_VALUE_EC;

	// Create the DOM Structure

	safeBuffer str;
	DOMDocument *doc = mp_env->getParentDocument();
	const XMLCh * prefix = mp_env->getDSIGNSPrefix();
	const XMLCh * prefix11 = mp_env->getDSIG11NSPrefix();

	makeQName(str, prefix, "KeyValue");

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

	makeQName(str, prefix11, "ECKeyValue");
	DOMElement * ec = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG11, str.rawXMLChBuffer());
	mp_env->doPrettyPrint(ret);
	ret->appendChild(ec);
	mp_env->doPrettyPrint(ec);
	mp_env->doPrettyPrint(ret);

	// Now create the value children

	makeQName(str, prefix11, "NamedCurve");
	DOMElement * v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG11, str.rawXMLChBuffer());
	mp_namedCurveElementNode = v;
	ec->appendChild(v);
	mp_env->doPrettyPrint(ec);
    v->setAttributeNS(NULL, DSIGConstants::s_unicodeStrURI, curveName);

	makeQName(str, prefix11, "PublicKey");
	v = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG11, str.rawXMLChBuffer());
	mp_ecPublicKeyTextNode = doc->createTextNode(publicKey);
	ec->appendChild(v);
	mp_env->doPrettyPrint(ec);
	v->appendChild(mp_ecPublicKeyTextNode);

	return ret;

}

void DSIGKeyInfoValue::setECNamedCurve(const XMLCh* curveName) {
	if (m_keyInfoType != KEYINFO_VALUE_EC) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set an EC NamedCurve from a non-EC KeyValue node");

	}

    static_cast<DOMElement*>(mp_namedCurveElementNode)->setAttributeNS(NULL, DSIGConstants::s_unicodeStrURI, curveName);
}

void DSIGKeyInfoValue::setECPublicKey(const XMLCh* publicKey) {

	if (m_keyInfoType != KEYINFO_VALUE_EC) {

		throw XSECException(XSECException::KeyInfoError,
			"Attempt to set an EC PublicKey from a non-EC KeyValue node");

	}

	mp_ecPublicKeyTextNode->setNodeValue(publicKey);
}

// --------------------------------------------------------------------------------
//           Other interface functions
// --------------------------------------------------------------------------------

DSIGKeyInfo::keyInfoType DSIGKeyInfoValue::getKeyInfoType(void) const {

	return m_keyInfoType;

}

const XMLCh * DSIGKeyInfoValue::getKeyName(void) const {

	return DSIGConstants::s_unicodeStrEmpty;

}

