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.

869 lines
25 KiB

  1. //
  2. // Pei-Hwa Lin (peiwhal), Feb 3, 1997
  3. //
  4. // Notes:
  5. // Compile switch : NO_FILE_WHEN_CREATE can turn on when wininet cache
  6. // would create url cache entry if attached file is empty.
  7. // LOG_CACHE_PATH will create log cache at the same level as
  8. // content cache.
  9. #include "private.h"
  10. #undef TF_THISMODULE
  11. #define TF_THISMODULE TF_TRACKCACHE
  12. #define MY_CACHE_FILE_ENTRY_SIZE 2048
  13. const TCHAR c_szExt[] = TEXT("log");
  14. //used for creating tracking container (registry)
  15. const TCHAR c_szLogContainer[] = TEXT("Log"); // if you modify this, modify iedev\inc\inetreg.h REGSTR_PATH_TRACKING too.
  16. const TCHAR c_szLogPrefix[] = TEXT("Log:");
  17. const char c_szLogContainerA[] = "Log";
  18. // helper function
  19. inline BOOL IsNumber(WCHAR x) { return (x >= L'0' && x <= L'9'); }
  20. /*=============================================================================
  21. FILEFROMPATH returns the filename of given filename which may include path.
  22. =============================================================================*/
  23. LPTSTR FileFromPath( LPCTSTR lpsz )
  24. {
  25. LPTSTR lpch;
  26. /* Strip path/drive specification from name if there is one */
  27. lpch = CharPrev( lpsz, lpsz + lstrlen(lpsz) );
  28. // special case for "http://server/domain/channel.cdf/"
  29. if (*lpch == '/') lpch = CharPrev( lpsz, lpch);
  30. while (lpch > lpsz)
  31. {
  32. if (*lpch == '/') {
  33. lpch = CharNext(lpch);
  34. break;
  35. }
  36. lpch = CharPrev( lpsz, lpch);
  37. }
  38. return(lpch);
  39. } /* end FileFromPath */
  40. // CDF updates, create new group and deal with previous posting information
  41. void
  42. CUrlTrackingCache :: Init(LPCWSTR pwszURL)
  43. {
  44. DWORD dwRetry;
  45. BSTR bstrEncoding = NULL;
  46. _groupId = 0;
  47. _pwszPostUrl = NULL;
  48. _pszChannelUrlSite = NULL;
  49. _pszPostUrlSite = NULL;
  50. _pwszEncodingMethod = NULL;
  51. _groupId = CreateUrlCacheGroup(CACHEGROUP_FLAG_GIDONLY, NULL);
  52. WriteLONGLONG(_pCDFStartItem, c_szTrackingCookie, _groupId);
  53. // #54653: remove previous tracking information, if any
  54. if (SUCCEEDED(ReadBSTR(_pCDFStartItem, c_szPostHeader, &bstrEncoding)))
  55. {
  56. WriteEMPTY(_pCDFStartItem, c_szPostHeader);
  57. SAFEFREEBSTR(bstrEncoding);
  58. }
  59. if (SUCCEEDED(ReadDWORD(_pCDFStartItem, c_szPostingRetry, &dwRetry)))
  60. WriteEMPTY(_pCDFStartItem, c_szPostingRetry);
  61. DoBaseURL(pwszURL);
  62. return;
  63. }
  64. void
  65. CUrlTrackingCache :: DoBaseURL(LPCWSTR pwszURL)
  66. {
  67. DWORD cbLen;
  68. DWORD useSecurity = 1;
  69. ASSERT(!_pszChannelUrlSite)
  70. cbLen = (lstrlenW(pwszURL)+1) * sizeof(WCHAR);
  71. _pszChannelUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen);
  72. #ifdef DEBUG
  73. HKEY hkey;
  74. // provide security switch for debugging
  75. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  76. MY_WEBCHECK_POST_REG,
  77. 0,
  78. KEY_READ,
  79. &hkey))
  80. {
  81. DWORD cbsize = sizeof(useSecurity);
  82. if (ERROR_SUCCESS == RegQueryValueEx(hkey,
  83. TEXT("PostSecurity"),
  84. NULL,
  85. NULL,
  86. (LPBYTE)&useSecurity,
  87. &cbsize))
  88. {
  89. if ((useSecurity == 0) && (NULL != _pszChannelUrlSite))
  90. StrCpyN(_pszChannelUrlSite, TEXT("http://"), cbLen / sizeof(WCHAR));
  91. }
  92. }
  93. #endif
  94. if ((useSecurity == 1) && (NULL != _pszChannelUrlSite))
  95. {
  96. MyOleStrToStrN(_pszChannelUrlSite, cbLen, pwszURL);
  97. *(FileFromPath( _pszChannelUrlSite )) = 0;
  98. }
  99. return;
  100. }
  101. // only track URLs come from the same server of Channel CDF or LogTarget URL
  102. //
  103. BOOL
  104. CUrlTrackingCache :: IsValidURL(LPCTSTR lpszURL)
  105. {
  106. BOOL bret;
  107. if (!_pszChannelUrlSite || !_pszPostUrlSite)
  108. return FALSE;
  109. if (!StrCmpNI(lpszURL, _pszChannelUrlSite, lstrlen(_pszChannelUrlSite)))
  110. bret = TRUE;
  111. else if (!StrCmpNI(lpszURL, _pszPostUrlSite, lstrlen(_pszPostUrlSite)))
  112. bret = TRUE;
  113. else
  114. bret = FALSE;
  115. return bret;
  116. }
  117. #define LOG_CACHE_PATH
  118. #ifdef LOG_CACHE_PATH
  119. LPSTR PathPreviousBackslashA(LPSTR psz)
  120. {
  121. LPSTR lpch = CharPrevA(psz, psz + lstrlenA(psz));
  122. for (; *lpch && *lpch != '\\'; lpch=CharPrevA(psz,lpch));
  123. return lpch;
  124. }
  125. //------------------------------------------------------------------------------
  126. // GetCacheLocation
  127. //
  128. // Purpose: Return the location of the logging cache
  129. // ***** GetUrlCacheConfigInfoW is yet implemented in wininet
  130. //------------------------------------------------------------------------------
  131. //
  132. HRESULT GetCacheLocation
  133. (
  134. LPTSTR pszCacheLocation,
  135. DWORD dwSize // no. of chars in pszCacheLocation
  136. )
  137. {
  138. HRESULT hr = S_OK;
  139. DWORD dwLastErr;
  140. LPINTERNET_CACHE_CONFIG_INFOA lpCCI = NULL;
  141. DWORD dwCCISize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
  142. BOOL fOnceErrored = FALSE;
  143. while (TRUE)
  144. {
  145. if ((lpCCI = (LPINTERNET_CACHE_CONFIG_INFOA)MemAlloc(LPTR,
  146. dwCCISize)) == NULL)
  147. {
  148. hr = E_OUTOFMEMORY;
  149. goto cleanup;
  150. }
  151. if (!GetUrlCacheConfigInfoA(lpCCI, &dwCCISize,
  152. CACHE_CONFIG_CONTENT_PATHS_FC))
  153. {
  154. if ((dwLastErr = GetLastError()) != ERROR_INSUFFICIENT_BUFFER ||
  155. fOnceErrored)
  156. {
  157. hr = HRESULT_FROM_WIN32(dwLastErr);
  158. goto cleanup;
  159. }
  160. //
  161. // We have insufficient buffer size; reallocate a buffer with the
  162. // new dwCCISize set by GetUrlCacheConfigInfo
  163. // Set fOnceErrored to TRUE so that we don't loop indefinitely
  164. //
  165. fOnceErrored = TRUE;
  166. }
  167. else
  168. {
  169. //
  170. LPSTR pszPath = lpCCI->CachePaths[0].CachePath;
  171. INT iLen;
  172. PathRemoveBackslashA(pszPath);
  173. *(PathPreviousBackslashA(pszPath)) = 0;
  174. iLen = lstrlenA(pszPath) + sizeof(CHAR); // + 1 is for the null char
  175. if ((((DWORD) iLen + ARRAYSIZE(c_szLogContainer) + 1) * sizeof(TCHAR)) < dwSize)
  176. {
  177. TCHAR szPathT[MAX_PATH];
  178. SHAnsiToTChar(pszPath, szPathT, ARRAYSIZE(szPathT));
  179. wnsprintf(pszCacheLocation, dwSize, TEXT("%s\\%s"), szPathT, c_szLogContainer);
  180. }
  181. else
  182. {
  183. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  184. }
  185. break;
  186. }
  187. SAFELOCALFREE(lpCCI);
  188. lpCCI = NULL;
  189. }
  190. cleanup:
  191. if (lpCCI != NULL)
  192. {
  193. LocalFree(lpCCI);
  194. }
  195. return hr;
  196. }
  197. #endif
  198. //-----------------------------------------------------------------------------
  199. //
  200. // ReadTrackingPrefix
  201. //
  202. // will create tracking container if current profile doesn't have one
  203. // **** FindFirstUrlCacheContainerW is yet implemented in wininet
  204. // **** FindNextUrlCacheContainerW is yet implemented either
  205. //-----------------------------------------------------------------------------
  206. LPTSTR
  207. ReadTrackingPrefix(void)
  208. {
  209. LPTSTR lpPfx = NULL;
  210. DWORD cbPfx = 0;
  211. struct {
  212. INTERNET_CACHE_CONTAINER_INFOA cInfo;
  213. CHAR szBuffer[MAX_PATH+INTERNET_MAX_URL_LENGTH+1];
  214. } ContainerInfo;
  215. DWORD dwModified, dwContainer;
  216. HANDLE hEnum;
  217. dwContainer = sizeof(ContainerInfo);
  218. hEnum = FindFirstUrlCacheContainerA(&dwModified,
  219. &ContainerInfo.cInfo,
  220. &dwContainer,
  221. 0);
  222. if (hEnum)
  223. {
  224. for (;;)
  225. {
  226. if (!StrCmpIA(ContainerInfo.cInfo.lpszName, c_szLogContainerA))
  227. {
  228. ASSERT(ContainerInfo.cInfo.lpszCachePrefix[0]);
  229. CHAR szPfx[MAX_PATH];
  230. DWORD cch = ARRAYSIZE(ContainerInfo.cInfo.lpszCachePrefix)+sizeof(CHAR);
  231. StrCpyNA(szPfx, ContainerInfo.cInfo.lpszCachePrefix, cch);
  232. cch *= sizeof(TCHAR);
  233. lpPfx = (LPTSTR)MemAlloc(LPTR, cch);
  234. if (!lpPfx)
  235. SetLastError(ERROR_OUTOFMEMORY);
  236. SHAnsiToTChar(szPfx, lpPfx, cch);
  237. break;
  238. }
  239. dwContainer = sizeof(ContainerInfo);
  240. if (!FindNextUrlCacheContainerA(hEnum, &ContainerInfo.cInfo, &dwContainer))
  241. {
  242. // This code used to check GetLastError() for ERROR_NO_MORE_ITEMS before
  243. // it would break. Well, that could put us in an infinite loop if the
  244. // reason for failure were something else (like insufficient buffer) because
  245. // wininet would not move forward in it's enumeration and we would not
  246. // have done anything to address the error.
  247. break;
  248. }
  249. }
  250. FindCloseUrlCache(hEnum);
  251. }
  252. if (!lpPfx)
  253. {
  254. LPTSTR pszCachePath = NULL;
  255. #ifdef LOG_CACHE_PATH
  256. TCHAR szCachePath[MAX_PATH];
  257. pszCachePath = (SUCCEEDED(GetCacheLocation(szCachePath, MAX_PATH))) ?
  258. szCachePath : NULL;
  259. #endif
  260. if (CreateUrlCacheContainer(c_szLogContainer,
  261. c_szLogPrefix,
  262. pszCachePath, // wininet bug:if NULL, will create under ..\History\Log //
  263. 8192, // dwCacheLimit,
  264. INTERNET_CACHE_CONTAINER_NOSUBDIRS, // dwContainerType,
  265. 0, // dwOptions,
  266. NULL, // pvBuffer,
  267. 0 // cbBuffer
  268. ))
  269. {
  270. return ReadTrackingPrefix();
  271. }
  272. // unable to create Log container, stop.
  273. }
  274. return lpPfx;
  275. }
  276. //-----------------------------------------------------------------------------
  277. //
  278. // ConvertToPrefixedUrl
  279. //
  280. // caller must release lplpPrefixedUrl
  281. //-----------------------------------------------------------------------------
  282. BOOL
  283. CUrlTrackingCache :: ConvertToPrefixedUrl
  284. (
  285. IN LPCTSTR lpUrl,
  286. IN LPTSTR* lplpPrefixedUrl
  287. )
  288. {
  289. BOOL bret = FALSE;
  290. ASSERT(lpUrl);
  291. if (!_lpPfx)
  292. _lpPfx = ReadTrackingPrefix();
  293. if (_lpPfx)
  294. {
  295. int len = lstrlen(lpUrl) + lstrlen(_lpPfx) + 1;
  296. *lplpPrefixedUrl = NULL;
  297. *lplpPrefixedUrl = (LPTSTR)MemAlloc(LPTR, len * sizeof(TCHAR));
  298. if (*lplpPrefixedUrl)
  299. {
  300. wnsprintf(*lplpPrefixedUrl, len, TEXT("%s%s"), _lpPfx, lpUrl);
  301. bret = TRUE;
  302. }
  303. else
  304. bret = FALSE;
  305. }
  306. return bret;
  307. }
  308. //-----------------------------------------------------------------------------
  309. //
  310. // RetrieveUrlCacheEntry
  311. //
  312. // caller must release lpCE
  313. //-----------------------------------------------------------------------------
  314. LPINTERNET_CACHE_ENTRY_INFO
  315. CUrlTrackingCache :: RetrieveUrlCacheEntry
  316. (
  317. IN LPCTSTR lpUrl
  318. )
  319. {
  320. LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
  321. DWORD cbSize;
  322. BOOL bret = FALSE;
  323. lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
  324. if (lpCE)
  325. {
  326. cbSize = MY_MAX_CACHE_ENTRY_INFO;
  327. while ((bret = GetUrlCacheEntryInfo(lpUrl, lpCE, &cbSize)) != TRUE)
  328. {
  329. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  330. {
  331. SAFELOCALFREE(lpCE);
  332. lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, cbSize);
  333. if (!lpCE)
  334. break;
  335. }
  336. else
  337. break;
  338. }
  339. }
  340. if (!bret && lpCE)
  341. {
  342. SAFELOCALFREE(lpCE);
  343. SetLastError(ERROR_FILE_NOT_FOUND);
  344. }
  345. return lpCE;
  346. }
  347. #define FILETIME_SEC 100000000
  348. #define SECS_PER_DAY (60 * 60 * 24)
  349. DWORD WCTOI(LPCWSTR pwstr)
  350. {
  351. DWORD dw;
  352. int len = lstrlenW(pwstr);
  353. dw = 0;
  354. for (int i = 0; i<len; i++)
  355. {
  356. if (!IsNumber(pwstr[i]))
  357. break;
  358. dw = dw * 10 + (pwstr[i] - L'0');
  359. }
  360. if (dw == 0) dw = 24;
  361. return dw;
  362. }
  363. //-----------------------------------------------------------------------------
  364. //
  365. // CreatePrefixedCacheEntry
  366. //
  367. // Create cache entry in Tracking cache bucket
  368. //-----------------------------------------------------------------------------
  369. HRESULT CreateLogCacheEntry
  370. (
  371. LPCTSTR lpPfxUrl,
  372. FILETIME ftExpire,
  373. FILETIME ftModified,
  374. DWORD CacheEntryType
  375. )
  376. {
  377. TCHAR lpFile[MAX_PATH];
  378. HRESULT hr = E_FAIL;
  379. DWORD cbSize;
  380. if (CreateUrlCacheEntry(lpPfxUrl, MY_CACHE_FILE_ENTRY_SIZE, c_szExt, lpFile, 0))
  381. {
  382. HANDLE hFile = CreateFile(lpFile,
  383. GENERIC_READ|GENERIC_WRITE,
  384. FILE_SHARE_READ,
  385. NULL,
  386. CREATE_ALWAYS,
  387. FILE_ATTRIBUTE_NORMAL,
  388. NULL);
  389. if (hFile == INVALID_HANDLE_VALUE)
  390. return hr;
  391. // note: wininet will not create the entry if file size equals to zero
  392. // WriteFile(hFile, c_szLogFields, g_ccLogFields, &cbSize, NULL);
  393. WriteFile(hFile, c_szEmptyLog, c_ccEmptyLog, &cbSize, NULL);
  394. CloseHandle(hFile);
  395. return (CommitUrlCacheEntry(lpPfxUrl,
  396. lpFile,
  397. ftExpire,
  398. ftModified,
  399. CacheEntryType,
  400. NULL,
  401. 0,
  402. NULL,
  403. 0)) ? S_OK : E_FAIL;
  404. }
  405. return hr;
  406. }
  407. HRESULT
  408. CUrlTrackingCache :: CreatePrefixedCacheEntry
  409. (
  410. IN LPCTSTR lpPfxUrl
  411. )
  412. {
  413. HRESULT hr = E_FAIL;
  414. LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
  415. FILETIME ftModified;
  416. // IE50: due to change to wininet cache group enumeration, now we save our filter
  417. // information _groupId along with each cache entry itself. the wininet url cache
  418. // no longer maintain this for us
  419. ftModified.dwHighDateTime = (DWORD)(_groupId >> 32);
  420. ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & _groupId);
  421. lpCE = RetrieveUrlCacheEntry(lpPfxUrl);
  422. if (lpCE )
  423. {
  424. // exist in Tracking bucket, set tracking flag
  425. // IE50: save _groupId info in LastModifiedTime
  426. lpCE->CacheEntryType |= _ConnectionScope;
  427. lpCE->LastModifiedTime.dwHighDateTime = ftModified.dwHighDateTime;
  428. lpCE->LastModifiedTime.dwLowDateTime = ftModified.dwLowDateTime;
  429. ASSERT(SetUrlCacheEntryInfo(lpCE->lpszSourceUrlName, lpCE,
  430. CACHE_ENTRY_ATTRIBUTE_FC | CACHE_ENTRY_MODTIME_FC) == TRUE);
  431. hr = S_OK;
  432. }
  433. else
  434. //FILE_NOT_FOUND, create it.
  435. {
  436. LONGLONG llExpireHorizon;
  437. SYSTEMTIME st;
  438. FILETIME ftMod, ftExpire;
  439. llExpireHorizon = (LONGLONG)(SECS_PER_DAY * _dwPurgeTime / 24);
  440. GetLocalTime(&st);
  441. SystemTimeToFileTime(&st, &ftMod);
  442. llExpireHorizon *= FILETIME_SEC;
  443. ftExpire.dwLowDateTime = ftMod.dwLowDateTime + (DWORD)(llExpireHorizon % 0xFFFFFFFF);
  444. ftExpire.dwHighDateTime = ftMod.dwHighDateTime + (DWORD)(llExpireHorizon / 0xFFFFFFFF);
  445. hr = CreateLogCacheEntry(lpPfxUrl, ftExpire, ftModified, _ConnectionScope);
  446. }
  447. SAFELOCALFREE(lpCE);
  448. return hr;
  449. }
  450. HRESULT
  451. CUrlTrackingCache :: AddToTrackingCacheEntry
  452. (
  453. IN LPCWSTR pwszUrl
  454. )
  455. {
  456. HRESULT hr = E_OUTOFMEMORY;
  457. TCHAR szCanonicalUrl[MAX_URL];
  458. DWORD dwSize = MAX_URL;
  459. LPTSTR lpUrl = NULL;
  460. LPTSTR lpPfxUrl = NULL;
  461. DWORD cbSize;
  462. PROPVARIANT vProp = {0};
  463. if (pwszUrl == NULL)
  464. return E_INVALIDARG;
  465. cbSize = lstrlenW(pwszUrl) + 1;
  466. lpUrl = (LPTSTR)MemAlloc(LPTR, cbSize * sizeof(TCHAR));
  467. if (!lpUrl)
  468. return hr;
  469. SHUnicodeToTChar(pwszUrl, lpUrl, cbSize);
  470. if (!IsValidURL(lpUrl))
  471. {
  472. MemFree(lpUrl);
  473. return E_INVALIDARG;
  474. }
  475. // canonicalize URL
  476. InternetCanonicalizeUrl(lpUrl, szCanonicalUrl, &dwSize, ICU_DECODE);
  477. SAFELOCALFREE(lpUrl);
  478. ConvertToPrefixedUrl(szCanonicalUrl, &lpPfxUrl);
  479. if (!lpPfxUrl)
  480. {
  481. return hr;
  482. }
  483. hr = CreatePrefixedCacheEntry(lpPfxUrl);
  484. if (SUCCEEDED(hr))
  485. {
  486. // exist in Tracking bucket, set tracking flag.
  487. vProp.vt = VT_UI4;
  488. vProp.ulVal = _ConnectionScope;
  489. hr = IntSiteHelper(szCanonicalUrl, &c_rgPropRead[PROP_TRACKING], &vProp, 1, TRUE);
  490. PropVariantClear( &vProp );
  491. }
  492. SAFELOCALFREE(lpPfxUrl);
  493. return hr;
  494. }
  495. //-----------------------------------------------------------------------------
  496. //
  497. // Process log related tags
  498. //
  499. //-----------------------------------------------------------------------------
  500. //
  501. // <LOGTARGET href="http://foo.htm" SCOPE="ALL"/>
  502. // <HTTP-EQUIV name="Encoding-type" value="gzip" />
  503. // <PurgeTime HOUR="12" />
  504. // </Logtarget>
  505. //
  506. HRESULT
  507. CUrlTrackingCache :: ProcessTrackingInLog
  508. (
  509. IXMLElement *pTracking
  510. )
  511. {
  512. HRESULT hr;
  513. LPWSTR pwszScope = NULL;
  514. if (_pwszPostUrl)
  515. return S_OK; // there are more than 1 logtarget, take whatever first was read
  516. hr = ReadAttribute(pTracking, L"HREF", &_pwszPostUrl); // must exist to enalbe logging
  517. if (FAILED(hr))
  518. return hr;
  519. // fill it in item for post agent
  520. WriteOLESTR(_pCDFStartItem, c_szTrackingPostURL, _pwszPostUrl);
  521. // #41460: add 2nd domain allowing tracking to
  522. DWORD cbLen = (lstrlenW(_pwszPostUrl)+1) * sizeof(WCHAR);
  523. _pszPostUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen);
  524. MyOleStrToStrN(_pszPostUrlSite, cbLen, _pwszPostUrl);
  525. *(FileFromPath( _pszPostUrlSite )) = 0;
  526. _ConnectionScope = TRACK_ONLINE_CACHE_ENTRY | TRACK_OFFLINE_CACHE_ENTRY;
  527. hr = ReadAttribute(pTracking, L"SCOPE", &pwszScope);
  528. if (SUCCEEDED(hr))
  529. {
  530. if (!StrCmpIW(pwszScope, L"OFFLINE"))
  531. _ConnectionScope = TRACK_OFFLINE_CACHE_ENTRY;
  532. else if (!StrCmpIW(pwszScope, L"ONLINE"))
  533. _ConnectionScope = TRACK_ONLINE_CACHE_ENTRY;
  534. SAFELOCALFREE(pwszScope);
  535. }
  536. RunChildElement(pTracking);
  537. // #42687: save purgetime to item and used later by post agent
  538. if (_pwszPurgeTime) // if not specify, default is 24 hours
  539. {
  540. _dwPurgeTime = WCTOI(_pwszPurgeTime);
  541. }
  542. DATE dt = 0.0;
  543. SYSTEMTIME st;
  544. GetLocalTime(&st);
  545. SystemTimeToVariantTime(&st, &dt);
  546. dt += ((DATE)_dwPurgeTime/24);
  547. #ifdef DEBUG
  548. VariantTimeToSystemTime(dt, &st);
  549. #endif
  550. WriteDATE(_pCDFStartItem, c_szPostPurgeTime, &dt);
  551. return S_OK;
  552. }
  553. //-----------------------------------------------------------------------------
  554. //
  555. // ProcessTrackingItems
  556. // <Item href="http://foo">
  557. // <Log value="document:view"/>
  558. // </Item>
  559. // or <Item>
  560. // <A href="http://foo" />
  561. // </Item>
  562. // This routine will setup tracking cache entries for all URLs which are
  563. // specified in CDF file to track. All URLs entries belong to same channel
  564. // are created in same cache group
  565. //-----------------------------------------------------------------------------
  566. HRESULT
  567. CUrlTrackingCache :: ProcessTrackingInItem
  568. (
  569. IXMLElement *pItem, //point to <Item> tag
  570. LPCWSTR pwszUrl, //absolute URL for item
  571. BOOL fForceLog //global log flag
  572. )
  573. {
  574. HRESULT hr = S_OK;
  575. _bTrackIt = fForceLog;
  576. if (!_bTrackIt)
  577. hr = RunChildElement(pItem);
  578. if (SUCCEEDED(hr) && _bTrackIt)
  579. hr = AddToTrackingCacheEntry(pwszUrl);
  580. return (_bTrackIt) ? S_OK : E_FAIL; // #42604: global logging, report if this item needs logged
  581. }
  582. HRESULT
  583. CUrlTrackingCache :: RunChildElement
  584. (
  585. IXMLElement* pElement
  586. )
  587. {
  588. IXMLElementCollection *pCollection;
  589. long lIndex = 0;
  590. long lMax;
  591. VARIANT vIndex, vEmpty;
  592. IDispatch *pDisp;
  593. IXMLElement *pItem;
  594. BSTR bstrTagName;
  595. HRESULT hr = E_FAIL;
  596. if (SUCCEEDED(pElement->get_children(&pCollection)) && pCollection)
  597. {
  598. if (SUCCEEDED(pCollection->get_length(&lMax)))
  599. {
  600. vEmpty.vt = VT_EMPTY;
  601. for (; lIndex < lMax; lIndex++)
  602. {
  603. vIndex.vt = VT_UI4;
  604. vIndex.lVal = lIndex;
  605. if (SUCCEEDED(pCollection->item(vIndex, vEmpty, &pDisp)))
  606. {
  607. if (SUCCEEDED(pDisp->QueryInterface(IID_IXMLElement, (void **)&pItem)))
  608. {
  609. if (SUCCEEDED(pItem->get_tagName(&bstrTagName)) && bstrTagName)
  610. {
  611. hr = ProcessItemInEnum(bstrTagName, pItem);
  612. SysFreeString(bstrTagName);
  613. }
  614. pItem->Release();
  615. }
  616. pDisp->Release();
  617. }
  618. }
  619. }
  620. pCollection->Release();
  621. }
  622. return hr;
  623. }
  624. HRESULT
  625. CUrlTrackingCache :: ProcessItemInEnum
  626. (
  627. LPCWSTR pwszTagName,
  628. IXMLElement *pItem
  629. )
  630. {
  631. HRESULT hr;
  632. LPWSTR pwszName = NULL;
  633. if (!StrCmpIW(pwszTagName, L"HTTP-EQUIV"))
  634. {
  635. DBG("CUrlTrackingCache processing HTTP-EQUIV");
  636. hr = ReadAttribute(pItem, L"NAME", &pwszName);
  637. if (SUCCEEDED(hr) && !StrCmpIW(pwszName, L"ENCODING-TYPE"))
  638. {
  639. hr = ReadAttribute(pItem, L"VALUE", &_pwszEncodingMethod);
  640. if (SUCCEEDED(hr) && *_pwszEncodingMethod)
  641. WriteOLESTR(_pCDFStartItem, c_szPostHeader, _pwszEncodingMethod);
  642. }
  643. SAFELOCALFREE(pwszName);
  644. }
  645. else if (!StrCmpIW(pwszTagName, L"PURGETIME"))
  646. {
  647. DBG("CUrlTrackingCache processing PurgeTime");
  648. return ReadAttribute(pItem, L"HOUR", &_pwszPurgeTime);
  649. }
  650. else if (!StrCmpIW(pwszTagName, L"LOG"))
  651. {
  652. DBG("CUrlTrackingCache processing Log");
  653. hr = ReadAttribute(pItem, L"VALUE", &pwszName);
  654. if (SUCCEEDED(hr))
  655. _bTrackIt = (!StrCmpIW(pwszName, L"document:view")) ? TRUE : FALSE;
  656. SAFELOCALFREE(pwszName);
  657. }
  658. return S_OK;
  659. }
  660. HRESULT
  661. CUrlTrackingCache :: ReadAttribute
  662. (
  663. IN IXMLElement* pItem,
  664. IN LPCWSTR pwszAttributeName,
  665. OUT LPWSTR* pwszAttributeValue
  666. )
  667. {
  668. VARIANT vProp;
  669. BSTR bstrName = NULL;
  670. HRESULT hr = E_FAIL;
  671. DWORD dwLen;
  672. vProp.vt = VT_EMPTY;
  673. bstrName = SysAllocString(pwszAttributeName);
  674. if (bstrName && SUCCEEDED(pItem->getAttribute(bstrName, &vProp)))
  675. {
  676. if (vProp.vt == VT_BSTR)
  677. {
  678. dwLen = sizeof(WCHAR) * (lstrlenW(vProp.bstrVal) + 1);
  679. *pwszAttributeValue = (LPWSTR)MemAlloc(LPTR, dwLen);
  680. if (*pwszAttributeValue)
  681. {
  682. StrCpyNW(*pwszAttributeValue, vProp.bstrVal, dwLen / sizeof(WCHAR));
  683. hr = S_OK;
  684. }
  685. VariantClear(&vProp);
  686. }
  687. }
  688. SysFreeString(bstrName);
  689. return hr;
  690. }
  691. //--------------------------------------------------------------------------
  692. //
  693. // CUrlTrackingCache
  694. //
  695. //--------------------------------------------------------------------------
  696. CUrlTrackingCache::CUrlTrackingCache
  697. (
  698. ISubscriptionItem *pCDFItem,
  699. LPCWSTR pwszURL
  700. )
  701. {
  702. _lpPfx = NULL;
  703. _dwPurgeTime = 24;
  704. _pCDFStartItem = pCDFItem;
  705. ASSERT(_pCDFStartItem);
  706. _pCDFStartItem->AddRef();
  707. Init(pwszURL);
  708. }
  709. CUrlTrackingCache::~CUrlTrackingCache()
  710. {
  711. SAFEFREEOLESTR(_pwszPostUrl);
  712. SAFEFREEOLESTR(_pwszEncodingMethod);
  713. SAFEFREEOLESTR(_pwszPurgeTime);
  714. SAFELOCALFREE(_pszChannelUrlSite);
  715. SAFELOCALFREE(_pszPostUrlSite);
  716. SAFELOCALFREE(_lpPfx);
  717. SAFERELEASE(_pCDFStartItem);
  718. }