//
// $Id: DOMOvalDataCollector.cpp,v 1.2 2004/07/08 15:34:11 bakerj Exp $
//
//************************** Property of the MITRE Corporation ***************************//
//
// Copyright (c) 2003 - The MITRE Corporation
//
// This file is part of the Query-based Network Assessment project.
//
// The Query-based Network Assessment is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License.
//
// The Query-based Network Assessment is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with the
// Query-based Network Assessment; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//****************************************************************************************//


#include "DOMOvalDataCollector.h"

//****************************************************************************************//
//								DOMOvalDataCollector Class								  //	
//****************************************************************************************//
DOMOvalDataCollector::DOMOvalDataCollector(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *oval,
								XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *data,
								string strFamily)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Init the DOMOvalDataCollector object
	//	oval	- the DOMDocument that represents the oval.xml
	//	data	- the DOMDocument that will contain the data model.
	//	family	- a flag indicating which family to gather data for.
	//
	// -----------------------------------------------------------------------

	string errMsg;

    try 
	{
        XMLPlatformUtils::Initialize();
    }
    catch (const XMLException& toCatch) 
	{
        errMsg.append("Error:  An error occured durring initialization of the xml utilities:\n");
        errMsg.append(DOMCommon::ToString(toCatch.getMessage()));
		errMsg.append("\n");

		throw DOMOvalDataCollectorException(errMsg);
    }

	//	validate inputs
	if(oval != NULL)
		ovalDoc = oval;
	else
		throw DOMOvalDataCollectorException("Error: The oval Document is NULL. Unable to initialize the data collector.");

	if(data != NULL)
		dataDoc = data;
	else
		throw DOMOvalDataCollectorException("Error: The data Document is NULL. Unable to initialize the data collector.");


	//	Get the system_characteristics node
	DOMNode *oval_dataNode = DOMCommon::FindNode(dataDoc, "system_characteristics");
	
	//	Set dataDoc Family on the oval node
	DOMCommon::AddAttribute((DOMElement*)oval_dataNode, "family", strFamily);

	//	Set the schema version for the data doc
	DOMCommon::AddAttribute((DOMElement*)oval_dataNode, "system_characteristics:schemaVersion", "1.0");

	//	Add the namespace info to the oval_data node
	DOMCommon::AddAttribute((DOMElement*)oval_dataNode, "xmlns", "http://oval.mitre.org/XMLSchema/system_characteristics");
	DOMCommon::AddAttribute((DOMElement*)oval_dataNode, "xmlns:system_characteristics", "http://oval.mitre.org/XMLSchema/system_characteristics");
	DOMCommon::AddAttribute((DOMElement*)oval_dataNode, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
}

DOMOvalDataCollector::~DOMOvalDataCollector()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Clean up after DOM
	// -----------------------------------------------------------------------

	XMLPlatformUtils::Terminate();
}


// ***************************************************************************************	//
//								Protected members											//
// ***************************************************************************************	//

int DOMOvalDataCollector::DetermineNodeFamily(DOMNode* node)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return the family of the node provided based on the xmlns associated 
	//	with the node. Throw an error if the the node does not have a xmlns
	//	attribute.
	//	
	// -----------------------------------------------------------------------
	
	int family = ERROR_OS_FAMILY;
	string attVal;
	string error;

	if(node != NULL)
	{
		//	get the xmlns attribute for the node
		attVal = DOMCommon::GetAttributeByName(node, "xmlns");
		if(attVal.compare("") != 0)
		{
			//	convert the attribute value to a family flag
			if(strstr(attVal.c_str(), "redhat") != NULL)
			{
				family = REDHAT_OS_FAMILY;
			}else if(strstr(attVal.c_str(), "solaris") != NULL)
			{
				family = SOLARIS_OS_FAMILY;
			}else if(strstr(attVal.c_str(),"windows") != NULL)
			{
				family = WINDOWS_OS_FAMILY;
			}else
			{
				family = UNSUPPORTED_OS_FAMILY;
			}

		}else
		{
			attVal = DOMCommon::GetAttributeByName(node, "id");
			throw DOMCommonException("Error: Unable to locate the xmlns attribute for the provided node: " + attVal);
		}

	}else
	{
		throw DOMCommonException("Error: Invalid node passed to 'DOMCommon::DetermineNodeFamily' function. The node can't be NULL");
	}

	return(family);
}

void DOMOvalDataCollector::RunTest(Probe *probe, ProbeData *probeDataIn)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Run the probe with the provided probe data. 
	//	Call the write method on each ProbeData object in the
	//	result vector.
	// -----------------------------------------------------------------------

	pdVector resultVector;

	//	Run the probe
	resultVector = probe->Run(probeDataIn);	

	///////////////////////////////////////////////////////////////////////////
	//	Write the result Data nodes and delete data items in result vector
	///////////////////////////////////////////////////////////////////////////
	ProbeData *tmp	= NULL;
	while(resultVector.size() !=0)
	{
		tmp = resultVector[resultVector.size()-1];
		tmp->Write(dataDoc);
		resultVector.pop_back();
		delete tmp;
		tmp = NULL;
	}
}

void DOMOvalDataCollector::WriteHostName(string hostName)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Add the host_name element to the data model
	//
	// -----------------------------------------------------------------------

	DOMNode * oval_dataNode = DOMCommon::FindNode(dataDoc, "system_characteristics");
	DOMElement*  tmpElem = dataDoc->createElement(XMLString::transcode("host_name"));
	DOMText *tmpTextNode = dataDoc->createTextNode(XMLString::transcode(hostName.c_str()));
	tmpElem->appendChild(tmpTextNode);
	oval_dataNode->appendChild(tmpElem);


}
void DOMOvalDataCollector::WriteIPAddress(string ipAddress)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Add the ip_address element to the data model
	//
	// -----------------------------------------------------------------------

	DOMNode * oval_dataNode = DOMCommon::FindNode(dataDoc, "system_characteristics");
	DOMElement*  tmpElem = dataDoc->createElement(XMLString::transcode("ip_address"));
	DOMText *tmpTextNode = dataDoc->createTextNode(XMLString::transcode(ipAddress.c_str()));
	tmpElem->appendChild(tmpTextNode);
	oval_dataNode->appendChild(tmpElem);

}

void DOMOvalDataCollector::WriteTimeStamp()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Add the time_stamp element to the data model
	//
	// -----------------------------------------------------------------------

	string time = Common::GetTimeStamp();

	DOMNode * oval_dataNode = DOMCommon::FindNode(dataDoc, "system_characteristics");
	DOMElement*  timeElem = dataDoc->createElement(XMLString::transcode("time_stamp"));
	DOMText *tmpTextNode = dataDoc->createTextNode(XMLString::transcode(time.c_str()));
	timeElem->appendChild(tmpTextNode);
	oval_dataNode->appendChild(timeElem);

}


//****************************************************************************************//
//						DOMOvalDataCollectorException Class								  //	
//****************************************************************************************//
DOMOvalDataCollectorException::DOMOvalDataCollectorException() : Exception()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Default constructor simply set the severity to ERROR_FATAL. This is 
	//	done with the explicit call to the Exception class default constructor.
	//
	// -----------------------------------------------------------------------

}

DOMOvalDataCollectorException::DOMOvalDataCollectorException(string errMsgIn) : Exception(errMsgIn)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Set the error message and then set the severity to ERROR_FATAL. This is 
	//	done with the explicit call to the Exception class constructor that 
	//	takes a single string param.
	//
	// -----------------------------------------------------------------------

}

DOMOvalDataCollectorException::~DOMOvalDataCollectorException()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Do nothing for now
	//
	// -----------------------------------------------------------------------

}

