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
869 lines
25 KiB
//
|
|
// 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);
|
|
}
|
|
|