📄 linkckview.cpp
字号:
// linkckView.cpp : implementation of the CLinkckView class
//
#include "stdafx.h"
#include "linkck.h"
#include <afxinet.h>
#include "urlinput.h"
#include "linkckDoc.h"
#include "linkckView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////
// CLinkckView
IMPLEMENT_DYNCREATE(CLinkckView, CFormView)
BEGIN_MESSAGE_MAP(CLinkckView, CFormView)
//{{AFX_MSG_MAP(CLinkckView)
ON_BN_CLICKED(IDC_SCAN, OnScan)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
ON_COMMAND(ID_FILE_SCAN, OnScan)
ON_LBN_DBLCLK(IDC_LB, OnScan)
ON_UPDATE_COMMAND_UI(ID_FILE_PRINT, OnUpdateFilePrint)
ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_PREVIEW, OnUpdateFilePrint)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
END_MESSAGE_MAP()
///////////////////////
// CLinkckView construction/destruction
void CLinkckView::OnFilePrintPreview()
{
AfxGetMainWnd()->ShowWindow(SW_MAXIMIZE);
CFormView::OnFilePrintPreview();
}
CLinkckView::CLinkckView()
: CFormView(CLinkckView::IDD)
{
//{{AFX_DATA_INIT(CLinkckView)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
PrintEnable=FALSE;
}
CLinkckView::~CLinkckView()
{
}
void CLinkckView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CLinkckView)
DDX_Control(pDX, IDC_LB, m_lb);
//}}AFX_DATA_MAP
}
BOOL CLinkckView::PreCreateWindow(CREATESTRUCT& cs)
{
return CFormView::PreCreateWindow(cs);
}
///////////////////////
// CLinkckView printing
BOOL CLinkckView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CLinkckView::OnBeginPrinting(CDC* /*pDC*/,
CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CLinkckView::OnEndPrinting(CDC* /*pDC*/,
CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
// Simple code to dump the results out to a printed page
void CLinkckView::OnPrint(CDC* pDC, CPrintInfo*)
{
int i;
int y=0,texthi;
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
texthi=tm.tmHeight+tm.tmExternalLeading;
for (i=1;i<m_lb.GetCount();i++)
{
CString item;
m_lb.GetText(i,item);
pDC->TabbedTextOut(5,y,item,0,NULL,0);
y+=texthi;
}
}
///////////////////////
// CLinkckView diagnostics
#ifdef _DEBUG
void CLinkckView::AssertValid() const
{
CFormView::AssertValid();
}
void CLinkckView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CLinkckDoc* CLinkckView::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CLinkckDoc)));
return (CLinkckDoc*)m_pDocument;
}
#endif //_DEBUG
///////////////////////
// CLinkckView message handlers
// Do a scan from user interface
void CLinkckView::OnScan()
{
CString URL;
CString err;
int sel=m_lb.GetCurSel();
if (sel==LB_ERR||sel==0||m_lb.GetItemData(sel)==-1)
{
// prompt if no good selection in the list box
CUrlInput indlg;
if (indlg.DoModal()==IDCANCEL) return;
URL=indlg.m_url;
}
else
{
m_lb.GetText(sel,URL);
}
// clear list box
m_lb.ResetContent();
m_lb.AddString("<<New URL>>");
// do real work
DoScan(URL);
// enable menu items
PrintEnable=TRUE;
}
// This routine really does the work
void CLinkckView::DoScan(CString & URL, BOOL recurse)
{
CString line;
int item;
CInternetSession session("Commando Link Check V1.0");
CStdioFile *f;
try
{
f=session.OpenURL(URL);
}
catch (...)
{
f=NULL;
}
// apparently the MFC Dlls don't export
// CHttpFile's runtime class? (see text)
if (f && f->IsKindOf(RUNTIME_CLASS(CHttpFile)))
// if (f && !strnicmp(URL,"http",4))
{
DWORD stat; // http status
CHttpFile *hf=(CHttpFile *)f;
hf->QueryInfoStatusCode(stat);
// only codes 200-299 are good
if (stat<200||stat>299)
{
f->Close();
f=NULL;
}
}
if (!f) // some problem
{
CString err;
err=URL;
err+="\tError!";
item=m_lb.AddString(err);
m_lb.SetItemData(item,-1);
return;
}
// go!
item=m_lb.AddString(URL);
m_lb.SetItemData(item,0);
// if recurse is true, then parse file
while (recurse && f->ReadString(line))
{
int n=0;
char *p, *e;
p=(char *)(LPCSTR)line;
do {
p=strchr(p,'='); // search for =
if (p) // backward search for HREF/SRC
{
if (toupper(p[-1])!='F' ||
toupper(p[-2])!='E' ||
toupper(p[-3])!='R' ||
toupper(p[-4])!='H')
if (toupper(p[-1])!='C' ||
toupper(p[-2])!='R' ||
toupper(p[-3])!='S')
{
p++;
continue;
}
if (p[1]=='"') // skip quotes
p++;
e=p+1+strcspn(p+1," \t\n>\"#");
*e='\0';
// don't recurse empty URLs (e.g., HREF=#anchor)
if (e!=p+1)
{
CString newURL;
ExpandURL(newURL,p+1,URL);
DoScan(newURL,FALSE);
}
*e=' ';
p=e+1;
}
} while (p && *p);
} // end while
f->Close();
}
void CLinkckView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit(FALSE);
}
void CLinkckView::ExpandURL(CString &result,
CString source,CString current)
{
CString proto,host,path,file,chost,cpath,cproto;
// break up both URLs
ParseURL(source,&proto,&host,&path,&file);
ParseURL(current,&cproto,&chost,&cpath,NULL);
// copy empty parts from current URL
if (proto.IsEmpty()) proto=cproto;
if (host.IsEmpty()) host=chost;
if (path.IsEmpty())
path=cpath;
else if (path[0]!='/'&&path[0]!='\\'&&!cpath.IsEmpty())
path=cpath+"/"+path;
result=proto + host ;
// if path is relative, prepend current path
if (!path.IsEmpty())
{
if (path[0]!='/' && path[0]!='\\')
result+="/";
result+= path;
}
if (!file.IsEmpty()) result+="/" + file;
}
// Homebrew URL parser AfxParseURL is too lazy to
// decide what is a file and what is a directory, so we
// do it ourselves (sigh)
void CLinkckView::ParseURL(CString url,CString *proto,
CString *host, CString *path,
CString *fileplus)
{
CString _proto, _host, _path, _fileplus;
int n;
n=url.Find("://");
if (n==-1) n=url.Find(":\\\\");
// get protocol
if (n!=-1)
{
_proto=url.Left(n+3);
url=url.Right(url.GetLength()-(n+3));
n=url.FindOneOf("/\\");
if (n==-1)
{ // get host
_host=url;
url="";
}
else
{
_host=url.Left(n);
url=url.Right(url.GetLength()-n);
}
}
// find path or file name
n=url.ReverseFind('/');
if (n==-1) n=url.ReverseFind('\\');
if (n!=-1)
{
_fileplus=url.Right(url.GetLength()-n-1);
_path=n==-1?url:url.Left(n);
if (!_path.IsEmpty()&&(_path[0]=='/'||
_path[0]=='\\'))
_path=_path.Right(_path.GetLength()-1);
}
else
{
_fileplus=url;
}
// Special case heruistic
// if host name and file provide, but no path then file
// is probably a path if it doesn't contain a period
if (!_host.IsEmpty() && _path.IsEmpty() &&
!_fileplus.IsEmpty() && _fileplus.Find('.')==-1)
{
_path="/" + _fileplus;
_fileplus="";
}
if (proto) *proto=_proto;
if (host) *host=_host;
if (path) *path=_path;
if (fileplus) *fileplus=_fileplus;
}
void CLinkckView::OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo,
POINT point, CPreviewView* pView)
{
AfxGetMainWnd()->ShowWindow(SW_NORMAL);
CFormView::OnEndPrintPreview(pDC, pInfo, point, pView);
}
void CLinkckView::OnUpdateFilePrint(CCmdUI* pCmdUI)
{
pCmdUI->Enable(PrintEnable);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -