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.

928 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(DWORD);
  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. StrCpy(_pszChannelUrlSite, TEXT("http://"));
  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. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  243. break;
  244. }
  245. }
  246. FindCloseUrlCache(hEnum);
  247. }
  248. if (!lpPfx)
  249. {
  250. LPTSTR pszCachePath = NULL;
  251. #ifdef LOG_CACHE_PATH
  252. TCHAR szCachePath[MAX_PATH];
  253. pszCachePath = (SUCCEEDED(GetCacheLocation(szCachePath, MAX_PATH))) ?
  254. szCachePath : NULL;
  255. #endif
  256. if (CreateUrlCacheContainer(c_szLogContainer,
  257. c_szLogPrefix,
  258. pszCachePath, // wininet bug:if NULL, will create under ..\History\Log //
  259. 8192, // dwCacheLimit,
  260. INTERNET_CACHE_CONTAINER_NOSUBDIRS, // dwContainerType,
  261. 0, // dwOptions,
  262. NULL, // pvBuffer,
  263. 0 // cbBuffer
  264. ))
  265. {
  266. return ReadTrackingPrefix();
  267. }
  268. // unable to create Log container, stop.
  269. }
  270. return lpPfx;
  271. }
  272. //-----------------------------------------------------------------------------
  273. //
  274. // ConvertToPrefixedUrl
  275. //
  276. // caller must release lplpPrefixedUrl
  277. //-----------------------------------------------------------------------------
  278. BOOL
  279. CUrlTrackingCache :: ConvertToPrefixedUrl
  280. (
  281. IN LPCTSTR lpUrl,
  282. IN LPTSTR* lplpPrefixedUrl
  283. )
  284. {
  285. BOOL bret = FALSE;
  286. ASSERT(lpUrl);
  287. if (!_lpPfx)
  288. _lpPfx = ReadTrackingPrefix();
  289. if (_lpPfx)
  290. {
  291. int len = lstrlen(lpUrl) + lstrlen(_lpPfx) + 1;
  292. *lplpPrefixedUrl = NULL;
  293. *lplpPrefixedUrl = (LPTSTR)MemAlloc(LPTR, len * sizeof(TCHAR));
  294. if (*lplpPrefixedUrl)
  295. {
  296. wnsprintf(*lplpPrefixedUrl, len, TEXT("%s%s"), _lpPfx, lpUrl);
  297. bret = TRUE;
  298. }
  299. else
  300. bret = FALSE;
  301. }
  302. return bret;
  303. }
  304. //-----------------------------------------------------------------------------
  305. //
  306. // RetrieveUrlCacheEntry
  307. //
  308. // caller must release lpCE
  309. //-----------------------------------------------------------------------------
  310. LPINTERNET_CACHE_ENTRY_INFO
  311. CUrlTrackingCache :: RetrieveUrlCacheEntry
  312. (
  313. IN LPCTSTR lpUrl
  314. )
  315. {
  316. LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
  317. DWORD cbSize;
  318. BOOL bret = FALSE;
  319. lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
  320. if (lpCE)
  321. {
  322. cbSize = MY_MAX_CACHE_ENTRY_INFO;
  323. while ((bret = GetUrlCacheEntryInfo(lpUrl, lpCE, &cbSize)) != TRUE)
  324. {
  325. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  326. {
  327. SAFELOCALFREE(lpCE);
  328. lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, cbSize);
  329. if (!lpCE)
  330. break;
  331. }
  332. else
  333. break;
  334. }
  335. }
  336. if (!bret && lpCE)
  337. {
  338. SAFELOCALFREE(lpCE);
  339. SetLastError(ERROR_FILE_NOT_FOUND);
  340. }
  341. return lpCE;
  342. }
  343. #define FILETIME_SEC 100000000
  344. #define SECS_PER_DAY (60 * 60 * 24)
  345. DWORD WCTOI(LPCWSTR pwstr)
  346. {
  347. DWORD dw;
  348. int len = lstrlenW(pwstr);
  349. dw = 0;
  350. for (int i = 0; i<len; i++)
  351. {
  352. if (!IsNumber(pwstr[i]))
  353. break;
  354. dw = dw * 10 + (pwstr[i] - L'0');
  355. }
  356. if (dw == 0) dw = 24;
  357. return dw;
  358. }
  359. //-----------------------------------------------------------------------------
  360. //
  361. // CreatePrefixedCacheEntry
  362. //
  363. // Create cache entry in Tracking cache bucket
  364. //-----------------------------------------------------------------------------
  365. #ifdef NO_FILE_WHEN_CREATE
  366. HRESULT CreateLogCacheEntry
  367. (
  368. LPCTSTR lpPfxUrl,
  369. FILETIME ftExpire,
  370. FILETIME ftModified,
  371. DWORD CacheEntryType
  372. )
  373. {
  374. TCHAR lpFile[MAX_PATH];
  375. BOOL bret;
  376. HRESULT hr = E_FAIL;
  377. if (CreateUrlCacheEntry(lpPfxUrl, MY_CACHE_FILE_ENTRY_SIZE, c_szExt, lpFile, 0))
  378. {
  379. lpFile[0] = '\0';
  380. bret = CommitUrlCacheEntry(lpPfxUrl,
  381. lpFile,
  382. ftExpire,
  383. ftModified,
  384. CacheEntryType,
  385. NULL,
  386. 0,
  387. NULL,
  388. 0);
  389. hr = bret ? S_OK : E_FAIL;
  390. }
  391. return hr;
  392. }
  393. #else
  394. HRESULT CreateLogCacheEntry
  395. (
  396. LPCTSTR lpPfxUrl,
  397. FILETIME ftExpire,
  398. FILETIME ftModified,
  399. DWORD CacheEntryType
  400. )
  401. {
  402. TCHAR lpFile[MAX_PATH];
  403. HRESULT hr = E_FAIL;
  404. DWORD cbSize;
  405. if (CreateUrlCacheEntry(lpPfxUrl, MY_CACHE_FILE_ENTRY_SIZE, c_szExt, lpFile, 0))
  406. {
  407. HANDLE hFile = CreateFile(lpFile,
  408. GENERIC_READ|GENERIC_WRITE,
  409. FILE_SHARE_READ,
  410. NULL,
  411. CREATE_ALWAYS,
  412. FILE_ATTRIBUTE_NORMAL,
  413. NULL);
  414. if (hFile == INVALID_HANDLE_VALUE)
  415. return hr;
  416. // note: wininet will not create the entry if file size equals to zero
  417. // WriteFile(hFile, c_szLogFields, g_ccLogFields, &cbSize, NULL);
  418. WriteFile(hFile, c_szEmptyLog, c_ccEmptyLog, &cbSize, NULL);
  419. CloseHandle(hFile);
  420. return (CommitUrlCacheEntry(lpPfxUrl,
  421. lpFile,
  422. ftExpire,
  423. ftModified,
  424. CacheEntryType,
  425. NULL,
  426. 0,
  427. NULL,
  428. 0)) ? S_OK : E_FAIL;
  429. }
  430. return hr;
  431. }
  432. #endif
  433. HRESULT
  434. CUrlTrackingCache :: CreatePrefixedCacheEntry
  435. (
  436. IN LPCTSTR lpPfxUrl
  437. )
  438. {
  439. HRESULT hr = E_FAIL;
  440. LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
  441. FILETIME ftModified;
  442. // IE50: due to change to wininet cache group enumeration, now we save our filter
  443. // information _groupId along with each cache entry itself. the wininet url cache
  444. // no longer maintain this for us
  445. ftModified.dwHighDateTime = (DWORD)(_groupId >> 32);
  446. ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & _groupId);
  447. lpCE = RetrieveUrlCacheEntry(lpPfxUrl);
  448. if (lpCE )
  449. {
  450. // exist in Tracking bucket, set tracking flag
  451. // IE50: save _groupId info in LastModifiedTime
  452. lpCE->CacheEntryType |= _ConnectionScope;
  453. lpCE->LastModifiedTime.dwHighDateTime = ftModified.dwHighDateTime;
  454. lpCE->LastModifiedTime.dwLowDateTime = ftModified.dwLowDateTime;
  455. ASSERT(SetUrlCacheEntryInfo(lpCE->lpszSourceUrlName, lpCE,
  456. CACHE_ENTRY_ATTRIBUTE_FC | CACHE_ENTRY_MODTIME_FC) == TRUE);
  457. hr = S_OK;
  458. }
  459. else
  460. //FILE_NOT_FOUND, create it.
  461. {
  462. LONGLONG llExpireHorizon;
  463. SYSTEMTIME st;
  464. FILETIME ftMod, ftExpire;
  465. llExpireHorizon = (LONGLONG)(SECS_PER_DAY * _dwPurgeTime / 24);
  466. GetLocalTime(&st);
  467. SystemTimeToFileTime(&st, &ftMod);
  468. llExpireHorizon *= FILETIME_SEC;
  469. ftExpire.dwLowDateTime = ftMod.dwLowDateTime + (DWORD)(llExpireHorizon % 0xFFFFFFFF);
  470. ftExpire.dwHighDateTime = ftMod.dwHighDateTime + (DWORD)(llExpireHorizon / 0xFFFFFFFF);
  471. hr = CreateLogCacheEntry(lpPfxUrl, ftExpire, ftModified, _ConnectionScope);
  472. }
  473. SAFELOCALFREE(lpCE);
  474. return hr;
  475. }
  476. HRESULT
  477. CUrlTrackingCache :: AddToTrackingCacheEntry
  478. (
  479. IN LPCWSTR pwszUrl
  480. )
  481. {
  482. HRESULT hr = E_OUTOFMEMORY;
  483. TCHAR szCanonicalUrl[MAX_URL];
  484. DWORD dwSize = MAX_URL;
  485. LPTSTR lpUrl = NULL;
  486. LPTSTR lpPfxUrl = NULL;
  487. DWORD cbSize;
  488. PROPVARIANT vProp = {0};
  489. if (pwszUrl == NULL)
  490. return E_INVALIDARG;
  491. cbSize = lstrlenW(pwszUrl) + 1;
  492. lpUrl = (LPTSTR)MemAlloc(LPTR, cbSize * sizeof(TCHAR));
  493. if (!lpUrl)
  494. return hr;
  495. SHUnicodeToTChar(pwszUrl, lpUrl, cbSize);
  496. if (!IsValidURL(lpUrl))
  497. {
  498. MemFree(lpUrl);
  499. return E_INVALIDARG;
  500. }
  501. // canonicalize URL
  502. InternetCanonicalizeUrl(lpUrl, szCanonicalUrl, &dwSize, ICU_DECODE);
  503. SAFELOCALFREE(lpUrl);
  504. ConvertToPrefixedUrl(szCanonicalUrl, &lpPfxUrl);
  505. if (!lpPfxUrl)
  506. {
  507. return hr;
  508. }
  509. hr = CreatePrefixedCacheEntry(lpPfxUrl);
  510. if (SUCCEEDED(hr))
  511. {
  512. // exist in Tracking bucket, set tracking flag.
  513. vProp.vt = VT_UI4;
  514. vProp.ulVal = _ConnectionScope;
  515. hr = IntSiteHelper(szCanonicalUrl, &c_rgPropRead[PROP_TRACKING], &vProp, 1, TRUE);
  516. PropVariantClear( &vProp );
  517. }
  518. SAFELOCALFREE(lpPfxUrl);
  519. return hr;
  520. }
  521. //-----------------------------------------------------------------------------
  522. //
  523. // SchedulePostAgent
  524. //
  525. // This routine will schedule post agent to upload tracking data
  526. //-----------------------------------------------------------------------------
  527. HRESULT
  528. CUrlTrackingCache :: SchedulePostAgent(void)
  529. {
  530. return E_NOTIMPL;
  531. }
  532. //-----------------------------------------------------------------------------
  533. //
  534. // OnProcessDone
  535. //
  536. //-----------------------------------------------------------------------------
  537. // called by CDF agent
  538. // fill information in item that Post agent would need to work
  539. HRESULT
  540. CUrlTrackingCache :: OnProcessDone
  541. (
  542. )
  543. {
  544. return E_NOTIMPL;
  545. }
  546. //-----------------------------------------------------------------------------
  547. //
  548. // Process log related tags
  549. //
  550. //-----------------------------------------------------------------------------
  551. //
  552. // <LOGTARGET href="http://foo.htm" SCOPE="ALL"/>
  553. // <HTTP-EQUIV name="Encoding-type" value="gzip" />
  554. // <PurgeTime HOUR="12" />
  555. // </Logtarget>
  556. //
  557. HRESULT
  558. CUrlTrackingCache :: ProcessTrackingInLog
  559. (
  560. IXMLElement *pTracking
  561. )
  562. {
  563. HRESULT hr;
  564. LPWSTR pwszScope = NULL;
  565. if (_pwszPostUrl)
  566. return S_OK; // there are more than 1 logtarget, take whatever first was read
  567. hr = ReadAttribute(pTracking, L"HREF", &_pwszPostUrl); // must exist to enalbe logging
  568. if (FAILED(hr))
  569. return hr;
  570. // fill it in item for post agent
  571. WriteOLESTR(_pCDFStartItem, c_szTrackingPostURL, _pwszPostUrl);
  572. // #41460: add 2nd domain allowing tracking to
  573. DWORD cbLen = (lstrlenW(_pwszPostUrl)+1) * sizeof(WCHAR);
  574. _pszPostUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen);
  575. MyOleStrToStrN(_pszPostUrlSite, cbLen, _pwszPostUrl);
  576. *(FileFromPath( _pszPostUrlSite )) = 0;
  577. _ConnectionScope = TRACK_ONLINE_CACHE_ENTRY | TRACK_OFFLINE_CACHE_ENTRY;
  578. hr = ReadAttribute(pTracking, L"SCOPE", &pwszScope);
  579. if (SUCCEEDED(hr))
  580. {
  581. if (!StrCmpIW(pwszScope, L"OFFLINE"))
  582. _ConnectionScope = TRACK_OFFLINE_CACHE_ENTRY;
  583. else if (!StrCmpIW(pwszScope, L"ONLINE"))
  584. _ConnectionScope = TRACK_ONLINE_CACHE_ENTRY;
  585. SAFELOCALFREE(pwszScope);
  586. }
  587. RunChildElement(pTracking);
  588. // #42687: save purgetime to item and used later by post agent
  589. if (_pwszPurgeTime) // if not specify, default is 24 hours
  590. {
  591. _dwPurgeTime = WCTOI(_pwszPurgeTime);
  592. }
  593. DATE dt = 0.0;
  594. SYSTEMTIME st;
  595. GetLocalTime(&st);
  596. SystemTimeToVariantTime(&st, &dt);
  597. dt += ((DATE)_dwPurgeTime/24);
  598. #ifdef DEBUG
  599. VariantTimeToSystemTime(dt, &st);
  600. #endif
  601. WriteDATE(_pCDFStartItem, c_szPostPurgeTime, &dt);
  602. return S_OK;
  603. }
  604. //-----------------------------------------------------------------------------
  605. //
  606. // ProcessTrackingItems
  607. // <Item href="http://foo">
  608. // <Log value="document:view"/>
  609. // </Item>
  610. // or <Item>
  611. // <A href="http://foo" />
  612. // </Item>
  613. // This routine will setup tracking cache entries for all URLs which are
  614. // specified in CDF file to track. All URLs entries belong to same channel
  615. // are created in same cache group
  616. //-----------------------------------------------------------------------------
  617. HRESULT
  618. CUrlTrackingCache :: ProcessTrackingInItem
  619. (
  620. IXMLElement *pItem, //point to <Item> tag
  621. LPCWSTR pwszUrl, //absolute URL for item
  622. BOOL fForceLog //global log flag
  623. )
  624. {
  625. HRESULT hr = S_OK;
  626. _bTrackIt = fForceLog;
  627. if (!_bTrackIt)
  628. hr = RunChildElement(pItem);
  629. if (SUCCEEDED(hr) && _bTrackIt)
  630. hr = AddToTrackingCacheEntry(pwszUrl);
  631. return (_bTrackIt) ? S_OK : E_FAIL; // #42604: global logging, report if this item needs logged
  632. }
  633. HRESULT
  634. CUrlTrackingCache :: RunChildElement
  635. (
  636. IXMLElement* pElement
  637. )
  638. {
  639. IXMLElementCollection *pCollection;
  640. long lIndex = 0;
  641. long lMax;
  642. VARIANT vIndex, vEmpty;
  643. IDispatch *pDisp;
  644. IXMLElement *pItem;
  645. BSTR bstrTagName;
  646. HRESULT hr = E_FAIL;
  647. if (SUCCEEDED(pElement->get_children(&pCollection)) && pCollection)
  648. {
  649. if (SUCCEEDED(pCollection->get_length(&lMax)))
  650. {
  651. vEmpty.vt = VT_EMPTY;
  652. for (; lIndex < lMax; lIndex++)
  653. {
  654. vIndex.vt = VT_UI4;
  655. vIndex.lVal = lIndex;
  656. if (SUCCEEDED(pCollection->item(vIndex, vEmpty, &pDisp)))
  657. {
  658. if (SUCCEEDED(pDisp->QueryInterface(IID_IXMLElement, (void **)&pItem)))
  659. {
  660. if (SUCCEEDED(pItem->get_tagName(&bstrTagName)) && bstrTagName)
  661. {
  662. hr = ProcessItemInEnum(bstrTagName, pItem);
  663. SysFreeString(bstrTagName);
  664. }
  665. pItem->Release();
  666. }
  667. pDisp->Release();
  668. }
  669. }
  670. }
  671. pCollection->Release();
  672. }
  673. return hr;
  674. }
  675. HRESULT
  676. CUrlTrackingCache :: ProcessItemInEnum
  677. (
  678. LPCWSTR pwszTagName,
  679. IXMLElement *pItem
  680. )
  681. {
  682. HRESULT hr;
  683. LPWSTR pwszName = NULL;
  684. if (!StrCmpIW(pwszTagName, L"HTTP-EQUIV"))
  685. {
  686. DBG("CUrlTrackingCache processing HTTP-EQUIV");
  687. hr = ReadAttribute(pItem, L"NAME", &pwszName);
  688. if (SUCCEEDED(hr) && !StrCmpIW(pwszName, L"ENCODING-TYPE"))
  689. {
  690. hr = ReadAttribute(pItem, L"VALUE", &_pwszEncodingMethod);
  691. if (SUCCEEDED(hr) && *_pwszEncodingMethod)
  692. WriteOLESTR(_pCDFStartItem, c_szPostHeader, _pwszEncodingMethod);
  693. }
  694. SAFELOCALFREE(pwszName);
  695. }
  696. else if (!StrCmpIW(pwszTagName, L"PURGETIME"))
  697. {
  698. DBG("CUrlTrackingCache processing PurgeTime");
  699. return ReadAttribute(pItem, L"HOUR", &_pwszPurgeTime);
  700. }
  701. else if (!StrCmpIW(pwszTagName, L"LOG"))
  702. {
  703. DBG("CUrlTrackingCache processing Log");
  704. hr = ReadAttribute(pItem, L"VALUE", &pwszName);
  705. if (SUCCEEDED(hr))
  706. _bTrackIt = (!StrCmpIW(pwszName, L"document:view")) ? TRUE : FALSE;
  707. SAFELOCALFREE(pwszName);
  708. }
  709. return S_OK;
  710. }
  711. HRESULT
  712. CUrlTrackingCache :: ReadAttribute
  713. (
  714. IN IXMLElement* pItem,
  715. IN LPCWSTR pwszAttributeName,
  716. OUT LPWSTR* pwszAttributeValue
  717. )
  718. {
  719. VARIANT vProp;
  720. BSTR bstrName = NULL;
  721. HRESULT hr = E_FAIL;
  722. DWORD dwLen;
  723. vProp.vt = VT_EMPTY;
  724. bstrName = SysAllocString(pwszAttributeName);
  725. if (bstrName && SUCCEEDED(pItem->getAttribute(bstrName, &vProp)))
  726. {
  727. if (vProp.vt == VT_BSTR)
  728. {
  729. dwLen = sizeof(WCHAR) * (lstrlenW(vProp.bstrVal) + 1);
  730. *pwszAttributeValue = (LPWSTR)MemAlloc(LPTR, dwLen);
  731. if (*pwszAttributeValue)
  732. {
  733. StrCpyW(*pwszAttributeValue, vProp.bstrVal);
  734. hr = S_OK;
  735. }
  736. VariantClear(&vProp);
  737. }
  738. }
  739. SysFreeString(bstrName);
  740. return hr;
  741. }
  742. //--------------------------------------------------------------------------
  743. //
  744. // CUrlTrackingCache
  745. //
  746. //--------------------------------------------------------------------------
  747. CUrlTrackingCache::CUrlTrackingCache
  748. (
  749. ISubscriptionItem *pCDFItem,
  750. LPCWSTR pwszURL
  751. )
  752. {
  753. _lpPfx = NULL;
  754. _dwPurgeTime = 24;
  755. _pCDFStartItem = pCDFItem;
  756. ASSERT(_pCDFStartItem);
  757. _pCDFStartItem->AddRef();
  758. Init(pwszURL);
  759. }
  760. CUrlTrackingCache::~CUrlTrackingCache()
  761. {
  762. SAFEFREEOLESTR(_pwszPostUrl);
  763. SAFEFREEOLESTR(_pwszEncodingMethod);
  764. SAFEFREEOLESTR(_pwszPurgeTime);
  765. SAFELOCALFREE(_pszChannelUrlSite);
  766. SAFELOCALFREE(_pszPostUrlSite);
  767. SAFELOCALFREE(_lpPfx);
  768. SAFERELEASE(_pCDFStartItem);
  769. }