www.pudn.com > NetPaw.rar > NetPawDoc.cpp
// NetPawDoc.cpp : CNetPawDoc 类的实现
//
#include "stdafx.h"
#include "NetPaw.h"
#include "mainfrm.h"
#include "fileview.h"
#include "downloadfile.h"
#include "crc32.h"
#include ".\netpawdoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CNetPawDoc
IMPLEMENT_DYNCREATE(CNetPawDoc, CDocument)
BEGIN_MESSAGE_MAP(CNetPawDoc, CDocument)
END_MESSAGE_MAP()
// CNetPawDoc 构造/析构
CNetPawDoc::CNetPawDoc()
: m_pCrc32(NULL)
, m_sProfName(_T(""))
, m_nMaxSpeed(0)
{
// TODO: 在此添加一次性构造代码
}
CNetPawDoc::~CNetPawDoc()
{
// save the current profile
SaveProfile();
// clear download files
if( m_pCrc32 )
{
delete m_pCrc32;
}
// clear downloading item
CDownloadFile *pDlFile;
map::iterator itor;
for(itor = m_mapDownldFile.begin(); itor != m_mapDownldFile.end(); itor++)
{
pDlFile = itor->second;
if( pDlFile )
{
delete pDlFile;
}
}
m_mapDownldFile.clear();
// clear downloaded
DONEITEM_S *pstDoneIt;
list::iterator itor2;
for(itor2 = m_lstDownloaded.begin(); itor2 != m_lstDownloaded.end(); itor2++)
{
pstDoneIt = *itor2;
if( pstDoneIt )
{
delete pstDoneIt;
}
}
m_lstDownloaded.clear();
}
BOOL CNetPawDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: 在此添加重新初始化代码
// (SDI 文档将重用该文档)
if( !m_pCrc32 )
{
m_pCrc32 = new CCrc32();
m_pCrc32->Init();
}
// get profile pathname
CString sPathName;
GetModuleFileName(NULL, sPathName.GetBuffer(MAX_PATH), MAX_PATH);
sPathName.ReleaseBuffer();
int nIndex = sPathName.ReverseFind('\\');
if( nIndex != -1 )
{
sPathName = sPathName.Left(nIndex);
}
m_sProfName = sPathName + PROFILE_NPJ;
// load the profile
CFileFind finder;
BOOL bFound = finder.FindFile( m_sProfName );
if( bFound )
{
LoadProfile();
}
return TRUE;
}
// CNetPawDoc 序列化
void CNetPawDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: 在此添加存储代码
}
else
{
// TODO: 在此添加加载代码
}
}
// CNetPawDoc 诊断
#ifdef _DEBUG
void CNetPawDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CNetPawDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CNetPawDoc 命令
LONGLONG CNetPawDoc::GetSelFileLen(void)
{
LONGLONG nLength = 0;
CDownloadFile *pDlFile = GetSelDownFile();
if( pDlFile )
{
nLength = pDlFile->GetFileLength();
}
return nLength;
}
CDownloadFile* CNetPawDoc::GetSelDownFile(void)
{
map::iterator itor;
CDownloadFile* pDlFile = NULL;
CString sFileName;
// get frame wnd
CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
ASSERT( pFrame );
// get file view
CFileView *pView = pFrame->GetRightPane();
if( pView )
{
pView->GetSelectedFileName(sFileName);
// find pointer in the map
if( (itor = m_mapDownldFile.find(sFileName)) != m_mapDownldFile.end() )
{
pDlFile = itor->second;
}
}
return pDlFile;
}
void CNetPawDoc::DeleteDlFile(CDownloadFile* pDlFile)
{
if( !pDlFile )
{
return;
}
// get file name from object name
CString sFileName = pDlFile->GetFileName();
// delete the object from the map
m_mapDownldFile.erase(sFileName);
delete pDlFile;
// notify views change
UpdateAllViews(NULL, UPDATE_ALL); // update all
}
DONEITEM_S* CNetPawDoc::GetSelDownloaded(void)
{
DONEITEM_S *pDoneIt = NULL, *pTmpIt;
// get frame wnd
CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
ASSERT( pFrame );
// get file view
CFileView *pView = pFrame->GetRightPane();
if( pView )
{
CString sFileName;
pView->GetSelectedFileName(sFileName);
list::iterator itor;
for( itor = m_lstDownloaded.begin(); itor != m_lstDownloaded.end(); itor++ )
{
pTmpIt = *itor;
if( pTmpIt && ( sFileName.CompareNoCase( pTmpIt->szFileName ) == 0 ) )
{
pDoneIt = pTmpIt;
}
}
}
return pDoneIt;
}
void CNetPawDoc::DeleteDownlded(DONEITEM_S* pDoneIt)
{
m_lstDownloaded.remove(pDoneIt);
delete pDoneIt;
// notify views change
UpdateAllViews(NULL, UPDATE_ALL); // update all
}
CDownloadFile* CNetPawDoc::NewDownldFile(DLFILEITEM_S *pstDlFileIt)
{
// allocate download file objects
CDownloadFile *pDlFile = new CDownloadFile( pstDlFileIt );
if( !pDlFile )
{
AfxMessageBox("创建对象错误\n");
return NULL;
}
// start download
if( !pDlFile->ParseFileName() )
{
delete pDlFile;
AfxMessageBox("无法解析URL\n");
return NULL;
}
// successfully connected, add the file into map
CString sFileName = pDlFile->GetFileName();
m_mapDownldFile.insert( pair (sFileName, pDlFile) );
return pDlFile;
}
void CNetPawDoc::SaveProfile(void)
{
CFile *pFile = new CFile();
try
{
if( !pFile->Open( m_sProfName, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive ) )
{
throw 0;
}
// save all class items
SaveDownldFile(pFile);
SaveDownldedFile(pFile);
SaveFavorites(pFile);
}
catch(CFileException *pEx)
{
pEx->ReportError();
pEx->Delete();
}
catch(...)
{
}
// should close before write CRC
delete pFile;
// write the CRC32 in header
WriteCrc32(m_sProfName);
}
void CNetPawDoc::SaveDownldFile(CFile *pFile)
{
// write an empty header
FILEHDR_S stFileHdr;
ZeroMemory(&stFileHdr, sizeof(FILEHDR_S));
pFile->Write( &stFileHdr, sizeof(FILEHDR_S) );
// write download file header
FOLDERCLASS_S stClass;
stClass.dwSeperator = 0x0A0D0A0D;
stClass.wClass = FOLDER_DOWNLDING;
stClass.wItems = (WORD)m_mapDownldFile.size();
pFile->Write(&stClass, sizeof(FOLDERCLASS_S));
// write download file items
map::iterator itor;
CDownloadFile *pDlFile;
for( itor = m_mapDownldFile.begin(); itor != m_mapDownldFile.end(); itor++ )
{
pDlFile = itor->second;
if( pDlFile )
{
pDlFile->SaveDlFileData(pFile);
}
}
}
void CNetPawDoc::SaveDownldedFile(CFile *pFile)
{
// write download file header
FOLDERCLASS_S stClass;
stClass.dwSeperator = 0x0A0D0A0D;
stClass.wClass = FOLDER_DOWNLDED;
stClass.wItems = (WORD)m_lstDownloaded.size();
pFile->Write(&stClass, sizeof(FOLDERCLASS_S));
// write download file items
list::iterator itor;
DONEITEM_S *pDoneItem;
for( itor = m_lstDownloaded.begin(); itor != m_lstDownloaded.end(); itor++ )
{
pDoneItem = *itor;
if( pDoneItem )
{
pFile->Write(pDoneItem, sizeof(DONEITEM_S));
}
}
}
void CNetPawDoc::SaveFavorites(CFile *pFile)
{
}
void CNetPawDoc::WriteCrc32(LPCTSTR szFileName)
{
// calculate the CRC32 value, header not included
DWORD dwCrc32;
m_pCrc32->FileCrc32Assembly(szFileName, dwCrc32, sizeof(FILEHDR_S));
CFile tmpFile;
if( !tmpFile.Open(szFileName, CFile::modeReadWrite | CFile::modeNoTruncate) )
{
AfxMessageBox("Open download profile failed.");
return;
}
// fill the file header and write
FILEHDR_S stFileHdr;
stFileHdr.wMagicWord = 0x504E;
stFileHdr.wReserved = 0;
stFileHdr.dwCrc = dwCrc32;
tmpFile.Write( &stFileHdr, sizeof(FILEHDR_S) );
}
BOOL CNetPawDoc::CheckCRC32(LPCTSTR szFileName)
{
CFile tmpFile;
if( !tmpFile.Open(szFileName, CFile::modeRead | CFile::shareDenyWrite) )
{
return FALSE;
}
// get the crc32 in the file header
FILEHDR_S stFileHdr;
tmpFile.Read( &stFileHdr, sizeof(FILEHDR_S) );
if( stFileHdr.wMagicWord != 0x504E )
{
return FALSE;
}
tmpFile.Close();
// check the CRC32 value, header not included
DWORD dwCrc32;
m_pCrc32->FileCrc32Assembly(szFileName, dwCrc32, sizeof(FILEHDR_S));
if( dwCrc32 != stFileHdr.dwCrc )
{
return FALSE;
}
return TRUE;
}
void CNetPawDoc::LoadProfile(void)
{
BOOL bValidPfile = TRUE;
// check crc of the existed file
if( !CheckCRC32(m_sProfName) )
{
DeleteFile(m_sProfName);
AfxMessageBox("Corrupted download profile is deleted\n");
return;
}
// open the profile
CFile *pFile = new CFile();
try
{
if( !pFile->Open( m_sProfName, CFile::modeRead | CFile::shareDenyWrite ) )
{
throw 0;
}
// load all class items
LoadDownldFile(pFile);
LoadDownldedFile(pFile);
LoadFavorites(pFile);
}
catch(CFileException *pEx)
{
pEx->ReportError();
pEx->Delete();
}
catch(...)
{
}
delete pFile;
}
void CNetPawDoc::LoadDownldFile(CFile *pFile)
{
// skip the file header
pFile->Seek( sizeof(FILEHDR_S), CFile::begin );
// read download items head
FOLDERCLASS_S stClass;
if( pFile->Read(&stClass, sizeof(FOLDERCLASS_S)) <= 0 )
{
return;
}
ASSERT(stClass.wClass == FOLDER_DOWNLDING);
// read items
DLFILEITEM_S stDlFile;
SEGMENT_S stBlock;
CDownloadFile* pDlFile;
for( int i = 0; i < stClass.wItems; i++ )
{
// get download file information
if( pFile->Read(&stDlFile, sizeof(DLFILEITEM_S)) <= 0 )
{
continue;
}
// do some valid check for the data
if( stDlFile.wBlocksToDo == 0 || stDlFile.wBlocksToDo > MAX_CONNECTIONS )
{
continue;
}
// create download file object
pDlFile = NewDownldFile( &stDlFile );
// get download range of each socket
for( int j = 0; j < stDlFile.wBlocksToDo; j++ )
{
if( pFile->Read( &stBlock, sizeof(SEGMENT_S) ) <= 0 )
{
continue;
}
// do some valid check for the data
if( stBlock.nDataFrom > stBlock.nDataTo || stBlock.nDataTo >= stDlFile.nFileLength )
{
continue;
}
// create socket
pDlFile->NewSocket( &stBlock );
}
}
}
void CNetPawDoc::LoadDownldedFile(CFile *pFile)
{
// read download items head
FOLDERCLASS_S stClass;
if( pFile->Read(&stClass, sizeof(FOLDERCLASS_S)) <= 0 )
{
return;
}
ASSERT(stClass.wClass == FOLDER_DOWNLDED);
DONEITEM_S *pstDoneIt;
for( int i = 0; i < stClass.wItems; i++ )
{
// get download file information
pstDoneIt = new DONEITEM_S;
if( pFile->Read(pstDoneIt, sizeof(DONEITEM_S)) <= 0 )
{
delete pstDoneIt;
continue;
}
m_lstDownloaded.push_back(pstDoneIt);
}
}
void CNetPawDoc::LoadFavorites(CFile *pFile)
{
}
void CNetPawDoc::NotifyFileDone(CDownloadFile* pDlFile)
{
// add to the downloaded class
PERFITEM_S stPerfIT;
pDlFile->GetPerfData(&stPerfIT);
// fill the done item structure
DONEITEM_S *pDoneItem = new DONEITEM_S;
pDoneItem->nFileLen = stPerfIT.nFileLength;
pDoneItem->fMeanSpeed = stPerfIT.fMeanSpeed;
pDoneItem->dUsedTime = stPerfIT.dUsedTime;
StrCopy( pDoneItem->szFileName, stPerfIT.szFileName, MAX_PATH/2 );
StrCopy( pDoneItem->szWebInfo, pDlFile->m_sWebInfo, MAX_PATH/2 );
m_lstDownloaded.push_back(pDoneItem);
// rename the file
CString sFileName, sOldName;
CNetPawApp *pApp = (CNetPawApp *)AfxGetApp();
if( pApp )
{
sFileName = pApp->m_sSavePath + '\\' + pDlFile->GetFileName();
sOldName = sFileName + _T(".npf");
}
MoveFile(sOldName, sFileName);
// delete the pDlFile from the downloading class
DeleteDlFile(pDlFile);
}