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

📄 davutil.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		if (m_rcvBody.fChunked)
			DEBUGCHK(0);
		else {
			m_rcvBody.dwRemaining = m_pRequest->m_dwContentLength-m_pRequest->m_bufRequest.Count();
			DEBUGCHK((int)m_rcvBody.dwRemaining > 0);
		}
	}

	if ((int) m_rcvBody.dwRemaining <= 0) {
		*pcbRead = 0;
		return TRUE;
	}

	*pcbRead = min(*pcbRead,m_rcvBody.dwRemaining);
	fRet = m_pRequest->ReadClient(szBuf,pcbRead);

	m_rcvBody.dwRemaining -= *pcbRead;

	if (!m_rcvBody.fChunked)
		return fRet;

	// chunked needs to parse through buffer (actually to the end of, +5 bytes at most) to look for next read size.
	return FALSE;
}

BOOL CWebDav::IsContentTypeXML(void) {
	PSTR szHeader;
	DWORD ccContent;
	
	const CHAR rgcDelimitSet[] = { ';', '\t', ' ', '\r', '\0' };

	if (NULL == (szHeader = m_pRequest->FindHttpHeader(cszContent_Type,ccContent_Type))) {
		// Note: If there is no content-type header we should return FALSE in this case,
		// however certain existing clients do not set the "content-type" field but send XML
		// anyway.  To work with them return TRUE.
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: Warning: WebDAV client did not set content-type, treating as if content-type: text/xml\r\n"));
		return TRUE;
	}

	// Content-length: may have extra info like "; charset=\"utf8\" appended to content-type, ignore it.
	ccContent = strcspn(szHeader,rgcDelimitSet);
	DEBUGCHK(ccContent);

	if ((TokensEqualAI(szHeader,cszTextXML,ccContent,ccTextXML)) ||
	    (TokensEqualAI(szHeader,cszApplicationXML,ccContent,ccApplicationXML)))
	{
		return TRUE;
	}
	return FALSE;
}

BOOL CXMLBuffer::SetStatusTag(RESPONSESTATUS rs) {
	CHAR szStatus[256];
	int iLen = sprintf(szStatus,"HTTP/1.1 %d %s",rgStatus[rs].dwStatusNumber,rgStatus[rs].pszStatusText);
	DEBUGCHK(iLen < sizeof(szStatus));
	DEBUGCHK(rs < STATUS_MAX);

	return (StartTag(cszStatus)   &&
	        Append(szStatus,iLen) &&
	        EndTag(cszStatus));
}

BOOL CWebDav::SetHREFTag(PCSTR szURL) {
	if (! m_bufResp.StartTag(cszHref))
		return FALSE;

	if (!BuildBaseURLFromSourceURL())
		return FALSE;

	if (szURL && ! m_bufResp.EncodeURL(szURL))
		return FALSE;

	if (! m_bufResp.EndTag(cszHref))
		return FALSE;

	return TRUE;
}

BOOL CWebDav::SetHREFTagFromDestinationPath(WIN32_FIND_DATA *pFindData, WCHAR *szDirectory, BOOL fRootDir, PCSTR szRootURL, BOOL fSkipFileMunge) {
	CHAR  szBuf[MINBUFSIZE]; // temp write buffer

	// When we're accessing root of physical filesystem, offset is different.
	DWORD ccDestPath = m_pRequest->IsRootPath() ? 0 : m_pRequest->m_ccWPath;

	if (!szRootURL)
		szRootURL = m_pRequest->m_pszURL;

	if (! m_bufResp.StartTag(cszHref))
		return FALSE;

	BOOL fAddSlash = (pFindData && !fSkipFileMunge && szDirectory && !URLHasTrailingSlashA(szRootURL));
	
	if (!BuildBaseURL(szRootURL,FALSE,fAddSlash))
		return FALSE;

	if (!fSkipFileMunge) {
		DEBUGCHK(pFindData != NULL);

		// Build up the remainder of URL by adding everything past the root of the destination path.
		DWORD ccBuf = 0;

		if (!fRootDir) {
			DEBUGCHK(wcslen(szDirectory+ccDestPath+1) > 0);
			DEBUGCHK((szDirectory[ccDestPath] == '\\') || (szDirectory[ccDestPath] == '/'));

			DWORD cc = MyW2UTF8(szDirectory+ccDestPath+1,szBuf,sizeof(szBuf));
			if (0 == cc)
				return FALSE;

			ccBuf += (cc-1);

			DEBUGCHK(szBuf[ccBuf] == 0);
			for (DWORD i = 0; i < ccBuf; i++) {
				if (szBuf[i] == '\\')
					szBuf[i] = '/';
			}
			szBuf[ccBuf]   = '/';
			szBuf[++ccBuf] = 0;
		}

		PREFAST_SUPPRESS(11,"fSkipFileMunge==FALSE ==> pFindData != NULL.");
		if (pFindData->cFileName[0]) {
			DWORD cc = MyW2UTF8(pFindData->cFileName,szBuf+ccBuf,sizeof(szBuf)-ccBuf);
			if (0 == cc)
				return FALSE;

			ccBuf += (cc-1);
		}

		if (IsDirectory(pFindData)) {
			szBuf[ccBuf]   = '/';
			szBuf[++ccBuf] = 0;
		}
		DEBUGCHK((ccBuf+1) < sizeof(szBuf));
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav SetHREFTagFromDestinationPath sets buffer = <<%a>>\r\n",szBuf));

		if (! m_bufResp.EncodeURL(szBuf))
			return FALSE;
	}

	if (! m_bufResp.EndTag(cszHref))
		return FALSE;

	return TRUE;
}

// Buildup <response> blob.
BOOL CWebDav::SetResponseTag(PCSTR szURL, RESPONSESTATUS rs) {
	DEBUGCHK(m_pRequest->m_rs == STATUS_MULTISTATUS);

	return ( m_bufResp.StartTag(cszResponse) &&
	         SetHREFTag(szURL)               &&
	         m_bufResp.SetStatusTag(rs)      &&
	         m_bufResp.EndTag(cszResponse));
}

BOOL CWebDav::SetMultiStatusErrorFromDestinationPath(RESPONSESTATUS rs, WIN32_FIND_DATA *pFindData, WCHAR *szDirectory, BOOL fRootDir, PCSTR szRootURL, BOOL fSkipFileMunge) {
	if (! SetMultiStatusResponse())
		return FALSE;

	return ( m_bufResp.StartTag(cszResponse) &&
	         SetHREFTagFromDestinationPath(pFindData,szDirectory,fRootDir,szRootURL,fSkipFileMunge)  &&
	         m_bufResp.SetStatusTag(rs)      &&
	         m_bufResp.EndTag(cszResponse));
}


BOOL CWebDav::SetMultiStatusErrorFromURL(RESPONSESTATUS rs, PCSTR szRootURL) {
	if (! SetMultiStatusResponse())
		return FALSE;

	return ( m_bufResp.StartTag(cszResponse) &&
	         SetHREFTagFromDestinationPath(NULL,NULL,FALSE,szRootURL,TRUE)  &&
	         m_bufResp.SetStatusTag(rs)      &&
	         m_bufResp.EndTag(cszResponse));
}

// Stub functions to call into class
BOOL SendPropertiesVisitFcn(CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot) {
	return pThis->SendPropertiesVisitFcn(pFindData, dwContext, szPath, fIsRoot);
}

BOOL SendPropertyNamesVisitFcn(CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot) {
	return pThis->SendPropertyNamesVisitFcn(pFindData, dwContext, szPath, fIsRoot);
}

BOOL DeleteVisitFcn(CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot) {
	return pThis->DeleteVisitFcn(pFindData, dwContext, szPath, fIsRoot);
}

BOOL MoveCopyVisitFcn(CWebDav *pThis, WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szPath, BOOL fIsRoot) {
	return pThis->MoveCopyVisitFcn(pFindData, dwContext, szPath, fIsRoot);
}


inline WCHAR * RemoveLastSlash(WCHAR *szBuffer) {
	WCHAR *wszEnd = wcsrchr(szBuffer,L'\\');

	// In case where szBuffer='\\', don't remove root slash
	if (wszEnd == szBuffer)
		wszEnd = szBuffer+1;
	
	*wszEnd = 0;
	return wszEnd;
}

typedef struct {
	WIN32_FIND_DATAW findData;
} RecurseStructInfo;



#ifdef _PREFAST_
// We turn of prefast here and rely entirely on DEBUGCHK in dbg builds rather
// than adding (for instance) if (wcslen(szPath)+1) >= SVSUTIL_ARRLEN(wszBuf1)) { DEBUGCHK(0); return; }
// because... this is a pretty heavily used function and we don't want to degrade
// performance.
#pragma prefast(disable:204 394 417,"RecursiveVisitDirs correctly calculates length needed at each stage")
#endif

BOOL CWebDav::RecursiveVisitDirs(WCHAR *szPath, DWORD dwContext, PFN_RECURSIVE_VISIT pfnVisit, BOOL fDeferDirectoryProcess) {
	WIN32_FIND_DATAW findData;
	BOOL      fRet = FALSE;
	BOOL      fMoreFiles = TRUE;

	WCHAR     wszBuf1[(10+MAX_PATH)*2];
	WCHAR     *wszEnd;
	DWORD     ccBuf1;

	// keeps track of recursive decent through directory tree
	SVSExpArray<RecurseStructInfo> findDataArray;
	HANDLE    hFileStack[MAX_PATH];
	int       iStackPtr = -1;
	BOOL      fIsRoot;

	DEBUGCHK((wcslen(szPath)+1) < SVSUTIL_ARRLEN(wszBuf1));

	wcscpy(wszBuf1,szPath);
	ccBuf1 = wcslen(wszBuf1);
	wszEnd = wszBuf1 + ccBuf1;

	if (URLHasTrailingSlashW(wszBuf1,ccBuf1))
		wcscpy(wszEnd,L"*");
	else
		wcscpy(wszEnd,L"\\*");

	if (INVALID_HANDLE_VALUE == (hFileStack[0] = FindFirstFile(wszBuf1, &findData))) {
		// root directory is empty.  Not an error, but we are done in this case.
		fRet = TRUE;
		goto done;
	}
	*wszEnd = 0;
	iStackPtr = 0;

	GetDepth();

	do {
startFileList:
		DEBUGCHK((iStackPtr >= 0) && (iStackPtr < SVSUTIL_ARRLEN(hFileStack)));
		fIsRoot = (iStackPtr==0);

		do {
			if (!fMoreFiles)
				break;

			if (IsDirectory(&findData) && fDeferDirectoryProcess) {
				if (!findDataArray.SRealloc(iStackPtr+1))
					goto done;

				findDataArray[iStackPtr].findData = findData;
			}
			else if (! pfnVisit(this,&findData,dwContext,wszBuf1,fIsRoot))
				goto done;

			if (IsDirectory(&findData) && (m_Depth == DEPTH_INFINITY)) {
				if (!URLHasTrailingSlashW(wszBuf1))
					*wszEnd++ = '\\';

				wcscpy(wszEnd,findData.cFileName);
				wszEnd = wszEnd + wcslen(findData.cFileName);
				wcscpy(wszEnd,L"\\*");
				DEBUGCHK(wcslen(wszBuf1) < SVSUTIL_ARRLEN(wszBuf1));

				// If call fails, continue processing.
				if (INVALID_HANDLE_VALUE == (hFileStack[++iStackPtr] = FindFirstFile(wszBuf1, &findData))) {
					*wszEnd = 0;
					iStackPtr--;

					if (fDeferDirectoryProcess) {
						if (! pfnVisit(this,&findDataArray[iStackPtr].findData,dwContext,wszBuf1,fIsRoot))
							goto done;
					}

					wszEnd = RemoveLastSlash(wszBuf1);
					continue;
				}
				*wszEnd = 0;
				goto startFileList;
			}
		}
		while (FindNextFile(hFileStack[iStackPtr], &findData));

		if (fDeferDirectoryProcess && !fIsRoot) {
			DEBUGCHK(iStackPtr >= 1);
			DEBUGCHK(IsDirectory(&findDataArray[iStackPtr-1].findData));
			if (! pfnVisit(this,&findDataArray[iStackPtr-1].findData,dwContext,wszBuf1,fIsRoot))
				goto done;
		}

		wszEnd = RemoveLastSlash(wszBuf1);

		FindClose(hFileStack[iStackPtr--]);

		if (iStackPtr == -1)
			break;

		fMoreFiles = FindNextFile(hFileStack[iStackPtr], &findData);
	} while (1);

	fRet = TRUE;
done:
	for (int i = 0; i <= iStackPtr; i++) {
		DEBUGCHK(hFileStack[i] != INVALID_HANDLE_VALUE);
		FindClose(hFileStack[i]);
	}

	return fRet;
}

#ifdef _PREFAST_
#pragma prefast(enable:204 394 417,"")
#endif


//
// CChunkedBuffer implementation
//

// Initial buffer is 8KB, second one is 16 KB, then 32, then 64KB.  We grow quickly
// because most likely scenarios are the tiny case (< 8KB) or the very large (>64KB), 
// so there's no point in reallocating 1 or 2 KB at a time.

// Only alloc on specified boundaries
inline DWORD GetNextBufSize(DWORD cbRequired) {
	if (cbRequired <= INITIAL_CHUNK_BUFFER_SIZE)
		return INITIAL_CHUNK_BUFFER_SIZE;
	else if (cbRequired <= (INITIAL_CHUNK_BUFFER_SIZE*2))
		return INITIAL_CHUNK_BUFFER_SIZE*2;
	else if (cbRequired <= (INITIAL_CHUNK_BUFFER_SIZE*4))
		return INITIAL_CHUNK_BUFFER_SIZE*4;
	else
		return MAX_CHUNK_BUFFER_SIZE;
}

BOOL CChunkedBuffer::AllocMem(DWORD cbSize) {
	BufferConsistencyChecks();
	DWORD dwAlloc = cbSize + m_iNextIn + CHUNK_RESERVE_SPACE;

⌨️ 快捷键说明

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