/**
 * \class CBaseXML  
 *  <b>XML Message formation class</b><br>
 *  Used to format an XML message into a string object for sending back to the QML MQ Server.
 *
 *
 *  Description:
 *
 *    Basic XML support routines for building complete messages.
 *
 *
 *  History
 *  =======
 *  20-09-2001  sidy  Began with msgKeyUpgrade()
 *  05-10-2001        Added msgRequestUpgrade()
 *  18-02-2002        Change all client calls to return a full XML Msg structure.
 *  19-04-2002        Added method clearBodyMessage();
 */

#include "stdafx.h"

#include <string>
#include <time.h>
#include <vector>

using namespace std;


#include "BaseXML.h"
#include "MD5Hash.h"

#ifdef _MQ_LINK_CLIENT_
#include "Configuration.h"
#endif


CBaseXML::CBaseXML()
{
	Messages.clear();
	msgIter=NULL;
}

CBaseXML::~CBaseXML()
{
	Messages.clear();
	msgIter=NULL;
}





/**
 *  getMessageDT()
 *
 *
 *  Return the Date and Time as formated strings.
 *
 *  @post   Returned buffer has the required data
 *  @return void
 */
void CBaseXML::getMessageDT( char *szDateBuff, char *szTimeBuff)
{
struct  tm *timenow;
time_t  longtime;
	
	time(&longtime);
	timenow = localtime(&longtime);

	sprintf(szDateBuff,"%04d%02d%02d",
		timenow->tm_year+1900,
		timenow->tm_mon+1,
		timenow->tm_mday);

	sprintf(szTimeBuff,"%02d%02d%02d",	
		timenow->tm_hour,
		timenow->tm_min,
		timenow->tm_sec	);
}




/**
 *  getClientWrapper()
 *
 *
 *  Common code to return the XML header
 *
 *  @pre     none
 *  @post    none
 *  @return  string of XML Header
 */
string CBaseXML::getClientWrapper()
{
	return ("<?xml version=\"1.0\"?>\r\n<QML>\r\n<MQClient src=\"MQLinkClient\">\r\n");
}




/**
 *  getServerTail()
 *
 *
 *  Common code to return the XML header
 *
 *  @pre     none
 *  @post    none
 *  @return  string of XML Header
 */
string CBaseXML::getServerTail()
{
	return ("</MQServer>\r\n</QML>\r\n");
}


string CBaseXML::getClientTail()
{
	return ("</MQClient>\r\n</QML>\r\n");
}



/**
 *  getMsgHdrSig()
 *
 *
 *  Given a header block, calculate the message hash, including secret key word
 *
 *  @pre     XML string is defined, secret key is defined
 *  @post    
 *  @return  string of XML Header Signature
 */
string CBaseXML::getMsgHdrSig(string hdrBlockXML, char *secret)
{
char *pBuff;
char rBuff[1024];	// return buffer



	memset(rBuff,0,sizeof(rBuff));
	unsigned int lenHdr = hdrBlockXML.length();
	unsigned int lenKey = strlen(secret);

	if((pBuff=(char*) malloc(lenHdr+lenKey+1))!=NULL)
	{
		CMD5Hash *pH = new CMD5Hash();
		strcpy(pBuff,hdrBlockXML.c_str());
		strcat(pBuff,secret);
		pH->getHash((unsigned char*)pBuff, (unsigned char*)rBuff);
		delete pH;
	}
	string xml ="<MsgHdrSecurity hashtype=\"MD5\" signature=\"";
	xml.append(rBuff);
	xml +="\"/>\r\n";
	return xml;
}






/**
 *  getMsgBodySig()
 *
 *
 *  Given a header block, calculate the message hash, including secret key word
 *
 *  @pre     XML string is defined, secret key is defined
 *  @post    
 *  @return  string of XML Header Signature
 */
string CBaseXML::getMsgBodySig(string bodyBlockXML, char *secret)
{
char *pBuff;
char rBuff[1024];	// return buffer

	memset(rBuff,0,sizeof(rBuff));
	unsigned int lenBody = bodyBlockXML.length();
	unsigned int lenKey = strlen(secret);

	if((pBuff=(char*) malloc(lenBody+lenKey+1))!=NULL)
	{
		CMD5Hash *pH = new CMD5Hash();
		strcpy(pBuff,bodyBlockXML.c_str());
		strcat(pBuff,secret);
		pH->getHash((unsigned char*)pBuff, (unsigned char*)rBuff);
		delete pH;
	}
	string xml ="<MsgBodySecurity hashtype=\"MD5\" signature=\"";
	xml.append(rBuff);
	xml +="\"/>\r\n";
	return xml;
}





/**
 *  getMessageHeader()
 *
 *
 *  Common code to return the XML header formatted with details about the XML message
 *  including date and time, source and md5 hash
 *
 *  @pre     appName points to a string buffer that holds application name
 *  @post    none
 *  @return  string of XML Header
 */
string CBaseXML::getMessageHeader(char *appName)
{
string xml="";
char szDate[128];
char szTime[128];

	if(strlen(appName) == 0) strcpy(appName,"unknown");

	memset(szDate,0,sizeof(szDate));
	memset(szTime,0,sizeof(szTime));
	getMessageDT(szDate,szTime);
	xml +="<MessageHeader>\r\n<MessageDT date=\"";
	xml.append(szDate);
	xml +="\" time=\"";
	xml.append(szTime);
	xml +="\"/>\r\n";

	xml +="<MessageSRC app=\"";
	xml.append(appName);
	xml +="\"/>\r\n";

	xml +="</MessageHeader>\r\n";
	return xml;
	
}





/**
 *  addMessageBody()
 *
 *
 *  Save the message into the vector
 *
 *  @pre     msg points to a string
 *  @post    vector =1
 *  @return  void
 */
void CBaseXML::addBodyMessage(string msg)
{
	Messages.push_back(msg);
}




/**
 *  getBodyMessage()
 *
 *
 *  Build a string that is all the messages that need to go in the body.
 *
 *  @pre     msg points to a string
 *  @post    vector =1
 *  @return  void
 */
string CBaseXML::getBodyMessage()
{
string xml="";
string msg="";


#ifdef _MQ_LINK_CLIENT_
	if(strlen(CConfiguration::GetInstance()->getChallengeCode())==0)
		xml ="<MsgBody challengeCode=\"None\">\r\n";		// need a challenge code
	else
#endif
		xml="<MsgBody>\r\n";
	if(Messages.size()!=0)
	{
		for(msgIter = Messages.begin(); msgIter!= Messages.end();  msgIter++)
		{
			msg.assign(*msgIter);
			xml += msg;
		}
	}

	xml+="</MsgBody>\r\n";
	return xml;
}


void CBaseXML::clearBodyMessages()
{
	Messages.clear();
}

