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

📄 vroots.hpp

📁 Windows CE 6.0 Server 源码
💻 HPP
📖 第 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: VROOTS.CPP
Abstract: Virtual roots handling mechanism.
--*/

typedef enum {
	AUTH_PUBLIC = 0,
	AUTH_USER	= 1,
	AUTH_ADMIN	= 2,
	AUTH_MAX    = 99
}
AUTHLEVEL;
	
typedef struct {
	int		iURLLen;
	PSTR	pszURL;
	int		iPathLen;
	PWSTR	wszPath;
	PSTR    pszRedirectURL;

	DWORD	dwPermissions;    // HSE_URL_xxx flags
	AUTHLEVEL	AuthLevel;    // What level of auth is required to gain access to this page?
	SCRIPT_TYPE ScriptType;   // Does vroot physical path map to an ASP or ISAPI?
	WCHAR *wszUserList;       // List of users that have access to this page.

	// Number of '/' (and '\\') chars in the vroot name, not counting initial '/' or last slash if no chars are after it.
	// So '/a' has 0, /a/b has 1, /a/b/c and /a/b/c/ both have 2.
	int   iNumSlashes;        


	unsigned int fRootDir     : 1;   // When pointing to root of filesys, special case handeling is needed.
	unsigned int fRedirect    : 1;   // TRUE if we should send a "302 redirect" response to client.
	unsigned int fDirBrowse   : 1;   // Is directory browsing allowed?
	unsigned int fNTLM        : 1;   // Will we do NTLM auth?
	unsigned int fBasic       : 1;   // Will we do BASIC auth?
	unsigned int fNegotiate   : 1;   // Will we do Negotiate auth?
}
VROOTINFO, *PVROOTINFO;


inline BOOL IsSlash(CHAR c) {
	return ((c == '/') || (c == '\\'));
}

inline int CountSignificantSlashesInURL(PCSTR pszURL, int iURLLen) {
	DWORD iSlashes = 0;
	// Skip first char '/', and don't check last character for ending '/'.
	for (int j = 1; j < iURLLen-1; j++) {
		if (IsSlash(pszURL[j]))
			iSlashes++;
	}

	return iSlashes;
}


// Used to split a URL and Path Translated apart for ISAPI/ASP scripts
inline void SetPathInfo(PSTR *ppszPathInfo,PSTR pszInputURL,int iURLLen) {
	int  iLen = strlen(pszInputURL+iURLLen) + 2;


	// If we've mapped the virtual root "/" to a script, need an extra "/" for the path
	// (normally we use the origial trailing "/", but in this case the "/" is the URL
	*ppszPathInfo = MySzAllocA((iURLLen == 1) ? iLen + 1 : iLen);  
	if (! (*ppszPathInfo))
		goto done;

	if (iURLLen == 1) {
		(*ppszPathInfo)[0] = '/';
		memcpy( (*ppszPathInfo) +1, pszInputURL + iURLLen, iLen);
	}
	else
		memcpy(*ppszPathInfo, pszInputURL + iURLLen, iLen);	


done:
	// URL shouldn't contain path info, break it apart
	pszInputURL[iURLLen] = 0;		
}

// We convert all '/' in URL to '\' in the filename just in case there's filesystems
// that are picky between / and \.  This won't affect most cases because even if user
// enters a '\' in URL, browser will change it to a '/' before sending it across wire.
inline void ConvertSlashes(WCHAR *szPath) {
	while (*szPath) {
		if (*szPath == '/')
			*szPath = '\\';

		szPath++;
	}
}


// Returns next occurence of either '/' or '\\'
inline PSTR GetNextSlash(PCSTR szString) {
	const CHAR cszSlashes[] = {'/', '\\', '\0'};
	return (PSTR)strpbrk(szString,cszSlashes);
}


class CVRoots {
	int	m_nVRoots;
	PVROOTINFO m_pVRoots;

	PVROOTINFO MatchVRoot(PCSTR pszInputURL, int iInputLen) {
		int i;

		// If there was an error on setting up the vroots, m_pVRoots = NULL.
		if (!m_pVRoots)
			return NULL;

		int iInputSlashes = CountSignificantSlashesInURL(pszInputURL,iInputLen);
		PCSTR szFirstUrlSlashInit = GetNextSlash(pszInputURL+1);
		if (NULL == szFirstUrlSlashInit)
			szFirstUrlSlashInit = strchr(pszInputURL,'\0');

		for (i = 0; i < m_nVRoots; i++) {
			int iLen = m_pVRoots[i].iURLLen;
			PCSTR szFirstUrlSlash = szFirstUrlSlashInit;
			
			// If this root maps to physical path "\", special case.
			// In general we store pszURL without trailing "/", however we have
			// to store trailing "/" for root directory.
			
			if (m_pVRoots[i].fRootDir && iLen != 1)
				iLen--;

			// URL isn't long enough to possibly match the vroot
			if (! (iLen && iInputLen >= iLen))
				continue;

			// If it's path '/', always match.
			if (iLen == 1) {
				DEBUGMSG(ZONE_VROOTS, (L"HTTPD: URL %a matched VRoot %a (path %s, perm=%d, auth=%d)\r\n", 
					pszInputURL, m_pVRoots[i].pszURL, m_pVRoots[i].wszPath, m_pVRoots[i].dwPermissions, m_pVRoots[i].AuthLevel));
				return &(m_pVRoots[i]);
			}

			// It's possible for a virtual root name to have multiple slashes, i.e.
			// '/a/b' could map to '\windows\www' whereas '/a' could be something else.
			// We need to accomodate this case, and also the case where a file name begins
			// with the same sequence of characters as a virtual root name -> i.e.
			// a request for '/webAdmin.htm' should not map to vroot '/webAdmin/', but instead to '/'.

			// First, figure out how much of URL to compare to a vroot based on number of slashes in vroot.
			int iNumSlashesInVRoot = m_pVRoots[i].iNumSlashes;

			// There's not enough slashes to possibly match, i.e. a request for /ABCD on vroot[i] = /A/B can't work.
			if (iInputSlashes < iNumSlashesInVRoot)
				continue;

			// Skip to either end of string or first '/'.  Go iNumSlashesInVRoot after
			// the first '/' if there is one, and then stop looking ahead.  This is len of URL to check against.
			while (iNumSlashesInVRoot) {
				PCSTR szFirstUrlSlashSave = szFirstUrlSlash;
				szFirstUrlSlash = GetNextSlash(szFirstUrlSlash+1);
				DEBUGCHK(szFirstUrlSlash || (iNumSlashesInVRoot == 1));

				if (NULL == szFirstUrlSlash)
					szFirstUrlSlash = strchr(szFirstUrlSlashSave,'\0');
					
				iNumSlashesInVRoot--;
			}

			int iURLLen = szFirstUrlSlash-pszInputURL;
			DEBUGCHK(iURLLen <= iInputLen);

			if ((iURLLen == m_pVRoots[i].iURLLen) && (0 == _memicmp(pszInputURL, m_pVRoots[i].pszURL, iURLLen))) {
				/*
				if (m_pVRoots[i].fRootDir) {
					// If it's not root dir, always matched.  Otherwise it's possible
					// there wasn't a match.  For root dirs, pszURL[iLen] is always "/"
					if (! (m_pVRoots[i].iURLLen == 1 || pszInputURL[iLen] == '/' || pszInputURL[iLen] == '\0'))
						continue;
				}
				*/

				DEBUGMSG(ZONE_VROOTS, (L"HTTPD: URL %a matched VRoot %a (path %s, perm=%d, auth=%d)\r\n", 
					pszInputURL, m_pVRoots[i].pszURL, m_pVRoots[i].wszPath, m_pVRoots[i].dwPermissions, m_pVRoots[i].AuthLevel));
				return &(m_pVRoots[i]);
			}
		}
		DEBUGMSG(ZONE_VROOTS, (L"HTTPD: URL %a did not matched any VRoot\r\n", pszInputURL));
		return NULL;
	}

	BOOL Init(CReg *pWebsite, BOOL fDefaultDirBrowse, BOOL fDefaultBasic, BOOL fDefaultNTLM, BOOL fDefaultNegotiate) {
		const WCHAR cszDLL[] = L".dll";
		const WCHAR cszASP[] = L".asp";
		
		int err  = 0;		//  err variable is used in non-Debug mode
		BOOL fChange;
		int i=0;

		// Registry doesn't allow keynames longer than MAX_PATH so we won't map URL prefixes longer than MAX_PATH
		WCHAR wszURL[MAX_PATH+1]; 
		WCHAR wszPath[MAX_PATH+1]; 
		wszURL[0]=wszPath[0]=0;

		// open the VRoots key
		CReg topreg((HKEY) (*pWebsite), RK_HTTPDVROOTS);

		// allocate space for as many VRoots as we have subkeys
		m_nVRoots = topreg.NumSubkeys();
		if(!m_nVRoots)
			myleave(80);
		// Zero the memory so we know what to deallocate and what not to.
		if(!(m_pVRoots = MyRgAllocZ(VROOTINFO, m_nVRoots)))
			myleave(81);

		// enumerate all subkeys. Their names are URLs, their default value is the corresponding path
		// Note: EnumKey takes sizes in chars, not bytes!
		for(i = 0; topreg.EnumKey(wszURL, CCHSIZEOF(wszURL)); ) {
			CReg subreg(topreg, wszURL);
			DEBUGCHK(i < m_nVRoots);

			memset(&m_pVRoots[i],0,sizeof(VROOTINFO));
			
			// get the unnamed value. Again size is in chars, not bytes.
			if(!subreg.ValueSZ(NULL, wszPath, CCHSIZEOF(wszPath)))  {  
				// iURLLen and iPathLen set to 0 already, so no case of corruption in MatchVRoot
				subreg.Reset();
				continue;
			} 
			else {
				CHAR pszURL[MAX_PATH+1];
				// convert URL to MBCS
				int iLen = m_pVRoots[i].iURLLen = MyW2A(wszURL, pszURL, sizeof(pszURL));
				if(!iLen)
					{ myleave(83); } 

⌨️ 快捷键说明

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