371 lines
13 KiB
C++
371 lines
13 KiB
C++
#include <assert.h>
|
|
#include "propreqs.h"
|
|
#include "httpstrm.clsid.h"
|
|
#include "ihttpstrm.h"
|
|
#include "strutil.h"
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
//
|
|
// DavInetPropFindRequest methods
|
|
//
|
|
|
|
// need a destructor, only member variable is CGenericList, which is declared on the stack,
|
|
// so it will be destroyed when this object is destroyed, but we need to destroy all the things that
|
|
// it points to.
|
|
//
|
|
|
|
CDavInetPropFindRequestImpl::~CDavInetPropFindRequestImpl ()
|
|
{
|
|
_genlst.PurgeAll();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CDavInetPropFindRequestImpl::SetPropInfo(LPCWSTR pwszNamespace,
|
|
LPCWSTR pwszPropname,
|
|
DAVPROPID propid)
|
|
{
|
|
// locals
|
|
HRESULT hres = S_OK;
|
|
LPWSTR pwszTemp = NULL;
|
|
UINT cchTemp; // space for string's NULL terminator
|
|
DAVPROPID* ppropid;
|
|
|
|
// check args
|
|
if (pwszPropname == NULL)
|
|
{
|
|
hres = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
|
|
// code
|
|
// -- copy fullname
|
|
cchTemp = lstrlen(pwszPropname);
|
|
|
|
if (pwszNamespace != NULL)
|
|
{
|
|
cchTemp += (lstrlen(pwszNamespace));
|
|
}
|
|
|
|
pwszTemp = AllocateStringW(cchTemp);
|
|
if (pwszTemp == NULL)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pwszTemp[0]=NULL;
|
|
if (pwszNamespace !=NULL)
|
|
{
|
|
lstrcat(pwszTemp, pwszNamespace);
|
|
}
|
|
lstrcat(pwszTemp, pwszPropname);
|
|
|
|
// -- copy propid
|
|
ppropid = (DAVPROPID*)malloc(sizeof(DAVPROPID));
|
|
if (ppropid == NULL)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
CopyMemory(ppropid, &propid, sizeof(DAVPROPID));
|
|
|
|
// -- add propid to the list of ids, organized by fullname
|
|
hres = _genlst.Add(pwszTemp,
|
|
ppropid,
|
|
sizeof(DAVPROPID));
|
|
}
|
|
free(pwszTemp);
|
|
}
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
BOOL __stdcall CDavInetPropFindRequestImpl::GetPropInfo(LPCWSTR pwszNamespace,
|
|
LPCWSTR pwszPropName,
|
|
LPDAVPROPID ppropid)
|
|
{
|
|
// locals
|
|
BOOL fReturnCode = FALSE;
|
|
HRESULT hres = S_OK;
|
|
LPWSTR pwszTemp = NULL;
|
|
UINT cchTemp=1;
|
|
UINT cbSize;
|
|
LPVOID lpv;
|
|
|
|
// check args
|
|
if (ppropid == NULL || pwszPropName == NULL)
|
|
{
|
|
hres = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
|
|
// code
|
|
// -- copy full name
|
|
cchTemp = lstrlen(pwszPropName);
|
|
if (pwszNamespace != NULL)
|
|
{
|
|
cchTemp += lstrlen(pwszNamespace);
|
|
}
|
|
|
|
pwszTemp = AllocateStringW(cchTemp);
|
|
if (pwszTemp == NULL)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pwszTemp[0]=NULL;
|
|
if (pwszNamespace !=NULL)
|
|
{
|
|
lstrcat(pwszTemp, pwszNamespace);
|
|
}
|
|
lstrcat(pwszTemp, pwszPropName);
|
|
|
|
|
|
// -- use the string to find the property
|
|
hres = _genlst.Find(pwszTemp,
|
|
&lpv,
|
|
&cbSize);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
if (hres == S_FALSE)
|
|
{
|
|
// if we didn't find it, then return FALSE
|
|
fReturnCode = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// otherwise, copy the data and then return TRUE
|
|
CopyMemory(ppropid, lpv, sizeof(PROPID));
|
|
fReturnCode = TRUE;
|
|
}
|
|
}
|
|
free(pwszTemp);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hres))
|
|
{
|
|
fReturnCode = FALSE;
|
|
}
|
|
return fReturnCode;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CDavInetPropFindRequestImpl::GetPropCount(UINT* cProp)
|
|
{
|
|
return _genlst.Size(cProp);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CDavInetPropFindRequestImpl::GetXmlUtf8(IStream** ppStream)
|
|
{
|
|
// locals
|
|
WCHAR wszTempPath[MAX_PATH];
|
|
WCHAR wszTempFname[MAX_PATH];
|
|
UINT cchTempFname;
|
|
LPWSTR pwszFileURL = NULL;
|
|
CQXML qxml;
|
|
CQXML* pqxml = NULL;
|
|
UINT i;
|
|
UINT cElements;
|
|
HRESULT hres = S_OK;
|
|
LPSTR pszXML = NULL;
|
|
LPWSTR pwszTag = NULL;
|
|
LPWSTR pwszTagNoAlias = NULL;
|
|
LPWSTR pwszXML = NULL;
|
|
ULONG cbWritten;
|
|
ULARGE_INTEGER cbNewPos;
|
|
|
|
|
|
// check args
|
|
if (ppStream == NULL)
|
|
{
|
|
hres = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
// code
|
|
// Create XML blob
|
|
hres = qxml.InitEmptyDoc(L"propfind", L"DAV", L"D");
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
// Populate XML blob
|
|
hres = _genlst.Size(&cElements);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
if (cElements > 0)
|
|
{
|
|
hres = qxml.AppendQXML(NULL, NULL, L"prop", L"DAV", L"D", TRUE, &pqxml);
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
if (hres == S_FALSE)
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < cElements; i++)
|
|
{
|
|
// for each element, get the tag and copy it.
|
|
hres = _genlst.GetTagByDex(i, &pwszTag);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
pwszTag = DuplicateStringW(pwszTag);
|
|
if (pwszTag == NULL)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// look for ':' in the tag
|
|
pwszTagNoAlias = wcschr(pwszTag, ':');
|
|
if (pwszTagNoAlias == NULL)
|
|
{
|
|
// if no ':' was found, then namespace is NULL
|
|
pwszTagNoAlias = pwszTag;
|
|
hres = pqxml->AppendTextNode(NULL, NULL, pwszTagNoAlias, NULL, NULL, NULL, FALSE);
|
|
}
|
|
else
|
|
{
|
|
// if : was found, then after the : is the tag with no alias, before is the namespace
|
|
*pwszTagNoAlias=NULL;
|
|
pwszTagNoAlias++;
|
|
// hres = pqxml->AppendTextNode(NULL, NULL, pwszTagNoAlias, pwszTag, L"Q", NULL, FALSE); // BUGBUG: what is Q?
|
|
hres = pqxml->AppendTextNode(NULL, NULL, pwszTagNoAlias, pwszTag, pwszTag, NULL, FALSE); // BUGBUG: use namespace instead of Q
|
|
}
|
|
|
|
free(pwszTag);
|
|
pwszTag = NULL;
|
|
}
|
|
}
|
|
if (FAILED(hres))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if we don't have any properties, that's our secret code for all the properties
|
|
hres = qxml.AppendTextNode(NULL, NULL, L"allprop", L"DAV", L"D", NULL, FALSE);
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
// convert XML blob to a string, convert string to ANSI string
|
|
hres = qxml.GetXMLTreeTextNoBuf(&pwszXML);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
pszXML = ConvertToANSI(CP_ACP, pwszXML);
|
|
if (pszXML == NULL)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// convert string to an IStream
|
|
// -- get the path and name for a new temp file
|
|
if (GetTempPath(MAX_PATH, wszTempPath) == 0)
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
else if (GetTempFileName(wszTempPath, L"DAV", 0, wszTempFname) == 0)
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
cchTempFname = lstrlen(wszTempFname);
|
|
pwszFileURL = AllocateStringW(cchTempFname + 8); // 8 for "file:///"
|
|
|
|
if (pwszFileURL == NULL)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// turn filepath into a file URL
|
|
lstrcpy(pwszFileURL, L"file:///");
|
|
lstrcpy(pwszFileURL+8, wszTempFname);
|
|
for (i = 8; i < 8 + cchTempFname; i++)
|
|
{
|
|
if (pwszFileURL[i] == '\\')
|
|
{
|
|
pwszFileURL[i] = '/';
|
|
}
|
|
}
|
|
|
|
// -- create IStream on that file
|
|
hres = ::CoCreateInstance(CLSID_HttpStrm,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
//IID_IStream,
|
|
IID_IHttpStrm,
|
|
(LPVOID*)ppStream);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = ((IHttpStrm*)*ppStream)->Open(pwszFileURL, TRUE, TRUE, TRUE);
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
// -- write ANSI string to the file
|
|
hres = (*ppStream)->Write((LPVOID)pszXML, lstrlenA(pszXML), &cbWritten);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
// -- seek the stream pointer to the start of the stream
|
|
LARGE_INTEGER largeint;
|
|
largeint.LowPart = 0;
|
|
largeint.HighPart = 0;
|
|
hres = (*ppStream)->Seek(largeint, STREAM_SEEK_SET, &cbNewPos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// release stuff
|
|
if (pwszTag != NULL)
|
|
{
|
|
free(pwszTag);
|
|
}
|
|
|
|
if (pwszXML != NULL)
|
|
{
|
|
qxml.ReleaseBuf(pwszXML);
|
|
}
|
|
|
|
if (pszXML != NULL)
|
|
{
|
|
free(pszXML);
|
|
}
|
|
|
|
if (pqxml != NULL)
|
|
{
|
|
delete pqxml;
|
|
}
|
|
|
|
// return value
|
|
return hres;
|
|
}
|
|
|