|
|
//
// Pei-Hwa Lin (peiwhal), Feb 3, 1997
//
// Notes:
// Compile switch : NO_FILE_WHEN_CREATE can turn on when wininet cache
// would create url cache entry if attached file is empty.
// LOG_CACHE_PATH will create log cache at the same level as
// content cache.
#include "private.h"
#undef TF_THISMODULE
#define TF_THISMODULE TF_TRACKCACHE
#define MY_CACHE_FILE_ENTRY_SIZE 2048
const TCHAR c_szExt[] = TEXT("log");
//used for creating tracking container (registry)
const TCHAR c_szLogContainer[] = TEXT("Log"); // if you modify this, modify iedev\inc\inetreg.h REGSTR_PATH_TRACKING too.
const TCHAR c_szLogPrefix[] = TEXT("Log:");
const char c_szLogContainerA[] = "Log";
// helper function
inline BOOL IsNumber(WCHAR x) { return (x >= L'0' && x <= L'9'); }
/*=============================================================================
FILEFROMPATH returns the filename of given filename which may include path. =============================================================================*/ LPTSTR FileFromPath( LPCTSTR lpsz ) { LPTSTR lpch;
/* Strip path/drive specification from name if there is one */ lpch = CharPrev( lpsz, lpsz + lstrlen(lpsz) );
// special case for "http://server/domain/channel.cdf/"
if (*lpch == '/') lpch = CharPrev( lpsz, lpch);
while (lpch > lpsz) { if (*lpch == '/') { lpch = CharNext(lpch); break; } lpch = CharPrev( lpsz, lpch); } return(lpch);
} /* end FileFromPath */
// CDF updates, create new group and deal with previous posting information
void CUrlTrackingCache :: Init(LPCWSTR pwszURL) { DWORD dwRetry; BSTR bstrEncoding = NULL;
_groupId = 0; _pwszPostUrl = NULL; _pszChannelUrlSite = NULL; _pszPostUrlSite = NULL; _pwszEncodingMethod = NULL; _groupId = CreateUrlCacheGroup(CACHEGROUP_FLAG_GIDONLY, NULL);
WriteLONGLONG(_pCDFStartItem, c_szTrackingCookie, _groupId);
// #54653: remove previous tracking information, if any
if (SUCCEEDED(ReadBSTR(_pCDFStartItem, c_szPostHeader, &bstrEncoding))) { WriteEMPTY(_pCDFStartItem, c_szPostHeader); SAFEFREEBSTR(bstrEncoding); }
if (SUCCEEDED(ReadDWORD(_pCDFStartItem, c_szPostingRetry, &dwRetry))) WriteEMPTY(_pCDFStartItem, c_szPostingRetry);
DoBaseURL(pwszURL); return; }
void CUrlTrackingCache :: DoBaseURL(LPCWSTR pwszURL) { DWORD cbLen; DWORD useSecurity = 1;
ASSERT(!_pszChannelUrlSite)
cbLen = (lstrlenW(pwszURL)+1) * sizeof(WCHAR); _pszChannelUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen);
#ifdef DEBUG
HKEY hkey;
// provide security switch for debugging
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, MY_WEBCHECK_POST_REG, 0, KEY_READ, &hkey)) { DWORD cbsize = sizeof(useSecurity); if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("PostSecurity"), NULL, NULL, (LPBYTE)&useSecurity, &cbsize)) { if ((useSecurity == 0) && (NULL != _pszChannelUrlSite)) StrCpyN(_pszChannelUrlSite, TEXT("http://"), cbLen / sizeof(WCHAR)); } }
#endif
if ((useSecurity == 1) && (NULL != _pszChannelUrlSite)) { MyOleStrToStrN(_pszChannelUrlSite, cbLen, pwszURL); *(FileFromPath( _pszChannelUrlSite )) = 0; } return; }
// only track URLs come from the same server of Channel CDF or LogTarget URL
//
BOOL CUrlTrackingCache :: IsValidURL(LPCTSTR lpszURL) { BOOL bret;
if (!_pszChannelUrlSite || !_pszPostUrlSite) return FALSE; if (!StrCmpNI(lpszURL, _pszChannelUrlSite, lstrlen(_pszChannelUrlSite))) bret = TRUE; else if (!StrCmpNI(lpszURL, _pszPostUrlSite, lstrlen(_pszPostUrlSite))) bret = TRUE; else bret = FALSE;
return bret; }
#define LOG_CACHE_PATH
#ifdef LOG_CACHE_PATH
LPSTR PathPreviousBackslashA(LPSTR psz) { LPSTR lpch = CharPrevA(psz, psz + lstrlenA(psz)); for (; *lpch && *lpch != '\\'; lpch=CharPrevA(psz,lpch)); return lpch; }
//------------------------------------------------------------------------------
// GetCacheLocation
//
// Purpose: Return the location of the logging cache
// ***** GetUrlCacheConfigInfoW is yet implemented in wininet
//------------------------------------------------------------------------------
//
HRESULT GetCacheLocation ( LPTSTR pszCacheLocation, DWORD dwSize // no. of chars in pszCacheLocation
) { HRESULT hr = S_OK; DWORD dwLastErr; LPINTERNET_CACHE_CONFIG_INFOA lpCCI = NULL; DWORD dwCCISize = sizeof(INTERNET_CACHE_CONFIG_INFOA); BOOL fOnceErrored = FALSE;
while (TRUE) { if ((lpCCI = (LPINTERNET_CACHE_CONFIG_INFOA)MemAlloc(LPTR, dwCCISize)) == NULL) { hr = E_OUTOFMEMORY; goto cleanup; }
if (!GetUrlCacheConfigInfoA(lpCCI, &dwCCISize, CACHE_CONFIG_CONTENT_PATHS_FC)) { if ((dwLastErr = GetLastError()) != ERROR_INSUFFICIENT_BUFFER || fOnceErrored) { hr = HRESULT_FROM_WIN32(dwLastErr); goto cleanup; }
//
// We have insufficient buffer size; reallocate a buffer with the
// new dwCCISize set by GetUrlCacheConfigInfo
// Set fOnceErrored to TRUE so that we don't loop indefinitely
//
fOnceErrored = TRUE; } else { //
LPSTR pszPath = lpCCI->CachePaths[0].CachePath; INT iLen;
PathRemoveBackslashA(pszPath); *(PathPreviousBackslashA(pszPath)) = 0; iLen = lstrlenA(pszPath) + sizeof(CHAR); // + 1 is for the null char
if ((((DWORD) iLen + ARRAYSIZE(c_szLogContainer) + 1) * sizeof(TCHAR)) < dwSize) { TCHAR szPathT[MAX_PATH];
SHAnsiToTChar(pszPath, szPathT, ARRAYSIZE(szPathT)); wnsprintf(pszCacheLocation, dwSize, TEXT("%s\\%s"), szPathT, c_szLogContainer); } else { hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); }
break; }
SAFELOCALFREE(lpCCI); lpCCI = NULL; }
cleanup: if (lpCCI != NULL) { LocalFree(lpCCI); }
return hr; } #endif
//-----------------------------------------------------------------------------
//
// ReadTrackingPrefix
//
// will create tracking container if current profile doesn't have one
// **** FindFirstUrlCacheContainerW is yet implemented in wininet
// **** FindNextUrlCacheContainerW is yet implemented either
//-----------------------------------------------------------------------------
LPTSTR ReadTrackingPrefix(void) { LPTSTR lpPfx = NULL;
DWORD cbPfx = 0; struct { INTERNET_CACHE_CONTAINER_INFOA cInfo; CHAR szBuffer[MAX_PATH+INTERNET_MAX_URL_LENGTH+1]; } ContainerInfo; DWORD dwModified, dwContainer; HANDLE hEnum; dwContainer = sizeof(ContainerInfo); hEnum = FindFirstUrlCacheContainerA(&dwModified, &ContainerInfo.cInfo, &dwContainer, 0);
if (hEnum) {
for (;;) { if (!StrCmpIA(ContainerInfo.cInfo.lpszName, c_szLogContainerA)) { ASSERT(ContainerInfo.cInfo.lpszCachePrefix[0]);
CHAR szPfx[MAX_PATH]; DWORD cch = ARRAYSIZE(ContainerInfo.cInfo.lpszCachePrefix)+sizeof(CHAR); StrCpyNA(szPfx, ContainerInfo.cInfo.lpszCachePrefix, cch);
cch *= sizeof(TCHAR); lpPfx = (LPTSTR)MemAlloc(LPTR, cch); if (!lpPfx) SetLastError(ERROR_OUTOFMEMORY);
SHAnsiToTChar(szPfx, lpPfx, cch); break; }
dwContainer = sizeof(ContainerInfo); if (!FindNextUrlCacheContainerA(hEnum, &ContainerInfo.cInfo, &dwContainer)) { // This code used to check GetLastError() for ERROR_NO_MORE_ITEMS before
// it would break. Well, that could put us in an infinite loop if the
// reason for failure were something else (like insufficient buffer) because
// wininet would not move forward in it's enumeration and we would not
// have done anything to address the error.
break; }
}
FindCloseUrlCache(hEnum); }
if (!lpPfx) { LPTSTR pszCachePath = NULL; #ifdef LOG_CACHE_PATH
TCHAR szCachePath[MAX_PATH];
pszCachePath = (SUCCEEDED(GetCacheLocation(szCachePath, MAX_PATH))) ? szCachePath : NULL; #endif
if (CreateUrlCacheContainer(c_szLogContainer, c_szLogPrefix, pszCachePath, // wininet bug:if NULL, will create under ..\History\Log //
8192, // dwCacheLimit,
INTERNET_CACHE_CONTAINER_NOSUBDIRS, // dwContainerType,
0, // dwOptions,
NULL, // pvBuffer,
0 // cbBuffer
)) { return ReadTrackingPrefix(); } // unable to create Log container, stop.
} return lpPfx; }
//-----------------------------------------------------------------------------
//
// ConvertToPrefixedUrl
//
// caller must release lplpPrefixedUrl
//-----------------------------------------------------------------------------
BOOL CUrlTrackingCache :: ConvertToPrefixedUrl ( IN LPCTSTR lpUrl, IN LPTSTR* lplpPrefixedUrl ) { BOOL bret = FALSE;
ASSERT(lpUrl); if (!_lpPfx) _lpPfx = ReadTrackingPrefix();
if (_lpPfx) { int len = lstrlen(lpUrl) + lstrlen(_lpPfx) + 1; *lplpPrefixedUrl = NULL; *lplpPrefixedUrl = (LPTSTR)MemAlloc(LPTR, len * sizeof(TCHAR)); if (*lplpPrefixedUrl) { wnsprintf(*lplpPrefixedUrl, len, TEXT("%s%s"), _lpPfx, lpUrl); bret = TRUE; } else bret = FALSE; }
return bret; }
//-----------------------------------------------------------------------------
//
// RetrieveUrlCacheEntry
//
// caller must release lpCE
//-----------------------------------------------------------------------------
LPINTERNET_CACHE_ENTRY_INFO CUrlTrackingCache :: RetrieveUrlCacheEntry ( IN LPCTSTR lpUrl ) { LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL; DWORD cbSize; BOOL bret = FALSE;
lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO); if (lpCE) { cbSize = MY_MAX_CACHE_ENTRY_INFO; while ((bret = GetUrlCacheEntryInfo(lpUrl, lpCE, &cbSize)) != TRUE) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { SAFELOCALFREE(lpCE);
lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, cbSize); if (!lpCE) break; } else break; } }
if (!bret && lpCE) { SAFELOCALFREE(lpCE); SetLastError(ERROR_FILE_NOT_FOUND); }
return lpCE; }
#define FILETIME_SEC 100000000
#define SECS_PER_DAY (60 * 60 * 24)
DWORD WCTOI(LPCWSTR pwstr) { DWORD dw; int len = lstrlenW(pwstr);
dw = 0; for (int i = 0; i<len; i++) { if (!IsNumber(pwstr[i])) break;
dw = dw * 10 + (pwstr[i] - L'0'); }
if (dw == 0) dw = 24; return dw; }
//-----------------------------------------------------------------------------
//
// CreatePrefixedCacheEntry
//
// Create cache entry in Tracking cache bucket
//-----------------------------------------------------------------------------
HRESULT CreateLogCacheEntry ( LPCTSTR lpPfxUrl, FILETIME ftExpire, FILETIME ftModified, DWORD CacheEntryType ) { TCHAR lpFile[MAX_PATH]; HRESULT hr = E_FAIL; DWORD cbSize;
if (CreateUrlCacheEntry(lpPfxUrl, MY_CACHE_FILE_ENTRY_SIZE, c_szExt, lpFile, 0)) { HANDLE hFile = CreateFile(lpFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return hr; // note: wininet will not create the entry if file size equals to zero
// WriteFile(hFile, c_szLogFields, g_ccLogFields, &cbSize, NULL);
WriteFile(hFile, c_szEmptyLog, c_ccEmptyLog, &cbSize, NULL); CloseHandle(hFile);
return (CommitUrlCacheEntry(lpPfxUrl, lpFile, ftExpire, ftModified, CacheEntryType, NULL, 0, NULL, 0)) ? S_OK : E_FAIL; }
return hr; }
HRESULT CUrlTrackingCache :: CreatePrefixedCacheEntry ( IN LPCTSTR lpPfxUrl ) { HRESULT hr = E_FAIL; LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL; FILETIME ftModified;
// IE50: due to change to wininet cache group enumeration, now we save our filter
// information _groupId along with each cache entry itself. the wininet url cache
// no longer maintain this for us
ftModified.dwHighDateTime = (DWORD)(_groupId >> 32); ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & _groupId);
lpCE = RetrieveUrlCacheEntry(lpPfxUrl); if (lpCE ) { // exist in Tracking bucket, set tracking flag
// IE50: save _groupId info in LastModifiedTime
lpCE->CacheEntryType |= _ConnectionScope; lpCE->LastModifiedTime.dwHighDateTime = ftModified.dwHighDateTime; lpCE->LastModifiedTime.dwLowDateTime = ftModified.dwLowDateTime;
ASSERT(SetUrlCacheEntryInfo(lpCE->lpszSourceUrlName, lpCE, CACHE_ENTRY_ATTRIBUTE_FC | CACHE_ENTRY_MODTIME_FC) == TRUE); hr = S_OK; } else //FILE_NOT_FOUND, create it.
{ LONGLONG llExpireHorizon; SYSTEMTIME st; FILETIME ftMod, ftExpire;
llExpireHorizon = (LONGLONG)(SECS_PER_DAY * _dwPurgeTime / 24);
GetLocalTime(&st); SystemTimeToFileTime(&st, &ftMod);
llExpireHorizon *= FILETIME_SEC; ftExpire.dwLowDateTime = ftMod.dwLowDateTime + (DWORD)(llExpireHorizon % 0xFFFFFFFF); ftExpire.dwHighDateTime = ftMod.dwHighDateTime + (DWORD)(llExpireHorizon / 0xFFFFFFFF);
hr = CreateLogCacheEntry(lpPfxUrl, ftExpire, ftModified, _ConnectionScope);
} SAFELOCALFREE(lpCE);
return hr; }
HRESULT CUrlTrackingCache :: AddToTrackingCacheEntry ( IN LPCWSTR pwszUrl ) { HRESULT hr = E_OUTOFMEMORY; TCHAR szCanonicalUrl[MAX_URL]; DWORD dwSize = MAX_URL; LPTSTR lpUrl = NULL; LPTSTR lpPfxUrl = NULL; DWORD cbSize; PROPVARIANT vProp = {0};
if (pwszUrl == NULL) return E_INVALIDARG;
cbSize = lstrlenW(pwszUrl) + 1; lpUrl = (LPTSTR)MemAlloc(LPTR, cbSize * sizeof(TCHAR)); if (!lpUrl) return hr;
SHUnicodeToTChar(pwszUrl, lpUrl, cbSize); if (!IsValidURL(lpUrl)) { MemFree(lpUrl); return E_INVALIDARG; }
// canonicalize URL
InternetCanonicalizeUrl(lpUrl, szCanonicalUrl, &dwSize, ICU_DECODE); SAFELOCALFREE(lpUrl); ConvertToPrefixedUrl(szCanonicalUrl, &lpPfxUrl); if (!lpPfxUrl) { return hr; }
hr = CreatePrefixedCacheEntry(lpPfxUrl); if (SUCCEEDED(hr)) { // exist in Tracking bucket, set tracking flag.
vProp.vt = VT_UI4; vProp.ulVal = _ConnectionScope; hr = IntSiteHelper(szCanonicalUrl, &c_rgPropRead[PROP_TRACKING], &vProp, 1, TRUE); PropVariantClear( &vProp ); }
SAFELOCALFREE(lpPfxUrl); return hr; }
//-----------------------------------------------------------------------------
//
// Process log related tags
//
//-----------------------------------------------------------------------------
//
// <LOGTARGET href="http://foo.htm" SCOPE="ALL"/>
// <HTTP-EQUIV name="Encoding-type" value="gzip" />
// <PurgeTime HOUR="12" />
// </Logtarget>
//
HRESULT CUrlTrackingCache :: ProcessTrackingInLog ( IXMLElement *pTracking ) {
HRESULT hr; LPWSTR pwszScope = NULL; if (_pwszPostUrl) return S_OK; // there are more than 1 logtarget, take whatever first was read
hr = ReadAttribute(pTracking, L"HREF", &_pwszPostUrl); // must exist to enalbe logging
if (FAILED(hr)) return hr;
// fill it in item for post agent
WriteOLESTR(_pCDFStartItem, c_szTrackingPostURL, _pwszPostUrl);
// #41460: add 2nd domain allowing tracking to
DWORD cbLen = (lstrlenW(_pwszPostUrl)+1) * sizeof(WCHAR); _pszPostUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen); MyOleStrToStrN(_pszPostUrlSite, cbLen, _pwszPostUrl); *(FileFromPath( _pszPostUrlSite )) = 0;
_ConnectionScope = TRACK_ONLINE_CACHE_ENTRY | TRACK_OFFLINE_CACHE_ENTRY; hr = ReadAttribute(pTracking, L"SCOPE", &pwszScope); if (SUCCEEDED(hr)) { if (!StrCmpIW(pwszScope, L"OFFLINE")) _ConnectionScope = TRACK_OFFLINE_CACHE_ENTRY; else if (!StrCmpIW(pwszScope, L"ONLINE")) _ConnectionScope = TRACK_ONLINE_CACHE_ENTRY;
SAFELOCALFREE(pwszScope); }
RunChildElement(pTracking);
// #42687: save purgetime to item and used later by post agent
if (_pwszPurgeTime) // if not specify, default is 24 hours
{ _dwPurgeTime = WCTOI(_pwszPurgeTime); }
DATE dt = 0.0; SYSTEMTIME st;
GetLocalTime(&st); SystemTimeToVariantTime(&st, &dt); dt += ((DATE)_dwPurgeTime/24); #ifdef DEBUG
VariantTimeToSystemTime(dt, &st); #endif
WriteDATE(_pCDFStartItem, c_szPostPurgeTime, &dt);
return S_OK; }
//-----------------------------------------------------------------------------
//
// ProcessTrackingItems
// <Item href="http://foo">
// <Log value="document:view"/>
// </Item>
// or <Item>
// <A href="http://foo" />
// </Item>
// This routine will setup tracking cache entries for all URLs which are
// specified in CDF file to track. All URLs entries belong to same channel
// are created in same cache group
//-----------------------------------------------------------------------------
HRESULT CUrlTrackingCache :: ProcessTrackingInItem ( IXMLElement *pItem, //point to <Item> tag
LPCWSTR pwszUrl, //absolute URL for item
BOOL fForceLog //global log flag
) { HRESULT hr = S_OK;
_bTrackIt = fForceLog;
if (!_bTrackIt) hr = RunChildElement(pItem);
if (SUCCEEDED(hr) && _bTrackIt) hr = AddToTrackingCacheEntry(pwszUrl); return (_bTrackIt) ? S_OK : E_FAIL; // #42604: global logging, report if this item needs logged
}
HRESULT CUrlTrackingCache :: RunChildElement ( IXMLElement* pElement ) { IXMLElementCollection *pCollection; long lIndex = 0; long lMax; VARIANT vIndex, vEmpty; IDispatch *pDisp; IXMLElement *pItem; BSTR bstrTagName; HRESULT hr = E_FAIL;
if (SUCCEEDED(pElement->get_children(&pCollection)) && pCollection) { if (SUCCEEDED(pCollection->get_length(&lMax))) { vEmpty.vt = VT_EMPTY;
for (; lIndex < lMax; lIndex++) { vIndex.vt = VT_UI4; vIndex.lVal = lIndex;
if (SUCCEEDED(pCollection->item(vIndex, vEmpty, &pDisp))) { if (SUCCEEDED(pDisp->QueryInterface(IID_IXMLElement, (void **)&pItem))) { if (SUCCEEDED(pItem->get_tagName(&bstrTagName)) && bstrTagName) { hr = ProcessItemInEnum(bstrTagName, pItem); SysFreeString(bstrTagName); } pItem->Release(); } pDisp->Release(); } }
} pCollection->Release(); }
return hr; }
HRESULT CUrlTrackingCache :: ProcessItemInEnum ( LPCWSTR pwszTagName, IXMLElement *pItem ) { HRESULT hr; LPWSTR pwszName = NULL;
if (!StrCmpIW(pwszTagName, L"HTTP-EQUIV")) { DBG("CUrlTrackingCache processing HTTP-EQUIV"); hr = ReadAttribute(pItem, L"NAME", &pwszName); if (SUCCEEDED(hr) && !StrCmpIW(pwszName, L"ENCODING-TYPE")) { hr = ReadAttribute(pItem, L"VALUE", &_pwszEncodingMethod); if (SUCCEEDED(hr) && *_pwszEncodingMethod) WriteOLESTR(_pCDFStartItem, c_szPostHeader, _pwszEncodingMethod); } SAFELOCALFREE(pwszName); } else if (!StrCmpIW(pwszTagName, L"PURGETIME")) { DBG("CUrlTrackingCache processing PurgeTime");
return ReadAttribute(pItem, L"HOUR", &_pwszPurgeTime); } else if (!StrCmpIW(pwszTagName, L"LOG")) { DBG("CUrlTrackingCache processing Log"); hr = ReadAttribute(pItem, L"VALUE", &pwszName); if (SUCCEEDED(hr)) _bTrackIt = (!StrCmpIW(pwszName, L"document:view")) ? TRUE : FALSE;
SAFELOCALFREE(pwszName); }
return S_OK; }
HRESULT CUrlTrackingCache :: ReadAttribute ( IN IXMLElement* pItem, IN LPCWSTR pwszAttributeName, OUT LPWSTR* pwszAttributeValue ) { VARIANT vProp; BSTR bstrName = NULL; HRESULT hr = E_FAIL; DWORD dwLen;
vProp.vt = VT_EMPTY; bstrName = SysAllocString(pwszAttributeName);
if (bstrName && SUCCEEDED(pItem->getAttribute(bstrName, &vProp))) { if (vProp.vt == VT_BSTR) { dwLen = sizeof(WCHAR) * (lstrlenW(vProp.bstrVal) + 1); *pwszAttributeValue = (LPWSTR)MemAlloc(LPTR, dwLen); if (*pwszAttributeValue) { StrCpyNW(*pwszAttributeValue, vProp.bstrVal, dwLen / sizeof(WCHAR)); hr = S_OK; }
VariantClear(&vProp); } }
SysFreeString(bstrName);
return hr; }
//--------------------------------------------------------------------------
//
// CUrlTrackingCache
//
//--------------------------------------------------------------------------
CUrlTrackingCache::CUrlTrackingCache ( ISubscriptionItem *pCDFItem, LPCWSTR pwszURL ) { _lpPfx = NULL; _dwPurgeTime = 24; _pCDFStartItem = pCDFItem;
ASSERT(_pCDFStartItem); _pCDFStartItem->AddRef();
Init(pwszURL); }
CUrlTrackingCache::~CUrlTrackingCache() {
SAFEFREEOLESTR(_pwszPostUrl); SAFEFREEOLESTR(_pwszEncodingMethod); SAFEFREEOLESTR(_pwszPurgeTime);
SAFELOCALFREE(_pszChannelUrlSite); SAFELOCALFREE(_pszPostUrlSite); SAFELOCALFREE(_lpPfx); SAFERELEASE(_pCDFStartItem); }
|