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

322 lines
14 KiB
C++

#include <assert.h>
#include "asynccall.h"
#include "qxml.h"
#include "strutil.h"
#include "regexp.h"
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CAsyncWntCallbackImpl::Init (IDavCallback* pcallback,
DWORD dwParam,
LPWSTR pwszUserName,
LPWSTR pwszPassword,
BOOL fNoRoot)
{
HRESULT hres = S_OK;
_pcallback = pcallback;
_dwParam = dwParam;
// if we have a password, must have a username
if (pwszUserName == NULL && pwszPassword != NULL)
{
hres = E_INVALIDARG;
}
if (SUCCEEDED(hres))
{
_fNoRoot = fNoRoot;
if (pwszUserName)
{
lstrcpyn(_wszUserName, pwszUserName, 255);
}
else
{
*_wszUserName = NULL;
}
if (pwszPassword)
{
lstrcpyn(_wszPassword, pwszPassword, 255);
}
else
{
*_wszPassword = NULL;
}
}
return hres;
}
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CAsyncWntCallbackImpl::OnAuthChallenge(TCHAR __RPC_FAR szUserName[ 255 ],
TCHAR __RPC_FAR szPassword[ 255 ])
{
HRESULT hres = S_OK;
if (*_wszUserName == NULL && *_wszPassword == NULL)
{
// if the user provided neither username nor password, we need to use the callback
hres = _pcallback->OnAuthChallenge(szUserName, szPassword);
}
else if (*_wszUserName != NULL && *_wszPassword == NULL)
{
// the user may have specified a name but no password, we should respect that
lstrcpyn(szUserName, _wszUserName, 255);
*_wszPassword = NULL;
}
else
{
// szPassword is not null, szUserName better be non-null too
// we can assert b/c we checked this in Init
assert(szUserName != NULL);
lstrcpyn(szUserName, _wszUserName, 255);
lstrcpyn(szPassword, _wszPassword, 255);
}
return hres;
}
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CAsyncWntCallbackImpl::Respond(LPWSTR pwszVerb,
LPWSTR pwszPath,
DWORD cchHeaders,
LPWSTR pwszHeaders,
DWORD dwStatusCode,
LPWSTR pwszStatusCode,
LPWSTR pwszContentType,
DWORD cbSent,
LPBYTE pbResponse,
DWORD cbResponse)
{
// local
HRESULT hres = S_OK;
CQXML qxml;
DAVRESPONSE davResponse;
// argument checking
if (pwszVerb == NULL || pwszPath == NULL || (cbResponse > 0 && pbResponse == NULL) || (cchHeaders == 0 && pwszHeaders != NULL))
{
hres = E_INVALIDARG;
}
else
{
// code
// -- populate the davResponse object to send back
davResponse.fDone = TRUE; // we are purely synchronous for now, we block until all data is ready
davResponse.uHTTPReturnCode = dwStatusCode;
if (dwStatusCode < 100) {
davResponse.hrResult = E_FAIL; // undefined
hres = E_INVALIDARG;
}
else if (dwStatusCode < 200) { // note that < 200 means 100-199
davResponse.hrResult = S_OK; // RFC 2616 defines 1?? as "informational", ignore
}
else if (dwStatusCode < 300) {
davResponse.hrResult = S_OK; // RFC 2616 defines 2?? as "OK"
}
else if (dwStatusCode < 400) {
davResponse.hrResult = E_FAIL; // RFC 2616 defines 3?? as "redirection", we can't support this for now
}
else if (dwStatusCode < 500) {
davResponse.hrResult = E_FAIL; // RFC 2616 defines 4?? as "error"
}
else if (dwStatusCode < 600) {
davResponse.hrResult = E_FAIL; // RFC 2616 defines 5?? as "internal server error"
}
else
{
davResponse.hrResult = E_FAIL; // undefinfed
hres = E_INVALIDARG;
}
// important: if there is no callback registered, then we just return the hrResult
if (_pcallback == NULL)
{
hres = davResponse.hrResult;
}
else if (SUCCEEDED(hres)) // check not if we got a success code, but if we got a VALID HTTP code
{
// now dispatch on the verb, executing the appropriate method and populating the davResponse object with more data
// for now, we don't do any work after the method, but we might in the future. (logging?)
if (lstrcmp(pwszVerb, L"GET") == 0)
{
hres = this->_RespondHandleGET(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"OPTIONS") == 0)
{
hres = this->_RespondHandleOPTIONS(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"HEAD") == 0)
{
hres = this->_RespondHandleHEAD(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"PUT") == 0)
{
hres = this->_RespondHandlePUT(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"POST") == 0)
{
hres = this->_RespondHandlePOST(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"MKCOL") == 0)
{
hres = this->_RespondHandleMKCOL(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"COPY") == 0)
{
hres = this->_RespondHandleCOPY(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"MOVE") == 0)
{
hres = this->_RespondHandleMOVE(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"DELETE") == 0)
{
hres = this->_RespondHandleDELETE(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"PROPFIND") == 0)
{
hres = this->_RespondHandlePROPFIND(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"PROPPATCH") == 0)
{
hres = this->_RespondHandlePROPPATCH(&davResponse,
pwszVerb,
pwszPath,
cchHeaders,
pwszHeaders,
dwStatusCode,
pwszStatusCode,
pwszContentType,
cbSent,
pbResponse,
cbResponse);
}
else if (lstrcmp(pwszVerb, L"SEARCH") == 0)
{
// parse the response as if it were a DAV SEARCH command
hres = E_INVALIDARG;
}
else if (lstrcmp(pwszVerb, L"REPLSEARCH") == 0)
{
// parse the response as if it were a DAV REPLSEARCH command
hres = E_INVALIDARG;
}
else
{
hres = E_INVALIDARG;
}
}
}
return hres;
}