/**
 * 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
 *
 * DSIG_Reference := Class for handling a DSIG reference element
 *
 * $Id$
 *
 */

// XSEC includes

#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMURL.hpp>
#include <xsec/transformers/TXFMDocObject.hpp>
#include <xsec/transformers/TXFMOutputFile.hpp>
#include <xsec/transformers/TXFMSHA1.hpp>
#include <xsec/transformers/TXFMMD5.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMSB.hpp>
#include <xsec/transformers/TXFMXPath.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMXSL.hpp>
#include <xsec/transformers/TXFMEnvelope.hpp>
#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/dsig/DSIGTransformList.hpp>
#include <xsec/dsig/DSIGTransformBase64.hpp>
#include <xsec/dsig/DSIGTransformEnvelope.hpp>
#include <xsec/dsig/DSIGTransformXPath.hpp>
#include <xsec/dsig/DSIGTransformXPathFilter.hpp>
#include <xsec/dsig/DSIGTransformXSL.hpp>
#include <xsec/dsig/DSIGTransformC14n.hpp>

#include <xsec/framework/XSECError.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECAlgorithmHandler.hpp>
#include <xsec/framework/XSECAlgorithmMapper.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/utils/XSECBinTXFMInputStream.hpp>

// Xerces

#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>

XERCES_CPP_NAMESPACE_USE

#include <iostream>

// --------------------------------------------------------------------------------
//           Some useful strings
// --------------------------------------------------------------------------------


static const XMLCh  s_unicodeStrURI[] =
{
        XERCES_CPP_NAMESPACE_QUALIFIER chLatin_U,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_R,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_I,
		XERCES_CPP_NAMESPACE_QUALIFIER chNull
};

static const XMLCh  s_unicodeStrxpointer[] =
{
        XERCES_CPP_NAMESPACE_QUALIFIER chLatin_x,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_p,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_o,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_i,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_n,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_t,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_e,
		XERCES_CPP_NAMESPACE_QUALIFIER chLatin_r,
		XERCES_CPP_NAMESPACE_QUALIFIER chNull
};

static const XMLCh s_unicodeStrRootNode[] =
{
		XERCES_CPP_NAMESPACE_QUALIFIER chOpenParen,
		XERCES_CPP_NAMESPACE_QUALIFIER chForwardSlash,
		XERCES_CPP_NAMESPACE_QUALIFIER chCloseParen,
		XERCES_CPP_NAMESPACE_QUALIFIER chNull
};

// --------------------------------------------------------------------------------
//           Constructors and Destructors
// --------------------------------------------------------------------------------


DSIGReference::DSIGReference(const XSECEnv * env, DOMNode *dom) :
	mp_formatter(NULL),
	mp_referenceNode(dom),
	mp_preHash(NULL),
	mp_manifestList(NULL),
	mp_URI(NULL),
	m_isManifest(false),
	mp_transformsNode(NULL),
	me_hashMethod(HASH_NONE),
	mp_hashValueNode(NULL),
	mp_env(env),
	mp_transformList(NULL),
	mp_algorithmURI(NULL),
	m_loaded(false) {

	// Should throw an exception if the node is not a REFERENCE element

	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
												XMLFormatter::UnRep_CharRef));
}

DSIGReference::DSIGReference(const XSECEnv * env) :
	mp_formatter(NULL),
	mp_referenceNode(NULL),
	mp_preHash(NULL),
	mp_manifestList(NULL),
	mp_URI(NULL),
	m_isManifest(false),
	mp_transformsNode(NULL),
	me_hashMethod(HASH_NONE),
	mp_hashValueNode(NULL),
	mp_env(env),
	mp_transformList(NULL),
	mp_algorithmURI(NULL),
	m_loaded(false) {

	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
											XMLFormatter::UnRep_CharRef));
};

DSIGReference::~DSIGReference() {

	// Destroy any associated transforms

	if (mp_transformList != NULL) {

		delete mp_transformList;
		mp_transformList = NULL;

	}

	if (mp_formatter != NULL)
		delete mp_formatter;

	if (mp_manifestList != NULL)
		delete mp_manifestList;

};

// --------------------------------------------------------------------------------
//           Creation of Transforms
// --------------------------------------------------------------------------------

void DSIGReference::createTransformList(void) {

	// Creates the transforms list
	safeBuffer str;
	const XMLCh * prefix;
	DOMDocument *doc = mp_env->getParentDocument();

	prefix = mp_env->getDSIGNSPrefix();

	if (mp_transformsNode == NULL) {

		// Need to create a transforms node
		makeQName(str, prefix, "Transforms");
		mp_transformsNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
		mp_referenceNode->insertBefore(mp_transformsNode, mp_referenceNode->getFirstChild());
		if (mp_env->getPrettyPrintFlag() == true)
			mp_referenceNode->insertBefore(doc->createTextNode(DSIGConstants::s_unicodeStrNL), mp_transformsNode);
		mp_env->doPrettyPrint(mp_transformsNode);

		// Create the list
		XSECnew(mp_transformList, DSIGTransformList());
	}

}

void DSIGReference::addTransform(DSIGTransform * txfm, DOMElement * txfmElt) {

	if (mp_transformList == NULL)
		createTransformList();

	mp_transformsNode->appendChild(txfmElt);
	mp_env->doPrettyPrint(mp_transformsNode);

	mp_transformList->addTransform(txfm);
}


DSIGTransformEnvelope * DSIGReference::appendEnvelopedSignatureTransform() {

	DOMElement *txfmElt;
	DSIGTransformEnvelope * txfm;

	XSECnew(txfm, DSIGTransformEnvelope(mp_env));
	txfmElt = txfm->createBlankTransform(mp_env->getParentDocument());

	addTransform(txfm, txfmElt);

	return txfm;

}

DSIGTransformBase64 * DSIGReference::appendBase64Transform() {

	DOMElement *txfmElt;
	DSIGTransformBase64 * txfm;

	XSECnew(txfm, DSIGTransformBase64(mp_env));
	txfmElt = txfm->createBlankTransform(mp_env->getParentDocument());

	addTransform(txfm, txfmElt);

	return txfm;

}

DSIGTransformXSL * DSIGReference::appendXSLTransform(DOMNode * stylesheet) {

	DOMElement *txfmElt;
	DSIGTransformXSL * txfm;

	XSECnew(txfm, DSIGTransformXSL(mp_env));
	txfmElt = txfm->createBlankTransform(mp_env->getParentDocument());
	txfm->setStylesheet(stylesheet);

	addTransform(txfm, txfmElt);

	return txfm;

}

DSIGTransformC14n * DSIGReference::appendCanonicalizationTransform(canonicalizationMethod cm) {

	DOMElement *txfmElt;
	DSIGTransformC14n * txfm;

	XSECnew(txfm, DSIGTransformC14n(mp_env));
	txfmElt = txfm->createBlankTransform(mp_env->getParentDocument());
	txfm->setCanonicalizationMethod(cm);

	addTransform(txfm, txfmElt);

	return txfm;

}

DSIGTransformC14n * DSIGReference::appendCanonicalizationTransform(
		const XMLCh * canonicalizationAlgorithmURI) {

	canonicalizationMethod cm;
	XSECmapURIToCanonicalizationMethod(canonicalizationAlgorithmURI, cm);

	return appendCanonicalizationTransform(cm);

}

DSIGTransformXPath * DSIGReference::appendXPathTransform(const char * expr) {

	DOMElement *txfmElt;
	DSIGTransformXPath * txfm;

	XSECnew(txfm, DSIGTransformXPath(mp_env));
	txfmElt = txfm->createBlankTransform(mp_env->getParentDocument());
	txfm->setExpression(expr);

	addTransform(txfm, txfmElt);

	return txfm;
}

DSIGTransformXPathFilter * DSIGReference::appendXPathFilterTransform(void) {

	DOMElement *txfmElt;
	DSIGTransformXPathFilter * txfm;

	XSECnew(txfm, DSIGTransformXPathFilter(mp_env));
	txfmElt = txfm->createBlankTransform(mp_env->getParentDocument());

	addTransform(txfm, txfmElt);
	mp_env->doPrettyPrint(txfmElt);

	return txfm;
}



// --------------------------------------------------------------------------------
//           Creation of blanks
// --------------------------------------------------------------------------------


DOMElement *DSIGReference::createBlankReference(const XMLCh * URI,
												const XMLCh * hashAlgorithmURI,
												const XMLCh * type) {

	// Reset this Reference just in case

	m_isManifest = false;
	mp_preHash = NULL;
	mp_manifestList = NULL;
	mp_transformsNode = NULL;
	mp_transformList = NULL;

	XSECmapURIToHashMethod(hashAlgorithmURI, me_hashMethod);

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

	makeQName(str, prefix, "Reference");

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

	// Set type
	if (type != NULL)
		ret->setAttributeNS(NULL, MAKE_UNICODE_STRING("Type"), type);

	// Set URI
	if (URI != NULL) {
		ret->setAttributeNS(NULL, s_unicodeStrURI, URI);
		mp_URI = ret->getAttributeNS(NULL, s_unicodeStrURI); // Used later on as a pointer
	}
	else {
		// Anonymous reference
		mp_URI = NULL;
	}

	// Create hash and hashValue nodes
	makeQName(str, prefix, "DigestMethod");
	DOMElement *digestMethod = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	mp_env->doPrettyPrint(ret);
	ret->appendChild(digestMethod);
	mp_env->doPrettyPrint(ret);

	digestMethod->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm,
		hashAlgorithmURI);

	// Retrieve the attribute value for later use
	mp_algorithmURI =
		digestMethod->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm);


	// DigestValue

	makeQName(str, prefix, "DigestValue");
	mp_hashValueNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	ret->appendChild(mp_hashValueNode);
	mp_env->doPrettyPrint(ret);
	mp_hashValueNode->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("Not yet calculated")));

	m_loaded = true;
	return ret;

}

// --------------------------------------------------------------------------------
//           setPreHashTransform - to set a transform to be used pre-hash
// --------------------------------------------------------------------------------


void DSIGReference::setPreHashTXFM(TXFMBase * t) {

	mp_preHash = t;

}

//           setId
// --------------------------------------------------------------------------------

void DSIGReference::setId(const XMLCh *id) {

    if (mp_referenceNode)
        ((DOMElement*)mp_referenceNode)->setAttributeNS(NULL, MAKE_UNICODE_STRING("Id"), id);

}

// --------------------------------------------------------------------------------
//           setType
// --------------------------------------------------------------------------------

void DSIGReference::setType(const XMLCh *type) {

    if (mp_referenceNode)
        ((DOMElement*)mp_referenceNode)->setAttributeNS(NULL, MAKE_UNICODE_STRING("Type"), type);

}

// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
//           isManifest
// --------------------------------------------------------------------------------

bool DSIGReference::isManifest() const {

	return m_isManifest;

}

// --------------------------------------------------------------------------------
//           getURI
// --------------------------------------------------------------------------------

const XMLCh * DSIGReference::getURI() const {

	return mp_URI;

}

// --------------------------------------------------------------------------------
//           getManifestReferenceList
// --------------------------------------------------------------------------------

DSIGReferenceList * DSIGReference::getManifestReferenceList() const {

	return mp_manifestList;

}

// --------------------------------------------------------------------------------
//           getURIBaseTransform
// --------------------------------------------------------------------------------

TXFMBase * DSIGReference::getURIBaseTXFM(DOMDocument * doc,
										 const XMLCh * URI,
										 const XSECEnv * env) {

	// Determine if this is a full URL or a pointer to a URL

	if (URI == NULL || (URI[0] != 0 &&
		URI[0] != XERCES_CPP_NAMESPACE_QUALIFIER chPound)) {

		TXFMURL * retTransform;

		// Have a URL!

		XSECnew(retTransform, TXFMURL(doc, env->getURIResolver()));

		try {
			((TXFMURL *) retTransform)->setInput(URI);
		}
		catch (...) {

			delete retTransform;
			throw;

		}

		return retTransform;

	}

	// Have a fragment URI from the local document
	TXFMDocObject * to;
	XSECnew(to, TXFMDocObject(doc));
	Janitor<TXFMDocObject> j_to(to);
	to->setEnv(env);

	// Find out what sort of object pointer this is.

	if (URI[0] == 0) {

		// empty pointer - use the document itself
		to->setInput(doc);
		to->stripComments();

	}

	else if (XMLString::compareNString(&URI[1], s_unicodeStrxpointer, 8) == 0) {

		// Have an xpointer
		if (strEquals(s_unicodeStrRootNode, &URI[9]) == true) {
			// Root node
			to->setInput(doc);

		}

		else if (URI[9] == XERCES_CPP_NAMESPACE_QUALIFIER chOpenParen &&
				URI[10] == XERCES_CPP_NAMESPACE_QUALIFIER chLatin_i &&
				URI[11] == XERCES_CPP_NAMESPACE_QUALIFIER chLatin_d &&
				URI[12] == XERCES_CPP_NAMESPACE_QUALIFIER chOpenParen &&
				URI[13] == XERCES_CPP_NAMESPACE_QUALIFIER chSingleQuote) {

			XMLSize_t len = XMLString::stringLen(&URI[14]);

			XMLCh* tmp = new XMLCh[len + 1];
			ArrayJanitor<XMLCh> j_tmp(tmp);

			XMLSize_t j = 14, i = 0;

			// Have an ID
			while (i < len && URI[j] != '\'') {
				tmp[i++] = URI[j++];
			}

			tmp[i] = XERCES_CPP_NAMESPACE_QUALIFIER chNull;
			
			if (URI[j] != '\'') {
				throw XSECException(XSECException::UnsupportedXpointerExpr);	
			}

			to->setInput(doc, tmp);

		}

		else {

			throw XSECException(XSECException::UnsupportedXpointerExpr);

		}

		// Keep comments in these situations
		to->activateComments();
	}

	else {

		to->setInput(doc, &URI[1]);

		// Remove comments
		to->stripComments();

	}

	j_to.release();
	return to;

}

// --------------------------------------------------------------------------------
//           load
// --------------------------------------------------------------------------------

void DSIGReference::load(void) {

	// Load reference info from XML

	DOMNamedNodeMap *atts = mp_referenceNode->getAttributes();
	DOMNode *tmpElt;

	const XMLCh * name;
	safeBuffer sbName;

	if (atts != 0) {

		XMLSize_t size = atts->getLength();

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

			name = atts->item(i)->getNodeName();
			sbName << (*mp_formatter << atts->item(i)->getNodeName());

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

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

				// Check if a manifest, otherwise ignore for now
				if (strEquals(atts->item(i)->getNodeValue(), DSIGConstants::s_unicodeStrURIMANIFEST))
					m_isManifest = true;

			}

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

				// For now ignore

			}

			else if (sbName.sbStrncmp("xmlns", 5) == 0) {

				// Ignore name spaces

			}

			else {
				//safeBuffer tmp, error;

				//error << (*mp_formatter << name);
				//tmp.sbStrcpyIn("Unknown attribute in <Reference> Element : ");
				//tmp.sbStrcatIn(error);

				throw XSECException(XSECException::UnknownDSIGAttribute,
					"Unknown attribute in <Reference> Element");

			}

		}

	}

	// Now check for Transforms
	tmpElt = mp_referenceNode->getFirstChild();

	while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE)) {
		if (tmpElt->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"EntityReference nodes in <Reference> are unsupported.");
		}
		// Skip text and comments
		tmpElt = tmpElt->getNextSibling();
	}

	if (tmpElt == 0) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
					"Expected <Transforms> or <DigestMethod> within <Reference>");

	}

	if (strEquals(getDSIGLocalName(tmpElt), "Transforms")) {

		// Store node for later use
		mp_transformsNode = tmpElt;

		// Load the transforms
		mp_transformList = loadTransforms(tmpElt, mp_formatter, mp_env);

		// Find next node
		tmpElt = tmpElt->getNextSibling();
		while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE)) {
			if (tmpElt->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
					"EntityReference nodes in <Reference> are unsupported.");
			}
			tmpElt = tmpElt->getNextSibling();
		}


	} /* if tmpElt node type = transforms */
	else {
		mp_transformList = NULL;
	}


	if (tmpElt == NULL || !strEquals(getDSIGLocalName(tmpElt), "DigestMethod")) {

		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
							"Expected <DigestMethod> element");

	}

	// Determine what the digest method actually is

	atts = tmpElt->getAttributes();
	unsigned int i;

	for (i = 0; i < atts->getLength() &&
		!strEquals(atts->item(i)->getNodeName(), DSIGConstants::s_unicodeStrAlgorithm); ++i);


	if (i == atts->getLength()) {

		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
							"Expected 'Algorithm' attribute in <DigestMethod>");

	}

	mp_algorithmURI = atts->item(i)->getNodeValue();

	// Determine hashing algorithm
	XSECmapURIToHashMethod(mp_algorithmURI, me_hashMethod);

	// Find the hash value node

	tmpElt = tmpElt->getNextSibling();

	while (tmpElt != 0 &&
		(tmpElt->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getDSIGLocalName(tmpElt), "DigestValue"))) {
		if (tmpElt->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"EntityReference nodes in <Reference> are unsupported.");
		}
		tmpElt = tmpElt->getNextSibling();
	}

	if (tmpElt == 0) {

		throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"Expected <DigestValue> within <Reference>");

	}

	mp_hashValueNode = tmpElt;

	// If we are a manifest, then we need to load the manifest references

	if (m_isManifest) {

		// Find the manifest node - we cheat and use a transform
		TXFMBase				* docObject;
		DOMNode					* manifestNode, * referenceNode;

		docObject = getURIBaseTXFM(mp_referenceNode->getOwnerDocument(), mp_URI,
			mp_env);

		manifestNode = docObject->getFragmentNode();
		delete docObject;

		// Now search downwards to find a <Manifest>
		if (manifestNode == 0 || manifestNode->getNodeType() != DOMNode::ELEMENT_NODE ||
			(!strEquals(getDSIGLocalName(manifestNode), "Object") && !strEquals(getDSIGLocalName(manifestNode), "Manifest"))) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <Manifest> or <Object> URI for Manifest Type <Reference>");

		}

		if (strEquals(getDSIGLocalName(manifestNode), "Object")) {

			// Find Manifest child
			manifestNode = manifestNode->getFirstChild();
			while (manifestNode != 0 && manifestNode->getNodeType() != DOMNode::ELEMENT_NODE) {
				if (manifestNode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
						"EntityReference nodes in <Reference> are unsupported.");
				}
				manifestNode = manifestNode->getNextSibling();
			}

			if (manifestNode == 0 || !strEquals(getDSIGLocalName(manifestNode), "Manifest"))
				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <Manifest> as child of <Object> for Manifest Type <Reference>");

		}

		// Now have the manifest node, find the first reference and load!
		referenceNode = manifestNode->getFirstChild();

		while (referenceNode != 0 &&
			(referenceNode->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getDSIGLocalName(referenceNode), "Reference"))) {
			if (referenceNode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
					"EntityReference nodes in <Reference> are unsupported.");
			}
			referenceNode = referenceNode->getNextSibling();
		}

		if (referenceNode == 0)
			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
			"Expected <Reference> as child of <Manifest>");

		// Have reference node, so lets create a list!
		mp_manifestList = DSIGReference::loadReferenceListFromXML(mp_env, referenceNode);

	} /* m_isManifest */

	m_loaded = true;

}

// --------------------------------------------------------------------------------
//           createReferenceListFromXML
// --------------------------------------------------------------------------------

DSIGReferenceList *DSIGReference::loadReferenceListFromXML(const XSECEnv * env, DOMNode *firstReference) {

	// Have the first reference element in the document,
	// so want to find and load them all

	DOMNode *tmpRef = firstReference;
	DSIGReferenceList * refList;
	DSIGReference * r;

	XSECnew(refList, DSIGReferenceList());
	Janitor<DSIGReferenceList> j_refList(refList);

	while (tmpRef != 0) {

		// Must be an element node

		if (tmpRef->getNodeType() != DOMNode::ELEMENT_NODE ||
			!strEquals(getDSIGLocalName(tmpRef), "Reference")) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <Reference> as child of <SignedInfo>");

		}

		XSECnew(r, DSIGReference(env, tmpRef));

		refList->addReference(r);

		// Load the reference before moving on
		r->load();

		// Find next element Node
		tmpRef = tmpRef->getNextSibling();

		while (tmpRef != 0 && tmpRef->getNodeType() != DOMNode::ELEMENT_NODE) {
			if (tmpRef->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
					"EntityReference nodes in <Reference> are unsupported.");
			}
			tmpRef = tmpRef->getNextSibling();
		}

	}

	j_refList.release();
	return refList;

}
// --------------------------------------------------------------------------------
//           Get the Canonicalised BYTE_STREAM of the reference data (and TXFMS)
// --------------------------------------------------------------------------------

XSECBinTXFMInputStream * DSIGReference::makeBinInputStream(void) const {

	// First set up for input

	TXFMChain * txfmChain;
	TXFMBase * currentTxfm;

	if (m_loaded == false) {

		throw XSECException(XSECException::NotLoaded,
			"calculateHash() called in DSIGReference before load()");

	}

	// Find base transform
	currentTxfm = getURIBaseTXFM(mp_referenceNode->getOwnerDocument(), mp_URI,
		mp_env);

	// Set up the transform chain

	txfmChain = createTXFMChainFromList(currentTxfm, mp_transformList);
	Janitor<TXFMChain> j_txfmChain(txfmChain);

	DOMDocument *d = mp_referenceNode->getOwnerDocument();

	// All transforms done.  If necessary, change the type from nodes to bytes

	if (txfmChain->getLastTxfm()->getOutputType() == TXFMBase::DOM_NODES) {

		TXFMC14n * c14n;
		XSECnew(c14n, TXFMC14n(d));
		txfmChain->appendTxfm(c14n);

	}

	// Now create the InputStream

	XSECBinTXFMInputStream * ret;
	ret = new XSECBinTXFMInputStream(txfmChain);	// Probs with MSVC++ mean no XSECnew
	j_txfmChain.release();		// Now owned by "ret"

	return ret;

}

// --------------------------------------------------------------------------------
//           Hash a reference list
// --------------------------------------------------------------------------------


void DSIGReference::hashReferenceList(const DSIGReferenceList *lst, bool interlocking) {

// Run through a list of hashes and checkHash for each one

	DSIGReference * r;
	int i = (int) lst->getSize();
	safeBuffer errStr;
	errStr.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty);

	// Run a VERY naieve process at the moment that assumes the list will "settle"
	// after N iterations through the list.  This will settle any inter-locking references
	// Where a hash in a later calculated reference could impact an already calculated hash
	// in a previous references
	//
	// If interlocking is set to false, assume there are no interacting <Reference> nodes

	do {

		for (int j = 0; j < i; ++j) {

			r = lst->item(j);

			// If this is a manifest we need to set all the references in the manifest as well

			if (r->isManifest())
				hashReferenceList(r->getManifestReferenceList());

			// Re-ordered as per suggestion by Peter Gubis to make it more likely
			// that hashes are correct on first pass when manifests are involved

			r->setHash();

		}

	} while (interlocking && !DSIGReference::verifyReferenceList(lst, errStr) && i-- >= 0);
}

// --------------------------------------------------------------------------------
//           Verify reference list
// --------------------------------------------------------------------------------

bool DSIGReference::verifyReferenceList(const DSIGReferenceList * lst, safeBuffer &errStr) {

	// Run through a list of hashes and checkHash for each one

	XSEC_USING_XERCES(NetAccessorException);

	DSIGReference * r;
	bool res = true;

	int size = (lst ? (int) lst->getSize() : 0);

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

		r = lst->item(i);

		try {
			if (!r->checkHash()) {

				// Failed
				errStr.sbXMLChCat("Reference URI=\"");
				errStr.sbXMLChCat(r->getURI());
				errStr.sbXMLChCat("\" failed to verify\n");

				res = false;

			}
		}
		catch (const NetAccessorException&) {

			res = false;

			errStr.sbXMLChCat("Error accessing network URI=\"");
			errStr.sbXMLChCat(r->getURI());
			errStr.sbXMLChCat("\".  Reference failed to verify\n");

		}
		catch (const XSECException& e) {

			if (e.getType() != XSECException::HTTPURIInputStreamError)
				throw;

			res = false;

			errStr.sbXMLChCat("Error accessing network URI=\"");
			errStr.sbXMLChCat(r->getURI());
			errStr.sbXMLChCat("\".  Reference failed to verify\n");

		}

		// if a manifest, check the manifest list
		if (r->isManifest())
			res = res & verifyReferenceList(r->getManifestReferenceList(), errStr);

	}

	return res;
}

// --------------------------------------------------------------------------------
//           processTransforms
// --------------------------------------------------------------------------------

TXFMChain * DSIGReference::createTXFMChainFromList(TXFMBase * input,
							DSIGTransformList * lst) {

	TXFMChain * ret;
	XSECnew(ret, TXFMChain(input));

	if (lst == NULL)
		return ret;

	Janitor<TXFMChain> j_ret(ret);

	DSIGTransformList::TransformListVectorType::size_type size, i;

	size = lst->getSize();

	if (size > 0) {

		// Iterate through the list

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

			lst->item(i)->appendTransformer(ret);

		}

	}

	j_ret.release();
	return ret;

}

// --------------------------------------------------------------------------------
//           loadTransforms
// --------------------------------------------------------------------------------

DSIGTransformList * DSIGReference::loadTransforms(
							DOMNode *transformsNode,
							XSECSafeBufferFormatter * formatter,
							const XSECEnv * env) {

	// This is defined as a static function, not because it makes use of any static variables
	// in the DSIGReference class, but to neatly link it to the other users

	if (transformsNode == 0 || (!strEquals(getDSIGLocalName(transformsNode), "Transforms") &&
		!strEquals(getXENCLocalName(transformsNode), "Transforms"))) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
					"Expected <Transforms> in function DSIGReference::processTransforms");

	}

	// Create the list
	DSIGTransformList * lst;
	XSECnew(lst, DSIGTransformList());
	Janitor<DSIGTransformList> j_lst(lst);

	// Find First transform

	DOMNode * transforms = transformsNode->getFirstChild();
	while (transforms != NULL && transforms->getNodeType() != DOMNode::ELEMENT_NODE)
		transforms = transforms->getNextSibling();

	while (transforms != NULL) {

		// Process each transform in turn
		if (!strEquals(getDSIGLocalName(transforms), "Transform")) {

			// Not what we expected to see!
			safeBuffer tmp, error;

			error << (*formatter << getDSIGLocalName(transforms));
			tmp.sbStrcpyIn("Unknown attribute in <Transforms> - Expected <Transform> found ");
			tmp.sbStrcatIn(error);
			tmp.sbStrcatIn(">.");

			throw XSECException(XSECException::ExpectedDSIGChildNotFound, error.rawCharBuffer());

		}

		DOMNamedNodeMap * transformAtts = transforms->getAttributes();

		unsigned int i;

		for (i = 0; i < transformAtts->getLength() &&
				!strEquals(transformAtts->item(i)->getNodeName(), DSIGConstants::s_unicodeStrAlgorithm); ++i);

		if (i == transformAtts->getLength()) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Algorithm attribute not found in <Transform> element");

		}

		safeBuffer algorithm;
		algorithm << (*formatter << transformAtts->item(i)->getNodeValue());

		// Determine what the transform is

		if (algorithm.sbStrcmp(URI_ID_BASE64) == 0) {

			DSIGTransformBase64 * b;
			XSECnew(b, DSIGTransformBase64(env, transforms));
			lst->addTransform(b);
			b->load();
		}

		else if (algorithm.sbStrcmp(URI_ID_XPATH) == 0) {

			DSIGTransformXPath * x;
			XSECnew(x, DSIGTransformXPath(env, transforms));
			lst->addTransform(x);
			x->load();
		}

		else if (algorithm.sbStrcmp(URI_ID_XPF) == 0) {

			DSIGTransformXPathFilter * xpf;

			XSECnew(xpf, DSIGTransformXPathFilter(env, transforms));
			lst->addTransform(xpf);
			xpf->load();

		}

		else if (algorithm.sbStrcmp(URI_ID_ENVELOPE) == 0) {

			DSIGTransformEnvelope * e;
			XSECnew(e, DSIGTransformEnvelope(env, transforms));
			lst->addTransform(e);
			e->load();
		}

		else if (algorithm.sbStrcmp(URI_ID_XSLT) == 0) {

			DSIGTransformXSL * x;
			XSECnew(x, DSIGTransformXSL(env, transforms));
			lst->addTransform(x);
			x->load();

		}


		else if (algorithm.sbStrcmp(URI_ID_C14N_COM) == 0 ||
			     algorithm.sbStrcmp(URI_ID_C14N_NOC) == 0 ||
			     algorithm.sbStrcmp(URI_ID_C14N11_COM) == 0 ||
                 algorithm.sbStrcmp(URI_ID_C14N11_NOC) == 0 ||
				 algorithm.sbStrcmp(URI_ID_EXC_C14N_COM) == 0 ||
				 algorithm.sbStrcmp(URI_ID_EXC_C14N_NOC) == 0) {

			DSIGTransformC14n * c;
			XSECnew(c, DSIGTransformC14n(env, transforms));
			lst->addTransform(c);
			c->load();

		}

		else {

			// Not what we expected to see!
			safeBuffer tmp;

			tmp.sbStrcpyIn("Unknown transform : ");
			tmp.sbStrcatIn(algorithm);
			tmp.sbStrcatIn(" found.");

			throw XSECException(XSECException::UnknownTransform, tmp.rawCharBuffer());
		}

		// Now find next element

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

	} /* while (transforms != NULL) */

	j_lst.release();
	return lst;
}

// --------------------------------------------------------------------------------
//           Set hash
// --------------------------------------------------------------------------------

void DSIGReference::setHash(void) {

    // Set up

    if (mp_hashValueNode == 0) {
        throw XSECException(XSECException::NotLoaded,
            "setHash() called in DSIGReference before load()");
    }

    unsigned int maxHashSize = XSECPlatformUtils::g_cryptoProvider->getMaxHashSize();

	XSECCryptoBase64 *	b64 = XSECPlatformUtils::g_cryptoProvider->base64();
	if (!b64) {
		throw XSECException(XSECException::CryptoProviderError,
				"Error requesting Base64 object from Crypto Provider");
	}

	Janitor<XSECCryptoBase64> j_b64(b64);

    // First determine the hash value
    XMLByte* calculatedHashVal = new XMLByte[maxHashSize];
    XMLByte* base64Hash = new XMLByte[maxHashSize * 2];

    unsigned int base64HashLen = 0;

    try {
        unsigned int calculatedHashLen = calculateHash(calculatedHashVal, maxHashSize);

        // Calculate the base64 value
        b64->encodeInit();
        base64HashLen = b64->encode(calculatedHashVal,
            calculatedHashLen,
            base64Hash,
            maxHashSize * 2);
        base64HashLen += b64->encodeFinish(&base64Hash[base64HashLen],
            (maxHashSize * 2) - base64HashLen);
    }
    catch (...) {
        delete[] calculatedHashVal;
        delete[] base64Hash;
        throw;
    }

    delete[] calculatedHashVal;

	// Ensure the string is terminated
	if (base64Hash[base64HashLen-1] == '\n')
		base64Hash[base64HashLen-1] = '\0';
	else
		base64Hash[base64HashLen] = '\0';

	// Now find the correct text node to re-set

	DOMNode* tmpElt = mp_hashValueNode->getFirstChild();

	while (tmpElt != NULL && tmpElt->getNodeType() != DOMNode::TEXT_NODE)
		tmpElt = tmpElt->getNextSibling();

	if (tmpElt == NULL) {
		// Need to create the underlying TEXT_NODE
		DOMDocument *doc = mp_referenceNode->getOwnerDocument();
		tmpElt = doc->createTextNode(MAKE_UNICODE_STRING((char *) base64Hash));
		mp_hashValueNode->appendChild(tmpElt);
	}
	else {
		tmpElt->setNodeValue(MAKE_UNICODE_STRING((char *) base64Hash));
	}

    delete[] base64Hash;
}




// --------------------------------------------------------------------------------
//           Create hash
// --------------------------------------------------------------------------------

unsigned int DSIGReference::calculateHash(XMLByte *toFill, unsigned int maxToFill) const {

	// Determine the hash value of the element

	// First set up for input

	TXFMBase * currentTxfm;
	TXFMChain * chain;

	unsigned int size;

	if (m_loaded == false) {

		throw XSECException(XSECException::NotLoaded,
			"calculateHash() called in DSIGReference before load()");

	}

	// Find base transform
	currentTxfm = getURIBaseTXFM(mp_referenceNode->getOwnerDocument(), mp_URI,
		mp_env);

	// Now build the transforms list
	// Note this passes ownership of currentTxfm to the function, so it is the
	// responsibility of createTXFMChain to ensure it gets deleted if this throws.

	chain = createTXFMChainFromList(currentTxfm, mp_transformList);
	Janitor<TXFMChain> j_chain(chain);

	DOMDocument *d = mp_referenceNode->getOwnerDocument();

	// All transforms done.  If necessary, change the type from nodes to bytes

	if (chain->getLastTxfm()->getOutputType() == TXFMBase::DOM_NODES) {

		TXFMC14n * c14n;
		XSECnew(c14n, TXFMC14n(d));
		chain->appendTxfm(c14n);

	}

	// Check to see if there is a final "application" transform prior to the hash

	if (mp_preHash != NULL) {

		chain->appendTxfm(mp_preHash);
		mp_preHash = NULL;	// Can't be re-used

	}

	// Check for debugging sink for the data
	TXFMBase* sink = XSECPlatformUtils::GetReferenceLoggingSink(d);
	if (sink)
		chain->appendTxfm(sink);


	// Get the mapping for the hash transform

	XSECAlgorithmHandler * handler =
		XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(mp_algorithmURI);

	if (handler == NULL) {


		throw XSECException(XSECException::SigVfyError,
			"Hash method unknown in DSIGReference::calculateHash()");

	}

	if (!handler->appendHashTxfm(chain, mp_algorithmURI)) {

		throw XSECException(XSECException::SigVfyError,
			"Unexpected error in handler whilst appending Hash transform");

	}

	// Now we have the hashing transform, run it.

	size = chain->getLastTxfm()->readBytes(toFill, maxToFill);

	// Clean out document if necessary
	chain->getLastTxfm()->deleteExpandedNameSpaces();

	return size;

}

// --------------------------------------------------------------------------------
//           Read hash
// --------------------------------------------------------------------------------

unsigned int DSIGReference::readHash(XMLByte *toFill, unsigned int maxToFill) const {

	// Determine the hash value stored in the reference

	// First set up for input

	unsigned int size;
	DOMNode *tmpElt;
	//const XMLCh * stringHash;

	TXFMBase * nextInput;

	DOMDocument *d = mp_referenceNode->getOwnerDocument();

	safeBuffer b64HashVal;

	// Find the hash value

	tmpElt = mp_referenceNode->getFirstChild();

	while (tmpElt != 0 && !strEquals(getDSIGLocalName(tmpElt), "DigestValue"))
		tmpElt = tmpElt->getNextSibling();

	if (tmpElt == NULL)
		// ERROR
		return 0;

	// Now read the DOMString of the hash

	tmpElt = tmpElt->getFirstChild();
	while (tmpElt != NULL && tmpElt->getNodeType() != DOMNode::TEXT_NODE)
		tmpElt = tmpElt->getNextSibling();

	if (tmpElt == NULL)
		// Something wrong with the underlying XML if no text was found
		throw XSECException(XSECException::NoHashFoundInDigestValue);

	b64HashVal << (*mp_formatter << tmpElt->getNodeValue());

	// Now have the value of the string - create a transform around it

	XSECnew(nextInput, TXFMSB(d));
	((TXFMSB *) nextInput)->setInput(b64HashVal);

	// Create a transform chain (really as a janitor for the entire list)
	TXFMChain * chain;
	XSECnew(chain, TXFMChain(nextInput));
	Janitor<TXFMChain> j_chain(chain);

	// Now create the base64 transform

	XSECnew(nextInput, TXFMBase64(d));
	chain->appendTxfm(nextInput);

	// Now get the value

	size = chain->getLastTxfm()->readBytes(toFill, maxToFill);

	// Clear any documentat modifications

	chain->getLastTxfm()->deleteExpandedNameSpaces();

	return size;

}



// --------------------------------------------------------------------------------
//           Check a reference
// --------------------------------------------------------------------------------

bool DSIGReference::checkHash() const {

	// Determine the hash value of the element and check if matches that stored in the
	// DigestValue part of the element

	// First set up for input

	unsigned int maxHashSize = XSECPlatformUtils::g_cryptoProvider->getMaxHashSize();

	XMLByte* calculatedHashVal = new XMLByte[maxHashSize];		// The hash that we determined

    unsigned int calculatedHashSize;

    try {
        if ((calculatedHashSize = calculateHash(calculatedHashVal, maxHashSize)) == 0)
            return false;
    }
    catch (...) {
        delete[] calculatedHashVal;
        throw;
    }

    XMLByte* readHashVal = new XMLByte [maxHashSize];			// The hash in the element

    if (readHash(readHashVal, maxHashSize) != calculatedHashSize) {
        delete[] calculatedHashVal;
        delete[] readHashVal;
        return false;
    }

	for (unsigned int i = 0; i < calculatedHashSize; ++i) {
        if (calculatedHashVal[i] != readHashVal[i]) {
            delete[] calculatedHashVal;
            delete[] readHashVal;
            return false;
        }

	}

    delete[] calculatedHashVal;
    delete[] readHashVal;

	// Got through with flying colours!
	return true;

}
