/**
 * 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
 *
 * simpleValidate := An application to validate an in-memory signature
 *
 * Author(s): Berin Lautenbach
 *
 * $ID$
 *
 * $LOG$
 *
 */

#include "IOStreamOutputter.hpp"

// XML-Security-C (XSEC)

#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/framework/XSECProvider.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>

#include "../utils/XSECDOMUtils.hpp"

// Xerces

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>

XERCES_CPP_NAMESPACE_USE

#ifdef XSEC_HAVE_XALAN
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
XALAN_USING_XALAN(XalanTransformer)
#endif

char docToValidate [4096] = "\
<PurchaseOrder>\n\
<Company>Widgets.Org</Company>\n\
<Product>A large widget</Product>\n\
<Amount>$16.50</Amount>\n\
<Due>16 January 2010</Due>\n\
<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n\
<ds:SignedInfo>\n\
<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/>\n\
<ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#dsa-sha1\"/>\n\
<ds:Reference URI=\"#xpointer(/)\">\n\
<ds:Transforms>\n\
<ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\n\
<ds:Transform Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/>\n\
</ds:Transforms>\n\
<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>\n\
<ds:DigestValue>n+6y945h/SvlVF9qBq+Lb4TrcOI=</ds:DigestValue>\n\
</ds:Reference>\n\
</ds:SignedInfo>\n\
<ds:SignatureValue>OmToLo8uEnK37nCFXDiZwgcsZGJ0aZ4AyECUy78DL91AHRRWdjllSQ==</ds:SignatureValue>\n\
<ds:KeyInfo>\n\
<ds:X509Data>\n\
<ds:X509SubjectName>C=AU, ST=Vic, O=XML-Security-C Project, CN=Samples Demo Certificate</ds:X509SubjectName>\n\
</ds:X509Data>\n\
</ds:KeyInfo>\n\
</ds:Signature>\n\
</PurchaseOrder>\n";

char cert[] = "\n\
MIIEETCCA9GgAwIBAgICEAEwCQYHKoZIzjgEAzB5MQswCQYDVQQGEwJBVTEMMAoG\n\
A1UECBMDVmljMRIwEAYDVQQHEwlNZWxib3VybmUxHzAdBgNVBAoTFlhNTC1TZWN1\n\
cml0eS1DIFByb2plY3QxEDAOBgNVBAsTB1hTRUMtQ0ExFTATBgNVBAMTDFhTRUMt\n\
Q0EgUm9vdDAeFw0wMjExMDUwMzE1NDFaFw0wMzExMDUwMzE1NDFaMF8xCzAJBgNV\n\
BAYTAkFVMQwwCgYDVQQIEwNWaWMxHzAdBgNVBAoTFlhNTC1TZWN1cml0eS1DIFBy\n\
b2plY3QxITAfBgNVBAMTGFNhbXBsZXMgRGVtbyBDZXJ0aWZpY2F0ZTCCAbgwggEs\n\
BgcqhkjOOAQBMIIBHwKBgQDj1jBku/y6COfkxmHMLS1behxr3ah8sFAk71EyuXLy\n\
2Ony989WUc52/5M3nNY9E/75KB3uKNcrnGY8Tfw85Wrehv7jSImCuxljtnomABTj\n\
9LBuGL9TfYBNBJI/0jNR0GOo0kQphoKFOvldtRIwRmtU5Mcamg9e5FOEjYJCSah5\n\
rwIVAOzWxorDrF4uwMIC/ss6PfibdNgHAoGBANLAOsJjpBQx43DgnNSkVJ518Tqz\n\
IHKpg9crAsCRd+Keipt/tVnOTA29uJZMo2wUSGC8Vj7tlreMJtxDUnLcRdX6EZwj\n\
WR9nBhLpzClndctjjLF5IkzCechQk7CNKmO2Z2gaD6K/hdfMixF/LH/1iHeYjTNZ\n\
vAhcExd1PRpV0207A4GFAAKBgQDNS3VPzSAL+I71/0EneTxLIyvAlROjnLVDd5LT\n\
vEAorjepo8v5/qgXNK4O32NlNZxSOD612Mr1Q8sLYDnx006t8x01A7St8f/jcd9y\n\
dIIomKMEs2hwahHt8p/jFdRJNXFFe4gQ2DM2cKRhZTEuL9qpv2AnPIIlGqnrlo1L\n\
o4gDb6OCAQEwgf4wCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH\n\
ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFA7Em1VK6/7qc88l7n8JnIOT\n\
QEArMIGjBgNVHSMEgZswgZiAFBKNX9CsAIsjUIFmVq4wE4wlOGC5oX2kezB5MQsw\n\
CQYDVQQGEwJBVTEMMAoGA1UECBMDVmljMRIwEAYDVQQHEwlNZWxib3VybmUxHzAd\n\
BgNVBAoTFlhNTC1TZWN1cml0eS1DIFByb2plY3QxEDAOBgNVBAsTB1hTRUMtQ0Ex\n\
FTATBgNVBAMTDFhTRUMtQ0EgUm9vdIIBADAJBgcqhkjOOAQDAy8AMCwCFDA7nNZe\n\
C6gSs+N7RRq7vLmx/IjjAhRJvfPZ/hvoN8fNpTmRoHtuzkSjcQ==";

int main (int argc, char **argv) {

	try {
		XMLPlatformUtils::Initialize();
#ifdef XSEC_HAVE_XALAN
		XalanTransformer::initialize();
#endif
		XSECPlatformUtils::Initialise();
	}
	catch (const XMLException &e) {

		cerr << "Error during initialisation of Xerces" << endl;
		cerr << "Error Message = : "
		     << e.getMessage() << endl;

	}

	// Use xerces to parse the document
	XercesDOMParser * parser = new XercesDOMParser;
	parser->setDoNamespaces(true);
	parser->setCreateEntityReferenceNodes(true);
	parser->setDoSchema(true);

	// Create an input source

	MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) docToValidate, (unsigned int) strlen(docToValidate), "XSECMem");

	XMLSize_t errorCount = 0;

	parser->parse(*memIS);
    errorCount = parser->getErrorCount();
    if (errorCount > 0) {
		cerr << "Error parsing input document\n";
		exit (1);
	}

    DOMDocument *doc = parser->getDocument();

	// Find the Amount node
	DOMNode *amt = doc->getDocumentElement();

	if (amt != NULL)
		amt = amt->getFirstChild();

	while (amt != NULL && (amt->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(amt->getNodeName(), "Amount")))
		amt = amt->getNextSibling();

	if (amt != NULL)
		amt = amt->getFirstChild();

	if (amt == NULL || amt->getNodeType() != DOMNode::TEXT_NODE) {
		cerr << "Error finding amount in purchase order" << endl;
		exit (1);
	}

	docSetup(doc);

	// Now create a signature object to validate the document

	XSECProvider prov;

	DSIGSignature * sig = prov.newSignatureFromDOM(doc);


	try {
		// Use the interface objects to get a signing key
		XSECCryptoX509* x509 = XSECPlatformUtils::g_cryptoProvider->X509();
		x509->loadX509Base64Bin(cert, (unsigned int) strlen(cert));
		
		sig->load();
		DSIGKeyInfoList * kinfList = sig->getKeyInfoList();
		
		// See if we can find a Key Name
		const XMLCh * kname;
		DSIGKeyInfoList::size_type size, i;
		size = kinfList->getSize();

		for (i = 0; i < size; ++i) {
			kname = kinfList->item(i)->getKeyName();
			if (kname != NULL) {
				char * n = XMLString::transcode(kname);
				cout << "Key Name = " << n << endl;
				XSEC_RELEASE_XMLCH(n);
			}
		}

		sig->setSigningKey(x509->clonePublicKey());

		cout << "Amount = " << amt << " -> ";

		if (sig->verify()) {
			cout << "Signature Valid\n";
		}
		else {
			char * err = XMLString::transcode(sig->getErrMsgs());
			cout << "Incorrect Signature\n";
			cout << err << endl;
			XSEC_RELEASE_XMLCH(err);
		}

		amt->setNodeValue(MAKE_UNICODE_STRING("$0.50"));
		
		cout << "Amount = " << amt << " -> ";

		if (sig->verify()) {
			cout << "Signature Valid\n";
		}
		else {
			char * err = XMLString::transcode(sig->getErrMsgs());
			cout << "Incorrect Signature\n";
			cout << err << endl;
			XSEC_RELEASE_XMLCH(err);
		}

		amt->setNodeValue(MAKE_UNICODE_STRING("$16.50"));
		
		cout << "Amount = " << amt << " -> ";

		if (sig->verify()) {
			cout << "Signature Valid\n";
		}
		else {
			char * err = XMLString::transcode(sig->getErrMsgs());
			cout << "Incorrect Signature\n";
			cout << err << endl;
			XSEC_RELEASE_XMLCH(err);
		}


	}

	catch (const XSECException &e)
	{
		cerr << "An error occurred during a signature load\n   Message: "
		<< e.getMsg() << endl;
		exit(1);
		
	}
	catch (const XSECCryptoException &e) {
		cerr << "An error occurred in the XML-Security-C Crypto routines\n   Message: "
		<< e.getMsg() << endl;
		exit(1);
	}
		
		// Clean up

	delete memIS;
	delete parser;

	return 0;
}
