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

  1. // AdFile.cpp: implementation of the CAdFile class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #undef max
  6. #include "AdRot.h"
  7. #include "AdFile.h"
  8. #include "RotObj.h"
  9. #include "sinstrm.h"
  10. extern CMonitor* g_pMonitor;
  11. #ifdef DBG
  12. #undef THIS_FILE
  13. static char THIS_FILE[]=__FILE__;
  14. #define new DEBUG_NEW
  15. #endif
  16. //--------------------------------------------------------------------
  17. // CAdFileNotify
  18. //--------------------------------------------------------------------
  19. CAdFileNotify::CAdFileNotify()
  20. : m_isNotified(0)
  21. {
  22. }
  23. void
  24. CAdFileNotify::Notify()
  25. {
  26. ::InterlockedExchange( &m_isNotified, 1 );
  27. }
  28. bool
  29. CAdFileNotify::IsNotified()
  30. {
  31. return ( ::InterlockedExchange( &m_isNotified, 0 ) ? true : false );
  32. }
  33. //--------------------------------------------------------------------
  34. // CAdFile
  35. //--------------------------------------------------------------------
  36. //////////////////////////////////////////////////////////////////////
  37. // Construction/Destruction
  38. //////////////////////////////////////////////////////////////////////
  39. CAdFile::CAdFile()
  40. : m_nBorder(defaultBorder),
  41. m_nHeight(defaultHeight),
  42. m_nWidth(defaultWidth),
  43. m_nVSpace(defaultVSpace),
  44. m_nHSpace(defaultHSpace),
  45. m_strRedirector( _T("")),
  46. m_fUTF8(false)
  47. {
  48. m_pNotify = new CAdFileNotify;
  49. }
  50. CAdFile::~CAdFile()
  51. {
  52. if ( g_pMonitor )
  53. {
  54. g_pMonitor->StopMonitoringFile( m_strFile.c_str() );
  55. }
  56. }
  57. //---------------------------------------------------------------------------
  58. //
  59. // ProcessAdFile will check the given filename, if it matches the one it
  60. // knows it currently has in memory, it will do nothing. If the filename
  61. // differs, the old ad information will be dumped, and the new information
  62. // parsed and stored.
  63. //
  64. //---------------------------------------------------------------------------
  65. bool
  66. CAdFile::ProcessAdFile(
  67. String strAdFile )
  68. {
  69. USES_CONVERSION;
  70. bool rc = false;
  71. UINT weightSum = 0;
  72. // block all other readers and writers
  73. CWriter wtr( *this );
  74. m_ads.erase( m_ads.begin(), m_ads.end() );
  75. // parse the file
  76. FileInStream fs;
  77. HRESULT hr = fs.Init( T2CA(strAdFile.c_str()) );
  78. if ( SUCCEEDED(hr) && fs.is_open())
  79. {
  80. if ( ReadHeader( fs ) )
  81. {
  82. while ( !fs.eof() )
  83. {
  84. // read one "ad record"
  85. String strGif;
  86. String strLink;
  87. String strAlt;
  88. String strWeight;
  89. ULONG lWeight = 0;
  90. fs >> strGif >> strLink;
  91. // this just gets us past the new line
  92. fs.readLine( strAlt );
  93. fs >> strWeight;
  94. // check for a negative impression value. RaiseException if
  95. // negative
  96. if (strWeight[0] == '-') {
  97. CAdRotator::RaiseException( IDS_ERROR_BAD_WEIGHT_VALUE );
  98. goto err;
  99. }
  100. lWeight = strWeight.toUInt32();
  101. weightSum += lWeight;
  102. if (weightSum > 10000) {
  103. CAdRotator::RaiseException( IDS_ERROR_WEIGHT_SUM_TOO_LARGE );
  104. goto err;
  105. }
  106. if ( lWeight != 0 )
  107. {
  108. CAdDescPtr pAd = new CAdDescriptor( lWeight, strLink, strGif, strAlt );
  109. if ( pAd.IsValid() )
  110. {
  111. // add one reference to the ad for each weight
  112. for( int i = 0; i < lWeight; i++ )
  113. {
  114. m_ads.push_back( pAd );
  115. }
  116. }
  117. }
  118. }
  119. if ( m_ads.size() > 0 )
  120. {
  121. if ( m_strFile != strAdFile )
  122. {
  123. g_pMonitor->StopMonitoringFile( m_strFile.c_str() );
  124. m_strFile = strAdFile;
  125. g_pMonitor->MonitorFile( m_strFile.c_str(), m_pNotify );
  126. }
  127. rc = true;
  128. }
  129. }
  130. else
  131. {
  132. CAdRotator::RaiseException( IDS_ERROR_CANNOT_READ_ROTATION_SCHEDULE_FILE );
  133. }
  134. }
  135. else
  136. {
  137. CAdRotator::RaiseException( IDS_ERROR_CANNOT_LOAD_ROTATION_SCHEDULE_FILE );
  138. }
  139. err:
  140. return rc;
  141. }
  142. //---------------------------------------------------------------------------
  143. //
  144. // Refresh will check to see if the cached information is out of date, if so
  145. // it will re-read the file
  146. //
  147. //---------------------------------------------------------------------------
  148. bool
  149. CAdFile::Refresh()
  150. {
  151. bool rc = false;
  152. if ( m_pNotify->IsNotified() )
  153. {
  154. rc = ProcessAdFile( m_strFile );
  155. }
  156. return rc;
  157. }
  158. //---------------------------------------------------------------------------
  159. //
  160. // ReadHeader will parse the header portion of the file. The header includes
  161. // some or all of the following fields: HEIGHT, WIDTH, BORDER, REDIRECT,
  162. // HSPACE, VSPACE. The fields are separated by newlines and the header is
  163. // terminated by an asterix.
  164. //
  165. //---------------------------------------------------------------------------
  166. bool
  167. CAdFile::ReadHeader(
  168. FileInStream& fs )
  169. {
  170. bool rc = false;
  171. // set defaults
  172. m_nHeight = defaultHeight;
  173. m_nWidth = defaultWidth;
  174. m_nHSpace = defaultHSpace;
  175. m_nVSpace = defaultVSpace;
  176. m_fUTF8 = fs.is_UTF8();
  177. bool done = false;
  178. while ( !fs.eof() && !done )
  179. {
  180. String strLine;
  181. String strName;
  182. fs.readLine( strLine );
  183. StringInStream sis( strLine );
  184. sis >> strName;
  185. HRESULT hr = S_OK;
  186. if ( _tcsicmp( strName.c_str(), _T("HEIGHT") ) == 0 )
  187. {
  188. hr = sis.readInt( m_nHeight );
  189. }
  190. else if ( _tcsicmp( strName.c_str(), _T("WIDTH") ) == 0 )
  191. {
  192. hr = sis.readInt( m_nWidth );
  193. }
  194. else if ( _tcsicmp( strName.c_str(), _T("VSPACE") ) == 0 )
  195. {
  196. hr = sis.readInt( m_nVSpace );
  197. }
  198. else if ( _tcsicmp( strName.c_str(), _T("HSPACE") ) == 0 )
  199. {
  200. hr = sis.readInt( m_nHSpace );
  201. }
  202. else if ( _tcsicmp( strName.c_str(), _T("REDIRECT") ) == 0 )
  203. {
  204. hr = sis.readString( m_strRedirector );
  205. }
  206. else if ( _tcsicmp( strName.c_str(), _T("BORDER" ) ) == 0 )
  207. {
  208. hr = sis.readInt16( m_nBorder );
  209. }
  210. else if ( _tcsicmp( strName.c_str(), _T("*") ) == 0 )
  211. {
  212. rc = true;
  213. done = true;
  214. }
  215. else
  216. {
  217. CAdRotator::RaiseException( IDS_ERROR_UNKNOWN_HEADER_NAME );
  218. }
  219. /*
  220. if ( hr != S_OK )
  221. {
  222. CAdRotator::RaiseException( IDS_ERROR_HEADER_HAS_NO_ASSOCIATED_VALUE );
  223. }
  224. */
  225. }
  226. return rc;
  227. }
  228. //---------------------------------------------------------------------------
  229. //
  230. // RandomAd chooses and ad at random from the list of ads. Since there
  231. // are multiple references to ads based on the weight, we need only produce
  232. // a random number between 0 and one less than the size of the list.
  233. //
  234. //---------------------------------------------------------------------------
  235. CAdDescPtr
  236. CAdFile::RandomAd() const
  237. {
  238. if (m_ads.size() > 0)
  239. return m_ads[ rand() % m_ads.size() ];
  240. else
  241. return NULL;
  242. }