WindowsXP-SP1/shell/shdocvw/privacyimport.cpp

1437 lines
44 KiB
C++

// PrivacyImport.cpp - handles parsing and import of privacy preferences
#include "priv.h"
#include "resource.h"
#include <mluisupp.h>
#include "SmallUtil.hpp"
#include "PrivacyImport.hpp"
#define MAX_TOKEN_SIZE 64
#define NUM_OF_ZONES (1 + IDS_PRIVACYXML6_COOKIEZONE_LAST - IDS_PRIVACYXML6_COOKIEZONE_FIRST)
#define NUM_OF_ACTIONS (1 + IDS_PRIVACYXML6_ACTION_LAST - IDS_PRIVACYXML6_ACTION_FIRST)
//
// DeleteCacheCookies was copy'n'pasted from Cachecpl.cpp
//
// Any changes to either version should probably be transfered to both.
//
BOOL DeleteCacheCookies()
{
BOOL bRetval = TRUE;
DWORD dwEntrySize, dwLastEntrySize;
LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry;
HANDLE hCacheDir = NULL;
dwEntrySize = dwLastEntrySize = MAX_CACHE_ENTRY_INFO_SIZE;
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFOA) new BYTE[dwEntrySize];
if( lpCacheEntry == NULL)
{
bRetval = FALSE;
goto Exit;
}
lpCacheEntry->dwStructSize = dwEntrySize;
Again:
if (!(hCacheDir = FindFirstUrlCacheEntryA("cookie:",lpCacheEntry,&dwEntrySize)))
{
delete [] lpCacheEntry;
switch(GetLastError())
{
case ERROR_NO_MORE_ITEMS:
goto Exit;
case ERROR_INSUFFICIENT_BUFFER:
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFOA)
new BYTE[dwEntrySize];
if( lpCacheEntry == NULL)
{
bRetval = FALSE;
goto Exit;
}
lpCacheEntry->dwStructSize = dwLastEntrySize = dwEntrySize;
goto Again;
default:
bRetval = FALSE;
goto Exit;
}
}
do
{
if (lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY)
DeleteUrlCacheEntryA(lpCacheEntry->lpszSourceUrlName);
dwEntrySize = dwLastEntrySize;
Retry:
if (!FindNextUrlCacheEntryA(hCacheDir,lpCacheEntry, &dwEntrySize))
{
delete [] lpCacheEntry;
switch(GetLastError())
{
case ERROR_NO_MORE_ITEMS:
goto Exit;
case ERROR_INSUFFICIENT_BUFFER:
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFOA)
new BYTE[dwEntrySize];
if( lpCacheEntry == NULL)
{
bRetval = FALSE;
goto Exit;
}
lpCacheEntry->dwStructSize = dwLastEntrySize = dwEntrySize;
goto Retry;
default:
bRetval = FALSE;
goto Exit;
}
}
}
while (TRUE);
Exit:
if (hCacheDir)
FindCloseUrlCache(hCacheDir);
return bRetval;
}
//*****************************************************************************************
//*****************************************************************************************
//
// CPrivacyXMLResourceStrings
//
// just stores the Privacy format XML strings..
class CPrivacyXMLResourceStrings
{
WCHAR m_szResourceString[IDS_PRIVACYXML6_LASTPRIVACYXML6
-IDS_PRIVACYXML6 + 1] [MAX_TOKEN_SIZE];
public:
LPCWSTR GetResourceString( int iIndex) { return m_szResourceString[ iIndex - IDS_PRIVACYXML6];};
BOOL Initialize()
{
for( int i = 0;
i < ARRAYSIZE(m_szResourceString);
i++)
{
if( 0 == MLLoadStringW( IDS_PRIVACYXML6 + i,
m_szResourceString[i], MAX_TOKEN_SIZE))
return FALSE;
}
return TRUE;
}
};
//*****************************************************************************************
//*****************************************************************************************
//
// CParseAccumulation is a class that stores the results of parsing an XML privacy
//preference file. These results can then be sent to the system after parsing
//successfully completes.
//
class CParseAccumulation : public CPrivacyXMLResourceStrings
{
public:
bool m_fFlushCookies;
bool m_fFlushSiteList;
bool m_fLeashCookies;
struct SPerZonePartyPreferences
{
UINT m_uiNoPolicyDefault;
UINT m_uiNoRuleDefault;
bool m_fAlwaysAllowSession;
CGrowingString m_cZonePreference;
};
struct SPerZonePreferences
{
UINT m_uiZoneID;
bool m_fSetZone;
SPerZonePartyPreferences m_party[2]; // first party = 0, third party = 1
};
SPerZonePreferences m_zonePref[NUM_OF_ZONES];
CQueueSortOf m_queueSitesToAccept;
CQueueSortOf m_queueSitesToReject;
~CParseAccumulation()
{
void* iterator;
iterator = NULL;
// free up the names sites to be accepted
while( NULL != (iterator = m_queueSitesToAccept.StepEnumerate( iterator)))
{
SysFreeString( (BSTR)m_queueSitesToAccept.Get( iterator));
}
iterator = NULL;
// free up the names of sites to be rejected
while( NULL != (iterator = m_queueSitesToReject.StepEnumerate( iterator)))
{
SysFreeString( (BSTR)m_queueSitesToReject.Get( iterator));
}
}
BOOL Initialize()
{
m_fFlushCookies = false;
m_fFlushSiteList = false;
m_fLeashCookies = true;
for( int i = 0; i < ARRAYSIZE( m_zonePref); i++)
{
m_zonePref[i].m_uiZoneID = 0;
m_zonePref[i].m_fSetZone = false;
m_zonePref[i].m_party[0].m_uiNoPolicyDefault = 0;
m_zonePref[i].m_party[0].m_uiNoRuleDefault = 0;
m_zonePref[i].m_party[0].m_fAlwaysAllowSession = false;
m_zonePref[i].m_party[1].m_uiNoPolicyDefault = 0;
m_zonePref[i].m_party[1].m_uiNoRuleDefault = 0;
m_zonePref[i].m_party[1].m_fAlwaysAllowSession = false;
}
return CPrivacyXMLResourceStrings::Initialize();
}
BOOL AddSiteRule( BSTR bstrDomain, DWORD uiAction)
{
if( uiAction == IDS_PRIVACYXML6_ACTION_ACCEPT)
return m_queueSitesToAccept.InsertAtEnd( (void*)bstrDomain) ? TRUE : FALSE;
else if( uiAction == IDS_PRIVACYXML6_ACTION_REJECT)
return m_queueSitesToReject.InsertAtEnd( (void*)bstrDomain) ? TRUE : FALSE;
else
return FALSE;
}
long GetZoneFromResource( UINT uiZoneResource)
{
switch(uiZoneResource)
{
case IDS_PRIVACYXML6_COOKIEZONE_INTERNET:
return URLZONE_INTERNET;
case IDS_PRIVACYXML6_COOKIEZONE_INTRANET:
return URLZONE_INTRANET;
case IDS_PRIVACYXML6_COOKIEZONE_TRUSTED:
return URLZONE_TRUSTED;
default:
return -1;
}
}
BOOL DoAccumulation()
{
BOOL returnValue = FALSE;
long i;
void* iterator;
if( m_fFlushSiteList)
InternetClearAllPerSiteCookieDecisions();
DWORD dwSetValue = m_fLeashCookies ? TRUE : FALSE;
SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_INTERNET_SETTINGS, REGSTR_VAL_PRIVLEASHLEGACY,
REG_DWORD, &dwSetValue, sizeof(DWORD));
if( m_fFlushCookies)
DeleteCacheCookies();
// Set compact policy response rules for each zone
for( i = 0; i < ARRAYSIZE(m_zonePref); i++)
{
if( !m_zonePref[i].m_fSetZone)
continue;
if( ERROR_SUCCESS !=
PrivacySetZonePreferenceW(
GetZoneFromResource(m_zonePref[i].m_uiZoneID),
PRIVACY_TYPE_FIRST_PARTY, PRIVACY_TEMPLATE_CUSTOM,
m_zonePref[i].m_party[0].m_cZonePreference.m_szString))
{
goto doneDoAccumulation;
}
if( ERROR_SUCCESS !=
PrivacySetZonePreferenceW(
GetZoneFromResource(m_zonePref[i].m_uiZoneID),
PRIVACY_TYPE_THIRD_PARTY, PRIVACY_TEMPLATE_CUSTOM,
m_zonePref[i].m_party[1].m_cZonePreference.m_szString))
{
goto doneDoAccumulation;
}
}
// If any per-site rules were specified, we modify the persite list..
if( NULL != m_queueSitesToAccept.StepEnumerate(NULL)
|| NULL != m_queueSitesToReject.StepEnumerate(NULL))
{
// First we clear all existing per site rules..
InternetClearAllPerSiteCookieDecisions();
// Then we add the Accept per-site exceptions
iterator = NULL;
while( NULL != (iterator = m_queueSitesToAccept.StepEnumerate( iterator)))
{
InternetSetPerSiteCookieDecision( (LPCWSTR)m_queueSitesToAccept.Get( iterator), COOKIE_STATE_ACCEPT);
}
// and then the Reject per-site exceptions
iterator = NULL;
while( NULL != (iterator = m_queueSitesToReject.StepEnumerate( iterator)))
{
InternetSetPerSiteCookieDecision( (LPCWSTR)m_queueSitesToReject.Get( iterator), COOKIE_STATE_REJECT);
}
}
returnValue = TRUE;
doneDoAccumulation:
return returnValue;
}
};
int FindP3PPolicySymbolWrap( LPCWSTR szSymbol)
{
char szSymBuffer[MAX_PATH];
int length = lstrlen( szSymbol);
if( length + 1 > ARRAYSIZE( szSymBuffer))
return -1;
szSymBuffer[0] = '\0';
SHTCharToAnsi( szSymbol, szSymBuffer, ARRAYSIZE( szSymBuffer));
return FindP3PPolicySymbol( szSymBuffer);
}
//*****************************************************************************
//*****************************************************************************
//
// XML Parsing functions
//
// These functions help parsing XML.
//
// GetNextToken looks at the node you are at (*ppCurrentNode) and tests
//if it has a particular tag value. If it does, *ppOutToken is set to
//be a pointer to the node, *ppCurrentNode is advanced to the next node,
//and *pfFoundToken is set to TRUE. If the *ppCurrentNode doesn't have
//the target tag, the *pfFoundToken is FALSE, *ppCurrentNode is unchanged,
//and *ppOutToken is NULL.
// If *ppCurrentNode is the last node, *ppCurrentNode would be advanced
//to NULL when finding the target token.
BOOL GetNextToken( IN OUT IXMLDOMNode ** ppCurrentNode, IN LPCWSTR szTargetToken,
OUT BOOL * pfFoundToken, OUT IXMLDOMNode ** ppOutTokenNode)
{
BOOL returnValue = FALSE;
HRESULT hr;
BSTR bstrNodeName = NULL;
VARIANT var;
VariantInit( &var);
if( *ppCurrentNode == NULL)
{
*pfFoundToken = FALSE;
*ppOutTokenNode = NULL;
returnValue = TRUE;
goto doneGetNextToken;
}
hr = (*ppCurrentNode)->get_nodeName( &bstrNodeName);
if( FAILED(hr))
goto doneGetNextToken;
if( 0 != StrCmpW( szTargetToken, bstrNodeName))
{
*pfFoundToken = FALSE;
*ppOutTokenNode = NULL;
returnValue = TRUE;
}
else
{
IXMLDOMNode * pNode = NULL;
hr = (*ppCurrentNode)->get_nextSibling( &pNode);
if( FAILED(hr))
goto doneGetNextToken;
*ppOutTokenNode = *ppCurrentNode;
if( hr == S_OK)
*ppCurrentNode = pNode;
else
*ppCurrentNode = NULL;
*pfFoundToken = TRUE;
returnValue = TRUE;
}
doneGetNextToken:
if( bstrNodeName != NULL)
SysFreeString( bstrNodeName);
return returnValue;
}
// GeAttributes retrieves the XML attributes for a node. The attributes to
//be fetched are passed in in array aszName, of length iStringCount. The results
//are returned as VT_BSTRs on success of VT_EMPTY on failure. The total number
//of attributes for the node is also returned (*plAllAttributesCount).
BOOL GetAttributes(
IN IXMLDOMNode * pNode, IN LPCWSTR * aszName, IN long iStringCount,
OUT VARIANT * aAttributeVariants, OUT long * plAllAttributesCount)
{
BOOL returnValue = FALSE;
HRESULT hr;
BSTR bstrAttributeName = NULL;
IXMLDOMNamedNodeMap * pAttributes = NULL;
IXMLDOMNode * pTempNode = NULL;
hr = pNode->get_attributes( &pAttributes);
if( FAILED(hr))
goto doneGetAttributes;
if( plAllAttributesCount != NULL)
{
hr = pAttributes->get_length( plAllAttributesCount);
if( FAILED(hr))
goto doneGetAttributes;
}
for( int i = 0; i < iStringCount; i++)
{
if( pTempNode != NULL)
pTempNode->Release();
pTempNode = NULL;
if( bstrAttributeName != NULL)
SysFreeString( bstrAttributeName);
bstrAttributeName = NULL;
aAttributeVariants[i].vt = VT_EMPTY;
aAttributeVariants[i].bstrVal = NULL;
bstrAttributeName = SysAllocString( aszName[i]);
if( bstrAttributeName == NULL)
continue;
// test if the ith attribute was set
hr = pAttributes->getNamedItem( bstrAttributeName, &pTempNode);
if( FAILED(hr) || pTempNode == NULL)
continue;
// get the value
hr = pTempNode->get_nodeTypedValue( &aAttributeVariants[i]);
// convert the value to a BSTR.
hr = VariantChangeType( &aAttributeVariants[i], &aAttributeVariants[i], NULL, VT_BSTR);
if( FAILED(hr) || aAttributeVariants[i].bstrVal == NULL)
{
VariantClear( &aAttributeVariants[i]);
aAttributeVariants[i].vt = VT_EMPTY;
aAttributeVariants[i].bstrVal = NULL;
}
}
returnValue = TRUE;
doneGetAttributes:
if( bstrAttributeName != NULL)
SysFreeString( bstrAttributeName);
if( pAttributes != NULL)
pAttributes->Release();
if( pTempNode != NULL)
pTempNode->Release();
return returnValue;
}
// The actions by GetActionByResource are formatted for
//PrivacySetZonePreference, like /token=n/ where n is the action.
LPCWSTR GetActionByResource( UINT uiActionResource)
{
switch( uiActionResource)
{
case IDS_PRIVACYXML6_ACTION_ACCEPT:
return L"=a/";
case IDS_PRIVACYXML6_ACTION_PROMPT:
return L"=p/";
case IDS_PRIVACYXML6_ACTION_FIRSTPARTY:
return L"=l/";
case IDS_PRIVACYXML6_ACTION_SESSION:
return L"=d/";
case IDS_PRIVACYXML6_ACTION_REJECT:
return L"=r/";
default:
ASSERT(0);
return L"r/";
}
}
LPCWSTR GetShortActionByResource( UINT uiActionResource)
{
switch( uiActionResource)
{
case IDS_PRIVACYXML6_ACTION_ACCEPT:
return L"=a";
case IDS_PRIVACYXML6_ACTION_PROMPT:
return L"=p";
case IDS_PRIVACYXML6_ACTION_FIRSTPARTY:
return L"=l";
case IDS_PRIVACYXML6_ACTION_SESSION:
return L"=d";
case IDS_PRIVACYXML6_ACTION_REJECT:
return L"=r";
default:
ASSERT(0);
return L"r";
}
}
// GetChildrenByName takes an XML node and returns all the subnodes
//with a particular name.
BOOL GetChildrenByName( IN IXMLDOMNode * pNode, IN LPCWSTR szName,
OUT IXMLDOMNodeList ** ppOutNodeList, OUT long * plCount)
{
BOOL returnValue = FALSE;
HRESULT hr;
BSTR bstr = NULL;
IXMLDOMNodeList * pSelectedNodes;
if( NULL == (bstr = SysAllocString( szName)))
goto doneGetChildrenByName;
hr = pNode->selectNodes( bstr, &pSelectedNodes);
if( FAILED(hr))
goto doneGetChildrenByName;
if( plCount != NULL)
{
hr = pSelectedNodes->get_length( plCount);
if( FAILED(hr))
goto doneGetChildrenByName;
}
returnValue = TRUE;
*ppOutNodeList = pSelectedNodes;
pSelectedNodes = NULL;
doneGetChildrenByName:
if( bstr != NULL)
SysFreeString( bstr);
if( pSelectedNodes != NULL)
pSelectedNodes->Release();
return returnValue;
}
//*****************************************************************************
//*****************************************************************************
//
// XML preference parsing functions
//
// These functions are specific to the v6 XML format of privacy preferences
//
// To make sense of these functions, their easiest to look at looking at
//the bottom function first, then moving up to the next function.
// parses <if expr="rule" action="act">
// where rule is like " token & ! token" and act is like "accept"
BOOL ParseIfRule( IN IXMLDOMNode* pIfNode,
CParseAccumulation::SPerZonePartyPreferences* pAccumParty,
CParseAccumulation& thisAccum)
{
BOOL returnValue = FALSE;
LONG lTemp;
UINT uiTemp;
VARIANT avarRule[2];
for( lTemp = 0; lTemp < ARRAYSIZE( avarRule); lTemp++)
VariantInit( &avarRule[lTemp]);
LPCWSTR aszRuleAttributes[2] =
{ thisAccum.GetResourceString(IDS_PRIVACYXML6_EXPR),
thisAccum.GetResourceString(IDS_PRIVACYXML6_ACTION)};
if( TRUE != GetAttributes(
pIfNode, aszRuleAttributes, ARRAYSIZE(aszRuleAttributes),
avarRule, &lTemp)
|| lTemp != 2
|| avarRule[0].vt == VT_EMPTY
|| avarRule[1].vt == VT_EMPTY)
{
goto doneParseIfRule;
}
// determine the action
UINT uiActionResource;
uiActionResource = 0;
for( uiTemp = IDS_PRIVACYXML6_ACTION_FIRST;
uiTemp <= IDS_PRIVACYXML6_ACTION_LAST;
uiTemp++)
{
if( 0 == StrCmp( avarRule[1].bstrVal, thisAccum.GetResourceString(uiTemp)))
uiActionResource = uiTemp;
}
if( uiActionResource == 0)
goto doneParseIfRule;
// Write the beginning of the next rule " /"
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(L" /"))
goto doneParseIfRule;
// Write the rule expression formatted for GetZoneFromResource
LPWSTR pCursor, pEndCursor;
pCursor = avarRule[0].bstrVal;
bool fContinue, fNegated;
fContinue = true;
while( fContinue)
{
while( *pCursor == L' ')
pCursor++;
fNegated = false;
while( *pCursor == L'!')
{
fNegated = !fNegated;
pCursor++;
while( *pCursor == L' ')
pCursor++;
}
if( fNegated)
{
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(L"!"))
goto doneParseIfRule;
}
while( *pCursor == L' ')
pCursor++;
pEndCursor = pCursor;
while( *pEndCursor != L'\0' && *pEndCursor != L',' && *pEndCursor != L' ')
{
pEndCursor++;
}
WCHAR szToken[10];
if( pEndCursor == pCursor
|| pEndCursor - pCursor > ARRAYSIZE(szToken)-1)
{
goto doneParseIfRule;
}
StrCpyNW( szToken, pCursor, (int)(pEndCursor-pCursor+1));
szToken[ pEndCursor-pCursor] = L'\0';
if( -1 == FindP3PPolicySymbolWrap( szToken))
goto doneParseIfRule;
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(szToken))
goto doneParseIfRule;
pCursor = pEndCursor;
while( *pCursor == L' ')
pCursor++;
fContinue = false;
if( *pCursor == L',')
{
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(L"&"))
goto doneParseIfRule;
fContinue = true;
pCursor++;
}
}
while( *pCursor == L' ')
pCursor++;
if( *pCursor != L'\0')
goto doneParseIfRule;
// Write the ending of the next rule "=action/"
if( TRUE != pAccumParty->m_cZonePreference.AppendToString( GetActionByResource(
uiActionResource)))
{
goto doneParseIfRule;
}
returnValue = TRUE;
doneParseIfRule:
for( lTemp = 0; lTemp < ARRAYSIZE( avarRule); lTemp++)
VariantClear( &avarRule[lTemp]);
return returnValue;
}
// parses <firstParty ...> or <thirdParty ...> elements
BOOL ParsePartyBlock( IN IXMLDOMNode* pPartyNode,
CParseAccumulation::SPerZonePartyPreferences* pAccumParty,
CParseAccumulation& thisAccum)
{
BOOL returnValue = FALSE;
long lTemp;
UINT uiTemp;
HRESULT hr;
IXMLDOMNode * pCurrentNode = NULL;
IXMLDOMNode * pRuleNode = NULL;
VARIANT avarAttributes[3];
for( lTemp = 0; lTemp < ARRAYSIZE( avarAttributes); lTemp++)
VariantInit( &avarAttributes[lTemp]);
LPCWSTR aszAttributes[3] =
{ thisAccum.GetResourceString(IDS_PRIVACYXML6_NOPOLICYDEFAULT),
thisAccum.GetResourceString(IDS_PRIVACYXML6_NORULESDEFAULT),
thisAccum.GetResourceString(IDS_PRIVACYXML6_ALWAYSALLOWSESSION)};
if( TRUE != GetAttributes( pPartyNode, aszAttributes, ARRAYSIZE(aszAttributes),
avarAttributes, &lTemp)
|| lTemp != 3
|| avarAttributes[0].vt == VT_EMPTY
|| avarAttributes[1].vt == VT_EMPTY
|| avarAttributes[2].vt == VT_EMPTY)
{
goto doneParsePartyBlock;
}
hr = pPartyNode->get_firstChild( &pCurrentNode);
if( FAILED(hr))
goto doneParsePartyBlock;
// Determine No Policy and No Rule Matched defaults
pAccumParty->m_uiNoPolicyDefault = 0;
pAccumParty->m_uiNoRuleDefault = 0;
for( uiTemp = IDS_PRIVACYXML6_ACTION_FIRST;
uiTemp <= IDS_PRIVACYXML6_ACTION_LAST;
uiTemp++)
{
if( 0 == StrCmp( avarAttributes[0].bstrVal, thisAccum.GetResourceString(uiTemp)))
pAccumParty->m_uiNoPolicyDefault = uiTemp;
if( 0 == StrCmp( avarAttributes[1].bstrVal, thisAccum.GetResourceString(uiTemp)))
pAccumParty->m_uiNoRuleDefault = uiTemp;
}
if( pAccumParty->m_uiNoPolicyDefault == 0 || pAccumParty->m_uiNoRuleDefault == 0)
goto doneParsePartyBlock;
// Determine if we should always allow session cookies.
if( 0 == StrCmp( avarAttributes[2].bstrVal,
thisAccum.GetResourceString(IDS_PRIVACYXML6_YES)))
{
pAccumParty->m_fAlwaysAllowSession = true;
}
else if( 0 == StrCmp( avarAttributes[2].bstrVal,
thisAccum.GetResourceString(IDS_PRIVACYXML6_NO)))
{
pAccumParty->m_fAlwaysAllowSession = false;
}
else
{
goto doneParsePartyBlock;
}
// Write the response if there is no policy
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(L"IE6-P3PV1/settings: nopolicy"))
goto doneParsePartyBlock;
if( TRUE != pAccumParty->m_cZonePreference.AppendToString( GetShortActionByResource(
pAccumParty->m_uiNoPolicyDefault)))
{
goto doneParsePartyBlock;
}
// If we allow all session cookies, write that rule.
if( pAccumParty->m_fAlwaysAllowSession)
{
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(L" session=a"))
goto doneParsePartyBlock;
}
// Write each of the rules in IF blocks
while( pCurrentNode != NULL)
{
if( pRuleNode != NULL)
pRuleNode->Release();
pRuleNode = NULL;
BOOL fFoundIfRule;
if( TRUE != GetNextToken(
&pCurrentNode, thisAccum.GetResourceString( IDS_PRIVACYXML6_IF),
&fFoundIfRule, &pRuleNode)
|| fFoundIfRule != TRUE)
{
goto doneParsePartyBlock;
}
if( TRUE != ParseIfRule( pRuleNode, pAccumParty, thisAccum))
goto doneParsePartyBlock;
}
// Write the command for the No Rule Matched rule..
if( TRUE != pAccumParty->m_cZonePreference.AppendToString(L" /"))
goto doneParsePartyBlock;
if( TRUE != pAccumParty->m_cZonePreference.AppendToString( GetActionByResource(
pAccumParty->m_uiNoRuleDefault)))
{
goto doneParsePartyBlock;
}
returnValue = TRUE;
doneParsePartyBlock:
if( pCurrentNode != NULL)
pCurrentNode->Release();
if( pRuleNode != NULL)
pRuleNode->Release();
for( lTemp = 0; lTemp < ARRAYSIZE( avarAttributes); lTemp++)
VariantClear( &avarAttributes[lTemp]);
return returnValue;
}
BOOL ParseP3pCookiePolicyBlock( IN IXMLDOMNode* pP3pPolicyNode, CParseAccumulation& thisAccum)
{
BOOL returnValue = FALSE;
HRESULT hr;
BOOL bl;
long iTemp;
VARIANT varZoneAttribute;
VariantInit( &varZoneAttribute);
IXMLDOMNode * pCurrentNode = NULL;
IXMLDOMNode * pFirstPartyNode = NULL;
IXMLDOMNode * pThirdPartyNode = NULL;
LPCWSTR aszAttributes[1] = { thisAccum.GetResourceString(IDS_PRIVACYXML6_COOKIEZONE_ZONE)};
if( TRUE != GetAttributes( pP3pPolicyNode,
aszAttributes, ARRAYSIZE( aszAttributes),
&varZoneAttribute, &iTemp)
|| iTemp != 1
|| varZoneAttribute.vt == VT_EMPTY)
{
goto doneParseP3pCookiePolicyBlock;
}
hr = pP3pPolicyNode->get_firstChild( &pCurrentNode);
if( FAILED( hr))
goto doneParseP3pCookiePolicyBlock;
if( TRUE != GetNextToken( &pCurrentNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_FIRSTPARTY),
&bl, &pFirstPartyNode)
|| bl != TRUE)
{
goto doneParseP3pCookiePolicyBlock;
}
if( TRUE != GetNextToken( &pCurrentNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_THIRDPARTY),
&bl, &pThirdPartyNode)
|| bl != TRUE)
{
goto doneParseP3pCookiePolicyBlock;
}
if( pCurrentNode != NULL) // to many elements ...
goto doneParseP3pCookiePolicyBlock;
long iCurrentZone;
iCurrentZone = -1;
for( iTemp = 0; iTemp < NUM_OF_ZONES; iTemp++)
{
if( 0 == StrCmp(varZoneAttribute.bstrVal,
thisAccum.GetResourceString( iTemp + IDS_PRIVACYXML6_COOKIEZONE_FIRST)))
{
iCurrentZone = iTemp;
}
}
if( iCurrentZone == -1)
goto doneParseP3pCookiePolicyBlock;
thisAccum.m_zonePref[iCurrentZone].m_uiZoneID = iCurrentZone + IDS_PRIVACYXML6_COOKIEZONE_FIRST;
thisAccum.m_zonePref[iCurrentZone].m_fSetZone = true;
if( TRUE != ParsePartyBlock( pFirstPartyNode, &(thisAccum.m_zonePref[iCurrentZone].m_party[0]),
thisAccum))
{
goto doneParseP3pCookiePolicyBlock;
}
if( TRUE != ParsePartyBlock( pThirdPartyNode, &(thisAccum.m_zonePref[iCurrentZone].m_party[1]),
thisAccum))
{
goto doneParseP3pCookiePolicyBlock;
}
returnValue = TRUE;
doneParseP3pCookiePolicyBlock:
VariantClear( &varZoneAttribute);
if( pCurrentNode != NULL)
pCurrentNode->Release();
if( pFirstPartyNode != NULL)
pFirstPartyNode->Release();
if( pThirdPartyNode != NULL)
pThirdPartyNode->Release();
return returnValue;
}
BOOL ParseMSIEPrivacyBlock( IXMLDOMNode* pMSIEPrivacyNode, CParseAccumulation& thisAccum)
{
bool returnValue = NULL;
HRESULT hr;
BOOL bl;
long iZoneIndex;
IXMLDOMNode * pCurrentNode = NULL;
IXMLDOMNode * pAlwaysReplayLegacyNode = NULL;
IXMLDOMNode * pFlushCookiesNode = NULL;
IXMLDOMNode * pFlushSiteListNode = NULL;
IXMLDOMNode * apZoneNode[NUM_OF_ZONES];
for( iZoneIndex = 0; iZoneIndex < ARRAYSIZE(apZoneNode); iZoneIndex++)
apZoneNode[iZoneIndex] = NULL;
// The correctness of attributes for this node was verified in
//LoadPrivacySettings().. (formatVersion="6.0")
hr = pMSIEPrivacyNode->get_firstChild( &pCurrentNode);
if( FAILED( hr))
goto doneParseMSIEPrivacyBlock;
for( iZoneIndex = 0; iZoneIndex < ARRAYSIZE( apZoneNode); iZoneIndex++)
{
if( TRUE != GetNextToken( &pCurrentNode,
thisAccum.GetResourceString(IDS_PRIVACYXML6_COOKIEZONE),
&bl, &apZoneNode[iZoneIndex]))
{
goto doneParseMSIEPrivacyBlock;
}
}
if( TRUE != GetNextToken( &pCurrentNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_ALWAYSREPLAYLEGACY),
&bl, &pAlwaysReplayLegacyNode))
{
goto doneParseMSIEPrivacyBlock;
}
thisAccum.m_fLeashCookies = pAlwaysReplayLegacyNode == NULL;
if( TRUE != GetNextToken( &pCurrentNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_FLUSHCOOKIES),
&bl, &pFlushCookiesNode))
{
goto doneParseMSIEPrivacyBlock;
}
thisAccum.m_fFlushCookies = pFlushCookiesNode != NULL;
if( TRUE != GetNextToken( &pCurrentNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_FLUSHSITELIST),
&bl, &pFlushSiteListNode))
{
goto doneParseMSIEPrivacyBlock;
}
thisAccum.m_fFlushSiteList = pFlushSiteListNode != NULL;
if( pCurrentNode != NULL)
goto doneParseMSIEPrivacyBlock;
for( iZoneIndex = 0; iZoneIndex < ARRAYSIZE( apZoneNode); iZoneIndex++)
{
if( apZoneNode[iZoneIndex] != NULL)
{
if( TRUE != ParseP3pCookiePolicyBlock( apZoneNode[iZoneIndex], thisAccum))
goto doneParseMSIEPrivacyBlock;
}
}
returnValue = TRUE;
doneParseMSIEPrivacyBlock:
if( pCurrentNode != NULL)
pCurrentNode->Release();
if( pAlwaysReplayLegacyNode != NULL)
pAlwaysReplayLegacyNode->Release();
if( pFlushCookiesNode != NULL)
pFlushCookiesNode->Release();
if( pFlushSiteListNode != NULL)
pFlushSiteListNode->Release();
for( iZoneIndex = 0; iZoneIndex < ARRAYSIZE(apZoneNode); iZoneIndex++)
{
if( apZoneNode[iZoneIndex] != NULL)
apZoneNode[iZoneIndex]->Release();
}
return returnValue;
}
BOOL ParsePerSiteRule( IXMLDOMNode* pPerSiteRule, CParseAccumulation& thisAccum)
{
BOOL returnValue = FALSE;
LONG lTemp;
VARIANT avarRule[2];
for( lTemp = 0; lTemp < ARRAYSIZE( avarRule); lTemp++)
VariantInit( &avarRule[lTemp]);
VARIANT varDomain;
VariantInit( &varDomain);
LPCWSTR aszRuleAttributes[2] =
{ thisAccum.GetResourceString(IDS_PRIVACYXML6_DOMAIN),
thisAccum.GetResourceString(IDS_PRIVACYXML6_ACTION)};
if( TRUE != GetAttributes(
pPerSiteRule, aszRuleAttributes, ARRAYSIZE(aszRuleAttributes),
avarRule, &lTemp)
|| lTemp != 2
|| avarRule[0].vt == VT_EMPTY
|| avarRule[1].vt == VT_EMPTY)
{
goto doneParsePerSiteRule;
}
// get the domain and make sure its legit
varDomain.vt = avarRule[0].vt;
varDomain.bstrVal = avarRule[0].bstrVal;
avarRule[0].vt = VT_EMPTY;
avarRule[0].bstrVal = NULL;
if( TRUE != IsDomainLegalCookieDomain( varDomain.bstrVal, varDomain.bstrVal))
goto doneParsePerSiteRule;
// get the action, ensuring its also legit
UINT uiActionResource;
if( 0 == StrCmp( avarRule[1].bstrVal, thisAccum.GetResourceString(IDS_PRIVACYXML6_ACTION_ACCEPT)))
uiActionResource = IDS_PRIVACYXML6_ACTION_ACCEPT;
else if( 0 == StrCmp( avarRule[1].bstrVal, thisAccum.GetResourceString(IDS_PRIVACYXML6_ACTION_REJECT)))
uiActionResource = IDS_PRIVACYXML6_ACTION_REJECT;
else
goto doneParsePerSiteRule;
// store the rule in the accumulated result
if( TRUE != thisAccum.AddSiteRule( varDomain.bstrVal, uiActionResource))
goto doneParsePerSiteRule;
varDomain.vt = VT_EMPTY;
varDomain.bstrVal = NULL;
returnValue = TRUE;
doneParsePerSiteRule:
for( lTemp = 0; lTemp < ARRAYSIZE( avarRule); lTemp++)
VariantClear( &avarRule[lTemp]);
VariantClear( &varDomain);
return returnValue;
}
BOOL ParseMSIEPerSiteBlock( IXMLDOMNode* pPerSiteRule, CParseAccumulation& thisAccum)
{
BOOL returnValue = FALSE;
HRESULT hr;
IXMLDOMNode * pCurrentNode = NULL;
IXMLDOMNode * pRuleNode = NULL;
hr = pPerSiteRule->get_firstChild( &pCurrentNode);
if( FAILED(hr))
goto doneParsePerSiteBlock;
while( pCurrentNode != NULL)
{
if( pRuleNode != NULL)
pRuleNode->Release();
pRuleNode = NULL;
BOOL fFoundPerSiteRule;
if( TRUE != GetNextToken(
&pCurrentNode, thisAccum.GetResourceString( IDS_PRIVACYXML6_SITE),
&fFoundPerSiteRule, &pRuleNode)
|| fFoundPerSiteRule != TRUE)
{
goto doneParsePerSiteBlock;
}
if( TRUE != ParsePerSiteRule( pRuleNode, thisAccum))
goto doneParsePerSiteBlock;
}
returnValue = TRUE;
doneParsePerSiteBlock:
if( pCurrentNode != NULL)
pCurrentNode->Release();
if( pRuleNode != NULL)
pRuleNode->Release();
return returnValue;
}
BOOL OpenXMLFile( LPCWSTR szFilename, IXMLDOMNode ** ppOutputNode)
{
BOOL returnValue = FALSE;
HRESULT hr;
VARIANT varFilename;
VariantInit( &varFilename);
IXMLDOMDocument * pXMLDoc = NULL;
IXMLDOMElement * pXMLRoot = NULL;
IXMLDOMNode * pRootNode = NULL;
hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument, (void**)&pXMLDoc);
if( FAILED(hr))
goto doneOpenXMLFile;
hr = pXMLDoc->put_async( VARIANT_FALSE);
if( FAILED(hr))
goto doneOpenXMLFile;
varFilename.vt = VT_BSTR;
varFilename.bstrVal = SysAllocString( szFilename);
if( varFilename.bstrVal == NULL)
goto doneOpenXMLFile;
VARIANT_BOOL varbool;
hr = pXMLDoc->load( varFilename, &varbool);
if( FAILED(hr) || varbool != VARIANT_TRUE)
goto doneOpenXMLFile;
hr = pXMLDoc->get_documentElement( &pXMLRoot);
if( FAILED(hr))
goto doneOpenXMLFile;
hr = pXMLRoot->QueryInterface( IID_IXMLDOMNode, (void **)&pRootNode);
if( FAILED(hr))
goto doneOpenXMLFile;
returnValue = TRUE;
*ppOutputNode = pRootNode;
pRootNode = NULL;
doneOpenXMLFile:
if( pXMLDoc != NULL)
pXMLDoc->Release();
if( pXMLRoot != NULL)
pXMLRoot->Release();
if( pRootNode != NULL)
pRootNode->Release();
VariantClear( &varFilename);
return returnValue;
}
//
// GetVersionedTag
//
// Looks at all tags in pSource with the tag szTargetTag. Returns
//the member with version fVersion. Fails if zero or >1 such
//tags are found.
//
BOOL GetVersionedTag( IXMLDOMNode* pSource, LPCWSTR szTargetTag, LPCWSTR szVersionAttribute, float fVersion,
IXMLDOMNode** ppOutputNode)
{
BOOL returnValue = FALSE;
HRESULT hr;
IXMLDOMNode * pNode = NULL;
IXMLDOMNode * pResult = NULL;
IXMLDOMNodeList * pRootNodeList = NULL;
IXMLDOMNode * pVersionAttribute = NULL;
VARIANT varVersion;
VariantInit( &varVersion);
// Get the elements in pSource with tag szTargetTag
long iListSize;
if( TRUE != GetChildrenByName( pSource, szTargetTag,
&pRootNodeList, &iListSize))
{
goto doneGetVersionedTag;
}
long iListIndex;
for( iListIndex = 0; iListIndex < iListSize; iListIndex++)
{
if( pNode != NULL)
pNode->Release();
pNode = NULL;
if( pVersionAttribute != NULL)
pVersionAttribute->Release();
pVersionAttribute = NULL;
VariantClear( &varVersion);
hr = pRootNodeList->get_item( iListIndex, &pNode);
if( FAILED(hr))
goto doneGetVersionedTag;
long iTotalAttributeCount;
LPCWSTR aszAttributes[1] = { szVersionAttribute};
if( TRUE != GetAttributes( pNode, aszAttributes, ARRAYSIZE(aszAttributes),
&varVersion, &iTotalAttributeCount)
|| varVersion.vt == VT_EMPTY)
{
continue;
}
hr = VariantChangeType( &varVersion, &varVersion, NULL, VT_R4);
if( FAILED(hr))
goto doneGetVersionedTag;
if( varVersion.fltVal != fVersion)
continue;
if( pResult == NULL)
{
pResult = pNode;
pNode = NULL;
}
else
{ // found multiple of right version.. syntax problem.
goto doneGetVersionedTag;
}
}
*ppOutputNode = pResult;
pResult = NULL;
returnValue = TRUE;
doneGetVersionedTag:
if( pNode != NULL)
pNode->Release();
if( pResult != NULL)
pResult->Release();
if( pRootNodeList != NULL)
pRootNodeList->Release();
if( pVersionAttribute != NULL)
pVersionAttribute->Release();
VariantClear( &varVersion);
return returnValue;
}
BOOL LoadPrivacySettings(LPCWSTR szFilename, CParseAccumulation& thisAccum,
IN OUT BOOL* pfParsePrivacyPreferences, IN OUT BOOL* pfParsePerSiteRules)
{
BOOL returnValue = FALSE;
IXMLDOMNode * pRootNode = NULL;
IXMLDOMNode * pPrivacyPreferencesNode = NULL;
IXMLDOMNode * pPerSiteSettingsNode = NULL;
// Load the XML file
if( TRUE != OpenXMLFile( szFilename, &pRootNode))
goto doneLoadPrivacySettings;
// Get the node containing privacy settings
if( TRUE != GetVersionedTag( pRootNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_ROOTPRIVACY),
thisAccum.GetResourceString(IDS_PRIVACYXML6_VERSION), 6.0, &pPrivacyPreferencesNode))
{
goto doneLoadPrivacySettings;
}
// Get the node containing per-site settings
if( TRUE != GetVersionedTag( pRootNode, thisAccum.GetResourceString(IDS_PRIVACYXML6_ROOTPERSITE),
thisAccum.GetResourceString(IDS_PRIVACYXML6_VERSION), 6.0, &pPerSiteSettingsNode))
{
goto doneLoadPrivacySettings;
}
// If we're supposed to import privacy preferences and we found some, parse privacy preferences.
if( *pfParsePrivacyPreferences == TRUE && pPrivacyPreferencesNode != NULL)
{
if( TRUE != ParseMSIEPrivacyBlock( pPrivacyPreferencesNode, thisAccum))
{
goto doneLoadPrivacySettings;
}
}
// If we're supposed to import per-site rules and we found some, parse per-site rules.
if( *pfParsePerSiteRules == TRUE && pPerSiteSettingsNode != NULL)
{
if( TRUE != ParseMSIEPerSiteBlock( pPerSiteSettingsNode, thisAccum))
{
goto doneLoadPrivacySettings;
}
}
// Indicate whether privacy preferences or per-site rules were parsed..
*pfParsePrivacyPreferences = (*pfParsePrivacyPreferences == TRUE) && (pPrivacyPreferencesNode != NULL);
*pfParsePerSiteRules = (*pfParsePerSiteRules == TRUE) && (pPerSiteSettingsNode != NULL);
returnValue = TRUE;
doneLoadPrivacySettings:
if( pRootNode != NULL)
pRootNode->Release();
if( pPrivacyPreferencesNode != NULL)
pPrivacyPreferencesNode->Release();
if( pPerSiteSettingsNode != NULL)
pPerSiteSettingsNode->Release();
return returnValue;
}
// Top-level import function.. optionally imports privacy settings and per-site rules.
//The flag in tells if those items should be parsed, the flag out indicates if they were found.
//
// Returns TRUE to indicate the import was successful, no syntax problems in the import
//file and the output flags are set.
//
// Returns FALSE if there were any problems loading the file or writing the imported settings.
SHDOCAPI_(BOOL) ImportPrivacySettings( IN LPCWSTR szFilename,
IN OUT BOOL* pfParsePrivacyPreferences,
IN OUT BOOL* pfParsePerSiteRules)
{
BOOL returnValue = FALSE;
CParseAccumulation thisAccum;
if( TRUE != thisAccum.Initialize())
goto doneImportPrivacySettings;
if( TRUE != LoadPrivacySettings( szFilename, thisAccum,
pfParsePrivacyPreferences, pfParsePerSiteRules))
goto doneImportPrivacySettings;
returnValue = thisAccum.DoAccumulation();
doneImportPrivacySettings:
return returnValue;
}
//*****************************************************************************************
//*****************************************************************************************
//
//*****************************************************************************************
//*****************************************************************************************
//
// Privacy Export
//
// This code exists to export the per-site list only.
//
CHAR g_szPerSiteFileBegin[] =
"\
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n\
<MSIEPrivacy>\r\n\
<MSIESiteRules formatVersion=\"6.0\">\r\n\
";
CHAR g_szPerSiteRule[] = "<site domain=\"%s\" \taction=\"%s\"></site>\r\n";
CHAR g_szAccept[] = "accept";
CHAR g_szReject[] = "reject";
CHAR g_szPerSiteFileEnd[] =
"\
</MSIESiteRules>\r\n\
</MSIEPrivacy>\r\n\
";
SHDOCAPI_(BOOL) ExportPerSiteListW( IN LPCWSTR szFilename)
{
BOOL retVal = FALSE;
CFileOutputStream OutputStream;
PCHAR pszRuleBuffer = NULL;
int iRuleIndex = 0;
// Allocate a temporary buffer to write the rules to
long cRuleBufferSize = MAX_URL_STRING + ARRAYSIZE( g_szPerSiteRule) + MAX_PATH;
pszRuleBuffer = new CHAR[ cRuleBufferSize];
if( pszRuleBuffer == NULL)
goto doneExportCookieFileW;
// Load the output file
if( !OutputStream.Load( szFilename, FALSE))
goto doneExportCookieFileW;
// Write the begining of the file.
if( !OutputStream.DumpStr( g_szPerSiteFileBegin, ARRAYSIZE( g_szPerSiteFileBegin) - 1))
goto doneExportCookieFileW;
// Enumerate the per-site rules and export the accept/reject rules
CHAR szSiteName[ MAX_URL_STRING];
DWORD cSiteNameSize;
DWORD dwDecision;
while( (cSiteNameSize = ARRAYSIZE( szSiteName)) // initialize in-out param
&& InternetEnumPerSiteCookieDecisionA( szSiteName, &cSiteNameSize, &dwDecision, iRuleIndex++))
{
if( dwDecision == COOKIE_STATE_ACCEPT
|| dwDecision == COOKIE_STATE_REJECT)
{
int iRuleLength =
wnsprintfA(pszRuleBuffer, cRuleBufferSize, g_szPerSiteRule,
szSiteName,
(dwDecision == COOKIE_STATE_ACCEPT) ? g_szAccept : g_szReject);
OutputStream.DumpStr( pszRuleBuffer, iRuleLength);
}
}
// Write the ending of the file.
if( !OutputStream.DumpStr( g_szPerSiteFileEnd, ARRAYSIZE( g_szPerSiteFileEnd) - 1))
goto doneExportCookieFileW;
retVal = TRUE;
doneExportCookieFileW:
if( pszRuleBuffer != NULL)
delete [] pszRuleBuffer;
return retVal;
}