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

📄 davimpl.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	RESPONSESTATUS  rs   = STATUS_INTERNALERR;
	BOOL            fRet = FALSE;

	authGranted = m_pRequest->DeterminePermissionGranted(pVRoot->wszUserList,m_pRequest->m_AuthLevelGranted);

	if (authGranted < pVRoot->AuthLevel) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: MOVE/COPY fails, destination root requires auth level (%d), user only has access (%d)\r\n",
		                        pVRoot->AuthLevel,authGranted));
		rs = STATUS_UNAUTHORIZED;
		goto done;
	}

	if (! (pVRoot->dwPermissions & HSE_URL_FLAGS_WRITE)) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: MOVE/COPY fails, virtual root of destination does not support writing\r\n"));
		rs = STATUS_FORBIDDEN;
		goto done;
	}

	if ( (!(pVRoot->dwPermissions & HSE_URL_FLAGS_SCRIPT_SOURCE)) && IsPathScript(szPath,pVRoot->ScriptType)) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: MOVE/COPY fails, attempting to write to a script resource but no HSE_URL_FLAGS_SCRIPT_SOURCE flags\r\n"));
		rs = STATUS_FORBIDDEN;
		goto done;
	}

	fRet = TRUE;
done:
	if (! fRet) {
		DEBUGCHK(rs != STATUS_INTERNALERR);
		SetMultiStatusErrorFromURL(rs,szDestURL);
	}

	return fRet;                             
}

BOOL RemoveDirVisitFcn(CWebDav *pThis, WIN32_FIND_DATA *pFindData, DWORD dwContext, WCHAR *szTraversalPath, BOOL fRootDir) {
	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav removing empty directories after move operation\r\n"));
	DEBUGMSG_VISIT_FCN("RemoveDirVisitFcn");

	// When we're doing a move of a collection, run through directory tree
	// (depth first) and remove directories of source.  Note that we don't delete
	// files and RemoveDirectory will fail if files are in sub-dir; this is by
	// design because source files may not be legitamitly moved due to error and
	// we wouldn't delete them in this case.

	if (IsDirectory(pFindData->dwFileAttributes)) {
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav RemoveDirectory(%s) on cleanup from move\r\n",szTraversalPath));

		// don't use ZONE_ERROR because it's legit to fail here
		if (! RemoveDirectory(szTraversalPath))
			DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav RemoveDirectory(%s) failed, GLE=0x%08x\r\n",szTraversalPath,GetLastError()));
	}
	return TRUE;
}

BOOL CWebDav::MoveCopyCollection(CMoveCopyContext *pcContext) {
	BOOL fRet = FALSE;

	DEBUGCHK(m_pRequest->m_rs == STATUS_OK);

	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav calls CreateDirectory(%s)\r\n",pcContext->wszDestPath));
	if (!CreateDirectory(pcContext->wszDestPath,NULL)) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: CreateDirectory(%s) failed, GLE=0x%08x\r\n",pcContext->wszDestPath,GetLastError()));
		SetMultiStatusErrorFromURL(GLEtoStatus(),pcContext->szDestURL);
		return TRUE;
	}

	fRet = RecursiveVisitDirs(m_pRequest->m_wszPath,(DWORD)pcContext,::MoveCopyVisitFcn,FALSE);
	if (pcContext->fDeleteSrc) {
		DEBUGCHK(m_Depth == DEPTH_INFINITY);
		// Recursively delete source directories now that we're through.

		if (RecursiveVisitDirs(m_pRequest->m_wszPath,0,::RemoveDirVisitFcn,TRUE))
			RemoveDirectory(m_pRequest->m_wszPath);
	}
	return fRet;
}


BOOL DeleteFileAndFileLock(WCHAR *szFile, CWebDavFileNode *pFileNode) {
	DEBUGCHK(g_pFileLockManager->IsLocked());

	if (pFileNode) {
		g_pFileLockManager->RemoveFileNodeFromLinkedList(pFileNode);
		g_pFileLockManager->DeInitAndFreeFileNode(pFileNode);
	}

	if (DeleteFile(szFile))
		return TRUE;

	DEBUGMSG(ZONE_ERROR,(L"HTTPD: DeleteFile(%s) fails, GLE=0x%08x\r\n",szFile,GetLastError()));
	return FALSE;
}

BOOL CWebDav::MoveCopyFile(BOOL fDeleteSrc, WCHAR *wszSrcPath, WCHAR *wszDestPath) {
	BOOL fRet;
	CWebDavFileNode *pSrcNode  = NULL;
	CWebDavFileNode *pDestNode = NULL;

	HANDLE hSrc       = INVALID_HANDLE_VALUE;
	HANDLE hDest      = INVALID_HANDLE_VALUE;
	BOOL   fCloseSrc  = FALSE;
	BOOL   fCloseDest = FALSE;
	CHAR   szBuf[MINBUFSIZE*3];
	DWORD  dwRead;
	DWORD  dwDummy;

	if (fDeleteSrc) {
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav calls MoveFile(%s,%s)\r\n",wszSrcPath,wszDestPath));
		fRet = MoveFile(wszSrcPath,wszDestPath);
	}
	else {
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav calls CopyFile(%s,%s,%d)\r\n",wszSrcPath,wszDestPath,(m_Overwrite & OVERWRITE_YES)));
		fRet = CopyFile(wszSrcPath,wszDestPath,(m_Overwrite & OVERWRITE_YES) ? FALSE : TRUE);
	}

	if (fRet)
		return TRUE;

	// If initial move/copy didn't work, perhaps it's because the file is LOCKED.
	// If client sent correct lock tokens along, unlock now.
	if (!CheckLockTokens())
		goto done;

	g_pFileLockManager->Lock();
	if (! g_pFileLockManager->CanPerformLockedOperation(wszSrcPath,wszDestPath,&m_lockIds,m_nLockTokens,&pSrcNode,&pDestNode)) {
		g_pFileLockManager->Unlock();
		DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: Client sent lock tokens, but they didn't correspond to file names %s and/or %s, move/copy failed\r\n",wszSrcPath,wszDestPath));
		goto done;
	}
	DEBUGCHK(g_pFileLockManager->IsLocked()); // on success, function leaves manager lockes to ensure pSrcNode and pDestNode are still valid.
	DEBUGCHK(pSrcNode || pDestNode); // at least one should be non-NULL on CanPerformLockedOperation() success.

	// It's possible that both files aren't lock.  If we don't get handle to file from
	// an existing lock, create it here.
	if (pSrcNode) {
		hSrc = pSrcNode->m_hFile;
		pSrcNode->SetBusy(TRUE);
	}
	else {
		fCloseSrc = TRUE;
		if (INVALID_HANDLE_VALUE == (hSrc = CreateFile(wszSrcPath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0))) {
			DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: CreateFile(%s) on src file during move/copy failed, GLE = 0x%08x\r\n",wszSrcPath,GetLastError()));
			goto doneInCS;
		}
	}

	if (pDestNode) {
		hDest = pDestNode->m_hFile;
		pDestNode->SetBusy(TRUE);
	}
	else {
		fCloseDest = TRUE;
		if (INVALID_HANDLE_VALUE == (hDest = CreateFile(wszDestPath, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0))) {
			DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: CreateFile(%s) on dest file during move/copy failed, GLE = 0x%08x\r\n",wszSrcPath,GetLastError()));
			goto doneInCS;
		}
	}
	// Since we could be copying megabytes, don't hold lock all this time.
	g_pFileLockManager->Unlock();

	SetFilePointer(hSrc,0,NULL,FILE_BEGIN);
	SetFilePointer(hDest,0,NULL,FILE_BEGIN);

	fRet = TRUE;

	while (ReadFile(hSrc, szBuf, sizeof(szBuf), &dwRead, 0) && dwRead) {
		if (! WriteFile(hDest,szBuf,dwRead,&dwDummy,NULL)) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: WriteFile(%s) during locked move/copy failed, GLE=0x%08x\r\n",wszDestPath,GetLastError()));
			fRet = FALSE;
			break;
		}
	}
	SetEndOfFile(hDest);

	g_pFileLockManager->Lock();

doneInCS:
	DEBUGCHK(g_pFileLockManager->IsLocked());

	if (pSrcNode)
		pSrcNode->SetBusy(FALSE);

	if (pDestNode)
		pDestNode->SetBusy(FALSE);

	if (fCloseSrc)
		MyCloseHandle(hSrc);

	if (fCloseDest)
		MyCloseHandle(hDest);
	
	if (fRet && fDeleteSrc)
		DeleteFileAndFileLock(wszSrcPath,pSrcNode);

	g_pFileLockManager->Unlock();
done:
	DEBUGCHK(! g_pFileLockManager->IsLocked());
	DEBUGMSG(ZONE_ERROR,(L"HTTPD: Failed move/copy %s-->%s, GLE=0x%08x\r\n",wszSrcPath,wszDestPath,GetLastError()));
	return fRet;
}

// MoveCopyVisitFcn is called by RecursiveVisitDirs when copying or moving a directory tree.
// It is responsible for creating directories that don't exist, checking to make sure
// if a file is a script that we have permission to access it, and doing copy/move itself.

// szTraversalPath is the path of the directory of the source that we're currently visiting,
// pFindData->cFileName is file name in the source (except when source is a directory
// itself, in which case szTraversalPath contains complete path).  

// Per the DAV spec, even if a specific operation fails for whatever reason, we 
// keep trying the move/copy.

BOOL CWebDav::MoveCopyVisitFcn(WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szTraversalPath, BOOL fRootDir) {
	CMoveCopyContext *pContext = (CMoveCopyContext *)dwContext;
	WCHAR szSource[MAX_PATH*2];
	WCHAR szDestination[MAX_PATH*2];
	DWORD ccWritten;
	DWORD ccRelativePath;
	BOOL  fSuccess = FALSE;
	RESPONSESTATUS rs = STATUS_MAX;

	DEBUGCHK(! URLHasTrailingSlashW(szTraversalPath));
	DEBUGCHK(! URLHasTrailingSlashW(pContext->wszDestPath));
	// Node we're visiting must be a subdirectory of the m_wszPath, which is source to do move/copy from.
	DEBUGCHK(0 == wcsncmp(szTraversalPath,m_pRequest->m_wszPath,m_pRequest->m_ccWPath));

	DEBUGMSG_VISIT_FCN("MoveCopyVisitFcn");

	// Buildup the destination path by concatinating the base directory of the
	// destination, the part of the current src path we're in (not including its
	// base directory).

	// tack on relative portion of src dir
	ccRelativePath = wcslen(szTraversalPath) - pContext->ccSrcPath;
	DEBUGCHK(((int)ccRelativePath >= 0));

	// Verify that we're not being requested to overflow szDestination's buffer.
	// +2 for up to two '\', +1 for NULL.
	DWORD ccMaxOutputRequired = wcslen(pContext->wszDestPath) + ccRelativePath + 2 +
	                            wcslen(pFindData->cFileName) + 1;

	if (ccMaxOutputRequired >= SVSUTIL_ARRLEN(szDestination)) {
		DEBUGCHK(0); // Calls above us should have caught this sooner.
		SetMultiStatusErrorFromDestinationPath(STATUS_INTERNALERR,pFindData,szTraversalPath,fRootDir,
			                                   pContext->szDestURL);
		return TRUE;
	}

	// root of dest dir
	wcscpy(szDestination,pContext->wszDestPath);
	ccWritten = pContext->ccDestPath;

	if (ccRelativePath) {
		szDestination[ccWritten++] = L'\\';
		wcscpy(szDestination+ccWritten,szTraversalPath+pContext->ccSrcPath);
		ccWritten += ccRelativePath;
	}

	if (IsDirectory(pFindData->dwFileAttributes)) {
		szDestination[ccWritten++] = L'\\';
		wcscpy(szDestination+ccWritten,pFindData->cFileName);

		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav calls CreateDirectory(%s)\r\n",szDestination));
		if (! CreateDirectory(szDestination,NULL)) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: CreateDirectory(%s) failed during recursive move/copy operation, GLE=0x%08x\r\n",szDestination,GetLastError()));
			SetMultiStatusErrorFromDestinationPath(GLEtoStatus(),pFindData,szTraversalPath,fRootDir,
			                                        pContext->szDestURL);
			return TRUE;
		}
		return TRUE;
	}

	if (( !(pContext->dwSrcPermFlags & HSE_URL_FLAGS_SCRIPT_SOURCE) || !(pContext->dwDestPermFlags & HSE_URL_FLAGS_SCRIPT_SOURCE)) &&
	    IsPathScript(pFindData->cFileName)) 
	{
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: Attempting to access script in recursive move/copy but script access not allowed, ACCESS DENIED\r\n"));
		SetMultiStatusErrorFromDestinationPath(STATUS_FORBIDDEN,pFindData,szTraversalPath,fRootDir);
		return TRUE;
	}

	// Add file name to destination.
	DEBUGCHK(! URLHasTrailingSlashW(szDestination));
	szDestination[ccWritten++] = L'\\';
	wcscpy(szDestination+ccWritten,pFindData->cFileName);
	DEBUGCHK(wcslen(szDestination) < SVSUTIL_ARRLEN(szDestination));

	// Buildup src path
	BuildFileName(szSource,szTraversalPath,pFindData->cFileName);
	DEBUGCHK(wcslen(szSource) < SVSUTIL_ARRLEN(szSource));

	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav calls %a on (%s --> %s)\r\n",pContext->fDeleteSrc ? "MOVE" : "COPY",
	                              szSource,szDestination));

	if (IsFileNameTooLongForFilesys(szSource) || IsFileNameTooLongForFilesys(szDestination)) 
		rs = STATUS_REQUEST_TOO_LARGE;
	else
		fSuccess = MoveCopyFile(pContext->fDeleteSrc,szSource,szDestination);

	if (!fSuccess) {
		PCSTR szURL = pContext->szDestURL;

		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav %a on (%s --> %s) fails, GLE=0x%08x\r\n",pContext->fDeleteSrc ? "MOVE" : "COPY",
		                          szSource,szDestination,GetLastError()));

		// Check to see if the file is locked, and also which file it is.
		if (rs == STATUS_MAX) {
			if (IsGLELocked()) {
				g_pFileLockManager->Lock();
				if (g_pFileLockManager->GetNodeFromFileName(szSource)) {
					szURL = m_pRequest->m_pszURL;
					rs = STATUS_LOCKED;
				}
				else if (g_pFileLockManager->GetNodeFromFileName(szDestination)) {
					rs = STATUS_LOCKED;
				}
				g_pFileLockManager->Unlock();
			}
			else
				rs = GLEtoStatus();
		}

		SetMultiStatusErrorFromDestinationPath(rs,pFindData,szTraversalPath,fRootDir,
			                                       szURL);
	}
	return TRUE;
}


//
//  Wrap Filesystem API calls
//


BOOL CWebDav::DavDeleteFile(WCHAR *szFile) {
	BOOL fRet = FALSE;

	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav calling DeleteFile(%s)\r\n",szFile));
	if (DeleteFile(szFile))
		return TRUE;

	// If delete failed because we have file locked and client sent lock tokens, try
	// going through lock manager.
	if (CheckLockTokens()) {
		CWebDavFileNode *pFileNode;

		g_pFileLockManager->Lock();

		if (g_pFileLockManager->CanPerformLockedOperation(szFile,NULL,&m_lockIds,m_nLockTokens,&pFileNode,NULL)) {
			// client sent a lock-token associated with the file.  Delete the lock token, and then the file
			fRet = DeleteFileAndFileLock(szFile,pFileNode);
			g_pFileLockManager->Unlock();
			return fRet;
		}
		g_pFileLockManager->Unlock();
	}

	DEBUGCHK(! g_pFileLockManager->IsLocked());
	DEBUGMSG(ZONE_ERROR,(L"HTTPD: Failed deleting file %s, GLE=0x%08x\r\n",szFile,GetLastError()));
	return FALSE;
}

⌨️ 快捷键说明

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