www.pudn.com > httpserve.rar > Httpdoc.cpp


// HttpDoc.cpp : implementation of the CHttpSvrDoc class 
// 
// This is a part of the Microsoft Foundation Classes C++ library. 
// Copyright (C) 1997-1998 Microsoft Corporation 
// All rights reserved. 
// 
// This source code is only intended as a supplement to the 
// Microsoft Foundation Classes Reference and related 
// electronic documentation provided with the library. 
// See these sources for detailed information regarding the 
// Microsoft Foundation Classes product. 
 
#include "stdafx.h" 
 
#include "HttpSvr.h" 
#include "HttpDoc.h" 
#include "Request.h" 
#include "GenPage.h" 
#include "NamePage.h" 
#include "RootPage.h" 
#include "Listen.h" 
#include "mainfrm.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrDoc 
 
IMPLEMENT_DYNCREATE(CHttpSvrDoc, CDocument) 
 
BEGIN_MESSAGE_MAP(CHttpSvrDoc, CDocument) 
	//{{AFX_MSG_MAP(CHttpSvrDoc) 
	ON_COMMAND(IDM_SVR_OPTIONS, OnSvrOptions) 
	ON_COMMAND(ID_FILE_RESTART, OnFileRestart) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrDoc construction/destruction 
 
CHttpSvrDoc::CHttpSvrDoc() 
{ 
	m_pListen = NULL; 
} 
 
CHttpSvrDoc::~CHttpSvrDoc() 
{ 
	// get rid of any lingering requests, JIC..... 
	while ( !m_reqList.IsEmpty() ) 
	{ 
		CRequest* pRequest = (CRequest*)(m_reqList.RemoveTail()); 
		pRequest->Release(); 
	} 
} 
 
BOOL CHttpSvrDoc::OnNewDocument() 
{ 
	CDocument::OnNewDocument(); 
 
	// zero the hits counter.... 
	m_nTotalHits = 0; 
	// assign default values.... 
	m_strServer = ((CHttpSvrApp*)AfxGetApp())->m_strDefSvr; 
	m_uPort = PORT_HTTP; 
	m_nSvrName = 0; 
	m_bLoggingOn = TRUE; 
	m_bAllowListing = TRUE; 
	m_bListIcon = TRUE; 
 
	// get the default root path.... 
	m_strRoot.LoadString( IDS_DEF_ROOT ); 
	m_strRoot = SEPCHAR + m_strRoot; 
	// ensure no final separator character.... 
	if ( m_strRoot[m_strRoot.GetLength()-1] == SEPCHAR ) 
		m_strRoot = m_strRoot.Left( m_strRoot.GetLength()-1 ); 
	// make into a full path string.... 
	GetFullPathName( m_strRoot, MAX_PATH, 
		m_strRoot.GetBuffer(MAX_PATH), NULL); 
	m_strRoot.ReleaseBuffer(); 
 
	// see if we need to automatically disable the icons 
	// in folder listings.... 
	CString strAdmin = m_strRoot + SEPCHAR + "SvrAdmin"; 
	DWORD dwAttr = GetFileAttributes( strAdmin ); 
	if ( dwAttr == (DWORD)(-1) || (dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 ) 
		m_bListIcon = FALSE; // don't allow icons 
 
	StartListening(); 
	SetTitle( NULL ); 
	return TRUE; 
} 
 
BOOL CHttpSvrDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{ 
	BOOL bOk = FALSE; 
	if ( CDocument::OnOpenDocument(lpszPathName) ) 
	{ 
		if ( (bOk = StartListening()) == FALSE ) 
			SetModifiedFlag( TRUE ); 
	} 
 
	return bOk; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrDoc serialization 
 
void CHttpSvrDoc::Serialize(CArchive& ar) 
{ 
	if (ar.IsStoring()) 
	{ 
		ar << m_strRoot; 
		ar << m_strServer; 
		ar << m_timeStarted; 
		ar << m_uPort; 
		ar << m_nSvrName; 
		ar << m_bLoggingOn; 
		ar << m_bListIcon; 
		ar << m_bAllowListing; 
	} 
	else 
	{ 
		ar >> m_strRoot; 
		ar >> m_strServer; 
		ar >> m_timeStarted; 
		ar >> m_uPort; 
		ar >> m_nSvrName; 
		ar >> m_bLoggingOn; 
		ar >> m_bListIcon; 
		ar >> m_bAllowListing; 
 
		if ( m_nSvrName == 0 ) 
			m_strServer = ((CHttpSvrApp*)AfxGetApp())->m_strDefSvr; 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrDoc diagnostics 
 
#ifdef _DEBUG 
void CHttpSvrDoc::AssertValid() const 
{ 
	CDocument::AssertValid(); 
} 
 
void CHttpSvrDoc::Dump(CDumpContext& dc) const 
{ 
	CDocument::Dump(dc); 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrDoc commands 
 
void CHttpSvrDoc::DocHit( CRequest* pRequest ) 
{ 
	// save the request object.... 
	pRequest->AddRef(); 
	m_reqList.AddTail( pRequest ); 
	// increment the total hit count.... 
	++m_nTotalHits; 
	// tell the view we got a new doc hit.... 
	UpdateAllViews( NULL, HINT_DOCHIT, pRequest ); 
} 
 
BOOL CHttpSvrDoc::IdleProc( LONG lCount ) 
{ 
	BOOL bMore = FALSE; 
	// if there's still requests in the list.... 
	if ( !m_reqList.IsEmpty() ) 
	{ 
		// pull off the first item.... 
		CRequest* pRequest = (CRequest*)(m_reqList.RemoveHead()); 
		// if it's done.... 
		if ( pRequest->m_bDone ) 
		{ 
			// process it for the stats.... 
			ExtractStats( pRequest ); 
			// done with it.... 
			pRequest->Release(); 
			// more idle needed if not empty.... 
			bMore = !m_reqList.IsEmpty(); 
		} 
		else 
		{ 
			// move to end of list.... 
			m_reqList.AddTail( pRequest ); 
			// still need to come back.... 
			bMore = TRUE; 
		} 
	} 
	return bMore; 
} 
 
void CHttpSvrDoc::ExtractStats( CRequest* pRequest ) 
{ 
	// increment the status' group count.... 
	if ( pRequest->m_uStatus >= 100 && pRequest->m_uStatus < 600 ) 
		++m_aReStats[ pRequest->m_uStatus/100 - 1 ]; 
	else 
		++m_aReStats[ STATUS_SERVERERR ]; // JIC 
 
	// see if we want to write entry in log file.... 
	if ( m_bLoggingOn ) 
	{ 
		CString strLog; 
		strLog.Format( IDS_STATUSFMT, pRequest->m_uStatus ); 
		strLog += pRequest->m_strHost + '\t' 
			+ pRequest->m_timeReq.Format( IDS_TIMEFORMAT ) + '\t' 
			+ pRequest->m_strURL + ' '; 
		if ( !pRequest->m_strArgs.IsEmpty() ) 
			strLog += CString("? ") + pRequest->m_strArgs; 
 
		strLog += '\n'; 
		CString strLogName = m_strTitleBase + pRequest->m_timeReq.Format(IDS_LOGFILEFMT); 
		CStdioFile fileLog( strLogName, 
			CFile::modeWrite | CFile::modeCreate | 
			CFile::modeNoTruncate | CFile::shareExclusive ); 
		// see if file is new and we need to write the header.... 
		if ( fileLog.SeekToEnd() == 0 ) 
		{ 
			// write page header..... 
			CString strHeader; 
			strHeader.Format( IDS_LOG_HEADER, pRequest->m_timeReq.Format(IDS_LONG_DATE) ); 
			fileLog.Write( strHeader, strHeader.GetLength() ); 
		} 
		fileLog.Write( strLog, strLog.GetLength() ); 
		fileLog.Close(); 
	} 
} 
 
 
void CHttpSvrDoc::OnCloseDocument() 
{ 
	StopListening(); 
	CDocument::OnCloseDocument(); 
} 
 
void CHttpSvrDoc::SetTitle(LPCTSTR lpszTitle) 
{ 
	CString strTitle; 
	if ( lpszTitle != NULL ) 
		m_strTitleBase = lpszTitle; 
 
	if ( m_strServer.IsEmpty() ) 
		strTitle = m_strTitleBase; 
	else if ( m_pListen == NULL ) 
		strTitle.Format( IDS_INVALID, m_strTitleBase ); 
	else 
	{ 
		if ( m_uPort != PORT_HTTP ) 
			strTitle.Format( IDS_DOCTITLE, m_strTitleBase, m_strServer, m_uPort ); 
		else 
			strTitle.Format( IDS_DOCTITLE_NOPORT, m_strTitleBase, m_strServer ); 
	} 
 
	CDocument::SetTitle( strTitle ); 
} 
 
void CHttpSvrDoc::OnSvrOptions() 
{ 
	// add and initialize the general page.... 
	CPropertySheet propOptions( IDS_OPTIONS ); 
	CGenPage genPage( this ); 
	genPage.m_bListIcon = m_bListIcon; 
	genPage.m_bAllowListing = m_bAllowListing; 
	genPage.m_bLoggingOn = m_bLoggingOn; 
	propOptions.AddPage( &genPage ); 
 
	// add and initialize the root dir page.... 
	CRootPage rootPage( this ); 
	rootPage.m_strRoot = m_strRoot; 
	propOptions.AddPage( &rootPage ); 
 
	// add and initialize the name page.... 
	CNamePage namePage( this ); 
	namePage.m_nNameSetting = m_nSvrName; 
	namePage.m_uPort = m_uPort; 
	if ( m_nSvrName ) 
		namePage.m_strName = m_strServer; 
	propOptions.AddPage( &namePage ); 
 
	m_bResetListen = FALSE; 
	propOptions.DoModal(); 
	if ( m_bResetListen ) 
	{ 
		StartListening(); 
		SetTitle( NULL ); 
	} 
} 
 
void CHttpSvrDoc::StopListening( void ) 
{ 
	if ( m_pListen != NULL ) 
	{ 
		m_pListen->Close(); 
		delete m_pListen; 
		m_pListen = NULL; 
	} 
} 
 
BOOL CHttpSvrDoc::StartListening( void ) 
{ 
	BOOL bOk = FALSE; 
	StopListening(); 
	m_pListen = new CListenSocket( this ); 
	if ( m_pListen ) 
	{ 
		if ( m_pListen->Create( m_uPort, SOCK_STREAM, FD_ACCEPT ) ) 
			bOk = m_pListen->Listen(); 
 
		if ( !bOk ) 
		{ 
			CString strMsg; 
			int nErr = m_pListen->GetLastError(); 
			if ( nErr == WSAEADDRINUSE ) 
				strMsg.Format( IDS_LISTEN_INUSE, m_uPort ); 
			else 
				strMsg.Format( IDS_LISTEN_ERROR, m_uPort ); 
 
			AfxMessageBox( strMsg, MB_OK|MB_ICONSTOP ); 
			m_pListen->Close(); 
			delete m_pListen; 
			m_pListen = NULL; 
		} 
	} 
	else 
		AfxMessageBox( IDS_CANT_LISTEN, MB_OK|MB_ICONSTOP ); 
 
	m_timeStarted = CTime::GetCurrentTime(); 
 
	return bOk; 
} 
 
 
 
void CHttpSvrDoc::OnFileRestart() 
{ 
	// this will close the connection if it's already open 
	// before starting again.... 
	StartListening(); 
}