Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

274 lines
7.7 KiB

// AdFile.cpp: implementation of the CAdFile class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#undef max
#include "AdRot.h"
#include "AdFile.h"
#include "RotObj.h"
#include "sinstrm.h"
extern CMonitor* g_pMonitor;
#ifdef DBG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//--------------------------------------------------------------------
// CAdFileNotify
//--------------------------------------------------------------------
CAdFileNotify::CAdFileNotify()
: m_isNotified(0)
{
}
void
CAdFileNotify::Notify()
{
::InterlockedExchange( &m_isNotified, 1 );
}
bool
CAdFileNotify::IsNotified()
{
return ( ::InterlockedExchange( &m_isNotified, 0 ) ? true : false );
}
//--------------------------------------------------------------------
// CAdFile
//--------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAdFile::CAdFile()
: m_nBorder(defaultBorder),
m_nHeight(defaultHeight),
m_nWidth(defaultWidth),
m_nVSpace(defaultVSpace),
m_nHSpace(defaultHSpace),
m_strRedirector( _T("")),
m_fUTF8(false)
{
m_pNotify = new CAdFileNotify;
}
CAdFile::~CAdFile()
{
if ( g_pMonitor )
{
g_pMonitor->StopMonitoringFile( m_strFile.c_str() );
}
}
//---------------------------------------------------------------------------
//
// ProcessAdFile will check the given filename, if it matches the one it
// knows it currently has in memory, it will do nothing. If the filename
// differs, the old ad information will be dumped, and the new information
// parsed and stored.
//
//---------------------------------------------------------------------------
bool
CAdFile::ProcessAdFile(
String strAdFile )
{
USES_CONVERSION;
bool rc = false;
UINT weightSum = 0;
// block all other readers and writers
CWriter wtr( *this );
m_ads.erase( m_ads.begin(), m_ads.end() );
// parse the file
FileInStream fs;
HRESULT hr = fs.Init( T2CA(strAdFile.c_str()) );
if ( SUCCEEDED(hr) && fs.is_open())
{
if ( ReadHeader( fs ) )
{
while ( !fs.eof() )
{
// read one "ad record"
String strGif;
String strLink;
String strAlt;
String strWeight;
ULONG lWeight = 0;
fs >> strGif >> strLink;
// this just gets us past the new line
fs.readLine( strAlt );
fs >> strWeight;
// check for a negative impression value. RaiseException if
// negative
if (strWeight[0] == '-') {
CAdRotator::RaiseException( IDS_ERROR_BAD_WEIGHT_VALUE );
goto err;
}
lWeight = strWeight.toUInt32();
weightSum += lWeight;
if (weightSum > 10000) {
CAdRotator::RaiseException( IDS_ERROR_WEIGHT_SUM_TOO_LARGE );
goto err;
}
if ( lWeight != 0 )
{
CAdDescPtr pAd = new CAdDescriptor( lWeight, strLink, strGif, strAlt );
if ( pAd.IsValid() )
{
// add one reference to the ad for each weight
for( int i = 0; i < lWeight; i++ )
{
m_ads.push_back( pAd );
}
}
}
}
if ( m_ads.size() > 0 )
{
if ( m_strFile != strAdFile )
{
g_pMonitor->StopMonitoringFile( m_strFile.c_str() );
m_strFile = strAdFile;
g_pMonitor->MonitorFile( m_strFile.c_str(), m_pNotify );
}
rc = true;
}
}
else
{
CAdRotator::RaiseException( IDS_ERROR_CANNOT_READ_ROTATION_SCHEDULE_FILE );
}
}
else
{
CAdRotator::RaiseException( IDS_ERROR_CANNOT_LOAD_ROTATION_SCHEDULE_FILE );
}
err:
return rc;
}
//---------------------------------------------------------------------------
//
// Refresh will check to see if the cached information is out of date, if so
// it will re-read the file
//
//---------------------------------------------------------------------------
bool
CAdFile::Refresh()
{
bool rc = false;
if ( m_pNotify->IsNotified() )
{
rc = ProcessAdFile( m_strFile );
}
return rc;
}
//---------------------------------------------------------------------------
//
// ReadHeader will parse the header portion of the file. The header includes
// some or all of the following fields: HEIGHT, WIDTH, BORDER, REDIRECT,
// HSPACE, VSPACE. The fields are separated by newlines and the header is
// terminated by an asterix.
//
//---------------------------------------------------------------------------
bool
CAdFile::ReadHeader(
FileInStream& fs )
{
bool rc = false;
// set defaults
m_nHeight = defaultHeight;
m_nWidth = defaultWidth;
m_nHSpace = defaultHSpace;
m_nVSpace = defaultVSpace;
m_fUTF8 = fs.is_UTF8();
bool done = false;
while ( !fs.eof() && !done )
{
String strLine;
String strName;
fs.readLine( strLine );
StringInStream sis( strLine );
sis >> strName;
HRESULT hr = S_OK;
if ( _tcsicmp( strName.c_str(), _T("HEIGHT") ) == 0 )
{
hr = sis.readInt( m_nHeight );
}
else if ( _tcsicmp( strName.c_str(), _T("WIDTH") ) == 0 )
{
hr = sis.readInt( m_nWidth );
}
else if ( _tcsicmp( strName.c_str(), _T("VSPACE") ) == 0 )
{
hr = sis.readInt( m_nVSpace );
}
else if ( _tcsicmp( strName.c_str(), _T("HSPACE") ) == 0 )
{
hr = sis.readInt( m_nHSpace );
}
else if ( _tcsicmp( strName.c_str(), _T("REDIRECT") ) == 0 )
{
hr = sis.readString( m_strRedirector );
}
else if ( _tcsicmp( strName.c_str(), _T("BORDER" ) ) == 0 )
{
hr = sis.readInt16( m_nBorder );
}
else if ( _tcsicmp( strName.c_str(), _T("*") ) == 0 )
{
rc = true;
done = true;
}
else
{
CAdRotator::RaiseException( IDS_ERROR_UNKNOWN_HEADER_NAME );
}
/*
if ( hr != S_OK )
{
CAdRotator::RaiseException( IDS_ERROR_HEADER_HAS_NO_ASSOCIATED_VALUE );
}
*/
}
return rc;
}
//---------------------------------------------------------------------------
//
// RandomAd chooses and ad at random from the list of ads. Since there
// are multiple references to ads based on the weight, we need only produce
// a random number between 0 and one less than the size of the list.
//
//---------------------------------------------------------------------------
CAdDescPtr
CAdFile::RandomAd() const
{
if (m_ads.size() > 0)
return m_ads[ rand() % m_ads.size() ];
else
return NULL;
}