home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / internet / httpsvr / httpdoc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  8.4 KB  |  347 lines

  1. // HttpDoc.cpp : implementation of the CHttpSvrDoc class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1997-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14.  
  15. #include "HttpSvr.h"
  16. #include "HttpDoc.h"
  17. #include "Request.h"
  18. #include "GenPage.h"
  19. #include "NamePage.h"
  20. #include "RootPage.h"
  21. #include "Listen.h"
  22. #include "mainfrm.h"
  23.  
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CHttpSvrDoc
  32.  
  33. IMPLEMENT_DYNCREATE(CHttpSvrDoc, CDocument)
  34.  
  35. BEGIN_MESSAGE_MAP(CHttpSvrDoc, CDocument)
  36.     //{{AFX_MSG_MAP(CHttpSvrDoc)
  37.     ON_COMMAND(IDM_SVR_OPTIONS, OnSvrOptions)
  38.     ON_COMMAND(ID_FILE_RESTART, OnFileRestart)
  39.     //}}AFX_MSG_MAP
  40. END_MESSAGE_MAP()
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CHttpSvrDoc construction/destruction
  44.  
  45. CHttpSvrDoc::CHttpSvrDoc()
  46. {
  47.     m_pListen = NULL;
  48. }
  49.  
  50. CHttpSvrDoc::~CHttpSvrDoc()
  51. {
  52.     // get rid of any lingering requests, JIC.....
  53.     while ( !m_reqList.IsEmpty() )
  54.     {
  55.         CRequest* pRequest = (CRequest*)(m_reqList.RemoveTail());
  56.         pRequest->Release();
  57.     }
  58. }
  59.  
  60. BOOL CHttpSvrDoc::OnNewDocument()
  61. {
  62.     CDocument::OnNewDocument();
  63.  
  64.     // zero the hits counter....
  65.     m_nTotalHits = 0;
  66.     // assign default values....
  67.     m_strServer = ((CHttpSvrApp*)AfxGetApp())->m_strDefSvr;
  68.     m_uPort = PORT_HTTP;
  69.     m_nSvrName = 0;
  70.     m_bLoggingOn = TRUE;
  71.     m_bAllowListing = TRUE;
  72.     m_bListIcon = TRUE;
  73.  
  74.     // get the default root path....
  75.     m_strRoot.LoadString( IDS_DEF_ROOT );
  76.     m_strRoot = SEPCHAR + m_strRoot;
  77.     // ensure no final separator character....
  78.     if ( m_strRoot[m_strRoot.GetLength()-1] == SEPCHAR )
  79.         m_strRoot = m_strRoot.Left( m_strRoot.GetLength()-1 );
  80.     // make into a full path string....
  81.     GetFullPathName( m_strRoot, MAX_PATH,
  82.         m_strRoot.GetBuffer(MAX_PATH), NULL);
  83.     m_strRoot.ReleaseBuffer();
  84.  
  85.     // see if we need to automatically disable the icons
  86.     // in folder listings....
  87.     CString strAdmin = m_strRoot + SEPCHAR + "SvrAdmin";
  88.     DWORD dwAttr = GetFileAttributes( strAdmin );
  89.     if ( dwAttr == (DWORD)(-1) || (dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 )
  90.         m_bListIcon = FALSE; // don't allow icons
  91.  
  92.     StartListening();
  93.     SetTitle( NULL );
  94.     return TRUE;
  95. }
  96.  
  97. BOOL CHttpSvrDoc::OnOpenDocument(LPCTSTR lpszPathName)
  98. {
  99.     BOOL bOk = FALSE;
  100.     if ( CDocument::OnOpenDocument(lpszPathName) )
  101.     {
  102.         if ( (bOk = StartListening()) == FALSE )
  103.             SetModifiedFlag( TRUE );
  104.     }
  105.  
  106.     return bOk;
  107. }
  108.  
  109. /////////////////////////////////////////////////////////////////////////////
  110. // CHttpSvrDoc serialization
  111.  
  112. void CHttpSvrDoc::Serialize(CArchive& ar)
  113. {
  114.     if (ar.IsStoring())
  115.     {
  116.         ar << m_strRoot;
  117.         ar << m_strServer;
  118.         ar << m_timeStarted;
  119.         ar << m_uPort;
  120.         ar << m_nSvrName;
  121.         ar << m_bLoggingOn;
  122.         ar << m_bListIcon;
  123.         ar << m_bAllowListing;
  124.     }
  125.     else
  126.     {
  127.         ar >> m_strRoot;
  128.         ar >> m_strServer;
  129.         ar >> m_timeStarted;
  130.         ar >> m_uPort;
  131.         ar >> m_nSvrName;
  132.         ar >> m_bLoggingOn;
  133.         ar >> m_bListIcon;
  134.         ar >> m_bAllowListing;
  135.  
  136.         if ( m_nSvrName == 0 )
  137.             m_strServer = ((CHttpSvrApp*)AfxGetApp())->m_strDefSvr;
  138.     }
  139. }
  140.  
  141. /////////////////////////////////////////////////////////////////////////////
  142. // CHttpSvrDoc diagnostics
  143.  
  144. #ifdef _DEBUG
  145. void CHttpSvrDoc::AssertValid() const
  146. {
  147.     CDocument::AssertValid();
  148. }
  149.  
  150. void CHttpSvrDoc::Dump(CDumpContext& dc) const
  151. {
  152.     CDocument::Dump(dc);
  153. }
  154. #endif //_DEBUG
  155.  
  156. /////////////////////////////////////////////////////////////////////////////
  157. // CHttpSvrDoc commands
  158.  
  159. void CHttpSvrDoc::DocHit( CRequest* pRequest )
  160. {
  161.     // save the request object....
  162.     pRequest->AddRef();
  163.     m_reqList.AddTail( pRequest );
  164.     // increment the total hit count....
  165.     ++m_nTotalHits;
  166.     // tell the view we got a new doc hit....
  167.     UpdateAllViews( NULL, HINT_DOCHIT, pRequest );
  168. }
  169.  
  170. BOOL CHttpSvrDoc::IdleProc( LONG lCount )
  171. {
  172.     BOOL bMore = FALSE;
  173.     // if there's still requests in the list....
  174.     if ( !m_reqList.IsEmpty() )
  175.     {
  176.         // pull off the first item....
  177.         CRequest* pRequest = (CRequest*)(m_reqList.RemoveHead());
  178.         // if it's done....
  179.         if ( pRequest->m_bDone )
  180.         {
  181.             // process it for the stats....
  182.             ExtractStats( pRequest );
  183.             // done with it....
  184.             pRequest->Release();
  185.             // more idle needed if not empty....
  186.             bMore = !m_reqList.IsEmpty();
  187.         }
  188.         else
  189.         {
  190.             // move to end of list....
  191.             m_reqList.AddTail( pRequest );
  192.             // still need to come back....
  193.             bMore = TRUE;
  194.         }
  195.     }
  196.     return bMore;
  197. }
  198.  
  199. void CHttpSvrDoc::ExtractStats( CRequest* pRequest )
  200. {
  201.     // increment the status' group count....
  202.     if ( pRequest->m_uStatus >= 100 && pRequest->m_uStatus < 600 )
  203.         ++m_aReStats[ pRequest->m_uStatus/100 - 1 ];
  204.     else
  205.         ++m_aReStats[ STATUS_SERVERERR ]; // JIC
  206.  
  207.     // see if we want to write entry in log file....
  208.     if ( m_bLoggingOn )
  209.     {
  210.         CString strLog;
  211.         strLog.Format( IDS_STATUSFMT, pRequest->m_uStatus );
  212.         strLog += pRequest->m_strHost + '\t'
  213.             + pRequest->m_timeReq.Format( IDS_TIMEFORMAT ) + '\t'
  214.             + pRequest->m_strURL + ' ';
  215.         if ( !pRequest->m_strArgs.IsEmpty() )
  216.             strLog += CString("? ") + pRequest->m_strArgs;
  217.  
  218.         strLog += '\n';
  219.         CString strLogName = m_strTitleBase + pRequest->m_timeReq.Format(IDS_LOGFILEFMT);
  220.         CStdioFile fileLog( strLogName,
  221.             CFile::modeWrite | CFile::modeCreate |
  222.             CFile::modeNoTruncate | CFile::shareExclusive );
  223.         // see if file is new and we need to write the header....
  224.         if ( fileLog.SeekToEnd() == 0 )
  225.         {
  226.             // write page header.....
  227.             CString strHeader;
  228.             strHeader.Format( IDS_LOG_HEADER, pRequest->m_timeReq.Format(IDS_LONG_DATE) );
  229.             fileLog.Write( strHeader, strHeader.GetLength() );
  230.         }
  231.         fileLog.Write( strLog, strLog.GetLength() );
  232.         fileLog.Close();
  233.     }
  234. }
  235.  
  236.  
  237. void CHttpSvrDoc::OnCloseDocument()
  238. {
  239.     StopListening();
  240.     CDocument::OnCloseDocument();
  241. }
  242.  
  243. void CHttpSvrDoc::SetTitle(LPCTSTR lpszTitle)
  244. {
  245.     CString strTitle;
  246.     if ( lpszTitle != NULL )
  247.         m_strTitleBase = lpszTitle;
  248.  
  249.     if ( m_strServer.IsEmpty() )
  250.         strTitle = m_strTitleBase;
  251.     else if ( m_pListen == NULL )
  252.         strTitle.Format( IDS_INVALID, m_strTitleBase );
  253.     else
  254.     {
  255.         if ( m_uPort != PORT_HTTP )
  256.             strTitle.Format( IDS_DOCTITLE, m_strTitleBase, m_strServer, m_uPort );
  257.         else
  258.             strTitle.Format( IDS_DOCTITLE_NOPORT, m_strTitleBase, m_strServer );
  259.     }
  260.  
  261.     CDocument::SetTitle( strTitle );
  262. }
  263.  
  264. void CHttpSvrDoc::OnSvrOptions()
  265. {
  266.     // add and initialize the general page....
  267.     CPropertySheet propOptions( IDS_OPTIONS );
  268.     CGenPage genPage( this );
  269.     genPage.m_bListIcon = m_bListIcon;
  270.     genPage.m_bAllowListing = m_bAllowListing;
  271.     genPage.m_bLoggingOn = m_bLoggingOn;
  272.     propOptions.AddPage( &genPage );
  273.  
  274.     // add and initialize the root dir page....
  275.     CRootPage rootPage( this );
  276.     rootPage.m_strRoot = m_strRoot;
  277.     propOptions.AddPage( &rootPage );
  278.  
  279.     // add and initialize the name page....
  280.     CNamePage namePage( this );
  281.     namePage.m_nNameSetting = m_nSvrName;
  282.     namePage.m_uPort = m_uPort;
  283.     if ( m_nSvrName )
  284.         namePage.m_strName = m_strServer;
  285.     propOptions.AddPage( &namePage );
  286.  
  287.     m_bResetListen = FALSE;
  288.     propOptions.DoModal();
  289.     if ( m_bResetListen )
  290.     {
  291.         StartListening();
  292.         SetTitle( NULL );
  293.     }
  294. }
  295.  
  296. void CHttpSvrDoc::StopListening( void )
  297. {
  298.     if ( m_pListen != NULL )
  299.     {
  300.         m_pListen->Close();
  301.         delete m_pListen;
  302.         m_pListen = NULL;
  303.     }
  304. }
  305.  
  306. BOOL CHttpSvrDoc::StartListening( void )
  307. {
  308.     BOOL bOk = FALSE;
  309.     StopListening();
  310.     m_pListen = new CListenSocket( this );
  311.     if ( m_pListen )
  312.     {
  313.         if ( m_pListen->Create( m_uPort, SOCK_STREAM, FD_ACCEPT ) )
  314.             bOk = m_pListen->Listen();
  315.  
  316.         if ( !bOk )
  317.         {
  318.             CString strMsg;
  319.             int nErr = m_pListen->GetLastError();
  320.             if ( nErr == WSAEADDRINUSE )
  321.                 strMsg.Format( IDS_LISTEN_INUSE, m_uPort );
  322.             else
  323.                 strMsg.Format( IDS_LISTEN_ERROR, m_uPort );
  324.  
  325.             AfxMessageBox( strMsg, MB_OK|MB_ICONSTOP );
  326.             m_pListen->Close();
  327.             delete m_pListen;
  328.             m_pListen = NULL;
  329.         }
  330.     }
  331.     else
  332.         AfxMessageBox( IDS_CANT_LISTEN, MB_OK|MB_ICONSTOP );
  333.  
  334.     m_timeStarted = CTime::GetCurrentTime();
  335.  
  336.     return bOk;
  337. }
  338.  
  339.  
  340.  
  341. void CHttpSvrDoc::OnFileRestart()
  342. {
  343.     // this will close the connection if it's already open
  344.     // before starting again....
  345.     StartListening();
  346. }
  347.