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

📄 davimpl.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		while (*szTrav) {
			DWORD ccTrav = strlen(szTrav);

			if (! m_bufResp.BeginBraceNoNS()      ||
			    ! m_bufResp.Append(szTrav,ccTrav) ||
			    ! m_bufResp.Append("/>",2)) {
				return FALSE;
			}

			szTrav += ccTrav + 1;
		}

		if (! m_bufResp.EndTag(cszProp)     || 
		    ! m_bufResp.EndTag(cszPropstat))
			return FALSE;
	}
	return TRUE;
}

// When an unknown XML tag is hit during processing a PROPPATCH or PROPFIND request,
// save that tag (converting to ASCII first) in a buffer so that 
BOOL CWebDav::AddUnknownXMLElement(const WCHAR *wszTagName, const DWORD ccTagName) {
	SVSUTIL_ASSERT((m_pRequest->m_idMethod == VERB_PROPFIND) || (m_pRequest->m_idMethod == VERB_PROPPATCH));
	UINT uiCodePage = GetUTF8OrACP();

	int iLen = WideCharToMultiByte(uiCodePage, 0, wszTagName, ccTagName, NULL, 0, 0, 0);

	if (iLen == 0) {
		DEBUGCHK(0);
		return TRUE;
	}

	if (! m_bufUnknownTags.AllocMem(iLen+1))
		return FALSE;

	WideCharToMultiByte(uiCodePage, 0,wszTagName, ccTagName, (CHAR*)m_bufUnknownTags.pBuffer+m_bufUnknownTags.uiNextIn, iLen, 0, 0);
	m_bufUnknownTags.uiNextIn += iLen;
	m_bufUnknownTags.AppendCHAR('\0'); // always succeeds because we alloc'd an extra byte for it above.

	return TRUE;
}

// Only returns property names associated with resource, not their values.
BOOL CWebDav::SendPropertyNamesVisitFcn(WIN32_FIND_DATA *pFindData, DWORD dwContext, WCHAR *szTraversalPath, BOOL fRootDir) {
	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav PROPFIND returning all property names\r\n"));
	DEBUGCHK(m_pRequest->m_rs == STATUS_MULTISTATUS);
	BOOL fIsRoot = (NULL==szTraversalPath);

	BOOL fRet = FALSE;

	if (! m_bufResp.StartTag(cszResponse))
		goto done;

	// <a:href>http://CEDevice/fileName/...</a:href>
	if (! SetHREFTagFromDestinationPath(pFindData,szTraversalPath,fRootDir,NULL,fIsRoot))
		goto done;

	// <a:propstat>
	if (! m_bufResp.StartTag(cszPropstat))
		goto done;

	// <a:status>	
	if (! m_bufResp.SetStatusTag(STATUS_OK))
		goto done;

	// <a:prop>
	if (! m_bufResp.StartTag(cszProp))
		goto done;

	if (! m_bufResp.SetEmptyElementNoEncode(cszGetcontentLengthNS,ccGetcontentLengthNS) ||  
	    ! m_bufResp.SetEmptyElementNoEncode(cszCreationDateNS,ccCreationDateNS) ||  
	    ! m_bufResp.SetEmptyElementNoEncode(cszDisplayName,ccDisplayName) ||
	    ! m_bufResp.SetEmptyElementNoEncode(cszGetETag,ccGetETag) ||
	    ! m_bufResp.SetEmptyElementNoEncode(cszLastModifiedNS,ccLastModifiedNS) ||
	    ! m_bufResp.SetEmptyElementNoEncode(cszSupportedLock,ccSupportedLock) ||
	    ! m_bufResp.SetEmptyElementNoEncode(cszLockDiscovery,ccLockDiscovery) ||
	    ! m_bufResp.SetEmptyElementNoEncode(cszIsHiddenNS,ccIsHiddenNS) ||
	    ! m_bufResp.SetEmptyElementNoEncode(cszIsCollectionNS,ccIsCollectionNS))
		goto done;

	// close up XML tags
	if (! m_bufResp.EndTag(cszProp)     || 
	    ! m_bufResp.EndTag(cszPropstat) ||
	    ! m_bufResp.EndTag(cszResponse))
		goto done;

	fRet = TRUE;
done:
	return fRet;
}

// Send all properties
BOOL CWebDav::SendProperties(DWORD dwDavPropFlags, BOOL fSendNamesOnly) {
	PFN_RECURSIVE_VISIT pfnVisit = fSendNamesOnly ? ::SendPropertyNamesVisitFcn : (::SendPropertiesVisitFcn);

	DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: WebDav PROPFIND sending properties for %s\r\n",m_pRequest->m_wszPath));
	DEBUGCHK(m_pRequest->m_rs == STATUS_OK);

	if (! DavGetFileAttributesEx()) {
		DEBUGCHK(0); // earlier GetFileAttributes() worked, this should too.
		SetStatus(STATUS_INTERNALERR);
		return FALSE;
	}

	SetMultiStatusResponse();

	// Print out the root node first.
	if (! pfnVisit(this,(WIN32_FIND_DATA*)&m_fileAttribs,dwDavPropFlags,NULL,FALSE))
		goto done;

	// If we're not a directory or if depth=0 on directory, we're done.
	if (! IsCollection() || (m_Depth == DEPTH_ZERO)) {
		return TRUE;
	}

	if (IsCollection() && (! m_pRequest->AllowDirBrowse())) {
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: PROPFIND requests collection info but dir brows turned off, only returning info on root dir\r\n"));
		return TRUE;
	}

	RecursiveVisitDirs(m_pRequest->m_wszPath,dwDavPropFlags,pfnVisit,FALSE);
done:
	// always return TRUE because we've set "Multistatus" error code.
	DEBUGCHK(m_pRequest->m_rs == STATUS_MULTISTATUS);
	return TRUE;
}

// Client has given us a restricted list of properties and/or files it wants
BOOL CWebDav::SendSubsetOfProperties(void) {
	DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: WebDav PROPFIND will send subset of properties based on XML body\r\n"));
	DEBUGCHK(m_pRequest->m_rs == STATUS_OK);

	BOOL fRet = FALSE;
	CPropFindParse cPropFind(this);

	return ParseXMLBody(&cPropFind);
}


void BuildFileName(WCHAR *szWriteBuf, WCHAR *szPath, WCHAR *szFileName) {
	DWORD ccFile;

	wcscpy(szWriteBuf,szPath);
	ccFile = wcslen(szWriteBuf);
	szWriteBuf[ccFile++] = '\\';
	wcscpy(szWriteBuf+ccFile,szFileName);
	DEBUGCHK(wcslen(szWriteBuf) < MAX_PATH);
}


//
//  PROPPATCH
//


// We'll pretend like we can handle all Win32 properties (we can only do Win32FileAttributes),
// and will return "403" for other properties.
BOOL CWebDav::SendPropPatchResponse(RESPONSESTATUS rs) {
	if ((m_dwPropPatchUpdate == 0) && (NULL == m_bufUnknownTags.pBuffer)) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: PROPPATCH did not set any elements, bad request\r\n"));
		SetStatus(STATUS_BADREQ);
		return FALSE;
	}

	if (! SetMultiStatusResponse()         ||
	    ! m_bufResp.StartTag(cszResponse)  ||
	    ! SetHREFTag()) {
		return  FALSE;
	}

	if (m_dwPropPatchUpdate) {
		if ( ! m_bufResp.StartTag(cszPropstat) ||
		     ! m_bufResp.SetStatusTag(rs)           ||
		     ! m_bufResp.StartTag(cszProp))
		{
		   	return FALSE;
		}

		if ((m_dwPropPatchUpdate & DAV_PROP_W32_FILE_ATTRIBUTES) && ! SetEmptyTagWin32NS(&m_bufResp,cszWin32FileAttribs,ccWin32FileAttribs))
			return FALSE;

		if ((m_dwPropPatchUpdate & DAV_PROP_W32_LAST_MODIFY_TIME) && ! SetEmptyTagWin32NS(&m_bufResp,cszWin32LastModifiedTime,ccWin32LastModifiedTime))
			return FALSE;

		if ((m_dwPropPatchUpdate & DAV_PROP_W32_CREATION_TIME) && ! SetEmptyTagWin32NS(&m_bufResp,cszWin32CreationTime,ccWin32CreationTime))
			return FALSE;

		if ((m_dwPropPatchUpdate & DAV_PROP_W32_LAST_ACCESS_TIME) && ! SetEmptyTagWin32NS(&m_bufResp,cszWin32LastAccessTime,ccWin32LastAccessTime))
			return FALSE;

		if (! m_bufResp.EndTag(cszProp)  ||
		    ! m_bufResp.EndTag(cszPropstat))
			return FALSE;
	}

	if (! SendUnknownXMLElementsIfNeeded(STATUS_FORBIDDEN))
		return FALSE;

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

	return TRUE;
}

// Effectively does a memset(0) on pFindData, but don't call memset to avoid 
// having to zero out long cFileName struct, can have same effect by setting its first byte = 0.
void ZeroW32FData(WIN32_FIND_DATAW *pFindData) {
	pFindData->dwFileAttributes = 0;
	pFindData->ftCreationTime.dwLowDateTime = pFindData->ftLastAccessTime.dwLowDateTime = pFindData->ftLastWriteTime.dwLowDateTime = 0;
	pFindData->ftCreationTime.dwHighDateTime = pFindData->ftLastAccessTime.dwHighDateTime = pFindData->ftLastWriteTime.dwHighDateTime = 0;
	pFindData->nFileSizeHigh = pFindData->nFileSizeLow = pFindData->dwOID = 0;
	pFindData->cFileName[0] = 0;
}

//
//  DELETE
//
BOOL CWebDav::DeleteVisitFcn(WIN32_FIND_DATAW *pFindData, DWORD dwContext, WCHAR *szTraversalPath, BOOL fRootDir) {
	CDavDeleteContext *pContext = (CDavDeleteContext*)dwContext;

	DEBUGCHK(! URLHasTrailingSlashW(szTraversalPath));

	DEBUGMSG_VISIT_FCN("DeleteVisitFcn");
	RESPONSESTATUS rs = STATUS_MAX;

	BOOL fRet = FALSE;
	
	if (IsDirectory(pFindData)) {
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav removing directory %s\r\n",szTraversalPath));
		fRet = RemoveDirectory(szTraversalPath);

		if (!fRet) {
			DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: RemoveDirectory(%s) failed, GLE=0x%08x\r\n",szTraversalPath,GetLastError()));
			// On non-empty dir, lower level set error
			if (SendErrorOnRemoveDirectoryFailure()) {
				// We don't use existing pFindData because it has the node directory name encoded in it,
				// but szTraversalPath also has this info in it, so we'd end up duplicating final file name.
				WIN32_FIND_DATAW w32FData;
				ZeroW32FData(&w32FData);
				SetMultiStatusErrorFromDestinationPath(GLEtoStatus(),&w32FData,szTraversalPath,fRootDir,pContext->szURL);
				return TRUE;
			}
			else {
				fRet = TRUE;
			}
		}
	}
	else {
		WCHAR szFile[MAX_PATH*2];
		if (!(m_pRequest->GetPerms() & HSE_URL_FLAGS_SCRIPT_SOURCE) && IsPathScript(pFindData->cFileName)) {
#if defined (DEBUG)
			BuildFileName(szFile,szTraversalPath,pFindData->cFileName);
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: Cannot MOVE/COPY %s, it is a script but SCRIPT_SOURCE permissions not granted\r\n",szFile));
#endif
			rs = STATUS_FORBIDDEN;
		}
		else {
			BuildFileName(szFile,szTraversalPath,pFindData->cFileName);
			fRet = DavDeleteFile(szFile);

			if (IsFileLocked(szFile)) {
				rs = STATUS_LOCKED;
			}
		}
	}

	if (!fRet && pContext->fSendErrorsToClient) {
		rs = (rs == STATUS_MAX) ? GLEtoStatus() : rs;
		SetMultiStatusErrorFromDestinationPath(rs,pFindData,szTraversalPath,fRootDir,pContext->szURL);
	}
	return TRUE;
}

BOOL CWebDav::DeleteCollection(WCHAR *wszPath, CHAR *szURL) {
	CDavDeleteContext cDel(szURL,TRUE);
	
	BOOL fRet = FALSE;

	// per spec, depth must be infinite
	if (! GetDepth() || m_Depth != DEPTH_INFINITY) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: DELETE fails, depth not valid or not set to \"infinity\"\r\n"));
		SetStatus(STATUS_BADREQ);
		return FALSE;
	}

	if (RecursiveVisitDirs(wszPath,(DWORD)&cDel,::DeleteVisitFcn,TRUE)) {
		if (! RemoveDirectory(wszPath)) {
			DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: WebDav removing directory %s, GLE=0x%08x\r\n",wszPath,GetLastError()));

			if (SendErrorOnRemoveDirectoryFailure())
				SetMultiStatusErrorFromURL(GLEtoStatus(),szURL);
		}
		else
			fRet = TRUE;
	}
	return fRet;
}


//
//  MOVE/COPY
//

// Returns a new buffer containing the canonicalized URL.  ppszDestinationPrefix is 
// pointer to raw headers containing http://... part of URL, ppszDestinationURL
// points to the URL portion.
PSTR CWebDav::GetDestinationHeader(PSTR *ppszDestinationPrefix, PSTR *ppszDestinationURL, PSTR *ppszSave) {
	PSTR  szDestinationPrefix  = NULL;
	PSTR  szDestinationURL     = NULL;
	PSTR  szDestination        = NULL;

	// Destination: header contains location of resource to write to.  May
	// be in form "http://CEDevice/destination", so need to crack this out, canonicalize,
	// and then find VRoot on the device it corresponds to (not necessarily the
	// vroot of m_pszURL).

	if (NULL == (szDestinationPrefix = m_pRequest->FindHttpHeader(cszDestination,ccDestination))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: MOVE/COPY fails, \"Destination:\" request header not present\r\n"));
		SetStatus(STATUS_BADREQ);
		goto done;
	}

	*ppszSave = strchr(szDestinationPrefix,'\r');
	DEBUGCHK(*(*ppszSave)); // request wouldn't have past had it been wrongly formatted
	*(*ppszSave) = 0;
	m_pRequest->DebugSetHeadersInvalid(TRUE);

	if (NULL == (szDestinationURL = SkipHTTPPrefixAndHostName(szDestinationPrefix))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: MOVE/COPY fails, \"Destination:\" header not formatted corectly.\r\n"));
		SetStatus(STATUS_BADREQ);
		goto done;
	}

	// szDestinationURL is pointer into m_pRequest->m_bufRequest.  Need 
	// a new copy of buffer for canonicalization.  +1 to store possible '/' at end.
	if (NULL == (szDestination = MySzAllocA(strlen(szDestinationURL)+1))) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: MOVE/COPY fails, server out of memory\r\n"));
		SetStatus(STATUS_INTERNALERR);
		goto done;
	}

	svsutil_HttpCanonicalizeUrlA(szDestinationURL,szDestination);
	RemoveTrailingSlashIfNeededA(szDestination);

done:
	if (szDestination) {
		*ppszDestinationPrefix = szDestinationPrefix;
		*ppszDestinationURL    = szDestinationURL;
	}

#if defined (DEBUG)
	if (m_pRequest->m_rs == STATUS_OK)
		DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav GetDestinationHeader sets canonicalized dest root = <<%a>>, destURL = <<%a>>\r\n",
		         szDestination,szDestinationURL));
#endif

	return szDestination;
}

// Determines whether we have write access to "Destination:" URL.  Parameters passed in are the 
// access permisions of the vroot in destination.
BOOL CWebDav::HasAccessToDestVRoot(CHAR *szDestURL, WCHAR *szPath, PVROOTINFO pVRoot) {
	AUTHLEVEL       authGranted = AUTH_PUBLIC;

⌨️ 快捷键说明

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