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

📄 request.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	}

	return;
}

BOOL CHttpRequest::IsNotModified(HANDLE hFile, DWORD dwLength) {
	if(m_ftIfModifiedSince.dwLowDateTime || m_ftIfModifiedSince.dwHighDateTime) {
		FILETIME ftModified;
		int iTemp;
		if(!GetFileTime(hFile, NULL, NULL, &ftModified)) {
			DEBUGMSG(ZONE_ERROR, (L"HTTPD: GetFileTime(%08x) failed\r\n", hFile));
			return FALSE; // assume it is modified
		}
		iTemp = CompareFileTime(&m_ftIfModifiedSince, &ftModified);

		DEBUGMSG(ZONE_RESPONSE, (L"HTTPD: IfModFT=%08x:%08x  ModFT=%08x:%08x IfModLen=%d Len=%d Compare=%d\r\n", 
			m_ftIfModifiedSince.dwHighDateTime, m_ftIfModifiedSince.dwLowDateTime ,
			ftModified.dwHighDateTime, ftModified.dwLowDateTime,
			m_dwIfModifiedLength, dwLength, iTemp));

		if((iTemp >= 0) && (m_dwIfModifiedLength==0 || (dwLength==m_dwIfModifiedLength)))
			return TRUE; // not modified
	}
	return FALSE; // assume modified
}


RESPONSESTATUS GLEtoStatus(int iGLE) {
	switch(iGLE)
	{
	case ERROR_PATH_NOT_FOUND: 
	case ERROR_FILE_NOT_FOUND: 
	case ERROR_INVALID_NAME: 
		return STATUS_NOTFOUND;
	case ERROR_ACCESS_DENIED: 
		return STATUS_FORBIDDEN;
	case ERROR_SHARING_VIOLATION:
		return STATUS_LOCKED;
	case ERROR_DISK_FULL:
		return STATUS_INSUFFICIENT_STORAGE;
	default:
		return STATUS_INTERNALERR;
	}
}

BOOL CHttpRequest::MapDirToDefaultPage(void)  {
	WCHAR wszTemp[MAX_PATH];
	DWORD ccNext = 0;

	if (m_ccWPath > ARRAYSIZEOF(wszTemp)) {
		DEBUGMSG(ZONE_REQUEST,(L"HTTPD: path is too long, will not attempt MapDirToDefaultPage\r\n"));
		return FALSE;
	}
	
	// make temp copy of dir path. append \ if reqd
	wcscpy(wszTemp, m_wszPath);
	// if we get here we have a trailing \ or / (otherwise we sent a redirect instead)
	DEBUGCHK(wszTemp[m_ccWPath-1]=='/' || wszTemp[m_ccWPath-1]=='\\');

	if (!m_pWebsite->m_wszDefaultPages)
		return FALSE;

	PWSTR wszNext=m_pWebsite->m_wszDefaultPages;
	ccNext = (1+wcslen(wszNext));

	for(; *wszNext; ccNext=(1+wcslen(wszNext)), wszNext+=ccNext) {
		if (ccNext + m_ccWPath >= ARRAYSIZEOF(wszTemp)) {
			// we'd overflow the buffer, and not interesting anyway because resulting name 
			// would be longer than filesys can handle in the 1st place.
			continue; 
		}
		
		wcscpy(wszTemp+m_ccWPath, wszNext);
		if((-1) != GetFileAttributes(wszTemp)) {	
			PWSTR pwsz;
			// found something
			DEBUGMSG(ZONE_RESPONSE, (L"HTTPD: Converting dir path (%s) to default page(%s)\r\n", m_wszPath, wszTemp));
			MyFree(m_wszPath);
			if (NULL == (m_wszPath = MySzDupW(wszTemp)))
				return FALSE;

			m_ccWPath = wcslen(m_wszPath);

			MyFree(m_wszExt);
			if (pwsz = wcsrchr(m_wszPath, '.'))
				m_wszExt = MySzDupW(pwsz);

			return TRUE;
		}
	}
	DEBUGMSG(ZONE_REQUEST, (L"HTTPD: No default page found in dir path (%s)\r\n", m_wszPath));
	return FALSE;
}


BOOL CHttpRequest::SendRedirectIfNeeded(void) {
	int iLen = strlen(m_pszURL);
	DEBUGCHK(iLen >= 1);

	if (! URLHasTrailingSlash()) {
		// we have allocated one extra char in m_pszURL already in case 
		// we needed to send a redirect back (see parser.cpp)
		m_pszURL[iLen]='/';
		m_pszURL[iLen+1]=0;

		CHttpResponse resp(this, STATUS_MOVED);
		resp.SendRedirect(m_pszURL); // send a special redirect body
		m_pszURL[iLen]=0; // restore m_pszURL 
		return TRUE;
	}

	return FALSE;
}


const char cszDirHeader1[] = "<head><title>%s - %s</title></head><body><H1>%s - %s</H1><hr>";
const char cszDirHeader2[] = "<A HREF=\"%s\">%s</A><br><br>";
const char cszPre[]        = "<pre>";
const char cszDirFooter[]  = "</pre><hr></body>";

#define MAXENTRYSIZE	(150+MAX_PATH+MAX_PATH)

BOOL CHttpRequest::EmitDirListing(void)  {
	WCHAR wszBuf1[MAX_PATH+10];
	WCHAR wszBuf2[MAX_PATH];
	char szHostBuf[MAX_PATH];

	if (m_ccWPath > ARRAYSIZEOF(wszBuf1))
		return FALSE;
	
	// generate listing into a buffer
	int  iSize = DIRBUFSIZE;
	PSTR pszBuf = MyRgAllocNZ(CHAR, iSize);
	int  iNext = 0;
	if(!pszBuf)
		return FALSE;

	// we know have enough space for the headers
	if ( 0 != gethostname(szHostBuf, sizeof(szHostBuf)))
		szHostBuf[0] = '\0';

	iNext += sprintf(pszBuf+iNext, cszDirHeader1, szHostBuf, m_pszURL, szHostBuf, m_pszURL);

	// find the parent path ignore the trailing slash (always present)

	int iURLLen = strlen(m_pszURL) - 2;
	for(int i=iURLLen; i>=0; i--)  {
		if(m_pszURL[i]=='/' || m_pszURL[i]=='\\')  {
			// Holds the string [Link to parent directory].
			WCHAR wszParentDirectory[256];
			CHAR szParentDirectory[256];
			LoadString(g_hInst,IDS_LINKTOPARENTDIR,wszParentDirectory,ARRAYSIZEOF(wszParentDirectory));
			MyW2A(wszParentDirectory,szParentDirectory,sizeof(szParentDirectory));

			// save & restore one char to temporarily truncate the URL at the parent path (incl slash)
			char chSave=m_pszURL[i+1];
			m_pszURL[i+1] = 0;
			
			iNext += sprintf(pszBuf+iNext, cszDirHeader2, m_pszURL, szParentDirectory);

			m_pszURL[i+1] = chSave;
			break;
		}
	}

	strcpy(pszBuf+iNext,cszPre);
	iNext += CONSTSIZEOF(cszPre);

	// create Find pattern
	DEBUGCHK(m_ccWPath == wcslen(m_wszPath));
	DEBUGCHK(URLHasTrailingSlashW(m_wszPath,m_ccWPath));
	WIN32_FIND_DATA fd;
	wcscpy(wszBuf1, m_wszPath);
	wcscpy(wszBuf1+m_ccWPath, L"*");

	// now iterate the files & subdirs (if any)
	HANDLE hFile = FindFirstFile(wszBuf1, &fd);
	if(INVALID_HANDLE_VALUE != hFile) {
		do {
			// check for space
			if((iSize-iNext) < MAXENTRYSIZE)  {
				if(!(pszBuf = MyRgReAlloc(CHAR, pszBuf, iSize, iSize+DIRBUFSIZE)))
					return FALSE;
				iSize += DIRBUFSIZE;
			}
			// convert date
			FILETIME   ftLocal;
			SYSTEMTIME stLocal;
			FileTimeToLocalFileTime(&fd.ftLastAccessTime, &ftLocal);
			FileTimeToSystemTime(&ftLocal, &stLocal);
			// format date
			GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_SHORTDATE, &stLocal, NULL, wszBuf1, CCHSIZEOF(wszBuf1));
			GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &stLocal, NULL, wszBuf2, CCHSIZEOF(wszBuf2));
			// generate HTML entry.
			const char cszDirEntry[]   = "%12S  %10S  %12d <A HREF=\"%S\">%S</A><br>";
			iNext += sprintf(pszBuf+iNext, cszDirEntry, wszBuf1, wszBuf2, fd.nFileSizeLow, fd.cFileName, fd.cFileName);
		}
		while(FindNextFile(hFile, &fd));
		// CloseHandle(hFile);	// This throws an exception on WinNT, use FindClose instead
		FindClose(hFile);
	}
	// emit footer
	strcpy(pszBuf+iNext,cszDirFooter);
	iNext += sizeof(cszDirFooter)-1;

	// create a response object & attach this body, then send headers & body
	CHttpResponse resp(this);
	resp.SetBody(pszBuf, cszTextHtml);
	resp.SendResponse();
	// free the buffer
	MyFree(pszBuf);
	return TRUE;
}


void CHttpRequest::Init(SOCKET sock, BOOL fSecure)  {
	memset(this, 0, sizeof(*this));

	m_dwSig              = CHTTPREQUEST_SIG;
	m_pFInfo             = CreateCFilterInfo();
	m_socket             = sock;
	m_dwVersion          = MAKELONG(0,1);
	m_fIsSecurePort      = fSecure;
	m_fHandleSSL         = fSecure && !g_pVars->m_fSSLSkipProcessing;
	m_pWebsite           = g_pVars;
	m_dwFileAttributes   = (DWORD)INVALID_HANDLE_VALUE;

	// put ourselves into linked list.
	m_pNext           = g_pRequestList;
	g_pRequestList    = this;
}


void CHttpRequest::RemoveFromList(void) {
	// Remove ourselves from global listening list
	EnterCriticalSection(&g_CritSect);

	g_pVars->m_nConnections--;
	DEBUGCHK(g_pVars->m_nConnections >= 0);

	CHttpRequest *pTrav = g_pRequestList;
	CHttpRequest *pFollow = NULL;
	
	while (pTrav) {
		if (pTrav == this) {
			if (pTrav == g_pRequestList)
				g_pRequestList = pTrav->m_pNext;

			if (pFollow)
				pFollow->m_pNext = pTrav->m_pNext;

			break;
		}

		pFollow = pTrav;
		pTrav   = pTrav->m_pNext;
	}
	DEBUGCHK(pTrav);

	CloseSocket(); // need to be procetced by CritSec because CloseAllConnections() my close on another thread.
	LeaveCriticalSection(&g_CritSect);
}

CHttpRequest::~CHttpRequest() {
	DEBUGMSG(ZONE_REQUEST,(L"HTTPD: Calling CHttpRequest destructor\r\n"));
	DEBUGCHK(m_dwSig == CHTTPREQUEST_SIG);

	FreeHeaders();
	FreeAuth();

	if(m_pFInfo) {
		delete m_pFInfo;
		m_pFInfo = 0;
	}

	FreeSecContextHandles(&m_AuthState);
	FreePersistedAuthInfo();

	if (m_fHandleSSL)
		CloseSSLSession();

	RemoveFromList();
}


//  Called right before each HTTP Request (multiple times for a persisted session)
//  Frees request specific data, like destructor but keeps session data
//  (Filter alloc'd mem, NTLM state) in place.

BOOL CHttpRequest::ReInit() {
	DEBUGMSG(ZONE_REQUEST,(L"HTTPD: Calling CHttpRequest ReInit (between requests)\r\n"));
	DEBUGCHK(m_dwSig == CHTTPREQUEST_SIG); // catch memory 

	FreeHeaders();
	FreeAuth();		

	m_idMethod           = VERB_UNKNOWN;
	m_dwFileAttributes   = (DWORD)INVALID_HANDLE_VALUE;
	m_fOptionsAsterisk   = FALSE;
	m_ccWPath            = 0;
	m_pVRoot             = NULL;
	m_fBufferedResponse  = FALSE;
	m_fResponseHTTP11    = FALSE;

	m_bufRequest.Reset();				
	m_bufRespHeaders.Reset();
	m_bufRespBody.Reset();
	memset(&m_ftIfModifiedSince,0,sizeof(m_ftIfModifiedSince));

	if (m_pFInfo) {
		if ( !m_pFInfo->ReInit() )
			return FALSE;
	}

	// NTLM stuff.  If we're in middle of conversation, don't delete NTLM state info
	// We never free the library here, only in the destructor.
	if (m_AuthState.m_Stage == SEC_STATE_DONE)  {
		FreeSecContextHandles(&m_AuthState);

		//  Set the flags so that we know the context isn't initialized.  This
		//  would be relevent if user typed the wrong password.
		m_AuthState.m_Stage = SEC_STATE_NO_INIT_CONTEXT;
	}

	// Certain values need to be zeroed
	m_dwContentLength = m_dwIfModifiedLength = m_dwVersion = 0;

	m_fKeepAlive = FALSE;
	m_hrPreviousReadClient = INPUT_OK;

	return TRUE;
}


//  If a filter makes a call to ServerSupportFunction to SEND_RESPONSE_HEADERS,

⌨️ 快捷键说明

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