⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 davxml.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: davxml.cpp
Abstract: WebDAV main verb handeling routines
--*/


#include "httpd.h"

// *****************************************************************
// Utility functions for parsing XML
// *****************************************************************
BOOL UTF8ToBSTR(PSTR psz, BSTR *ppBstr) {
	DWORD cp = CP_UTF8;

	int iLen = MultiByteToWideChar(cp, 0, psz, -1, NULL, NULL);
	if (0 == iLen) {
		cp = CP_ACP;
		iLen = MultiByteToWideChar(cp, 0, psz, -1, NULL, NULL);

		if (0 == iLen) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: Unable to convert UTF8 text to UNICODE.  GLE=0x%08x\r\n",GetLastError()));
			return FALSE;
		}
	}

	if (NULL == ((*ppBstr) = SysAllocStringByteLen(NULL,(iLen+1)*sizeof(WCHAR)))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: SysAllocStringByteLen fails.  GLE=0x%08x\r\n",GetLastError()));
		return FALSE;
	}

	MultiByteToWideChar(cp, 0, psz, -1, *ppBstr, iLen);
	return TRUE;
}


// Creates a SAX parser and passes it pParser, which implements logic for
// particular verb.
BOOL CWebDav::ParseXMLBody(ISAXContentHandler *pParser, BOOL fSetDefaultStatus) {
	BOOL    fCoUnInit        = FALSE;
	HRESULT hr               = E_FAIL;
	RESPONSESTATUS rs        = STATUS_INTERNALERR;
	ISAXXMLReader* pReader   = NULL;
	VARIANT varInput;

	memset(&varInput,0,sizeof(varInput));

	DEBUGCHK(m_pRequest->m_rs == STATUS_OK);
	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav initiating SAX parser to parse XML body\r\n"));

	if (STATUS_OK != (rs = VerifyXMLBody()))
		goto done;

	rs = STATUS_INTERNALERR;

	if (FAILED(hr = CoInitializeEx(NULL,COINIT_MULTITHREADED))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: CoInitializeEx failed, GLE=0x%08x\r\n",GetLastError()));
		goto done;
	}
	fCoUnInit = TRUE;

	if (FAILED(hr = CoCreateInstance(CLSID_SAXXMLReader, NULL, CLSCTX_INPROC_SERVER, IID_ISAXXMLReader, (void**)&pReader))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: CoCreateInstance(CLSID_SAXXMLReader) failed, error=0x%08x\r\n",hr));
		goto done;
	}

	if (FAILED(hr = pReader->putContentHandler(pParser))) {
		DEBUGMSG(ZONE_ERROR, (L"HTTPD: ISAXXMLReader::putContentHandler failed, error=0x%08x\r\n",hr));
		goto done;
	}

	varInput.vt          = VT_BSTR;
	if (!UTF8ToBSTR((PSTR)m_pRequest->m_bufRequest.Data(),&varInput.bstrVal))
		goto done;

	if (FAILED(hr = pReader->parse(varInput))) {
		// If the parse routines didn't set the error otherwise, assume it was invalid XML that caused problem.
		if (m_pRequest->m_rs == STATUS_OK)
			rs = STATUS_BADREQ;

		DEBUGMSG (ZONE_ERROR, (L"HTTPD: ISAXXMLReader::parse().  Error = 0x%08x\r\n",hr));
		goto done;
	}

	hr = S_OK;
done:
	if (varInput.bstrVal)
		SysFreeString(varInput.bstrVal);

	if (pReader)
		pReader->Release();

	if (fCoUnInit)
		CoUninitialize();

	if (fSetDefaultStatus) {
		// For PROPFIND, the ISAXContentHandler implementation does all the logic processing.
		// If it did not set a status, means that the XML tags it required to see
		// never were parsed, so set appropriate errors now as appropriate.
		if ((hr==S_OK) && !m_fSetStatus) {
			rs = STATUS_BADREQ;
		}
		DEBUGCHK(rs != STATUS_OK);

		if (m_pRequest->m_rs == STATUS_OK) {
			SetStatus(rs);
			return FALSE;
		}
	}
	else if ((hr != S_OK) && !m_fSetStatus) {
		// On PROPPATCH and LOCK, routine outside of ISAXContentHandler,
		// handles most of the logic, so don't set default errors.
		SetStatus(rs);
	}
	
	return (hr == S_OK);
}

// 
BOOL CLockParse::WriteXMLTagToBuffer(const wchar_t * pwchNamespaceUri, int cchNamespaceUri, const wchar_t * pwchLocalName, 
                     int cchLocalName, const wchar_t * pwchQName, int cchQName, ISAXAttributes * pAttributes, BOOL fIsStartTag) {

	if (fIsStartTag) {
		if (FAILED(m_OwnerXML.startElement(pwchNamespaceUri,cchNamespaceUri,pwchLocalName,cchLocalName,pwchQName,cchQName,pAttributes)))
			return FALSE;
	}
	else {
		if (FAILED(m_OwnerXML.endElement(pwchNamespaceUri,cchNamespaceUri,pwchLocalName,cchLocalName,pwchQName,cchQName)))
			return FALSE;
	}


	return TRUE;
}


#if defined (DEBUG)
inline void DebugOutUnexpectedToken(const CHAR *szTokenExpected, const CHAR *szLocalName, int ccLocalName) {
	DEBUGMSG(ZONE_ERROR,(L"HTTPD: Error  parsing xml, expecting token \"%a:\", got %*a\r\n",szTokenExpected,ccLocalName,szLocalName));
}
inline void DebugOutInvalidChild(const CHAR *szCurrentNode) {
	DEBUGMSG(ZONE_ERROR,(L"HTTPD: Error  parsing xml, node \"%a:\" has a child node, illegal\r\n",szCurrentNode));
}
inline void DebugOutUnknown(void) {
	DEBUGMSG(ZONE_ERROR,(L"HTTPD: Error, xml parser in unknown state due to unhandled tags.  Reqeust fails.\r\n"));
}

#else
inline void DebugOutUnexpectedToken(const CHAR *szTokenExpected, const CHAR *szLocalName, int ccLocalName) { ; }
inline void DebugOutInvalidChild(const CHAR *szCurrentNode) { ; }
inline void DebugOutUnknown(void) { ; }
#endif


const WCHAR cwszDavNameSpace[]           = L"DAV:";
const DWORD ccDavNameSpace               = SVSUTIL_CONSTSTRLEN(cwszDavNameSpace);

BOOL CDavParse::VerifyNS(DAV_NAMESPACE ns, const WCHAR *szNamespace, DWORD ccNamespace) {
	switch (ns) {
	case NAMESPACE_DAV:
		if ( ! TokensEqualW(szNamespace,cwszDavNameSpace,ccNamespace)) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: Error parsing DAV xml, expecting NS \"%s:\", got %*s\r\n",cwszDavNameSpace,ccNamespace,szNamespace));
			return FALSE;
		}
		break;

/*	case NAMESPACE_MS:
		if ( ! TokensEqualW(szNamespace,cwszMSNamespace,ccNamespace)) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: Error parsing DAV xml, expecting NS \"%s:\", got %*s\r\n",cwszMSNamespace,ccNamespace,szNamespace));
			return FALSE;
		}
		break;
*/
	default:
		SVSUTIL_ASSERT(0);
		return FALSE;
	}
	return TRUE;
}

#define VerifyRequiredTagC(szTokenExpected,szLocalName,ccLocalName) VerifyRequiredTag(szTokenExpected,SVSUTIL_CONSTSTRLEN(szTokenExpected),szLocalName,ccLocalName)

BOOL CDavParse::PrepareNonEmptyBuf(void) {
	if (m_Chars.uiNextIn == 0) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: WebDAV request fails, an element that requires data did not set it\r\n"));
		return FALSE;
	}

	if (! m_Chars.AppendWCHAR(L'\0')) {
		return FALSE;
	}

	return TRUE;
}

// called when a token must match szTokenExpected.
BOOL CDavParse::VerifyRequiredTag(const CHAR *szTokenExpected, DWORD ccExpected, const CHAR *szLocalName, DWORD ccLocalName) {
	if (! TokensEqualA(szTokenExpected,szLocalName,ccExpected,ccLocalName)) {
		DebugOutUnexpectedToken(szTokenExpected,szLocalName,ccLocalName);
		return FALSE;
	}
	return TRUE;
}


// Checks that content-length !=0, that the content-type is xml, and that we're not
// receiving more than m_dwPostReadSize bytes.
RESPONSESTATUS CWebDav::VerifyXMLBody(void) {
	if (! IsContentTypeXML()) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: WebDav request fails, client did not set content-type to XML\r\n"));
		return STATUS_BADREQ;
	}

	if (! HasBody()) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: WebDav request fails, client did not send body (required)\r\n"));
		return STATUS_LENGTH_REQUIRED;
	}

	if (! HasServerReadAllData()) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: WebDav request fails, client sent %d body bytes, content-length = %d\r\n",m_pRequest->m_bufRequest.Count(),m_pRequest->m_dwContentLength));
		return STATUS_REQUEST_TOO_LARGE;
	}
	return STATUS_OK;
}


// *****************************************************************
// Implementations of classes that parse XML.
// *****************************************************************

//
// PROPFIND
//  
const CHAR  cszPropfind[]   = "propfind";
const DWORD ccPropfind      = SVSUTIL_CONSTSTRLEN(cszPropfind);
const CHAR  cszPropName[]   = "propname";
const DWORD ccPropName      = SVSUTIL_CONSTSTRLEN(cszPropName);
const CHAR  cszAllProp[]    = "allprop";
const DWORD ccAllProp       = SVSUTIL_CONSTSTRLEN(cszAllProp);


#define LOCAL_NAME_SIZE     256

inline BOOL ConvertXMLTagToANSI(const wchar_t * pwchLocalName, int cchLocalName, PSTR szLocalName) {
	int nChars;
	UINT uiCodePage = GetUTF8OrACP();

	if (0 == (nChars = WideCharToMultiByte(uiCodePage, 0, pwchLocalName, cchLocalName, szLocalName, LOCAL_NAME_SIZE-1, 0, 0))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: DAV request failed, WideCharToMultiByte(%s,len=%d) failed, GLE=0x%08x\r\n",pwchLocalName,cchLocalName));
		return FALSE;
	}
	szLocalName[nChars] = 0;

	return TRUE;
}


HRESULT STDMETHODCALLTYPE CPropFindParse::startElement(const wchar_t * pwchNamespaceUri, int cchNamespaceUri, const wchar_t * pwchLocalName, 
                          int cchLocalName, const wchar_t * pwchQName, int cchQName, ISAXAttributes * pAttributes) {
	m_Chars.Reset();

	CHAR szLocalName[LOCAL_NAME_SIZE];
	if (! ConvertXMLTagToANSI(pwchLocalName,cchLocalName,szLocalName))
		return E_FAIL;

	switch (m_State) {
		case DAV_STATE_UNINITAILIZED:
			if (! VerifyNS(NAMESPACE_DAV,pwchNamespaceUri,cchNamespaceUri) ||
			    ! VerifyRequiredTagC(cszPropfind,szLocalName,cchLocalName))
				return E_FAIL;

			m_State = PROPFIND_STATE_PROPFIND;
		break;

		case PROPFIND_STATE_ALLPROP:
		case PROPFIND_STATE_PROPNAME:
		case DAV_STATE_UNKNOWN:
			DebugOutUnknown();
			return E_FAIL;
		break;

		case PROPFIND_STATE_PROPFIND:
			if (! VerifyNS(NAMESPACE_DAV,pwchNamespaceUri,cchNamespaceUri))
				return E_FAIL;

			if (TokensEqualAC(szLocalName,AllProp,cchLocalName))
				m_State = PROPFIND_STATE_ALLPROP;
			else if (TokensEqualAC(szLocalName,PropName,cchLocalName))
				m_State = PROPFIND_STATE_PROPNAME;
			else if (TokensEqualAC(szLocalName,Prop,cchLocalName))
				m_State = PROPFIND_STATE_PROP;
			else {
				DebugOutUnexpectedToken("prop, propname, or anyprop",szLocalName,cchLocalName);
				return E_FAIL;
			}
		break;

		case PROPFIND_STATE_PROP:
		//	if (! VerifyNS(NAMESPACE_DAV,pwchNamespaceUri,cchNamespaceUri))
		//		return E_FAIL;

			if (TokensEqualAC(szLocalName,GetcontentLength,cchLocalName))
				m_State = PROPFIND_STATE_CONTENT_LEN;
			else if (TokensEqualAC(szLocalName,DisplayName,cchLocalName))
				m_State = PROPFIND_STATE_DISPLAY_NAME;
			else if (TokensEqualAC(szLocalName,CreationDate,cchLocalName))
				m_State = PROPFIND_STATE_CREATION_DATE;
			else if (TokensEqualAC(szLocalName,GetETag,cchLocalName))
				m_State = PROPFIND_STATE_GET_ETAG;
			else if (TokensEqualAC(szLocalName,LastModified,cchLocalName))
				m_State = PROPFIND_STATE_LAST_MODIFIED;
			else if (TokensEqualAC(szLocalName,ResourceType,cchLocalName))
				m_State = PROPFIND_STATE_RESOURCE_TYPE;
			else if (TokensEqualAC(szLocalName,IsHidden,cchLocalName))
				m_State = PROPFIND_STATE_IS_HIDDEN;
			else if (TokensEqualAC(szLocalName,IsCollection,cchLocalName))
				m_State = PROPFIND_STATE_IS_COLLECTION;
			else if (TokensEqualAC(szLocalName,SupportedLock,cchLocalName))
				m_State = PROPFIND_STATE_SUPPORTED_LOCK;
			else if (TokensEqualAC(szLocalName,LockDiscovery,cchLocalName))
				m_State = PROPFIND_STATE_LOCK_DISCOVERY;
			else if (TokensEqualAC(szLocalName,GetcontentType,cchLocalName))
				m_State = PROPFIND_STATE_CONTENT_TYPE;
			else {
				DebugOutUnexpectedToken("recognized prop tags",szLocalName,cchLocalName);

				if ((m_iUnknownDepth == 0) && ! m_pWebDav->AddUnknownXMLElement(pwchQName,cchQName))
					return E_FAIL;

				SetUnknownTag();
			}
		break;

		default:
			DebugOutUnexpectedToken("???",szLocalName,cchLocalName);
			//SetUnknownTag();
			return E_FAIL;
		break;
	}

	return S_OK;

}


HRESULT STDMETHODCALLTYPE CPropFindParse::endElement(const wchar_t  *pwchNamespaceUri, int cchNamespaceUri, const wchar_t  *pwchLocalName,
	                                 int cchLocalName, const wchar_t  *pwchQName, int cchQName) {

	BOOL fRet = TRUE;

	switch (m_State) {
		case PROPFIND_STATE_PROPFIND:
			m_State  = DAV_STATE_UNKNOWN;
		break;

		case PROPFIND_STATE_ALLPROP:
			m_State = PROPFIND_STATE_PROPFIND;
			fRet = m_pWebDav->SendProperties(DAV_PROP_ALL,FALSE);
		break;

		case PROPFIND_STATE_PROPNAME:
			m_State = PROPFIND_STATE_PROPFIND;
			fRet = m_pWebDav->SendProperties(DAV_PROP_ALL,TRUE);
		break;

		case PROPFIND_STATE_PROP:
			m_State = PROPFIND_STATE_PROPFIND;
			fRet = m_pWebDav->SendProperties(m_dwDavProperties,FALSE);
		break;

		case PROPFIND_STATE_CONTENT_LEN:
			m_dwDavProperties  |= DAV_PROP_CONTENT_LENGTH; 
			m_State            = PROPFIND_STATE_PROP;
		break;

		case PROPFIND_STATE_DISPLAY_NAME:
			m_dwDavProperties  |= DAV_PROP_DISPLAY_NAME; 
			m_State            = PROPFIND_STATE_PROP;
		break;
		
		case PROPFIND_STATE_CREATION_DATE:
			m_dwDavProperties  |= DAV_PROP_CREATION_DATE;
			m_State            = PROPFIND_STATE_PROP;
		break;
		
		case PROPFIND_STATE_GET_ETAG:
			m_dwDavProperties  |= DAV_PROP_GET_ETAG; 
			m_State            = PROPFIND_STATE_PROP;
		break;
		
		case PROPFIND_STATE_LAST_MODIFIED:
			m_dwDavProperties  |= DAV_PROP_GET_LAST_MODIFIED; 
			m_State            = PROPFIND_STATE_PROP;
		break;
		
		case PROPFIND_STATE_RESOURCE_TYPE:
			m_dwDavProperties  |= DAV_PROP_RESOURCE_TYPE; 
			m_State            = PROPFIND_STATE_PROP;
		break;

		case PROPFIND_STATE_IS_HIDDEN:
			m_dwDavProperties  |= DAV_PROP_IS_HIDDEN; 
			m_State            = PROPFIND_STATE_PROP;
		break;

		case PROPFIND_STATE_IS_COLLECTION:
			m_dwDavProperties  |= DAV_PROP_IS_COLLECTION; 
			m_State            = PROPFIND_STATE_PROP;
		break;

		case PROPFIND_STATE_SUPPORTED_LOCK:
			m_dwDavProperties  |= DAV_PROP_SUPPORTED_LOCK; 
			m_State            = PROPFIND_STATE_PROP;
		break;

		case PROPFIND_STATE_LOCK_DISCOVERY:
			m_dwDavProperties  |= DAV_PROP_LOCK_DISCOVERY; 
			m_State            = PROPFIND_STATE_PROP;
		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -