|
|
#include <wininetp.h>
#include "p3ppolicy.h"
#include "download.h"
#include "xmlwrapper.h"
#define CheckAndRelease(p) { if (p) p->Release(); }
INTERNETAPI_(int) GetP3PPolicy(P3PCURL pszPolicyURL, HANDLE hDestination, P3PCXSL pszXSLtransform, P3PSignal *pSignal) {
Policy_Request *pRequest = new Policy_Request(pszPolicyURL, hDestination, pszXSLtransform, pSignal); int result = P3P_Error;
if (pRequest) { if (pSignal) { DWORD dwThreadID; CreateThread(NULL, 0, P3PRequest::ExecRequest, (void*)pRequest, 0, &dwThreadID); result = P3P_InProgress; pSignal->hRequest = (P3PHANDLE) pRequest; } else { result = pRequest->execute(); delete pRequest; } }
return result; }
/*
Implementation of Policy_Request object */ Policy_Request::Policy_Request(P3PCURL pszP3PPolicy, HANDLE hDest, P3PCXSL pszXSLtransform, P3PSignal *pSignal) : P3PRequest(pSignal) {
this->pszPolicyID = strdup(pszP3PPolicy); this->pwszStyleSheet = pszXSLtransform; this->hDestination = hDest;
pszInlineName = strchr(pszPolicyID, '#'); if (pszInlineName) *pszInlineName++ = '\0'; }
Policy_Request::~Policy_Request() {
free(pszPolicyID); endDownload(hPrimaryIO); }
bool Policy_Request::policyExpired(IXMLDOMDocument *pDocument, const char *pszPolicyID) {
/* If no expiration is given in the document,
it defaults to 24hr lifetime (P3Pv1 spec) */ bool fExpired = false;
/* Find an EXPIRY element contained in a POLICIES element.
Simply searching for EXPIRY will not work because in the case of inline policies, we can have more than one tag in a document */ TreeNode *pTree = createXMLtree(pDocument), *pPolicies = pTree ? pTree->find("POLICIES") : NULL, *pExpiry = pPolicies ? pPolicies->find("EXPIRY", 1) : NULL;
if (pExpiry) {
FILETIME ftExpires = { 0x0, 0x0 };
if (const char *pszAbsExpiry = pExpiry->attribute("date")) setExpiration(pszPolicyID, pszAbsExpiry, FALSE, &ftExpires); else if (const char *pszRelExpiry = pExpiry->attribute("max-age")) setExpiration(pszPolicyID, pszRelExpiry, TRUE, &ftExpires);
FILETIME ftNow; GetSystemTimeAsFileTime(&ftNow); if (ftNow>ftExpires) fExpired = true; }
delete pTree; return fExpired; }
int Policy_Request::execute() {
IXMLDOMElement *pRootNode = NULL; IXMLDOMNode *pPolicyElem = NULL; IXMLDOMDocument *pDocument = NULL; int result = P3P_Failed; char achFinalLocation[URL_LIMIT]; char achFilePath[MAX_PATH];
ResourceInfo ri;
ri.pszFinalURL = achFinalLocation; ri.cbURL = URL_LIMIT; ri.pszLocalPath = achFilePath; ri.cbPath = MAX_PATH;
int docsize = downloadToCache(pszPolicyID, &ri, &hPrimaryIO, this);
if (docsize<=0) { result = P3P_NotFound; goto EndRequest; }
P3PCURL pszFinalURL = achFinalLocation;
pDocument = parseXMLDocument(achFilePath);
if (!pDocument) { result = P3P_FormatErr; goto EndRequest; }
if (policyExpired(pDocument, pszPolicyID)) { result = P3P_Expired; goto EndRequest; } HRESULT hr;
/* Inline policy? */ if (pszInlineName) {
/* YES-- use XPath query to locate correct name */ char achXPathQuery[URL_LIMIT]; wsprintf(achXPathQuery, "//POLICY[@name=\"%s\"]", pszInlineName);
BSTR bsQuery = ASCII2unicode(achXPathQuery); hr = pDocument->selectSingleNode(bsQuery, &pPolicyElem); SysFreeString(bsQuery); } else { pDocument->get_documentElement(&pRootNode); if (pRootNode) pRootNode->QueryInterface(IID_IXMLDOMElement, (void**) &pPolicyElem); }
if (!pPolicyElem) { result = P3P_FormatErr; goto EndRequest; }
BSTR bsPolicy = NULL;
/* Apply optional XSL transform */ if (pwszStyleSheet) {
/* This XSL transformation only works on XMLDOMDocument objects, not
fragments or individual XMLDOMNodes. */ IXMLDOMDocument *pXSLdoc = createXMLDocument(), *pPolicyDoc = createXMLDocument();
if (!(pXSLdoc && pPolicyDoc)) goto ReleaseXML; BSTR bsFragment = NULL; VARIANT_BOOL fLoadPolicy = FALSE, fLoadXSL = FALSE; pPolicyElem->get_xml(&bsFragment); if (bsFragment) { pPolicyDoc->loadXML(bsFragment, &fLoadPolicy); SysFreeString(bsFragment); } else goto ReleaseXML;
if (BSTR bsStyleSheet = (BSTR) pwszStyleSheet) pXSLdoc->loadXML(bsStyleSheet, &fLoadXSL);
if (fLoadPolicy && fLoadXSL) pPolicyDoc->transformNode(pXSLdoc, &bsPolicy); else result = P3P_XMLError;
ReleaseXML: CheckAndRelease(pPolicyDoc); CheckAndRelease(pXSLdoc); } else if (pPolicyElem) pPolicyElem->get_xml(&bsPolicy); if (bsPolicy) {
int cbBytes = SysStringByteLen(bsPolicy);
unsigned long dwWritten;
/* need BOM (byte order marker) for Unicode content.
NOTE: this logic assumes we are writing at beggining of a file. */ WriteFile(hDestination, "\xFF\xFE", 2, &dwWritten, NULL);
WriteFile(hDestination, bsPolicy, cbBytes, &dwWritten, NULL);
SysFreeString(bsPolicy); result = P3P_Success; }
EndRequest: /* release the DOM interfaces */ CheckAndRelease(pPolicyElem); CheckAndRelease(pRootNode); CheckAndRelease(pDocument);
/* close the primary-IO handle and set it to NULL */ endDownload(hPrimaryIO); hPrimaryIO = NULL;
return result; }
|