⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mailbox.cpp

📁 一个邮件客户端源代码,包括收发邮件,安排日程等很多内容
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Copyright (C) 1997-2002 Valeriy Ovechkin
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// Mailbox.cpp : implementation file
//
/////////////////////////////////////////////////////////////////////
//
//   File : Mailbox.cpp
//   Description : basic connection code
//
//   Modification history ( date, name, description ) : 
//		1.	17.12.2002	Igor Green, mmm3@grigsoft.com
//			Partial preview support
//		2.	22.01.2003	brendanryan59 (BRN)
//			Fixed problem with -- in header data
//
//HISTORY_ENTRY_END:2!22.01.2003
/////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MD5.h"
#include "Magic.h"
#include "Excerpt.h"
#include "Mailbox.h"
#include "MagicDoc.h"
#include "MagicFrame.h"
#include "MailboxView.h"
#include "SecureString.h"

#include <afxpriv.h>
#undef IsLoggingEnabled // clashed with a class member

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
void CMailbox::RecoverString( CString &str )
{
	str.MakeReverse();
	srand( m_intClue ^ 0x55555555 );
	for( int i = str.GetLength(); i; --i ) 
	{
		TCHAR ch = TCHAR(str.GetAt( i-1 ) ^ (TCHAR) rand());
		str.SetAt( i-1,  ch);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CMailbox
/* version history:
252: flag for new Doc version
251: added APOP disable flag
 */


IMPLEMENT_SERIAL( CMailbox, CAsyncSocket, 252 | VERSIONABLE_SCHEMA );

CMailbox::CMailbox()
:	m_bitSelected(1),
	m_bitCreated(1),
	m_bitDeleted(0),
	m_intOrder(0),
	m_tServerSupportsAPOP( true ),
	m_tServerSupportsUIDL( true ),
	m_tServerSupportsBurstWrites( true ),
	m_bLog( false )
{
	InitializeServerTraits();

	m_nUnread = 0;

	m_hResolveJob = 0;
	m_pResolveBuffer = NULL;
	m_arrayExcerpt.SetSize( 0, 8 );

	m_uMciID = 0;
	m_hCmdID = 0;
	m_intChanged = -1;

	m_intState = MBOX_NOT_CHECKED;
	m_intClue = 0xBadBabe ^ (int) this;
	m_intPort = 110;
	m_nExtraLines=0;
	m_intPoll = 10;
	m_dwFlags = MBF_DEFAULT;
	m_intElapsed = theApp.intCheckImmediately ? -1 : 0;

	m_intCommand = ACTION_DEFAULT;
	m_intCommandRun = COMMAND_RUN_NORMAL;
	m_intPlayback = ACTION_DEFAULT;
	m_intPlaybackDevice = PLAYBACK_DEVICE_FILE;
	m_intMessage = FALSE;
}

CMailbox::~CMailbox()
{
	CancelPendingJobs();

	m_bitDeleted = 1;
	Change( COLUMN_STATE );

	CWnd *wnd = (CWnd*) AfxGetMainWnd();
	if( wnd ) wnd->SendMessage( VM_UPDATEITEM, (WPARAM) this );

	int i = m_arrayExcerpt.GetSize();
	while( i ) delete m_arrayExcerpt[--i];
	m_arrayExcerpt.RemoveAll();
}

/////////////////////////////////////////////////////////////////////////////
// CMailbox message handlers

void CMailbox::Serialize( CArchive& ar ) 
{
	if( ar.IsLoading() ) // READ
	{
		int intVersion = ar.GetObjectSchema();

		if( intVersion < 250 )
		{
			DWORD wordTmp;
			ar >> wordTmp; m_intClue = (int) wordTmp;
			ar >> wordTmp; m_intPort = (int) wordTmp;
			ar >> wordTmp; m_intPoll = (int) wordTmp;
			ar >> wordTmp; m_ulongIP = (int) wordTmp;
			ar >> m_strPass;
			ar >> m_strUser;
			ar >> m_strHost;
			
			if( 200 <= intVersion )
			{
				ar >> m_strAlias;
				ar >> wordTmp; m_intCommand = (int) wordTmp;
				ar >> wordTmp; m_intCommandRun = (int) wordTmp;
				ar >> m_strCommand;
				ar >> wordTmp; m_intPlayback = (int) wordTmp;
				ar >> wordTmp; m_intPlaybackDevice = (int) wordTmp;
				ar >> m_strPlayback;
				ar >> wordTmp; m_intMessage = (int) wordTmp;
			}

			m_intClue ^= 0xAAAAAAAA;
			m_intPort ^= m_intClue;
			m_intPoll ^= m_intClue;
			m_ulongIP ^= m_intClue;
			m_intCommand ^= m_intClue;
			m_intCommandRun ^= m_intClue;
			m_intPlayback ^= m_intClue;
			m_intPlaybackDevice ^= m_intClue;
			m_intMessage ^= m_intClue;
			RecoverString( m_strAlias );
			RecoverString( m_strUser );
			RecoverString( m_strHost );
			RecoverString( m_strPass );
			RecoverString( m_strCommand );
			RecoverString( m_strPlayback );
		}
		else // if( 250 <= intVersion )
		{
			DWORD dwTmp;
			ar >> dwTmp; m_intClue = (int) dwTmp;
			ar >> dwTmp; m_intPort = (int) dwTmp;
			ar >> dwTmp; m_intPoll = (int) dwTmp;
			ar >> dwTmp; m_ulongIP = (int) dwTmp;
			ar >> dwTmp; m_intCommand = (int) dwTmp;
			ar >> dwTmp; m_intCommandRun = (int) dwTmp;
			ar >> dwTmp; m_intPlayback = (int) dwTmp;
			ar >> dwTmp; m_intPlaybackDevice = (int) dwTmp;
			ar >> dwTmp; m_intMessage = (int) dwTmp;
			if (intVersion >= 251)
			{
				ar >> m_dwFlags;
			}
			else
				m_dwFlags = MBF_DEFAULT;
			if (intVersion >= 252)
				ar >> m_nExtraLines;
			else
				m_nExtraLines = 255;


			// assure checksum
			DWORD dwCheckSum = 0;
			ar >> dwCheckSum;
			dwCheckSum ^= m_intClue ^ m_intPort ^ m_intPoll ^ m_ulongIP ^ 
				m_intCommand ^ m_intCommandRun ^ 
				m_intPlayback ^ m_intPlaybackDevice ^ 
				m_intMessage;
			if( dwCheckSum ) AfxThrowArchiveException( CArchiveException::badIndex, _T("") );

			CSecureString sstrTmp; 
			sstrTmp.Serialize( ar ); sstrTmp.DecodeString( m_intClue, m_strPass ); 
			sstrTmp.Serialize( ar ); sstrTmp.DecodeString( m_intClue, m_strUser ); 
			sstrTmp.Serialize( ar ); sstrTmp.DecodeString( m_intClue, m_strHost ); 
			sstrTmp.Serialize( ar ); sstrTmp.DecodeString( m_intClue, m_strAlias ); 
			sstrTmp.Serialize( ar ); sstrTmp.DecodeString( m_intClue, m_strCommand ); 
			sstrTmp.Serialize( ar ); sstrTmp.DecodeString( m_intClue, m_strPlayback ); 
		}

		m_ulongIP = 0;
	}
	else // WRITE
	{
		ar << (DWORD) m_intClue;
		ar << (DWORD) m_intPort;
		ar << (DWORD) m_intPoll;
		ar << (DWORD) m_ulongIP;
		ar << (DWORD) m_intCommand;
		ar << (DWORD) m_intCommandRun;
		ar << (DWORD) m_intPlayback;
		ar << (DWORD) m_intPlaybackDevice;
		ar << (DWORD) m_intMessage;
		ar << (DWORD) m_dwFlags;
		if (m_nExtraLines==255)
			m_nExtraLines = 0;
		ar << (BYTE)  m_nExtraLines;

		// calculate checksum
		DWORD dwCheckSum = 0;
		dwCheckSum ^= m_intClue ^ m_intPort ^ m_intPoll ^ m_ulongIP ^ 
			m_intCommand ^ m_intCommandRun ^ m_intPlayback ^ 
			m_intPlaybackDevice ^ m_intMessage;
		ar << dwCheckSum;

		CSecureString sstrTmp; 
		sstrTmp.EncodeString( m_intClue, m_strPass ); sstrTmp.Serialize( ar );
		sstrTmp.EncodeString( m_intClue, m_strUser ); sstrTmp.Serialize( ar );
		sstrTmp.EncodeString( m_intClue, m_strHost ); sstrTmp.Serialize( ar );
		sstrTmp.EncodeString( m_intClue, m_strAlias ); sstrTmp.Serialize( ar );
		sstrTmp.EncodeString( m_intClue, m_strCommand ); sstrTmp.Serialize( ar );
		sstrTmp.EncodeString( m_intClue, m_strPlayback ); sstrTmp.Serialize( ar );
	}
}

void CMailbox::SetAlias( CString &strAlias )
{
	if( m_strAlias == strAlias ) return;
	m_strAlias = strAlias;
	Change( COLUMN_ALIAS );
	SetClue();
}

void CMailbox::SetUser( CString &strUser )
{
	if( m_strUser == strUser ) return;
	m_strUser = strUser;
	Change( COLUMN_USER );
	SetState( MBOX_NOT_CHECKED );
	SetClue();
}

void CMailbox::SetHost( CString &strHost )
{
	if( m_strHost == strHost ) return;
	m_strHost = strHost;
	Change( COLUMN_HOST );
	InitializeServerTraits();
	SetState( MBOX_NOT_CHECKED );
	SetClue();
}

void CMailbox::SetPass( CString &strPass, BOOL bAsk )
{
	if (bAsk)
		m_strPass.IsEmpty();
	else
		m_strPass = strPass;
	SetBoolFlag(m_dwFlags, MBF_ASK_PASS, bAsk);
	SetClue();
}

void CMailbox::SetState( int intState )
{
	if( STATE_FINAL( m_intState ) && !STATE_FINAL( intState ) )
	{
		Create();
		m_strLastError.Empty();
	}

	if( !STATE_FINAL( m_intState ) && STATE_FINAL( intState ) ) 
	{ 
#if 0
		// For the socket about to be closed.
		SOCKET hDeadSocket = m_hSocket;

		CAsyncSocket::Close();
		// or for CSocket-derived class:
		// CSocket::Close();

		MSG msg;
		CSocket::ProcessAuxQueue();
		while(::PeekMessage(&msg,NULL,
			 WM_SOCKET_NOTIFY,WM_SOCKET_DEAD,PM_REMOVE))
		{
			::DispatchMessage(&msg);
			if( (msg.message==WM_SOCKET_DEAD) &&
				((SOCKET)msg.wParam==hDeadSocket))
			{
				break;
			}
		}
#else
		Close();
#endif
		CancelPendingJobs();
		Change( COLUMN_MAIL );
	}

	m_intState = intState;
	Change( COLUMN_STATE );

	if( MBOX_CHECKED == intState )
	{
		Change( COLUMN_ELAPSED );
		m_intElapsed = 0;
	}
	else if( MBOX_NOT_CHECKED == intState )
	{
		Change( COLUMN_MAIL );
		Change( COLUMN_ELAPSED );
		m_intElapsed = -1;
		int i = m_arrayExcerpt.GetSize();
		while( i ) delete m_arrayExcerpt[ --i ];
		m_arrayExcerpt.RemoveAll();
	}
	else if( MBOX_INTERRUPTED_BY_USER )
	{
	}
}

void CMailbox::SetPort( int intPort )
{
	if( m_intPort == intPort ) return;
	m_intPort = intPort;
	Change( COLUMN_PORT );
	SetClue();
}


void CMailbox::SetSpecTOP( int nTOP)
{
	BOOL bNow = GetBoolFlag(m_dwFlags, MBF_SPEC_TOP);
	if( bNow == nTOP ) return;
	SetBoolFlag(m_dwFlags, MBF_SPEC_TOP, nTOP);
	Change( COLUMN_POLL );
	SetClue();
}

void CMailbox::DisableAPOP( int nDisable )
{
	BOOL bNow = GetBoolFlag(m_dwFlags, MBF_NO_APOP);
	if( bNow == nDisable ) return;
	SetBoolFlag(m_dwFlags, MBF_NO_APOP, nDisable);
	Change( COLUMN_POLL );
	SetClue();
}

void CMailbox::Disable( int nDisable )
{
	BOOL bNow = GetBoolFlag(m_dwFlags, MBF_PASSIVE);
	if( bNow == nDisable ) return;
	SetBoolFlag(m_dwFlags, MBF_PASSIVE, nDisable);
	Change( COLUMN_POLL );
	SetClue();
}

void CMailbox::SetPoll( int intPoll )
{
	if( m_intPoll == intPoll ) return;
	m_intPoll = intPoll;
	Change( COLUMN_POLL );
	SetClue();
}

void CMailbox::BeginResolveHostByName()
{
	if( m_strHost.IsEmpty() ) { SetState( MBOX_INVALID_HOST ); return; }
	SetState( MBOX_RESOLVING );

	ASSERT( !m_pResolveBuffer && !m_hResolveJob );

	char szHost[256] = ""; CharToOem( m_strHost, szHost );

	m_ulongIP = inet_addr( szHost );
	if( INADDR_NONE == m_ulongIP )
	{
		m_ulongIP = 0;
		m_pResolveBuffer = new char[ MAXGETHOSTSTRUCT ];
		m_hResolveJob = WSAAsyncGetHostByName(
			AfxGetMainWnd()->m_hWnd,
			VM_END_RESOLVE_HOST_BY_NAME,
			szHost,
			m_pResolveBuffer,
			MAXGETHOSTSTRUCT );
	}
	else
	{
		Check();
	}
}

void CMailbox::EndResolveHostByName( WPARAM wParam, LPARAM lParam )
{
	if( m_hResolveJob != (HANDLE) wParam ) return;

	if( HIWORD( lParam ) ) SetState( MBOX_INVALID_HOST );
	else
	{
		m_ulongIP = *(ULONG*) ( (struct hostent*) m_pResolveBuffer )->h_addr;
		Check();
	}

	m_hResolveJob = 0;
	delete m_pResolveBuffer;
	m_pResolveBuffer = NULL;
}

void CMailbox::Check()
{
	if( MBOX_CONNECTING == m_intState )
	{
		// MFC can't handle the case when Close is called before OnConnect had fired.
		// as a result, an assertion occurs in sockcore.cpp on line 513.
		// this measure will avoid the problem in the first place.
		return;
	}

	if( !STATE_FINAL( m_intState ) )
	{
		SetState( MBOX_CANNOT_CHECK );
	}

	if( !m_ulongIP )
	{
		BeginResolveHostByName();
		return;
	}

	SetState( MBOX_CONNECTING ); 
	SOCKADDR_IN a;
	a.sin_family = AF_INET;
	a.sin_port = htons( (u_short)m_intPort );
	a.sin_addr.S_un.S_addr = m_ulongIP;
	
	if( !Connect( (SOCKADDR*) &a, sizeof(a) ) &&
		( WSAEWOULDBLOCK != GetLastError() ) )
	{
		TRACE2( "Socket Error #%d; [%s] cannot connect\n", GetLastError(), m_strAlias );
		SetState( MBOX_SOCKET_ERROR );
	}
}

void CMailbox::StopChecking()
{
	if( !STATE_FINAL( m_intState ) )
	{
		SetState( MBOX_INTERRUPTED_BY_USER );
	}

	// clear out all pending tasks
	for( int i = m_arrayExcerpt.GetSize(); i; --i )
	{
		m_arrayExcerpt[i-1]->m_bitRemoveFromServer = false;
		m_arrayExcerpt[i-1]->m_bitDownloadData = false;
		m_arrayExcerpt[i-1]->m_bitPreviewData = false;
		m_arrayExcerpt[i-1]->Change( COLUMN_MBOX );
	}
}

void CMailbox::OnConnect( int nErrorCode )
{
	if( nErrorCode ) 
	{
		TRACE2( "Socket Error #%d; [%s] OnConnect: cannot connect\n", nErrorCode, m_strAlias );
		SetState( MBOX_CANNOT_CONNECT );
		InitializeServerTraits();
	}
	else
	{
		TRACE1( "Socket connected #%d\n", m_hSocket );
	}

	m_strLog.Empty();
}

void CMailbox::OnReceive( int nErrorCode )
{
	char szPacket[ 1024 ];
	
	if( nErrorCode ) { SetState( MBOX_NETWORK_FAILED ); return; }
	
	while( TRUE )
	{
		switch( nErrorCode = Receive( szPacket, sizeof( szPacket )-1 ) )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -