📄 reqsock.cpp
字号:
{
int ndx;
// a local reference to the root....
CString& strRoot = m_pDoc->m_strRoot;
// change all SEPCHARs to forward slashes....
while ( (ndx=strFile.Find( SEPCHAR )) != -1 )
strFile = strFile.Left( ndx ) + '/' + strFile.Mid(ndx+1);
// now add the prefix and server, and cut the root....
CString strPort;
UINT uPort = m_pDoc->m_uPort;
if ( uPort != PORT_HTTP )
strPort.Format( ":%d", uPort );
strFile = CString("http://")
+ m_pDoc->m_strServer
+ strPort
+ strFile.Mid(strRoot.GetLength());
return TRUE;
}
int CRequestSocket::StuffString( const CString& strData )
{
int nLen = strData.GetLength()*sizeof(TCHAR);
// make sure there's enough room....
if ( m_cbOut + nLen > m_buf.GetSize() )
{
int nChunks = nLen/1024 + 1;
m_buf.SetSize( m_cbOut + nChunks*1024 );
}
// copy the data....
MoveMemory( m_buf.GetData() + m_cbOut, (LPCSTR)strData, nLen );
m_cbOut += nLen;
// return amount of space left....
return (int)(m_buf.GetSize() - m_cbOut);
}
int CRequestSocket::StuffString( UINT uId )
{
CString str;
BOOL bOk = str.LoadString( uId );
ASSERT(bOk);
return StuffString( str );
}
int CRequestSocket::StuffStatus( const CString& strStatus )
{
CString strVer = "HTTP/1.0 ";
StuffString( strVer );
StuffString( strStatus );
StuffString( CRLF );
// stuff the server name....
CString strServer;
if ( strServer.LoadString( IDS_SERVER_NAME ) && !strServer.IsEmpty() )
StuffHeader( "Server", strServer );
// stuff the date....
return StuffHeader( "Date", GetHttpDate() );
}
int CRequestSocket::StuffStatus( UINT uStatus )
{
CString strStatus;
BOOL bOk = strStatus.LoadString( uStatus );
ASSERT(bOk);
// save the status for this request....
m_pRequest->m_uStatus = uStatus;
// stuff the HTTP status line....
return StuffStatus( strStatus );
}
int CRequestSocket::StuffError( UINT uMsg )
{
StuffStatus( uMsg );
return StuffString( CRLF );
}
int CRequestSocket::StuffHeader( CString strName, CString strValue )
{
StuffString( strName );
StuffString( ": " );
StuffString( strValue );
return StuffString( CRLF );
}
int CRequestSocket::StuffHeader( CString strName, int nValue )
{
CString strValue;
StuffString( strName );
StuffString( ": " );
strValue.Format( "%d", nValue );
StuffString( strValue );
return StuffString( CRLF );
}
BOOL CRequestSocket::StuffHeading( void )
{
BOOL bContinue = FALSE;
if ( m_pRequest->m_dwAttr & FILE_ATTRIBUTE_HIDDEN )
{
// never show hidden files....
StuffError( IDS_STATUS_FORBIDDEN );
}
else if ( m_pRequest->m_dwAttr & FILE_ATTRIBUTE_DIRECTORY )
{
if ( m_pDoc->m_bAllowListing )
{
// create a directory listing....
StuffStatus( IDS_STATUS_OK );
StuffString( CRLF );
bContinue = TRUE;
}
else
StuffError( IDS_STATUS_FORBIDDEN );
}
#ifdef IMPL_CGI
else if ( m_hFile != INVALID_HANDLE_VALUE )
{
// cgi's output file will be opened already....
CString strStatus, strHeaders;
// loop until we find a blank line....
DWORD dwRead = 0;
CByteArray baFile;
baFile.SetSize( 1024 );
// read next chunk....
if(!ReadFile( m_hFile, baFile.GetData(),
(DWORD)baFile.GetSize(), &dwRead, NULL ))
{
BOOL bOk = strStatus.LoadString(IDS_STATUS_SVRERROR);
ASSERT(bOk);
dwRead = 0;
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
while ( dwRead > 0 )
{
int ndx = 0;
while( GetLine( baFile, dwRead, ndx ) == TRUE )
{
BOOL bSave = TRUE;
// stuff any non-empty lines.....
if ( m_strLine.IsEmpty() )
{
// we found our empty line;
// back up to where we left off....
DWORD dwPos = 0;
dwPos = SetFilePointer( m_hFile,
ndx - dwRead,
NULL, FILE_CURRENT );
// and we're off....
bContinue = TRUE;
break;
}
else
{
int nPos = m_strLine.Find( ':' );
if ( nPos != -1 )
{
CString strName = m_strLine.Left( nPos );
strName.TrimLeft();
strName.TrimRight();
CString strVal = m_strLine.Mid( nPos+1 );
strVal.TrimLeft();
strVal.TrimRight();
if ( strName.CompareNoCase("Status") == 0 )
{
strStatus = strVal;
bSave = FALSE;
}
else if ( strName.CompareNoCase("Location") == 0 )
{
BOOL bOk = strStatus.LoadString( IDS_STATUS_MOVEDTEMP );
ASSERT(bOk);
}
}
}
// save the header (if we want to)....
if ( bSave )
strHeaders += m_strLine + CRLF;
m_strLine.Empty();
}
// read next chunk if we're not done....
if ( bContinue )
break;
else
if(!ReadFile( m_hFile, baFile.GetData(),
(DWORD)baFile.GetSize(), &dwRead, NULL ))
{
BOOL bOk = strStatus.LoadString(IDS_STATUS_SVRERROR);
ASSERT(bOk);
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
}
if ( strStatus.IsEmpty() )
StuffStatus( IDS_STATUS_OK );
else
StuffStatus( strStatus );
// stuff the headers....
StuffString( strHeaders );
// stuff the blank line....
StuffString( CRLF );
}
#endif // IMPL_CGI
else
{
// open the file....
m_hFile = CreateFile( m_pRequest->m_strFullPath,
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL );
if ( m_hFile != INVALID_HANDLE_VALUE )
{
if ( m_reqStatus != REQ_SIMPLE )
{
CTime timeIfMod;
CString strIfMod = m_pRequest->GetHeaderValue( "If-Modified-Since" );
if ( strIfMod.GetLength() > 0 &&
FromHttpTime( strIfMod, timeIfMod ) &&
!IfModSince( timeIfMod ) )
{
// eh, it hasn't been modified....
StuffStatus( IDS_STATUS_NOTMODIFIED );
// don't need it anymore....
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
else
{
// send it off....
StuffStatus( IDS_STATUS_OK );
// any other header info....
StuffFileType();
StuffHeader( "Content-length", GetFileSize( m_hFile, NULL ) );
// get the last modified time....
FILETIME ft;
if ( GetFileTime( m_hFile, NULL, NULL, &ft ) )
{
StuffHeader( "Last-Modified", GetHttpDate( &ft ) );
}
bContinue = TRUE;
}
// blank line....
StuffString( CRLF );
}
else
bContinue = TRUE;
}
else
{
// couldn't open; try again later....
StuffError( IDS_STATUS_SVCUNAVAIL );
}
}
return bContinue;
}
void CRequestSocket::StartTargetStuff( void )
{
if ( m_hFile != INVALID_HANDLE_VALUE)
{
DWORD dwRead = 0;
// read the first chunk....
if(ReadFile( m_hFile, m_buf.GetData() + m_cbOut,
(DWORD)(m_buf.GetSize()-m_cbOut), &dwRead, NULL ) && dwRead > 0)
{
m_cbOut += dwRead;
}
else
{
// nothing read.... close the file....
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
}
else if ( m_pRequest->m_dwAttr & FILE_ATTRIBUTE_DIRECTORY )
StuffListing();
else
StuffString( CRLF );
}
void CRequestSocket::StuffListing( void )
{
BOOL bRoot = FALSE;
BOOL bIcons = m_pDoc->m_bListIcon;
CString strIcon;
CString strLine = CString("http://")
+ m_pDoc->m_strServer
+ m_pRequest->m_strURL;
CString strDir = m_pRequest->m_strURL;
CString strMask = m_pRequest->m_strFullPath;
// make sure URL ends in a slash....
if ( strDir.GetAt( strDir.GetLength()-1 ) != '/' )
strDir += '/';
// is this the server's root folder?
else if ( strDir.Compare( "/" ) == 0 )
bRoot = TRUE;
// create the file search mask....
AddFile( strMask, IDS_DIRMASK );
StuffString( IDS_CONTENTS_PRE );
StuffString( strLine );
StuffString( IDS_CONTENTS_POST );
if ( bRoot )
StuffString( IDS_CONTENTS_DESC );
if ( bIcons )
{
BOOL bOk = strIcon.LoadString( IDS_ICON_BLANK );
ASSERT(bOk);
}
strLine.Format( IDS_CONTENTS_HEADING, strIcon );
StuffString( strLine );
int nFiles = 0;
WIN32_FIND_DATA fd;
// find the first file that matches the mask....
HANDLE fh = FindFirstFile( strMask, &fd );
if ( fh != INVALID_HANDLE_VALUE )
{
// create a line for the found file....
nFiles += StuffListingFile( &fd, strDir, bIcons );
// loop through all other files....
while ( FindNextFile( fh, &fd ) )
nFiles += StuffListingFile( &fd, strDir, bIcons );
}
if ( nFiles == 0 )
StuffString( IDS_CONTENTS_EMPTY );
StuffString( IDS_CONTENTS_FOOTER );
// only add the parent link if there is one....
if ( !bRoot )
{
if ( bIcons )
{
BOOL bOk = strIcon.LoadString( IDS_ICON_PARENT );
ASSERT(bOk);
}
strLine.Format( IDS_CONTENTS_PARENT, strIcon );
StuffString( strLine );
}
// add the note and end it....
StuffString( IDS_CONTENTS_NOTE );
StuffString( CRLF );
}
int CRequestSocket::StuffListingFile( WIN32_FIND_DATA* pfd, const CString& strDir, BOOL bIcons )
{
int nFile = 0;
// don't include '.', '..' or hidden files....
if ( lstrcmp( pfd->cFileName, "." ) && lstrcmp( pfd->cFileName, ".." )
&& (pfd->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0 )
{
CString strSize, strIcon = "";
CString strLine, strFile = pfd->cFileName;
CTime timeFile( pfd->ftLastWriteTime );
BOOL bFolder = ((pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
BOOL bOk = TRUE;
if ( bIcons && bFolder )
bOk = strIcon.LoadString( IDS_ICON_FOLDER );
else if ( bIcons )
bOk = strIcon.LoadString( IDS_ICON_FILE );
ASSERT(bOk);
// create the link string....
CString strLink = strDir + strFile;
// make sure spaces are replaced with '%20'...
int ndx;
while ( (ndx=strLink.Find(' ')) != -1 )
strLink = strLink.Left(ndx) + "%20" + strLink.Mid( ndx+1 );
// format the size string....
if ( bFolder )
strSize = " Folder";
else if ( pfd->nFileSizeHigh > 0 )
strSize = " > 4GB"; // yeah, right.
else if ( pfd->nFileSizeLow < 1024 )
strSize = " < 1K";
else
strSize.Format( "%7dK", pfd->nFileSizeLow/1024 );
strLine.Format( IDS_CONTENTS_FORMAT,
timeFile.Format( IDS_FILETIMEFMT ),
strSize, strLink, strIcon, strFile );
StuffString( strLine );
nFile = 1;
}
return nFile;
}
BOOL CRequestSocket::StartSvrApp( void )
{
#ifdef IMPL_CGI
if ( m_pRequest->m_dwExecute != CRequest::APP_ISAPI )
return CGIStart();
else
{
StuffError( IDS_STATUS_NOTIMPL );
return FALSE;
}
#else // IMPL_CGI
StuffError( IDS_STATUS_NOTIMPL );
return FALSE;
#endif // IMPL_CGI
}
#ifdef IMPL_CGI
BOOL CRequestSocket::CGIStart( void )
{
BOOL bOk = FALSE;
// get the temp path...
CString strTempPath;
DWORD dwSize = 0;
if((dwSize = GetTempPath( 0, NULL )) == 0)
return FALSE;
GetTempPath(dwSize,strTempPath.GetBuffer(dwSize));
strTempPath.ReleaseBuffer();
// create a temporary file for the output....
CString strTempName;
GetTempFileName( strTempPath, "CGI", 0, strTempName.GetBuffer(dwSize+12) );
strTempName.ReleaseBuffer();
m_hFile = CreateFile( strTempName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, &g_sa,
CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, NULL );
if ( m_hFile != INVALID_HANDLE_VALUE )
{
// create the cancel event....
m_pCancel = new CEvent;
if ( m_pCancel )
{
// make sure the event is reset....
m_pCancel->ResetEvent();
// create the CGI thread suspended....
m_pThread = AfxBeginThread( (AFX_THREADPROC)CGIThread,
(LPVOID)this, THREAD_PRIORITY_NORMAL, 0,
CREATE_SUSPENDED, NULL );
if ( m_pThread )
{
// don't self-destruct (we must delete)....
m_pThread->m_bAutoDelete = FALSE;
// resume...
m_pThread->ResumeThread();
bOk = TRUE;
}
}
}
if ( bOk == FALSE )
{
StuffError( IDS_STATUS_SVRERROR );
if( m_hFile != INVALID_HANDLE_VALUE )
{ // JIC....
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
}
return bOk;
}
void AddEnvVar( CString& strEnv, CString strName, CString strVal )
{
// add the name=val pair to the env in alphabetical order....
strEnv += strName + '=' + strVal + '\a';
}
UINT CGIThread( LPVOID pvParam )
{
CRequestSocket* pReqSock = (CRequestSocket*)pvParam;
CRequest* pRequest = pReqSock->m_pRequest;
BOOL bOk = FALSE;
DWORD dwErr;
HANDLE hWritePipe, hReadPipe;
// create a pipe we'll use for STDIN....
if ( CreatePipe( &hReadPipe, &hWritePipe, &g_sa, 0 ) )
{
// get the command line together....
CString strCmdLine = pRequest->m_strFullPath
+ ' '
+ Decode( pRequest->m_strArgs, TRUE );
// get the directory....
CString strDir = pRequest->m_strFullPath;
int ndx = strDir.ReverseFind( SEPCHAR );
// assume we found it....
strDir = strDir.Left( ndx+1 );
// create an environment for the CGI process....
DWORD dwCreateFlags = 0;
#ifdef UNICODE
dwCreateFlags = CREATE_UNICODE_ENVIRONMENT;
#endif // UNICODE
CEnvironment cEnv;
CString strValue;
BOOL bOk = strValue.LoadString( IDS_SERVER_NAME );
ASSERT(bOk);
cEnv.Add( "SERVER_SOFTWARE", strValue );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -