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

📄 reqsock.cpp

📁 一个网路服务器程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		cEnv.Add( "SERVER_NAME", pReqSock->m_pDoc->m_strServer );
		cEnv.Add( "GATEWAY_INTERFACE", "CGI/1.1" );
		cEnv.Add( "SERVER_PROTOCOL", "HTTP/1.0" );
		strValue.Format( "%d", pReqSock->m_pDoc->m_uPort );
		cEnv.Add( "SERVER_PORT", strValue );

		cEnv.Add( "REQUEST_METHOD", pRequest->m_strMethod );
		cEnv.Add( "SCRIPT_NAME", pRequest->m_strURL );
		cEnv.Add( "QUERY_STRING", pRequest->m_strArgs );
		cEnv.Add( "REMOTE_ADDR", pRequest->m_strHost );
		if ( pRequest->m_cbBody > 0 )
		{
			cEnv.Add( "CONTENT_LENGTH", pRequest->GetHeaderValue("Content-Length") );
			cEnv.Add( "CONTENT_TYPE", pRequest->GetHeaderValue("Content-Type") );
		}
		if ( !pRequest->m_strPathInfo.IsEmpty() )
		{
			cEnv.Add( "PATH_INFO", pRequest->m_strPathInfo );
			cEnv.Add( "PATH_TRANSLATED", pRequest->m_strPathTranslated );
		}

		// all the passed headers prefixed with "HTTP_"....
		POSITION pos = pRequest->m_mapHeaders.GetStartPosition();
		while ( pos != NULL )
		{
			// get the name/value pair....
			CString strName, strValue;
			pRequest->m_mapHeaders.GetNextAssoc( pos, strName, strValue );
			HeaderToEnvVar( strName );
			// set the environment variable....
			cEnv.Add( strName, strValue );
		}

		// create the process....
		LPVOID pEnv = (LPVOID)cEnv.GetBlock();
		PROCESS_INFORMATION pi;
		STARTUPINFO si = {0};
		si.cb = sizeof(si);
		si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
		si.wShowWindow = SW_HIDE;
		si.hStdInput = hReadPipe;
		si.hStdOutput = pReqSock->m_hFile;
		si.hStdError = pReqSock->m_hFile;
		bOk = CreateProcess( NULL, strCmdLine.GetBuffer(1),
			NULL, NULL, TRUE,
			dwCreateFlags, pEnv,
			strDir, &si, &pi );
		strCmdLine.ReleaseBuffer();
		// if created....
		if ( bOk )
		{
			// release our hold on the thread....
			CloseHandle( pi.hThread );
			// send the body of the post to the stdin....
			if ( pRequest->m_cbBody > 0 )
			{
				DWORD dwWritten = 0;
				WriteFile( hWritePipe, pRequest->m_baBody.GetData(),
					pRequest->m_cbBody, &dwWritten, NULL );
			}
			// wait for either cancel or process done....
			HANDLE aHandles[2];
			aHandles[0] = pi.hProcess;
			aHandles[1] = pReqSock->m_pCancel->m_hObject;
			if ( WaitForMultipleObjects( 2, aHandles, FALSE, INFINITE ) == WAIT_OBJECT_0 )
			{
				// process finished; notify main thread....
				AfxGetApp()->m_pMainWnd->PostMessage( WSM_CGIDONE, 0, (LPARAM)pReqSock );
			}
			else
			{
				// canceled or some other error....
				bOk = FALSE;
			}
			// close our hold on it....
			CloseHandle( pi.hProcess );
		}
		else
			dwErr = GetLastError();

		// close the stdin pipe....
		CloseHandle( hWritePipe );
		CloseHandle( hReadPipe );
		delete pEnv;
	}
	if ( bOk == FALSE && pReqSock->m_hFile != INVALID_HANDLE_VALUE )
	{ // JIC....
		CloseHandle( pReqSock->m_hFile );
		pReqSock->m_hFile = INVALID_HANDLE_VALUE;
	}

	return (bOk?0:1);
}

void CRequestSocket::CGIDone( void )
{
	if ( !m_bKilled )
	{
		// flush the temp file's buffers....
#pragma warning(disable : 4244)
		BOOL bSucceed = FALSE;
		bSucceed = FlushFileBuffers( m_hFile );
        if (bSucceed)
        {
		    // go to start of file....
		    DWORD dwPos = 0;
		    dwPos = SetFilePointer( m_hFile, 0, NULL, FILE_BEGIN );
		    // output the header....
		    StuffHeading();
		    if ( m_pRequest->m_strMethod.Compare( "HEAD" ) )
			    StartTargetStuff();
		    else
		    {
			    CloseHandle( m_hFile );
			    m_hFile = INVALID_HANDLE_VALUE;
		    }
		    BOOL bOk = AsyncSelect( FD_WRITE | FD_CLOSE );
            ASSERT(bOk);
        }
		else
		{
			CloseHandle( m_hFile );
			m_hFile = INVALID_HANDLE_VALUE;
		}
#pragma warning(default : 4244)
	}
	else
	{
		CloseHandle( m_hFile );
		m_hFile = INVALID_HANDLE_VALUE;
	}
}

void HeaderToEnvVar( CString& strVar )
{
	int ndx;
	// make upper case, change '-' to '_', and prefix....
	strVar.MakeUpper();
	while( (ndx = strVar.Find('-')) != -1 )
		strVar = strVar.Left(ndx) + '_' + strVar.Mid(ndx+1);
	strVar = "HTTP_" + strVar;
}

CEnvironment::CEnvironment( void )
{
	m_nSize = 2;
}

CEnvironment::~CEnvironment( void )
{
}

BOOL CEnvironment::Add( CString name, CString value )
{
	BOOL bOk = TRUE;
	// create the entry pair string....
	CString strPair = name + __TEXT('=') + value;
	m_nSize += strPair.GetLength() + 1;
	POSITION pos = m_list.GetHeadPosition();

	// find the first item bigger than this string....
	while( pos != NULL )
	{
		if ( m_list.GetAt(pos).CompareNoCase(strPair) > 0 )
		{
			m_list.InsertBefore( pos, strPair );
			break;
		}
		m_list.GetNext( pos );
	}
	if ( pos == NULL )
		m_list.AddTail( strPair );

	return bOk;
}

LPVOID CEnvironment::GetBlock( void )
{
	// allocate a block....
	PTCHAR pBlock = new TCHAR[m_nSize];
    size_t nSizeLeft = m_nSize;
	if ( pBlock )
	{
		// iterate through the list....
		PTCHAR pPos = pBlock;
		POSITION pos = m_list.GetHeadPosition();
		while( pos != NULL )
		{
			CString& str = m_list.GetNext( pos );
			// copy the string....
            StringCbCopy( pPos, nSizeLeft, str );
			pPos += str.GetLength() + 1;
            nSizeLeft -= (str.GetLength() + 1);
		}
		// NULL for the whole list....
		*pPos = __TEXT('\0');
	}
	return pBlock;
}
#endif // IMPL_CGI

CString CRequestSocket::GetHttpDate( LPFILETIME pft )
{
	SYSTEMTIME st;
	if ( pft )
		FileTimeToSystemTime( pft, &st );
	else
		GetSystemTime( &st );

	CTime timeHttp( st );
	return timeHttp.Format( IDS_HTTPTIME );
}

BOOL CRequestSocket::IfModSince( const CTime& timeIfMod )
{
	// assume it has been modified....
	BOOL bOk = TRUE;
	FILETIME ft;
	if ( GetFileTime( m_hFile, NULL, NULL, &ft ) )
	{
		SYSTEMTIME st;
		if ( FileTimeToSystemTime( &ft, &st ) )
		{
			CTime timeFile( st );
			if ( timeFile <= timeIfMod )
				bOk = FALSE;
		}
	}
	return bOk;
}

static int IntVal( CString strVal )
{
	int nVal = 0;
	strVal.TrimLeft();
	for( int ndx = 0; ndx < strVal.GetLength(); ++ndx )
		nVal = nVal*10 + strVal.GetAt(ndx) - '0';

	return nVal;
}

static int MonthFromStr( const CString& str )
{
	LPSTR aMonths[] = {
		"xxx", "jan", "feb", "mar", "apr", "may", "jun",
		"jul", "aug", "sep", "oct", "nov", "dec" };
	for( int nMonth=1; nMonth <= 12; ++nMonth )
	{
		if ( str.CompareNoCase( aMonths[nMonth] ) == 0 )
			break;
	}

	return nMonth;
}

// Dow, dd Mon year hh:mm:ss GMT
#pragma warning(disable : 4244)
BOOL CRequestSocket::FromHttpTime( const CString& strHttp, CTime& timeHttp )
{
	// assume we couldn't get a good time conversion....
	BOOL bOk = FALSE;
	SYSTEMTIME st = {0};
	int ndx;
	switch( strHttp.GetAt(3) )
	{
	case ',':
		// read RFC-1123 (preferred)....
		st.wDay = IntVal( strHttp.Mid(5,2) );
		st.wMonth = MonthFromStr( strHttp.Mid(8,3) );
		st.wYear = IntVal( strHttp.Mid(12,4) );
		st.wHour = IntVal( strHttp.Mid(17,2) );
		st.wMinute = IntVal( strHttp.Mid(20,2) );
		st.wSecond = IntVal( strHttp.Mid(23,2) );
		break;
	case ' ':
		// read ANSI-C time format....
		st.wDay = IntVal( strHttp.Mid(8,2) );
		st.wMonth = MonthFromStr( strHttp.Mid(4,3) );
		st.wYear = IntVal( strHttp.Mid(20,4) );
		st.wHour = IntVal( strHttp.Mid(11,2) );
		st.wMinute = IntVal( strHttp.Mid(14,2) );
		st.wSecond = IntVal( strHttp.Mid(17,2) );
		break;
	default:
		if ( (ndx = strHttp.Find( ", " )) != -1 )
		{
			st.wDay = IntVal( strHttp.Mid(ndx+2,2) );
			st.wMonth = MonthFromStr( strHttp.Mid(ndx+5,3) );
			st.wYear = IntVal( strHttp.Mid(ndx+9,2) );
			st.wHour = IntVal( strHttp.Mid(ndx+12,2) );
			st.wMinute = IntVal( strHttp.Mid(ndx+15,2) );
			st.wSecond = IntVal( strHttp.Mid(ndx+18,2) );
			// add the correct century....
			st.wYear += (st.wYear > 50)?1900:2000;
		}
		break;
	}
	// if year not zero, we pulled the info out of the string....
	if ( st.wYear != 0 )
	{
		// assume GMT....
		CTime strTime( st );
		// check to see if the minutes are the same....
		if ( strTime.GetMinute() == st.wMinute )
		{
			// assume it worked....
			timeHttp = strTime;
			bOk = TRUE;
		}
	}
	return bOk;
}
#pragma warning(default : 4244)

int CRequestSocket::AddRef( void )
{
	return ++m_nRefs;
}

int CRequestSocket::Release( void )
{
	int nRefs = --m_nRefs;
	if ( nRefs == 0 )
		delete this;
	return nRefs;
}



void CRequestSocket::StuffFileType( void )
{
	// get the extension....
	CString strExt = m_pRequest->m_strFullPath.Mid(
		m_pRequest->m_strFullPath.ReverseFind('.') );
	// find it in the registry....
	HKEY hKey = NULL;
	if ( RegOpenKeyEx( HKEY_CLASSES_ROOT, strExt,
		0, KEY_READ, &hKey ) == ERROR_SUCCESS )
	{
		DWORD dwSize = 0;
		// see how long the data is....
		if ( RegQueryValueEx( hKey, "Content Type", NULL, NULL,
			NULL, &dwSize ) == ERROR_SUCCESS )
		{
			CString strType;
			LONG lRet = RegQueryValueEx( hKey, "Content Type", NULL, NULL,
				(LPBYTE)strType.GetBuffer( dwSize ), &dwSize );
			strType.ReleaseBuffer();
			if ( lRet == ERROR_SUCCESS )
				StuffHeader( "Content-type", strType );
		}
		RegCloseKey( hKey );
	}
}

CString Decode( const CString& str, BOOL bQuery )
{
	int ndx;
	CString strDecoded = str;
	// special processing or query strings....
	if ( bQuery )
	{
		// change all '+' to ' '....
		while( (ndx=strDecoded.Find('+')) != -1 )
			strDecoded = strDecoded.Left(ndx) + ' ' + strDecoded.Mid(ndx+1);
	}

	// first see if there are any %s to decode....
	if ( strDecoded.Find( '%' ) != -1 )
	{
		// iterate through the string, changing %dd to special char....
		for( ndx=0; ndx < strDecoded.GetLength(); ndx++ )
		{
			char ch = strDecoded.GetAt( ndx );
			if ( ch == '%' )
			{
				if ( strDecoded.GetAt( ndx+1 ) == '%' )
				{
					// wanna keep one percent sign....
					strDecoded = strDecoded.Left(ndx) + strDecoded.Mid(ndx+1);
				}
				else
				{
#pragma warning(disable : 4244)
					// assume we have a hex value....
					char ch1 = strDecoded.GetAt(ndx+1);
					char ch2 = strDecoded.GetAt(ndx+2);
					ch1 = ch1 >= 'A' ? (ch1&0xdf)-'A' : ch1-'0';
					ch2 = ch2 >= 'A' ? (ch2&0xdf)-'A' : ch2-'0';
					// replace the escape sequence with the char....
					strDecoded = strDecoded.Left(ndx)
						+ (char)(ch1*16 + ch2)
						+ strDecoded.Mid( ndx+3 );
#pragma warning(default : 4244)
				}
			}
		}
	}
	return strDecoded;
}

CString CRequestSocket::StripLast( CString& strPath )
{
	CString strExtra;
	if ( !strPath.IsEmpty() )
	{
		int ndx = strPath.ReverseFind( SEPCHAR );
		if ( ndx < 0 )
			ndx = 0;
		strExtra = strPath.Mid( ndx );
		strPath = strPath.Left( ndx );
	}
	return strExtra;
}

BOOL CRequestSocket::CheckDefault( UINT uList, BOOL bExecute )
{
	BOOL bFound = FALSE;
	DWORD dwAttr;
	CString strDefault, strDefList;
	BOOL bOk =strDefList.LoadString( uList );
    ASSERT(bOk);
	while ( !strDefList.IsEmpty() )
	{
		int ndx;
		strDefault = m_pRequest->m_strFullPath;
		if ( (ndx=strDefList.Find('\n')) == -1 )
		{
			AddFile( strDefault, strDefList );
			strDefList.Empty();
		}
		else
		{
			AddFile( strDefault, strDefList.Left(ndx) );
			strDefList = strDefList.Mid( ndx+1 );
		}
		if ( (dwAttr=GetFileAttributes(strDefault)) != -1 &&
			(dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 )
		{
			bFound = TRUE;
			break;
		}
	}
	if ( bFound )
	{
		// redirect to the default file....
		PathToURL( strDefault );
		if ( bExecute )
			strDefault += '?';

		StuffStatus( IDS_STATUS_MOVEDTEMP );
		StuffHeader( "Location", strDefault );
		StuffString( CRLF );
	}
	return bFound;
}

BOOL CRequestSocket::IsSvrApp( void )
{
	BOOL bOk = FALSE;
	int ndx = m_pRequest->m_strFullPath.ReverseFind( '.' );
	if ( ndx != -1 )
	{
		CString strExt = m_pRequest->m_strFullPath.Mid( ndx+1 );
		CString strAvail;
		// check if CGI app....
		BOOL bLoadStringOk = strAvail.LoadString( IDS_APP_CGI );
        ASSERT(!bLoadStringOk);
		bOk = CheckExt( strExt, strAvail, CRequest::APP_CGI );
		if ( !bOk )
		{
			bLoadStringOk = strAvail.LoadString( IDS_APP_ISAPI );
            ASSERT(!bLoadStringOk);
			bOk = CheckExt( strExt, strAvail, CRequest::APP_ISAPI );
		}
	}

	return bOk;
}

BOOL CRequestSocket::CheckExt( const CString& strExt, CString& strAvail, DWORD dwType )
{
	BOOL bMatch = FALSE;
	CString strPossible;
	// loop through all possible exts....
	while( !strAvail.IsEmpty() )
	{
		int ndx = strAvail.ReverseFind('\n');
		if ( ndx == -1 )
		{
			strPossible = strAvail;
			strAvail.Empty();
		}
		else
		{
			strPossible = strAvail.Mid( ndx+1 );
			strAvail = strAvail.Left( ndx );
		}
		if ( strExt.CompareNoCase( strPossible ) == 0 )
		{
			m_pRequest->m_dwExecute = dwType;
			bMatch = TRUE;
			break;
		}
	}
	return bMatch;
}

⌨️ 快捷键说明

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