//
// $Id: Common.cpp,v 1.15 2007/01/09 17:43:01 bakerj Exp $
//
//****************************************************************************************//
// Copyright (c) 2002-2007, The MITRE Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice, this list
//       of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice, this 
//       list of conditions and the following disclaimer in the documentation and/or other
//       materials provided with the distribution.
//     * Neither the name of The MITRE Corporation nor the names of its contributors may be
//       used to endorse or promote products derived from this software without specific 
//       prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//****************************************************************************************//

#include "Common.h"


UniqueStringVector::UniqueStringVector(StringVector* strings) {
	// caller is responsible for providing a ptr to a StringVector
	// caller is responsible for cleaning up after the StringVector
	// is no longer needed.
	this->uniqueStrings = strings;
}

UniqueStringVector::~UniqueStringVector() {

}

StringVector* UniqueStringVector::GetUniqueStrings() {
	return this->uniqueStrings;
}

void UniqueStringVector::Append(string newString) {
	if(!this->Exists(newString)) {
		this->uniqueStrings->push_back(newString);
	}
}

bool UniqueStringVector::Exists(string newString) {
	bool exists = false;

	StringVector::iterator iterator;
	for(iterator = this->uniqueStrings->begin(); iterator != this->uniqueStrings->end(); iterator++) {
		if(newString.compare((*iterator)) == 0) {
			exists = true;
		}
	}			

	return exists;
}

// Initialize static variables.
string	Common::dataFile			= "system-characteristics.xml";
string	Common::xmlfile				= "definitions.xml";
string	Common::outputFilename		= "results.xml";
string	Common::externalVariablesFile	= "external-variables.xml";
string	Common::xmlfileMD5			= "";
string	Common::startTime			= "";

bool Common::noXsl                  = false;
string Common::xslFile				= "results_to_html.xsl";
string Common::xslOutputFile		= "results.html";

bool	Common::generateMD5			= false;
bool	Common::useProvidedData		= false;
bool	Common::verifyXMLfile		= true;

#ifdef WIN32
	char Common::fileSeperator = '\\';
#else
	char Common::fileSeperator = '/';
#endif

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Accessors  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

string Common::GetDatafile()
{
	return dataFile;	
}

bool Common::GetGenerateMD5()
{
	return generateMD5;	
}

string Common::GetXMLfile()
{
	return xmlfile;	
}

string Common::GetXMLfileMD5()
{
	return xmlfileMD5;	
}

string Common::GetOutputFilename()
{
	return outputFilename;	
}

bool Common::GetUseProvidedData()
{
	return useProvidedData;	
}

string Common::GetExternalVariableFile()
{
	return externalVariablesFile;	
}

bool Common::GetVerifyXMLfile()
{
	return verifyXMLfile;
}

string Common::GetXSLFilename()
{
	return Common::xslFile;	
}
string Common::GetXSLOutputFilename()
{
	return Common::xslOutputFile;	
}
bool Common::GetNoXsl() {
	return Common::noXsl;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Mutators  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

void Common::SetDataFile(string fileIn)
{
	dataFile = fileIn;	
}

void Common::SetGenerateMD5(bool genMD5In)
{
	generateMD5 = genMD5In;
}

void Common::SetXMLfile(string xmlfileIn)
{
	xmlfile = xmlfileIn;
}

void Common::SetXMLfileMD5(string xmlfileMD5In)
{
	xmlfileMD5 = xmlfileMD5In;
}

void Common::SetOutputFilename(string outputFilenameIn)
{
	outputFilename = outputFilenameIn;
}

void Common::SetUseProvidedData(bool useDataIn)
{
	useProvidedData = useDataIn;
}

void Common::SetExternalVariableFile(string varFilenameIn)
{
	externalVariablesFile = varFilenameIn;
}

void Common::SetVerifyXMLfile(bool verifyXMLfileIn)
{
	verifyXMLfile = verifyXMLfileIn;
}

void Common::SetXSLFilename(string in)
{
	Common::xslFile = in;
}

void Common::SetXSLOutputFilename(string in)
{
	Common::xslOutputFile = in;
}
void Common::SetNoXsl(bool noXsl) {
	Common::noXsl = noXsl;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Public Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

string Common::PadString(string strIn, unsigned int desiredLength)
{
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  Pad the provided string with spaces so that it is the desired length.
	//
	//------------------------------------------------------------------------------------//

	while(strIn.length() < desiredLength) {
		strIn.append(" ");
	}

	return strIn;
}

string Common::PadStringWithChar(string strIn, char pad, unsigned int desiredLength) {
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  Pad the provided string with the specified char so that it is the desired length.
	//
	//------------------------------------------------------------------------------------//

	while(strIn.length() < desiredLength) {
		strIn = strIn + pad;
	}

	return strIn;
}

string Common::SwitchChar(string fixedString, string oldChr, string newChr)
{
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  This function takes a string and searches for all oldChrs.  If one is found,
	//  it is replaced with a newChr.  It is only intended to work with a single char 
	//	at a time. No multiple char strings allowed
	//
	//------------------------------------------------------------------------------------//

	if(oldChr.length() != 1 || newChr.length() != 1)
		throw CommonException("Error: (SwitchChar) can only switch strings of length = 1.");

	unsigned int pos = fixedString.find(oldChr, 0);
	while (pos != string::npos)
	{
		fixedString.erase(pos, 1);
		fixedString.insert(pos, newChr);
		pos = fixedString.find(oldChr, pos+1);
	}

	return fixedString;
}

string Common::GetTimeStamp()
{
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  Retrieve the date/time.  The final output will be in the format:
	//
	//	  yyyy-mm-ddThh:mm:ss	2006-08-16T14:21:38
	//
	//------------------------------------------------------------------------------------//

	char tmpbuf[128];
	
	time_t tmpTime;
	struct tm *todayTime;
	
	// Get the time as a long integer, then convert it to local time.
	time(&tmpTime);
	todayTime = localtime(&tmpTime);
	
	// Build the time string.
	char *format = "%Y-%m-%dT%H:%M:%S";
	strftime(tmpbuf, 128-1, format, todayTime);

	// Make sure the buffer is null terminated.
	tmpbuf[sizeof(tmpbuf)-1] = '\0';
	
	return (tmpbuf);
}

string Common::ToString(int num)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return a the int as a string
	//
	// -----------------------------------------------------------------------
	ostringstream result;
	result << num;

	return result.str();
}
string Common::ToString(long num)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return a the long as a string
	//
	// -----------------------------------------------------------------------
	ostringstream result;
	result << num;

	return result.str();
}
string Common::ToString(bool b)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return a the bool as a string
	//
	// -----------------------------------------------------------------------
	
	if(b) 
		return "true";
	else 
		return "false";
}

string Common::ToString(char c)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return a the char as a string
	//
	// -----------------------------------------------------------------------
	
	string str;
	str = c;
	return str;
}

string Common::ToString(unsigned long num)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return a the unsigned long as a string
	//
	// -----------------------------------------------------------------------
	ostringstream result;
	result << num;

	return result.str();
}


//****************************************************************************************//
//							CommonException Class										  //	
//****************************************************************************************//
CommonException::CommonException(string errMsgIn, int severity, Exception* ex) : Exception(errMsgIn, severity, ex) {
	// -----------------------------------------------------------------------
	//	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.
	//
	// -----------------------------------------------------------------------

}

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

}
