// PrivacyImport.cpp - handles parsing and import of privacy preferences #include "priv.h" #include "resource.h" #include #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 // 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 or 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[] = "\ \r\n\ \r\n\ \r\n\ "; CHAR g_szPerSiteRule[] = "\r\n"; CHAR g_szAccept[] = "accept"; CHAR g_szReject[] = "reject"; CHAR g_szPerSiteFileEnd[] = "\ \r\n\ \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; }