#include #include "map2policy.h" #include "download.h" #include "policyref.h" #include "p3pparser.h" const char gszP3PWellKnownLocation[] = "/w3c/p3p.xml"; #define different(s, p) !(s&&p&&!strcmp(s,p)) INTERNETAPI_(int) MapResourceToPolicy(P3PResource *pResource, P3PURL pszPolicy, unsigned long dwSize, P3PSignal *pSignal) { int ret = P3P_Error; MR2P_Request *pRequest = new MR2P_Request(pResource, pszPolicy, dwSize, pSignal); if (pRequest) { if (!pSignal) { ret = pRequest->execute(); delete pRequest; } else { DWORD dwThreadID; CreateThread(NULL, 0, P3PRequest::ExecRequest, (void*)pRequest, 0, &dwThreadID); pSignal->hRequest = pRequest->GetHandle(); ret = P3P_InProgress; } } return ret; } INTERNETAPI_(int) GetP3PRequestStatus(P3PHANDLE hObject) { P3PObject *pObject = (P3PObject*) hObject; P3PRequest *pRequest = (P3PRequest*) pObject; return pRequest->queryStatus(); } INTERNETAPI_(int) FreeP3PObject(P3PHANDLE hObject) { P3PObject *pObject = (P3PObject*) hObject; pObject->Free(); return P3P_Done; } /* Implementation of MR2P_Request class */ MR2P_Request::MR2P_Request(P3PResource *pResource, P3PURL pszPolicy, unsigned long dwSize, P3PSignal *pSignal) : P3PRequest(pSignal) { static BOOL fNoInterrupt = TRUE; this->pResource = pResource; this->pszPolicyOut = pszPolicy; this->dwLength = dwSize; cTries = 0; ppPriorityOrder = NULL; pLookupContext = NULL; pszPolicyInEffect = NULL; } MR2P_Request::~MR2P_Request() { delete [] ppPriorityOrder; endDownload(hPrimaryIO); } int MR2P_Request::execute() { int nDepth = 0; P3PResource *pr; /* Clear out parameters */ *pszPolicyOut = '\0'; /* Determine depth of the resource tree */ for (pr=pResource; pr; pr=pr->pContainer) nDepth++; /* Construct priority order for trying the policy-reference files. According P3P V1 spec, we traverse the tree downwards starting with top-level document */ int current = nDepth; ppPriorityOrder = new P3PResource*[nDepth]; for (pr=pResource; pr; pr=pr->pContainer) ppPriorityOrder[--current] = pr; for (int k=0; kpszLocation, gszP3PWellKnownLocation, achWellKnownLocation, &dwLength, 0); P3PCURL pszReferrer = pr->pszLocation; /* Since policy-refs derived from link-tag, P3P headers or the well-known location could be same URL, we avoid trying the same PREF multiple times as an optimization In order of precedence: - Check well known location first -- always defined */ if (tryPolicyRef(achWellKnownLocation, pszReferrer)) break; /* ... followed by policy-ref from P3P header, if one exists and is different from the well-known location */ if (pr->pszP3PHeaderRef && different(pr->pszP3PHeaderRef, achWellKnownLocation) && tryPolicyRef(pr->pszP3PHeaderRef, pszReferrer)) break; /* followed by policy-ref from HTML link tag, if one exists and is different from both the well-known location and P3P header */ if (pr->pszLinkTagRef && different(pr->pszLinkTagRef, achWellKnownLocation) && different(pr->pszLinkTagRef, pr->pszP3PHeaderRef) && tryPolicyRef(pr->pszLinkTagRef, pszReferrer)) break; } int ret = pszPolicyInEffect ? P3P_Done : P3P_NoPolicy; return ret; } bool MR2P_Request::tryPolicyRef(P3PCURL pszPolicyRef, P3PCURL pszReferrer) { if (pszPolicyRef==NULL) return false; P3PCHAR achFinalLocation[URL_LIMIT]; unsigned long dwSpace = URL_LIMIT; char achFilePath[MAX_PATH]; ResourceInfo ri; ri.pszFinalURL = achFinalLocation; ri.cbURL = URL_LIMIT; ri.pszLocalPath = achFilePath; ri.cbPath = MAX_PATH; if (downloadToCache(pszPolicyRef, &ri, &hPrimaryIO, this)>0) { P3PContext context = { ri.pszFinalURL, pszReferrer }; context.ftExpires = ri.ftExpiryDate; P3PPolicyRef *pPolicyRef = interpretPolicyRef(achFilePath, &context); if (pPolicyRef) { FILETIME ftCurrentTime; GetSystemTimeAsFileTime(&ftCurrentTime); if (pPolicyRef->getExpiration() > ftCurrentTime) pszPolicyInEffect = pPolicyRef->mapResourceToPolicy(pResource->pszLocation, pResource->pszVerb); if (pszPolicyInEffect) strncpy(pszPolicyOut, pszPolicyInEffect, dwLength); delete pPolicyRef; } } /* close the primary-IO handle and set it to NULL */ endDownload(hPrimaryIO); hPrimaryIO = NULL; return (pszPolicyInEffect!=NULL); }