2025-04-27 07:49:33 -04:00

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;
}