/**
 * 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/dsig/DSIGSignature.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>

#include "../utils/XSECDOMUtils.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;

}

