Source code of Windows XP (NT5)
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.

570 lines
18 KiB

  1. // a class to maintain the PICS data. It reads and write it to the metabase and
  2. // reads the file and all that. It also serves as a wrapper for the PICS parsing
  3. // objects that have already been written elsewhere
  4. // Created 4/18/97 by BoydM
  5. #include "stdafx.h"
  6. #include <iadmw.h>
  7. #include "cnfgprts.h"
  8. #include "parserat.h"
  9. #include "RatData.h"
  10. #include <iiscnfg.h>
  11. #include <wrapmb.h>
  12. #include "metatool.h"
  13. #include <isvctrl.h>
  14. #include "mdobjs.h"
  15. #include <winsock2.h>
  16. // Here is the plan. First, we scan the local directory - looking for all
  17. // the .rat files, load them and parse them
  18. //----------------------------------------------------------------
  19. CRatingsData::CRatingsData(IMSAdminBase* pMB):
  20. iRat(0),
  21. m_fEnabled( FALSE ),
  22. m_start_minute(0),
  23. m_start_hour(0),
  24. m_start_day(0),
  25. m_start_month(0),
  26. m_start_year(0),
  27. m_expire_minute(0),
  28. m_expire_hour(0),
  29. m_expire_day(0),
  30. m_expire_month(0),
  31. m_expire_year(0),
  32. m_pMB( pMB )
  33. {
  34. }
  35. //----------------------------------------------------------------
  36. CRatingsData::~CRatingsData()
  37. {
  38. // delete the rating systems
  39. DWORD nRats = (DWORD)rgbRats.GetSize();
  40. for ( DWORD iRat = 0; iRat < nRats; iRat++ )
  41. delete rgbRats[iRat];
  42. }
  43. //----------------------------------------------------------------
  44. BOOL CRatingsData::FCreateURL( CString &sz )
  45. {
  46. CHAR nameBuf[MAX_PATH+1];
  47. // start it off with the mandatory http header
  48. sz.LoadString( IDS_HTTP_HEADER );
  49. // get the host name of the machine
  50. if ( gethostname( nameBuf, sizeof(nameBuf)) )
  51. return FALSE;
  52. sz += nameBuf;
  53. // next, we need to add on the virtual path supplied by the metabase location
  54. // but that means starting by finding the root portion of the string
  55. CString szVir = m_szMeta;
  56. CString szRoot = _T("/Root");
  57. szVir = szVir.Right( szVir.GetLength() - szVir.Find(szRoot) );
  58. szVir = szVir.Right( szVir.GetLength() - szRoot.GetLength() );
  59. // concatenate and done
  60. sz += szVir;
  61. return TRUE;
  62. }
  63. //----------------------------------------------------------------
  64. // generate the label and save it into the metabase
  65. void CRatingsData::SaveTheLable()
  66. {
  67. BOOL fBuiltLabel = FALSE;
  68. BOOL f;
  69. // prepare the metabase wrapper
  70. CWrapMetaBase mbWrap;
  71. f = mbWrap.FInit(m_pMB);
  72. if ( !f ) return;
  73. // if the rating is NOT enabled, delete any existing label and return
  74. if ( !m_fEnabled )
  75. {
  76. // attempt to open the object we want to store into
  77. if ( mbWrap.Open( m_szMeta, METADATA_PERMISSION_WRITE ) )
  78. {
  79. // delete any existing PICS metaobject
  80. // f = mbWrap.DeleteData( _T(""), MD_HTTP_PICS, IIS_MD_UT_FILE, MULTISZ_METADATA );
  81. f = mbWrap.DeleteData( _T(""), MD_HTTP_PICS, MULTISZ_METADATA );
  82. // close the metabase
  83. mbWrap.Close();
  84. }
  85. //leave
  86. return;
  87. }
  88. else
  89. {
  90. CString szLabel;
  91. // first, we add the actual HTTP header to the header
  92. // szLabel = _T("Protocol: {PICS-1.0 {headers PICS-Label}}\nPICS-Label: ");
  93. szLabel = _T("PICS-Label: ");
  94. // create the URL string for this label
  95. CString szURL;
  96. FCreateURL( szURL );
  97. // create the modified string for this label
  98. CString szMod;
  99. CreateDateSz( szMod, m_start_day, m_start_month, m_start_year, m_start_hour, m_start_minute );
  100. // create the exipres string for this label
  101. CString szExpire;
  102. CreateDateSz( szExpire, m_expire_day, m_expire_month, m_expire_year, m_expire_hour, m_expire_minute );
  103. // tell each ratings system object to add its label to the string
  104. DWORD nRatingSystems = (DWORD)rgbRats.GetSize();
  105. for ( DWORD iRat = 0; iRat < nRatingSystems; iRat++ )
  106. {
  107. // build the label string
  108. rgbRats[iRat]->OutputLabels( szLabel, szURL, m_szEmail, szMod, szExpire );
  109. }
  110. // the data gets saved as a multisz, so prep it up
  111. PTCHAR psz = szLabel.GetBuffer( szLabel.GetLength()+4 );
  112. DWORD dw = szLabel.GetLength();
  113. // add the second null
  114. psz[dw + 1] = 0;
  115. psz[dw + 2] = 0;
  116. // save the data
  117. // save the PICS header string
  118. // f = SetMetaData(&mbWrap, szPartial, MD_HTTP_PICS, IIS_MD_UT_FILE,
  119. // psz, szLabel.GetLength()+2 );
  120. // f = SetMetaMultiSz( &mbWrap, m_szMeta, MD_HTTP_PICS, IIS_MD_UT_FILE,
  121. // psz, dw+2 );
  122. f = SetMetaMultiSz(m_pMB, m_szServer, m_szMeta, _T(""), MD_HTTP_PICS,
  123. IIS_MD_UT_FILE, psz, dw+2, TRUE );
  124. // release the buffer
  125. szLabel.ReleaseBuffer();
  126. // these changes are permanent - so write them out
  127. if ( f )
  128. mbWrap.Save();
  129. }
  130. }
  131. //----------------------------------------------------------------
  132. BOOL CRatingsData::FInit( CString szServer, CString szMeta )
  133. {
  134. CWinApp* pApp = AfxGetApp();
  135. CString sz;
  136. BOOL fGotSomething = FALSE;
  137. BOOL fFoundAFile = FALSE;
  138. // store the target metabase location
  139. m_szServer = szServer;
  140. m_szMeta = szMeta;
  141. // build the search string
  142. CString szSearch;
  143. // the ratings files are in the system32 directory. First, get that
  144. // directory from the system. The first call is to get the size of the buffer.
  145. // add one for the terminating NULL
  146. DWORD cchSysDir = GetSystemDirectory( NULL, 0 ) + 1;
  147. // if we didn't get one - fail
  148. if ( cchSysDir == 1 ) return FALSE;
  149. // Now get it for real
  150. cchSysDir = GetSystemDirectory( szSearch.GetBuffer(cchSysDir), cchSysDir );
  151. szSearch.ReleaseBuffer();
  152. // if we didn't get one - fail
  153. if ( !cchSysDir ) return FALSE;
  154. // finish making it a proper search string
  155. //
  156. // RONALDM -- add .rat to only find rat files.
  157. //
  158. szSearch += _T("\\*.rat");
  159. // scan the local files looking for rat files. For each we find, load
  160. // them into the list of rat files
  161. BOOL fKeepGoing = TRUE;
  162. CFileFind finder;
  163. fFoundAFile = finder.FindFile( szSearch );
  164. while ( fFoundAFile )
  165. {
  166. // get rid of the directories right away
  167. if ( finder.MatchesMask( FILE_ATTRIBUTE_DIRECTORY ) )
  168. {
  169. // get the next file
  170. fFoundAFile = finder.FindNextFile();
  171. continue;
  172. }
  173. // get and normalize the path
  174. sz = finder.GetFilePath();
  175. sz.MakeLower();
  176. // if it is a rat file, go for it
  177. //
  178. // RONALDM -- changed the mask so that this is all that's necc.
  179. //
  180. //if ( sz.Find(_T(".rat")) > 0 )
  181. {
  182. // set the found flag based on if we can load it
  183. fGotSomething |= FLoadRatingsFile( sz );
  184. }
  185. // get the next file
  186. if ( !fKeepGoing )
  187. {
  188. fFoundAFile = FALSE;
  189. }
  190. else
  191. {
  192. fKeepGoing = finder.FindNextFile();
  193. }
  194. }
  195. // if we loaded a file, check what is in the metabase and load the values
  196. if ( fGotSomething )
  197. {
  198. LoadMetabaseValues();
  199. }
  200. else
  201. {
  202. // if we didn't find any rat files, tell the user and return
  203. AfxMessageBox( IDS_RAT_FINDFILE_ERROR );
  204. }
  205. // return the answer
  206. return fGotSomething;
  207. }
  208. //----------------------------------------------------------------
  209. // load a ratings file
  210. BOOL CRatingsData::FLoadRatingsFile( CString szFilePath )
  211. {
  212. HANDLE hFile;
  213. HANDLE hFileMapping;
  214. VOID * pMem;
  215. BOOL fParsed = FALSE;
  216. hFile = CreateFile( szFilePath,
  217. GENERIC_READ,
  218. 0,
  219. NULL,
  220. OPEN_EXISTING,
  221. FILE_ATTRIBUTE_NORMAL,
  222. NULL );
  223. if ( hFile == INVALID_HANDLE_VALUE )
  224. {
  225. return FALSE;
  226. }
  227. hFileMapping = CreateFileMapping( hFile,
  228. NULL,
  229. PAGE_READONLY,
  230. 0,
  231. 0,
  232. NULL );
  233. if ( hFileMapping == NULL )
  234. {
  235. CloseHandle( hFile );
  236. return FALSE;
  237. }
  238. pMem = MapViewOfFile( hFileMapping,
  239. FILE_MAP_READ,
  240. 0,
  241. 0,
  242. 0 );
  243. if ( pMem == NULL )
  244. {
  245. CloseHandle( hFileMapping );
  246. CloseHandle( hFile );
  247. return FALSE;
  248. }
  249. // parse this and load it in and all that stuff
  250. fParsed = FParseRatingsFile( (LPSTR) pMem, szFilePath );
  251. UnmapViewOfFile( pMem );
  252. CloseHandle( hFileMapping );
  253. CloseHandle( hFile );
  254. // return the answer
  255. return fParsed;
  256. }
  257. //----------------------------------------------------------------
  258. BOOL CRatingsData::FParseRatingsFile( LPSTR pData, CString szPath )
  259. {
  260. HRESULT hres;
  261. BOOL fSuccess = FALSE;
  262. // first, try and parse the data
  263. PicsRatingSystem* pRating = new PicsRatingSystem();
  264. // parse the data
  265. hres = pRating->Parse( pData );
  266. fSuccess = (hres == 0);
  267. // if it didn't parse, leave now
  268. if ( !fSuccess )
  269. {
  270. delete pRating;
  271. return FALSE;
  272. }
  273. // add the rat to the list of parsed rats
  274. rgbRats.Add( pRating );
  275. return fSuccess;
  276. }
  277. //----------------------------------------------------------------
  278. // create a date string
  279. void CRatingsData::CreateDateSz( CString &sz, WORD day, WORD month, WORD year, WORD hour, WORD minute )
  280. {
  281. // get the local time zone
  282. TIME_ZONE_INFORMATION tZone;
  283. INT hrZone, mnZone;
  284. DWORD dwDaylight = GetTimeZoneInformation( &tZone );
  285. // Fix for 339525: Boyd, this could be negative and must be signed type!
  286. LONG tBias;
  287. // First, calculate the correct bias - depending whether or not
  288. // we are in daylight savings time.
  289. if ( dwDaylight == TIME_ZONE_ID_DAYLIGHT )
  290. {
  291. tBias = tZone.Bias + tZone.DaylightBias;
  292. }
  293. else
  294. {
  295. tBias = tZone.Bias + tZone.StandardBias;
  296. }
  297. // calculate the hours and minutes offset for the time-zone
  298. hrZone = tBias / 60;
  299. mnZone = tBias % 60;
  300. // need to handle time zones east of GMT
  301. if ( hrZone < 0 )
  302. {
  303. hrZone *= (-1);
  304. mnZone *= (-1);
  305. // make the string
  306. sz.Format( _T("%04d.%02d.%02dT%02d:%02d+%02d%02d"), year, month, day, hour, minute, hrZone, mnZone );
  307. }
  308. else
  309. {
  310. // make the string
  311. sz.Format( _T("%04d.%02d.%02dT%02d:%02d-%02d%02d"), year, month, day, hour, minute, hrZone, mnZone );
  312. }
  313. }
  314. //----------------------------------------------------------------
  315. // read a date string
  316. void CRatingsData::ReadDateSz( CString sz, WORD* pDay, WORD* pMonth, WORD* pYear, WORD* pHour, WORD* pMinute )
  317. {
  318. CString szNum;
  319. WORD i;
  320. DWORD dw;
  321. // year
  322. szNum = sz.Left( sz.Find(_T('.')) );
  323. i = (WORD)swscanf( szNum, _T("%d"), &dw );
  324. *pYear = (WORD)dw;
  325. sz = sz.Right( sz.GetLength() - szNum.GetLength() - 1 );
  326. // month
  327. szNum = sz.Left( sz.Find(_T('.')) );
  328. i = (WORD)swscanf( szNum, _T("%d"), &dw );
  329. *pMonth = (WORD)dw;
  330. sz = sz.Right( sz.GetLength() - szNum.GetLength() - 1 );
  331. // day
  332. szNum = sz.Left( sz.Find(_T('T')) );
  333. i = (WORD)swscanf( szNum, _T("%d"), &dw );
  334. *pDay = (WORD)dw;
  335. sz = sz.Right( sz.GetLength() - szNum.GetLength() - 1 );
  336. // hour
  337. szNum = sz.Left( sz.Find(_T(':')) );
  338. i = (WORD)swscanf( szNum, _T("%d"), &dw );
  339. *pHour = (WORD)dw;
  340. sz = sz.Right( sz.GetLength() - szNum.GetLength() - 1 );
  341. // minute
  342. szNum = sz.Left( 2 );
  343. i = (WORD)swscanf( szNum, _T("%d"), &dw );
  344. *pMinute = (WORD)dw;
  345. }
  346. //----------------------------------------------------------------
  347. // for simplicity's sake (and for the sake of gettings done) only check the
  348. // metabase values against the first loaded ratings system. Everything I've
  349. // been hearing is that there will be only one.
  350. void CRatingsData::LoadMetabaseValues()
  351. {
  352. CString szRating;
  353. BOOL f;
  354. // prepare the metabase wrapper
  355. CWrapMetaBase mbWrap;
  356. f = mbWrap.FInit(m_pMB);
  357. if ( !f ) return;
  358. // if we succeded in building the lables, save it in the metabase
  359. // attempt to open the object we want to store into
  360. CString szMeta;
  361. // arg arg arg. For things like directories, the metapath may not exist
  362. // seperate the partial path from the base - the root is always SZ_ROOT
  363. szMeta = SZ_W3_ROOT;
  364. m_szMetaPartial = m_szMeta.Right(m_szMeta.GetLength() - szMeta.GetLength() );
  365. // save the data
  366. if ( mbWrap.Open( szMeta, METADATA_PERMISSION_READ ) )
  367. {
  368. DWORD cbData;
  369. // attempt to read the data from the metabase
  370. WCHAR* pData= (WCHAR*)mbWrap.GetData( m_szMetaPartial, MD_HTTP_PICS, IIS_MD_UT_FILE, MULTISZ_METADATA,
  371. &cbData, METADATA_INHERIT | METADATA_PARTIAL_PATH );
  372. // copy the string into place
  373. if ( pData )
  374. szRating = pData;
  375. // free the buffer
  376. mbWrap.FreeWrapData( pData );
  377. // close the metabase
  378. mbWrap.Close();
  379. // if we got the string, parse it and all that jazz
  380. if ( !szRating.IsEmpty() )
  381. ParseMetaRating( szRating );
  382. }
  383. }
  384. //----------------------------------------------------------------
  385. // NOTE: this is a pretty fragile reading of the PICS file. If things are
  386. // not in the order that this file would write them back out in, it will fail.
  387. // however, This will work on PICS ratings that this module has written out,
  388. // which should pretty much be all of them
  389. // it also assumes that one-letter abbreviations are used just about everywhere
  390. #define RAT_PERSON_DETECTOR _T("by \"")
  391. #define RAT_LABEL_DETECTOR _T("l ")
  392. #define RAT_ON_DETECTOR _T("on \"")
  393. #define RAT_EXPIRE_DETECTOR _T("exp \"")
  394. #define RAT_RAT_DETECTOR _T("r (")
  395. void CRatingsData::ParseMetaRating( CString szRating )
  396. {
  397. CString szScratch;
  398. // if we got here, then we know that the rating system is enabled
  399. m_fEnabled = TRUE;
  400. // operate on a copy of the data
  401. CString szRat;
  402. // skip past the http headerpart
  403. szRat = szRating.Right( szRating.GetLength() - szRating.Find(_T("\"http://")) - 1 );
  404. szRat = szRat.Right( szRat.GetLength() - szRat.Find(_T('\"')) - 1 );
  405. szRat.TrimLeft();
  406. // the next bit should be the label indicator. Skip over it
  407. if ( szRat.Left(wcslen(RAT_LABEL_DETECTOR)) == RAT_LABEL_DETECTOR )
  408. szRat = szRat.Right( szRat.GetLength() - wcslen(RAT_LABEL_DETECTOR) );
  409. // we should now be at the author part. If it is there, load it in
  410. if ( szRat.Left(wcslen(RAT_PERSON_DETECTOR)) == RAT_PERSON_DETECTOR )
  411. {
  412. szRat = szRat.Right( szRat.GetLength() - wcslen(RAT_PERSON_DETECTOR) );
  413. m_szEmail = szRat.Left( szRat.Find(_T('\"')) );
  414. szRat = szRat.Right( szRat.GetLength() - m_szEmail.GetLength() - 1 );
  415. szRat.TrimLeft();
  416. }
  417. // next should be the modification date
  418. // we should now be at the author part. If we are, load it in
  419. if ( szRat.Left(wcslen(RAT_ON_DETECTOR)) == RAT_ON_DETECTOR )
  420. {
  421. szRat = szRat.Right( szRat.GetLength() - wcslen(RAT_ON_DETECTOR) );
  422. szScratch = szRat.Left( szRat.Find(_T('\"')) );
  423. szRat = szRat.Right( szRat.GetLength() - szScratch.GetLength() - 1 );
  424. szRat.TrimLeft();
  425. ReadDateSz( szScratch, &m_start_day, &m_start_month, &m_start_year,
  426. &m_start_hour, &m_start_minute );
  427. }
  428. // next should be the expiration date
  429. // we should now be at the author part. If we are, load it in
  430. if ( szRat.Left(wcslen(RAT_EXPIRE_DETECTOR)) == RAT_EXPIRE_DETECTOR )
  431. {
  432. szRat = szRat.Right( szRat.GetLength() - wcslen(RAT_EXPIRE_DETECTOR) );
  433. szScratch = szRat.Left( szRat.Find(_T('\"')) );
  434. szRat = szRat.Right( szRat.GetLength() - szScratch.GetLength() - 1 );
  435. szRat.TrimLeft();
  436. ReadDateSz( szScratch, &m_expire_day, &m_expire_month, &m_expire_year,
  437. &m_expire_hour, &m_expire_minute );
  438. }
  439. // we should now be at the actual ratings part. If we are, load it in as one string first
  440. if ( szRat.Left(wcslen(RAT_RAT_DETECTOR)) == RAT_RAT_DETECTOR )
  441. {
  442. szRat = szRat.Right( szRat.GetLength() - wcslen(RAT_RAT_DETECTOR) );
  443. szScratch = szRat.Left( szRat.Find(_T(')')) );
  444. szRat = szRat.Right( szRat.GetLength() - szScratch.GetLength() - 1 );
  445. szRat.TrimLeft();
  446. // loop through all the value pairs in the ratings string
  447. while ( szScratch.GetLength() )
  448. {
  449. // this part goes <ch> sp <ch> so that we know we can use chars 0 and 2
  450. ParseMetaPair( szScratch[0], szScratch[2] );
  451. // cut down the string
  452. szScratch = szScratch.Right( szScratch.GetLength() - 3 );
  453. szScratch.TrimLeft();
  454. }
  455. }
  456. }
  457. //----------------------------------------------------------------
  458. void CRatingsData::ParseMetaPair( TCHAR chCat, TCHAR chVal )
  459. {
  460. // check validity of the value character
  461. if ( (chVal < _T('0')) || (chVal > _T('9')) )
  462. return;
  463. // convert the value into a number - the quick way
  464. WORD value = chVal - _T('0');
  465. // try all the categories
  466. DWORD nCat = rgbRats[0]->arrpPC.Length();
  467. for ( DWORD iCat = 0; iCat < nCat; iCat++ )
  468. {
  469. // stop at the first successful setting
  470. if ( rgbRats[0]->arrpPC[iCat]->FSetValuePair((CHAR)chCat, (CHAR)value) )
  471. break;
  472. }
  473. }