www.pudn.com > httpserve.rar > HTTPVIEW.CPP


// HttpView.cpp : implementation of the CHttpSvrView 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 "Http.h" 
#include "HttpDoc.h" 
#include "HttpView.h" 
#include "RootDlg.h" 
#include "NoRoot.h" 
#include "Request.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrView 
 
IMPLEMENT_DYNCREATE(CHttpSvrView, CListView) 
 
BEGIN_MESSAGE_MAP(CHttpSvrView, CListView) 
	//{{AFX_MSG_MAP(CHttpSvrView) 
	ON_COMMAND(IDM_VIEW_LARGE, OnViewLarge) 
	ON_UPDATE_COMMAND_UI(IDM_VIEW_LARGE, OnUpdateViewLarge) 
	ON_COMMAND(IDM_VIEW_LIST, OnViewList) 
	ON_UPDATE_COMMAND_UI(IDM_VIEW_LIST, OnUpdateViewList) 
	ON_COMMAND(IDM_VIEW_REPORT, OnViewReport) 
	ON_UPDATE_COMMAND_UI(IDM_VIEW_REPORT, OnUpdateViewReport) 
	ON_COMMAND(IDM_VIEW_SMALL, OnViewSmall) 
	ON_UPDATE_COMMAND_UI(IDM_VIEW_SMALL, OnUpdateViewSmall) 
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick) 
	ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetDispInfo) 
	ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnDeleteItem) 
	ON_COMMAND(IDM_VIEW_CLEAR, OnViewClear) 
	//}}AFX_MSG_MAP 
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk) 
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick) 
	ON_COMMAND(IDM_POPUP_CLEAR, OnPopupClear) 
	ON_COMMAND(IDM_POPUP_EDIT, OnPopupEdit) 
	ON_COMMAND(IDM_POPUP_OPEN, OnPopupOpen) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrView construction/destruction 
 
CHttpSvrView::CHttpSvrView() 
{ 
	m_phdPopup = NULL; 
} 
 
CHttpSvrView::~CHttpSvrView() 
{ 
} 
 
BOOL CHttpSvrView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	cs.style = (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; 
	cs.style |= LVS_AUTOARRANGE; 
	return CListView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrView drawing 
 
void CHttpSvrView::OnDraw(CDC* pDC) 
{ 
	CHttpSvrDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
} 
 
void CHttpSvrView::OnInitialUpdate() 
{ 
	CHttpSvrDoc* pDoc = GetDocument(); 
	CListView::OnInitialUpdate(); 
	// get the root directory.... 
	CString strRoot = pDoc->m_strRoot; 
	// make sure it exists and it's a folder.... 
	BOOL bLoop = TRUE; 
	while ( bLoop ) 
	{ 
		DWORD dwAttr = GetFileAttributes( strRoot ); 
		if ( dwAttr == -1 ) 
		{ 
			CNoRootDlg dlg; 
			dlg.m_strRoot = strRoot; 
			UINT uButton = dlg.DoModal(); 
			if ( uButton == IDOK ) 
			{ 
				strRoot = dlg.m_strRoot; 
				dwAttr = GetFileAttributes( strRoot ); 
				if ( dwAttr == -1 ) 
				{ 
					if ( !CreateDirectory( strRoot, NULL ) ) 
					{ 
						MessageBox( "Create Directory failed", 
							strRoot, MB_ICONEXCLAMATION|MB_OK ); 
					} 
				} 
			} 
			else // no.... 
				bLoop = FALSE; // use it anyway 
		} 
		else if ( (dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 ) 
		{ 
			CBadRootDlg dlg; 
			dlg.m_strRoot = strRoot; 
			if ( dlg.DoModal() == IDCANCEL ) 
				bLoop = FALSE; // use it anyway 
		} 
		else 
		{ 
			// root is okay, save it.... 
			if ( strRoot.CompareNoCase(pDoc->m_strRoot) != 0 ) 
			{ 
				pDoc->m_strRoot = strRoot; 
				pDoc->SetModifiedFlag( TRUE ); 
			} 
			bLoop = FALSE;  // okay! 
		} 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrView diagnostics 
 
#ifdef _DEBUG 
void CHttpSvrView::AssertValid() const 
{ 
	CListView::AssertValid(); 
} 
 
void CHttpSvrView::Dump(CDumpContext& dc) const 
{ 
	CListView::Dump(dc); 
} 
 
CHttpSvrDoc* CHttpSvrView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHttpSvrDoc))); 
	return (CHttpSvrDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CHttpSvrView message handlers 
 
BOOL CHttpSvrView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{ 
	BOOL bCreated = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); 
	if ( bCreated ) 
	{ 
		CListCtrl& listView = GetListCtrl(); 
		int aWidths[] = { 150, 200, 50, 140, 225, 200 }; 
		CString strHeading; 
 
		for ( int iCol = 0; iCol < C_COLUMNS; iCol++) { 
			strHeading.LoadString( IDS_COLUMN1 + iCol ); 
			listView.InsertColumn( iCol, strHeading, LVCFMT_LEFT, 
				aWidths[iCol], iCol ); 
		} 
 
		// Create the full-sized and small icon image lists. 
		if ( m_ilLarge.Create( IDB_IMAGES, 32, 1, RGB(0,255,0) ) ) 
		{ 
			listView.SetImageList( &m_ilLarge, LVSIL_NORMAL ); 
		} 
		if ( m_ilSmall.Create( IDB_SMALLIMAGES, 16, 1, RGB(0,255,0) ) ) 
		{ 
			listView.SetImageList( &m_ilSmall, LVSIL_SMALL); 
		} 
	} 
	return bCreated; 
} 
 
void CHttpSvrView::SetListView( DWORD dwView ) 
{ 
	CListCtrl& list = GetListCtrl(); 
	DWORD dwStyle = GetWindowLong( list.m_hWnd, GWL_STYLE ); 
	if ( (dwStyle & LVS_TYPEMASK) != dwView ) 
		SetWindowLong( list.m_hWnd, GWL_STYLE, 
			(dwStyle & ~LVS_TYPEMASK) | dwView ); 
} 
 
void CHttpSvrView::OnViewLarge() 
{ 
	SetListView( LVS_ICON ); 
} 
 
void CHttpSvrView::OnUpdateViewLarge(CCmdUI* pCmdUI) 
{ 
	CListCtrl& list = GetListCtrl(); 
	DWORD dwStyle = GetWindowLong( list.m_hWnd, GWL_STYLE ) & LVS_TYPEMASK; 
	pCmdUI->SetCheck( dwStyle == LVS_ICON ); 
} 
 
void CHttpSvrView::OnViewList() 
{ 
	SetListView( LVS_LIST ); 
} 
 
void CHttpSvrView::OnUpdateViewList(CCmdUI* pCmdUI) 
{ 
	CListCtrl& list = GetListCtrl(); 
	DWORD dwStyle = GetWindowLong( list.m_hWnd, GWL_STYLE ) & LVS_TYPEMASK; 
	pCmdUI->SetCheck( dwStyle == LVS_LIST ); 
} 
 
void CHttpSvrView::OnViewReport() 
{ 
	SetListView( LVS_REPORT ); 
} 
 
void CHttpSvrView::OnUpdateViewReport(CCmdUI* pCmdUI) 
{ 
	CListCtrl& list = GetListCtrl(); 
	DWORD dwStyle = GetWindowLong( list.m_hWnd, GWL_STYLE ) & LVS_TYPEMASK; 
	pCmdUI->SetCheck( dwStyle == LVS_REPORT ); 
} 
 
void CHttpSvrView::OnViewSmall() 
{ 
	SetListView( LVS_SMALLICON ); 
} 
 
void CHttpSvrView::OnUpdateViewSmall(CCmdUI* pCmdUI) 
{ 
	CListCtrl& list = GetListCtrl(); 
	DWORD dwStyle = GetWindowLong( list.m_hWnd, GWL_STYLE ) & LVS_TYPEMASK; 
	pCmdUI->SetCheck( dwStyle == LVS_SMALLICON ); 
} 
 
int CALLBACK 
CompareHitDocs( CHitDoc* doc1, CHitDoc* doc2, LPARAM lCol ) 
{ 
	int nCmp = 0; 
	switch( lCol ) 
	{ 
	case COLUMN_PATH: 
		nCmp = doc1->m_strFolder.CompareNoCase( doc2->m_strFolder ); 
		break; 
	case COLUMN_HITS: 
		if ( doc1->m_nHits > doc2->m_nHits ) 
			nCmp = -1; 
		else if ( doc1->m_nHits < doc2->m_nHits ) 
			nCmp = 1; 
		break; 
	case COLUMN_LAST: 
		if ( doc1->m_timeLastHit > doc2->m_timeLastHit ) 
			nCmp = -1; 
		else if ( doc1->m_timeLastHit < doc2->m_timeLastHit ) 
			nCmp = 1; 
		break; 
	case COLUMN_CMD: 
		nCmp = doc1->m_strCommand.CompareNoCase( doc2->m_strCommand ); 
		break; 
	case COLUMN_URL: 
		nCmp = doc1->m_strURL.CompareNoCase( doc2->m_strURL ); 
		break; 
	default: 
		// put folders ahead of everything.... 
		if ( doc1->m_bFolder && !doc2->m_bFolder ) 
			nCmp = -1; 
		else if ( !doc1->m_bFolder && doc2->m_bFolder ) 
			nCmp = 1; 
		// sort successfully hit docs.... 
		else if ( doc1->m_nStatus == 200 && doc2->m_nStatus == 200 ) 
		{ 
			nCmp = doc1->m_strFile.CompareNoCase( doc2->m_strFile ); 
			if ( nCmp == 0 ) 
				nCmp = doc1->m_strFolder.CompareNoCase( doc2->m_strFolder ); 
		} 
		// put hit docs ahead of status items.... 
		else if ( doc1->m_nStatus == 200 ) 
			nCmp = -1; 
		else if ( doc2->m_nStatus == 200 ) 
			nCmp = 1; 
		// sort status items by status value.... 
		else if ( doc1->m_nStatus < doc2->m_nStatus ) 
			nCmp = -1; 
		else if ( doc1->m_nStatus > doc2->m_nStatus ) 
			nCmp = 1; 
		break; 
	} 
	return nCmp; 
} 
 
void CHttpSvrView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; 
	CListCtrl& list = GetListCtrl(); 
	list.SortItems( (PFNLVCOMPARE)CompareHitDocs, pNMListView->iSubItem ); 
	*pResult = 0; 
} 
 
void CHttpSvrView::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; 
	if ( pDispInfo->item.mask & LVIF_TEXT ) 
	{ 
		CHitDoc* pHitDoc = (CHitDoc*)(pDispInfo->item.lParam); 
		switch( pDispInfo->item.iSubItem ) 
		{ 
		case COLUMN_FILE: 
			lstrcpy( pDispInfo->item.pszText, pHitDoc->m_strFile ); 
			break; 
		case COLUMN_PATH: 
			lstrcpy( pDispInfo->item.pszText, pHitDoc->m_strFolder ); 
			break; 
		case COLUMN_HITS: 
			wsprintf( pDispInfo->item.pszText, "%d", pHitDoc->m_nHits ); 
			break; 
		case COLUMN_LAST: 
			if ( pHitDoc->m_nHits > 0 ) 
				lstrcpy( pDispInfo->item.pszText, (pHitDoc->m_nHits) 
					? pHitDoc->m_timeLastHit.Format( IDS_TIMEFORMAT ) 
					: "" ); 
			break; 
		case COLUMN_URL: 
			lstrcpy( pDispInfo->item.pszText, pHitDoc->m_strURL ); 
			break; 
		case COLUMN_CMD: 
			lstrcpy( pDispInfo->item.pszText, pHitDoc->m_strCommand ); 
			break; 
		} 
	} 
	*pResult = 0; 
} 
 
void CHttpSvrView::OnDeleteItem(NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; 
	CListCtrl& list = GetListCtrl(); 
	LV_ITEM lvi; 
	lvi.mask = LVIF_PARAM; 
	lvi.iItem = pNMListView->iItem; 
	lvi.iSubItem = 0; 
	if ( list.GetItem( &lvi ) == TRUE ) 
	{ 
		CHitDoc* pHit = (CHitDoc*)(lvi.lParam); 
		delete pHit; 
	} 
	*pResult = 0; 
} 
 
int 
CHttpSvrView::GetImage( CHitDoc* pHitDoc ) 
{ 
	// indexes into image maps for (status/100).... 
	int aStatImg[] = { 2, 5, 5, 4, 3, 3 }; 
	int iImage; 
	if ( pHitDoc->m_nStatus != 0 && pHitDoc->m_nStatus != 200 ) 
		iImage = aStatImg[ pHitDoc->m_nStatus/100]; // status image 
	else if ( pHitDoc->m_dwExecute ) 
		iImage = 2; // CGI executables 
	else if ( pHitDoc->m_nHits == 0 ) 
		iImage = 0; // no hits yet 
	else if ( pHitDoc->m_bFolder ) 
		iImage = 1; // folder image 
	else 
		iImage = 0; // document 
 
	return iImage; 
} 
 
void CHttpSvrView::RegisterHit( CListCtrl& list, CRequest* pRequest ) 
{ 
	CHitDoc* pHitDoc = new CHitDoc( pRequest ); 
	if ( pHitDoc ) 
		InsertHitDoc( pHitDoc ); 
} 
 
void CHttpSvrView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{ 
	if ( lHint == HINT_DOCHIT ) 
	{ 
		CRequest* pRequest = (CRequest*)pHint; 
		CListCtrl& list = GetListCtrl(); 
		RegisterHit( list, pRequest ); 
	} 
} 
 
void CHttpSvrView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	// Get the control.... 
	CListCtrl& list = GetListCtrl(); 
	int nSelected = list.GetSelectedCount(); 
	// only proceed if one item selected.... 
	if ( nSelected == 1 ) 
	{ 
		// find the selected item.... 
		int ndx = 0; 
		int nItems = list.GetItemCount(); 
		while ( ndx < nItems ) 
		{ 
			if ( list.GetItemState( ndx, LVIS_SELECTED ) == LVIS_SELECTED ) 
			{ 
				LV_ITEM lvi; 
				lvi.mask = LVIF_PARAM; 
				lvi.iItem = ndx; 
				lvi.iSubItem = 0; 
				if ( list.GetItem( &lvi ) ) 
				{ 
					// only do something for OK and non-executable hits... 
					CHitDoc* pHitDoc = (CHitDoc*)(lvi.lParam); 
					if ( pHitDoc->m_nStatus == IDS_STATUS_OK && 
						pHitDoc->m_dwExecute == 0 ) 
					{ 
						ShellExecute( GetSafeHwnd(), "open", 
							pHitDoc->m_strFile, NULL, 
							pHitDoc->m_strFolder, SW_SHOW ); 
					} 
				} 
				break; 
			} 
			++ndx; 
		} 
	} 
	*pResult = 0; 
} 
 
void CHttpSvrView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	// Get the control.... 
	CListCtrl& list = GetListCtrl(); 
	if ( list.GetSelectedCount() == 1 ) 
	{ 
		CPoint point; 
		if ( GetCursorPos( &point ) ) 
			DoContextMenu( point ); 
	} 
 
	*pResult = 0; 
} 
 
void CHttpSvrView::DoContextMenu( const CPoint& point ) 
{ 
	m_phdPopup = NULL; 
	// Get the control.... 
	CListCtrl& list = GetListCtrl(); 
	CPoint ptList = point; 
	list.ScreenToClient( &ptList ); 
	int ndx = list.HitTest( ptList ); 
	if ( ndx != -1 ) 
	{ 
		LV_ITEM lvi; 
		lvi.mask = LVIF_PARAM; 
		lvi.iItem = ndx; 
		lvi.iSubItem = 0; 
		if ( list.GetItem( &lvi ) ) 
		{ 
			CHitDoc* pHitDoc = (CHitDoc*)(lvi.lParam); 
			// get the popup menu type index.... 
			int nType = 0; 
			if ( pHitDoc->m_dwExecute ) 
				nType = 1; 
			else if ( pHitDoc->m_nStatus != 200 ) 
				nType = 2; 
 
			// load the menus.... 
			CMenu menuPopups; 
			if ( menuPopups.LoadMenu( IDM_POPUPS ) ) 
			{ 
				// get the popup.... 
				CMenu* pMenu = menuPopups.GetSubMenu( nType ); 
				if ( pMenu != NULL ) 
				{ 
					m_phdPopup = pHitDoc; 
					pMenu->TrackPopupMenu( TPM_LEFTALIGN|TPM_RIGHTBUTTON, 
						point.x, point.y, this ); 
				} 
			} 
		} 
	} 
} 
 
void CHttpSvrView::OnPopupClear() 
{ 
	if ( m_phdPopup != NULL ) 
	{ 
		// Get the control.... 
		CListCtrl& list = GetListCtrl(); 
		LV_FINDINFO lvfi; 
		lvfi.flags = LVFI_PARAM; 
		lvfi.lParam = (LPARAM)m_phdPopup; 
		int ndx = list.FindItem( &lvfi ); 
		if ( ndx != -1 ) 
			list.DeleteItem( ndx ); 
	} 
} 
 
void CHttpSvrView::OnPopupEdit() 
{ 
	if ( m_phdPopup != NULL ) 
	{ 
		ShellExecute( GetSafeHwnd(), "edit", 
			m_phdPopup->m_strFile, NULL, 
			m_phdPopup->m_strFolder, SW_SHOW ); 
	} 
} 
 
void CHttpSvrView::OnPopupOpen() 
{ 
	if ( m_phdPopup != NULL ) 
	{ 
		ShellExecute( GetSafeHwnd(), "open", 
			m_phdPopup->m_strFile, NULL, 
			m_phdPopup->m_strFolder, SW_SHOW ); 
	} 
} 
 
BOOL CHttpSvrView::InsertHitDoc( CHitDoc* pHitDoc ) 
{ 
	CListCtrl& list = GetListCtrl(); 
	// look for a match on the file name.... 
	LV_FINDINFO lvfi; 
	lvfi.flags = LVFI_STRING; 
	lvfi.psz = pHitDoc->m_strFile; 
	int ndx = list.FindItem( &lvfi ); 
	while ( ndx != -1 ) 
	{ 
		// match found; see if folder matches.... 
		CString strFolder = list.GetItemText( ndx, COLUMN_PATH ); 
		if ( strFolder.CompareNoCase( pHitDoc->m_strFolder ) == 0 ) 
		{ 
			// matched; get the old HitDoc.... 
			LV_ITEM lvi; 
			lvi.mask = LVIF_PARAM; 
			lvi.iItem = ndx; 
			lvi.iSubItem = 0; 
			if ( list.GetItem( &lvi ) ) 
			{ 
				// get the old count 
				CHitDoc* pOldHit = (CHitDoc*)(lvi.lParam); 
				// add in the previous hits.... 
				pHitDoc->m_nHits += pOldHit->m_nHits; 
				// delete the old hit.... 
				delete pOldHit; 
				// update with new HitDoc.... 
				lvi.mask = LVIF_IMAGE|LVIF_PARAM; 
				lvi.iImage = GetImage( pHitDoc ); 
				lvi.lParam = (LPARAM)pHitDoc; 
				list.SetItem( &lvi ); 
				// indicate we've made changes.... 
				list.Update( lvi.iItem ); 
				break; 
			} 
		} 
		// get next item.... 
		ndx = list.FindItem( &lvfi, ndx ); 
	} 
	// if we didn't find anything.... 
	if ( ndx == -1 ) 
	{ 
		// didn't find a match; add it to the list.... 
		LV_ITEM lvi; 
		lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE; 
		lvi.iItem = 0; 
		lvi.iSubItem = 0; 
		lvi.pszText = LPSTR_TEXTCALLBACK; 
		lvi.lParam = (LPARAM)pHitDoc; 
		lvi.iImage = GetImage( pHitDoc ); 
		if ( (ndx=list.InsertItem( &lvi )) != -1 ) 
		{ 
			// add all the callback sub items.... 
			lvi.mask = LVIF_TEXT; 
			lvi.pszText = LPSTR_TEXTCALLBACK; 
			lvi.iItem = ndx; 
			for( int subNdx=1; subNdx < C_COLUMNS; ++subNdx ) 
			{ 
				lvi.iSubItem = subNdx; 
				list.SetItem( &lvi ); 
			} 
		} 
		else 
		{ 
			// insert failed; kill it.... 
			delete pHitDoc; 
			pHitDoc = NULL; 
		} 
	} 
	return (pHitDoc != NULL); 
} 
 
void CHttpSvrView::OnViewClear() 
{ 
	CListCtrl& list = GetListCtrl(); 
	list.DeleteAllItems(); 
}