//
// $Id: RPMInfoData.cpp,v 1.1 2004/06/01 17:05:19 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
//
//****************************************************************************************//
//
//  file:	RPMInfoData.cpp
//  author: Jon Baker	
//  date:   02 Februauy 2004
//
//	This class will store all data for a RPMInfoData. 
//	The class is a child class of ProbeData and implments the Write() function.
//****************************************************************************************//

#include "RPMInfoData.h"

//****************************************************************************************//
//								RPMInfoData Class										  //	
//****************************************************************************************//
RPMInfoData::RPMInfoData(DOMNode *test)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Initialize a new RPMInfoData and populate with the node's data
	// -----------------------------------------------------------------------

	string testName;

	//	Validate the test node
	if(test->getNodeType() != DOMNode::ELEMENT_NODE )
	{
		throw ProbeDataException("Error: RPMInfoData() Invalid test node specified. Only ELEMENT_NODE's are allowed.");
	}else
	{
		testName = DOMCommon::ToString(test->getNodeName());
		if(testName.compare("rpminfo_test") != 0)
			throw ProbeDataException("Error: RPMInfoData() Invalid test node specified. Received: " + testName);
	}

	//	Init the data members
       	testId = "";
	name = new TypedData(LITTERAL_TYPE, "");
	name_found = "";
	epoch = "";
	version = "";
	release = "";
	arch = "";
	msg = "";

	//	Call the parse node function
	ParseNode(test);
}

RPMInfoData::RPMInfoData()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Initialize a new RPMInfoData as an empty object.
	// -----------------------------------------------------------------------

	testId = "";
        name = new TypedData(LITTERAL_TYPE, "");
	name_found = "";
	epoch = "";
	version = "";
	release = "";
	arch = "";
	msg = "";
}

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

}
// ***************************************************************************************	//
//								Public members												//
// ***************************************************************************************	//
void RPMInfoData::Write(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *dataDocument)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Create a new rpminfo_test node and add it to the dataDocument.
	//	
	// -----------------------------------------------------------------------

	DOMText *tmpTextNode = NULL;

	//	Create a new test node
	DOMElement *rpminfo_test = CreateNewTestNode(dataDocument, "rpminfo_test");

	//	Add the arch element - as a string
	AddChildNode(dataDocument, rpminfo_test, "arch", arch);

	//	Add the epoch element - as a string
	AddChildNode(dataDocument, rpminfo_test, "epoch", epoch);

	//	Create the name eelment and add to the rpminfo_test
	//      If a pattern match was specified and the pattern was not found set the exists attribute to false
	//         and do not write the pattern.
	//      If the name was not found set the exists attribute to false.
	//      If the name was found set the data for the name and leave the exists attribute off.
	//      If a pattern match was specified and a match was found leave off the exists attribute
	//         and add the name_found element.
	DOMElement*  nameElem = dataDocument->createElement(XMLString::transcode("name"));
	if( (name->data.compare("") == 0 && name->type == LITTERAL_TYPE) ||         // litteral and name not found
	    (name_found.compare("") == 0 && name->type == PATTERN_MATCH_TYPE) )     // Pattern match and no match found
	{
		DOMCommon::AddAttribute(nameElem, "exists", "false");
	}else
	{
		tmpTextNode = dataDocument->createTextNode(XMLString::transcode(name->data.c_str()));
		nameElem->appendChild(tmpTextNode);
	}
	rpminfo_test->appendChild(nameElem);

	//	Create the name_found eelment and add to the rpminfo_test if it exists
	if(name_found.compare("") != 0) 
		AddChildNode(dataDocument, rpminfo_test, "name_found", name_found);

	//	Add the release element - as a string
	AddChildNode(dataDocument, rpminfo_test, "release", release);

	//	Add the version element - as a string
	AddChildNode(dataDocument, rpminfo_test, "version", version);

	//	Add the message element - as a string
	AddChildNode(dataDocument, rpminfo_test, "message", msg);
}

// ***************************************************************************************	//
//								Private members												//
// ***************************************************************************************	//
void RPMInfoData::ParseNode(DOMNode *test)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Parse the node gathering all data to popular this RPMInfoData
	//	Really just need to gather the Test id.
	// -----------------------------------------------------------------------

	///////////////////////////////////////////////////////////////////////////
	//	Get the test id
	///////////////////////////////////////////////////////////////////////////
	testId = DOMCommon::GetAttributeByName(test, "id");
	if(testId.compare("") == 0)
		throw ProbeDataException("Error: Unable to find the 'id' attribute for a Red Hat rpm info test.");	


	///////////////////////////////////////////////////////////////////////////
	//	Gather the data needed to call the probe
	///////////////////////////////////////////////////////////////////////////
	string childName	= "";
	string childOp		= "";
	
	DOMNode *rpminfoChild;
	DOMNodeList *rpminfoChildList;

	//	get a list of the child nodes and their values
	rpminfoChildList = test->getChildNodes();
	unsigned int index = 0;
	while(index < rpminfoChildList->getLength())
	{
		rpminfoChild = rpminfoChildList->item(index);

		//	only concerned with ELEMENT_NODEs
		if (rpminfoChild->getNodeType() == DOMNode::ELEMENT_NODE)
		{
			//	get the name of the child
			childName = DOMCommon::ToString(rpminfoChild->getNodeName());

			//	Get the child's operator
			childOp = DOMCommon::GetAttributeByName(rpminfoChild, "operator");
			
			//	Get the name value	
			if(strncmp(childName.c_str(), "name", 4)==0)
			{
				if(childOp.compare("pattern match") == 0)
					name->type = PATTERN_MATCH_TYPE;
				else
					name->type = LITTERAL_TYPE;

				name->data = DOMCommon::GetDataNodeValue(rpminfoChild);
			}
		}
		index ++;
	}
}
