// WMLogMgr.cpp: implementation of the WMLogMgr class.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Robert Cunnings. All rights reserved.
//
// You may copy, modify, distribute or publish this code free of charge.
//
// NO WARRANTY: This software is provided AS IS, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// WMLogMgr class - a class for logging support.
// 
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WMLogMgr.h"
#include "WMLogRec.h"
#include "time.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

WMLogMgr::WMLogMgr()
{
	// set time zone in hours
	TIME_ZONE_INFORMATION info;
	long Zone;
	DWORD ret = GetTimeZoneInformation(&info);
	if (ret == 0xFFFFFFFF || ret == TIME_ZONE_ID_UNKNOWN)
    {
		Zone = 0L;
    }
	else
    {
		Zone = info.Bias / 60L;
    }
	Zone *= 100L;
	char szBuffer[32];
	_snprintf(szBuffer, 31, _T("%04d"), Zone);
    szBuffer[31] = 0;
	m_strTimeZone = szBuffer;
	InitializeCriticalSection(&m_CSServerLog);
	InitializeCriticalSection(&m_CSUserAgentLog);
	InitializeCriticalSection(&m_CSSOAPTraceLog);
	// intialize flags
	m_bServerLogEnable = false;
	m_bUserAgentLogEnable = false;
	m_bSOAPTraceLogEnable = false;
    m_uRotationPeriod = 0;
    m_uRotationStartTime = GetTickCount();
}

WMLogMgr::~WMLogMgr()
{
	// close the log files
	FlushLogFiles();
	if (m_bServerLogEnable && m_fileServerLog.is_open())
    {
		m_fileServerLog.close();
    }
	if (m_bUserAgentLogEnable && m_fileUserAgentLog.is_open())
    {
		m_fileUserAgentLog.close();
    }
	if (m_fileSOAPTraceLog.is_open())
    {
		m_fileSOAPTraceLog.close();
    }
	DeleteCriticalSection(&m_CSServerLog);
	DeleteCriticalSection(&m_CSUserAgentLog);
	DeleteCriticalSection(&m_CSSOAPTraceLog);
}

void WMLogMgr::EnableServerLog(bool bFlag)
{
	m_bServerLogEnable = bFlag;
}

void WMLogMgr::EnableUserAgentLog(bool bFlag)
{
	m_bUserAgentLogEnable = bFlag;
}

void WMLogMgr::EnableSOAPTraceLog(bool bFlag)
{
	m_bSOAPTraceLogEnable = bFlag;
}

/////////////////////////////////////////////////////////////////////////////
// Logging handlers

void WMLogMgr::OpenServerLogFile()
{
	EnterCriticalSection(&m_CSServerLog);
	// we may have just turned logging off,
	// so check this before m_bLogEnable
	if (m_fileServerLog.is_open())
		m_fileServerLog.close();
	if (m_bServerLogEnable == FALSE)
	{
		LeaveCriticalSection(&m_CSServerLog);
		return;
	}
	// now try to open/create the file
	m_fileServerLog.open(m_strServerLogPath.c_str(), ios_base::out | ios_base::app);
	LeaveCriticalSection(&m_CSServerLog);
}

void WMLogMgr::WriteServerLog(COMLOGREC& LogRec)
{
	EnterCriticalSection(&m_CSServerLog);
	if (m_bServerLogEnable && m_fileServerLog.is_open())
	{
		char szBuffer[64];
		strftime(szBuffer, 64, _T("%d/%b/%Y:%H:%M:%S"), localtime(&LogRec.DateTime));
		m_fileServerLog << LogRec.strClient << " "
					 << LogRec.strLoginId << " "
					 << LogRec.strUsername << " ["
					 << szBuffer
					 << " -" << m_strTimeZone << "] \""
					 << LogRec.strRequest << "\" "
					 << LogRec.lStatus << " "
					 << LogRec.lBytes << "\n";
	}
	LeaveCriticalSection(&m_CSServerLog);
}

void WMLogMgr::OpenUserAgentLogFile()
{
	EnterCriticalSection(&m_CSUserAgentLog);
	// we may have just turned logging off,
	// so check this before m_bLogEnable
	if (m_fileUserAgentLog.is_open())
    {
		m_fileUserAgentLog.close();
    }
	if (m_bUserAgentLogEnable == FALSE)
	{
		LeaveCriticalSection(&m_CSUserAgentLog);
		return;
	}
	// now try to open/create the file
	m_fileUserAgentLog.open(m_strUserAgentLogPath.c_str(), ios_base::out | ios_base::app);
	LeaveCriticalSection(&m_CSUserAgentLog);
}

void WMLogMgr::WriteUserAgentLog (const string& strUserAgent)
{
	EnterCriticalSection(&m_CSUserAgentLog);
	if (m_bUserAgentLogEnable && m_fileUserAgentLog.is_open())
	{
		m_fileUserAgentLog << strUserAgent << "\n";
	}
	LeaveCriticalSection(&m_CSUserAgentLog);
}

void WMLogMgr::OpenSOAPTraceLogFile()
{
	EnterCriticalSection(&m_CSSOAPTraceLog);
	if (m_fileSOAPTraceLog.is_open())
    {
		m_fileSOAPTraceLog.close();
    }
	// now try to open/create the file
	m_fileSOAPTraceLog.open(m_strSOAPTraceLogPath.c_str(), ios_base::out | ios_base::app);
	LeaveCriticalSection(&m_CSSOAPTraceLog);
}

void WMLogMgr::WriteSOAPTraceLog (const string& strData)
{
	EnterCriticalSection(&m_CSSOAPTraceLog);
	if (m_fileSOAPTraceLog.is_open())
	{
		m_fileSOAPTraceLog << strData << "\n";
	}
	LeaveCriticalSection(&m_CSSOAPTraceLog);
}

BOOL WMLogMgr::OpenLogFiles()
{
	// open log files
	OpenServerLogFile();
	OpenUserAgentLogFile();
	OpenSOAPTraceLogFile();
	return TRUE;
}

void WMLogMgr::FlushLogFiles()
{
    bool bRotate = false;
    unsigned int uTickCount = 0;
	char szSuffix[64];
    char szFullPath[_MAX_PATH];
    char szDrive[_MAX_DRIVE];
    char szDirPath[_MAX_DIR];
    char szFilename[_MAX_FNAME];
	char szExtension[_MAX_EXT];
    if (m_uRotationPeriod > 0)
    {
        uTickCount = GetTickCount();
        if (uTickCount - m_uRotationStartTime >= m_uRotationPeriod)
        {
            bRotate = true;
            m_uRotationStartTime = uTickCount;
	        time_t Time;
	        time(&Time);
	        struct tm *pGMT = gmtime(&Time);
	        strftime(szSuffix, 128, "_%y%m%d%H%MGMT", pGMT);
        }
    }

	EnterCriticalSection(&m_CSServerLog);
	if (m_bServerLogEnable && m_fileServerLog.is_open())
    {
		m_fileServerLog.flush();
        if (bRotate == true)
        {
            char szTemp[_MAX_FNAME];
            m_fileServerLog.close();
	        _splitpath(m_strServerLogPath.c_str(), szDrive, szDirPath, szFilename, szExtension);
            _snprintf(szTemp, _MAX_FNAME, "%s%s", szFilename, szSuffix);
            szTemp[_MAX_FNAME] = 0;
            _makepath(szFullPath, szDrive, szDirPath, szTemp, szExtension);
            rename(m_strServerLogPath.c_str(), szFullPath);
	        m_fileServerLog.open(m_strServerLogPath.c_str(), ios_base::out | ios_base::app);
        }
    }
	LeaveCriticalSection(&m_CSServerLog);

	EnterCriticalSection(&m_CSUserAgentLog);
	if (m_bUserAgentLogEnable && m_fileUserAgentLog.is_open())
    {
		m_fileUserAgentLog.flush();
        if (bRotate == true)
        {
            char szTemp[_MAX_FNAME];
            m_fileUserAgentLog.close();
	        _splitpath(m_strUserAgentLogPath.c_str(), szDrive, szDirPath, szFilename, szExtension);
            _snprintf(szTemp, _MAX_FNAME, "%s%s", szFilename, szSuffix);
            szTemp[_MAX_FNAME] = 0;
            _makepath(szFullPath, szDrive, szDirPath, szTemp, szExtension);
            rename(m_strUserAgentLogPath.c_str(), szFullPath);
	        m_fileUserAgentLog.open(m_strUserAgentLogPath.c_str(), ios_base::out | ios_base::app);
        }
    }
	LeaveCriticalSection(&m_CSUserAgentLog);

	EnterCriticalSection(&m_CSSOAPTraceLog);
	if (m_fileSOAPTraceLog.is_open())
    {
		m_fileSOAPTraceLog.flush();
        if (bRotate == true)
        {
            char szTemp[_MAX_FNAME];
            m_fileSOAPTraceLog.close();
	        _splitpath(m_strSOAPTraceLogPath.c_str(), szDrive, szDirPath, szFilename, szExtension);
            _snprintf(szTemp, _MAX_FNAME, "%s%s", szFilename, szSuffix);
            szTemp[_MAX_FNAME] = 0;
            _makepath(szFullPath, szDrive, szDirPath, szTemp, szExtension);
            rename(m_strSOAPTraceLogPath.c_str(), szFullPath);
	        m_fileSOAPTraceLog.open(m_strSOAPTraceLogPath.c_str(), ios_base::out | ios_base::app);
        }
    }
	LeaveCriticalSection(&m_CSSOAPTraceLog);
}