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

📄 webdav.h

📁 Windows CE 6.0 Server 源码
💻 H
📖 第 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: webdav.h
Abstract: Web Dav declarations
--*/


//
// Constants and enumerations
//

typedef enum {
	RT_NULL = 0,
	RT_DOCUMENT,
	RT_STRUCTURED_DOCUMENT,
	RT_COLLECTION
} RESOURCE_TYPE;

typedef enum {
	DEPTH_UNKNOWN = 0,
	DEPTH_ZERO,
	DEPTH_ONE,
	DEPTH_INFINITY,
	DEPTH_ONE_NOROOT,
	DEPTH_INFINITY_NOROOT,
} DEPTH_TYPE;

typedef enum {
	OVERWRITE_NO      = 0x0,
	OVERWRITE_YES     = 0x1,
	OVERWRITE_RENAME  = 0x2
} OVERWRITE_TYPE;



#define TokensEqualA(s1,s2,c1,c2)  (((int)(c1)==(int)(c2)) && (0==strncmp((s1),(s2),(c1))))
#define TokensEqualAI(s1,s2,c1,c2) (((c1)==(c2)) && (0==_strnicmp((s1),(s2),(c1))))

// When using const data, assume there's a cszStrName and corresponding ccStrName
#define TokensEqualAC(s1, StrName, c1)   TokensEqualA(s1,csz##StrName, c1, cc##StrName)

#define TokensEqualW2(s1,s2,c1,c2) (((c1)==(c2)) && (0==wcsncmp((s1),(s2),(c1))))
#define TokensEqualW(s1,s2,c1)     TokensEqualW2(s1,s2,c1,SVSUTIL_CONSTSTRLEN(s2))

#define DEBUG_CHECK_ERRCODE(fRet)  DEBUGCHK((fRet && IS_STATUS_2XX(m_pRequest->m_rs)) || (!fRet && !IS_STATUS_2XX(m_pRequest->m_rs)))


// 
//  Chunked Body Response Buffer
//

// How large to allocate on.  Each initial alloc will be two times greater.
#define INITIAL_CHUNK_BUFFER_SIZE      0x2000
// This is the largest the actual body (non-chunked pieces) can grow to.
#define MAX_CHUNK_BODY_SIZE            0xFFEE
// reserve first 6 bytes of the buffer for length of the chunked encode (4 bytes) and for CRLF (2 bytes).
#define CHUNK_PREAMBLE                 6
// How many bytes to set '0CRLFCRLF'
#define CHUNK_CLOSE_LEN                5
// reserve 7 extra bytes for closing of buffer.  2 for CRLF at end of each chunk, 5 for the final "0CRLFCRLF" that signifies we're done sending.
#define CHUNK_POSTAMBLE                (CHUNK_CLOSE_LEN+2)
// How much extra space to reserve for the buffer
#define CHUNK_RESERVE_SPACE            (CHUNK_PREAMBLE+CHUNK_POSTAMBLE)
// Largest buffer can grow to that holds all this stuff
#define MAX_CHUNK_BUFFER_SIZE          (INITIAL_CHUNK_BUFFER_SIZE*8)


class CChunkedBuffer {
private:
	// We use chunked-encoding on certain responses for optimization.
	// When the buffer goes above MAX_CHUNK_BODY_SIZE, we immediatly send response.

	// NOTE: these variables should *never* be accessed from functions outside this class,
	//       as there are a number of idiosyncracies in maintaining a chunked buffer.
	//       Always use accessors!

	char         *m_pszBuf;  // pointer to allocated mem
	DWORD        m_iNextIn;  // next character to read from
	DWORD        m_iSize;    // size of buffer
protected:
	CHttpRequest *m_pRequest;
	BOOL         m_fSentFirstChunk;       // Have we sent our first body response to client yet?

	void       WriteCloseChunk(PSTR szBuf, DWORD dwOffset);
public:
	CChunkedBuffer(CHttpRequest *pR) {
		memset(this,0,sizeof(*this));
		m_pRequest = pR;
	}

	~CChunkedBuffer() {
		FinalBufferConsistencyCheck();
	
		if (m_pszBuf)
			g_funcFree(m_pszBuf,g_pvFreeData);
	}

	BOOL AllocMem(DWORD cbSize);
	BOOL Append(PCSTR pszData, DWORD ccData);
	BOOL FlushBuffer(BOOL fFinalChunk=FALSE);
	BOOL AbortiveError(void);

	BOOL AppendCHAR(const CHAR cAppend) {
		return Append((char *)&cAppend,sizeof(CHAR));
	}

	BOOL IsEmpty(void) {
		return ((m_pszBuf==NULL) && (m_iSize==0));
	}

#if defined (DEBUG)
	BOOL       m_fFinalDataSent;  // will be set true once we're done sending
	
	void BufferConsistencyChecks(void) {
		if (m_pszBuf)
			DEBUGCHK(m_iNextIn && m_iSize);
		else
			DEBUGCHK(!m_iNextIn && !m_iSize);

		DEBUGCHK(m_iNextIn <= m_iSize);

		if (m_iNextIn)
			DEBUGCHK(m_iNextIn >= CHUNK_PREAMBLE);

		// buffer is allocated on predefined boundaries.
		switch (m_iSize) {
			case 0:
			case INITIAL_CHUNK_BUFFER_SIZE:
			case (INITIAL_CHUNK_BUFFER_SIZE*2):
			case (INITIAL_CHUNK_BUFFER_SIZE*4):
			case MAX_CHUNK_BUFFER_SIZE:
				break;

			default:
				DEBUGCHK(0);
		}
	}

	// Make sure that we've flushed the buffer.
	void FinalBufferConsistencyCheck(void) {
		BufferConsistencyChecks();
		DEBUGCHK(m_iNextIn == 0 || m_iNextIn == CHUNK_PREAMBLE);
		if (m_iNextIn)
			DEBUGCHK(!m_pRequest->m_fResponseHTTP11 || m_fFinalDataSent);
	}
#else
	void BufferConsistencyChecks(void)     { ; }
	void FinalBufferConsistencyCheck(void) { ; }
#endif // DEBUG

};

extern const char  cszPrefixBraceOpen[];
extern const DWORD ccPrefixBraceOpen;
extern const char  cszPrefixBraceEnd[];
extern const DWORD ccPrefixBraceEnd;

class CXMLBuffer : public CChunkedBuffer {

public:
	CXMLBuffer(CHttpRequest *pR) : CChunkedBuffer(pR) { 
		; 
	}
	~CXMLBuffer() { ; }

	BOOL Encode(PCSTR pszData);
	BOOL EncodeURL(PCSTR pszData);

	BOOL BeginBrace(void) {
		return Append(cszPrefixBraceOpen,ccPrefixBraceOpen);
	}

	BOOL CloseBrace(void) {
		return AppendCHAR('>');
	}

	BOOL EndBrace(void) {
		return Append(cszPrefixBraceEnd,ccPrefixBraceEnd);
	}

	BOOL BeginBraceNoNS(void) {
		return AppendCHAR('<');
	}

	BOOL StartTag(const CHAR *szElementName)  {
		if (!BeginBrace() ||
		    !Encode(szElementName) ||
		    !CloseBrace())
			return FALSE;
		return TRUE;
	}

	BOOL StartTagNoEncode(const CHAR *szElementName, int ccElementName=-1) {
		if (!BeginBrace() ||
		    !Append(szElementName,(ccElementName==-1) ? strlen(szElementName) : ccElementName) ||
		    !CloseBrace())
			return FALSE;
		return TRUE;
	}
	
	BOOL EndTag(const CHAR *szElementName) { 
		if (!EndBrace() ||
		    !Encode(szElementName) ||
		    !CloseBrace() )
			return FALSE;
		return TRUE;
	}

	BOOL SetCRLF(void) {
		return Append("\r\n",2);
	}

	BOOL SetEmptyElement(const CHAR *szElementName) {
		if (!BeginBrace() ||
		    !Encode(szElementName) ||
		    !Append("/>",2))
			return FALSE;
		return TRUE;
	}

	BOOL SetEmptyElementNoEncode(const CHAR *szElementName, int ccElementName=-1) {
		if (!BeginBrace() ||
		    !Append(szElementName,(ccElementName==-1) ? strlen(szElementName) : ccElementName) ||
		    !Append("/>",2))
			return FALSE;
		return TRUE;
	}

	// Setting tags in an 207 multistatus XML blob
	BOOL SetStatusTag(RESPONSESTATUS rs);
};

#define RECEIVE_SIZE_UNINITIALIZED   ((DWORD)-1)

// For keeping track of receiving POST data.
class CReceiveBody {
public:
	BOOL  fChunked;
	// length of unread portion of current chunk, or length of remaining POST body in non-chunked.
	DWORD dwRemaining;

	CReceiveBody() {
		dwRemaining = RECEIVE_SIZE_UNINITIALIZED;
	}

	~CReceiveBody() { ; }
} ;


// For recursing through directory structure.
class CWebDav;
class CWebDavFileNode;

typedef BOOL (WINAPI *PFN_RECURSIVE_VISIT)(CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot);

BOOL SendPropertiesVisitFcn    (CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot);
BOOL SendPropertyNamesVisitFcn (CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot);
BOOL DeleteVisitFcn            (CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot);
BOOL MoveCopyVisitFcn          (CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot);


// When recursing through directories performing a move or copy, info to keep 
// our place in the stack during calls to MoveCopyVisitFcn().
class CMoveCopyContext { 
public:
	DWORD dwSrcPermFlags;  // HSE_URL_FLAGS_xxx perms for source VRoot
	DWORD dwDestPermFlags; // HSE_URL_FLAGS_xxx perms for destination VRoot

	PSTR  szDestURL;       // canonicalized destination URL
	WCHAR *wszDestPath;    // root of physical path to write data to.
	DWORD ccDestPath;      // number of WCHARs in dest physical path
	DWORD ccSrcPath;       // number of WCHARs in source physical path
	BOOL  fDeleteSrc;      // copy or move files?

	CMoveCopyContext(BOOL fDelSrc, DWORD dwSrc, DWORD dwDest, PSTR szURL, WCHAR *wszPath, DWORD ccSrcP) {
		dwSrcPermFlags   = dwSrc;
		dwDestPermFlags  = dwDest;
		szDestURL        = szURL;
		wszDestPath      = wszPath;
		ccDestPath       = wcslen(wszDestPath);
		ccSrcPath        = ccSrcP;
		fDeleteSrc       = fDelSrc;
	}

	~CMoveCopyContext() {
		// do not free string resources, they are pointers to static buffers in calling function.
	}
};

// When recursing through directories on a delete, options info
class CDavDeleteContext {
public:
	CHAR *szURL;
	BOOL fSendErrorsToClient;

	CDavDeleteContext(CHAR *sz, BOOL f) { 
		szURL = sz;
		fSendErrorsToClient = f;
	}
};

typedef SVSExpArray<__int64> LockIdArray;

//
//  Main WebDAV class
//
class CWebDav {
friend class CWebDavFileLockManager;

public:
	CHttpRequest     *m_pRequest;             // request class
private:
	RESOURCE_TYPE    m_rt;                    // are we a directory, file, or a non-existant resource?
	DEPTH_TYPE       m_Depth;                 // "Depth:" HTTP header
	DWORD            m_Overwrite;             // "overwrite: " HTTP header
	CXMLBuffer       m_bufResp;               // Response class that generates chunked HTTP and encodes XML data.
	SVSSimpleBuffer  m_bufUnknownTags;        // PROPFIND or PROPPATCH tags that WinCE doesn't support are stored in a NULL separeted list of strings to be sent back later to client.
	CHAR             m_szHostName[MAX_PATH];  // cache the host name to only call gethostname() once
	DWORD            m_ccHostName;            // length of m_szHostName
	CReceiveBody     m_rcvBody;               // Context used when calling WriteFile during a PUT
	BOOL             m_fSetStatus;            // Have we sent "207" headers already?
public:
	BOOL             m_fXMLBody;              // are we sending XML?

	DWORD            m_dwPropPatchUpdate;     // fields that have been updated during PROPPATCH.

private:
	WIN32_FILE_ATTRIBUTE_DATA m_fileAttribs;            // cache attribs to only call GetFileAttributesEx(m_pRequest->m_wszPath,...) once.
	BOOL                      m_fRetrievedFileAttribs;  // have we called GetFileAttributesEx() yet?
	LockIdArray               m_lockIds;                // store lock tokens
	int                       m_nLockTokens;            // number of lock tokens we've parsed from (if: XXX field)

	// ******************************************************
	// Utility functions
	// ******************************************************
	BOOL IsGLELocked(void) {
		// in theory ERROR_SHARING_VIOLATION should be only error code we'd take to mean a locking 
		// violation.  However some CE filesystems set ERROR_ACCESS_DENIED as error code when
		// they mean ERROR_SHARING_VIOLATION.  BUGBUG - what are prospects for getting this fixed on all filesystems?

		DWORD dw = GetLastError();
		return ((dw == ERROR_SHARING_VIOLATION) || (dw == ERROR_ACCESS_DENIED));

⌨️ 快捷键说明

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