Commit bdab3045 authored by bienvenu%netscape.com's avatar bienvenu%netscape.com
Browse files

make pop3 protocol use mailbox parse and line buffer

parent 3a6a2f17
Loading
Loading
Loading
Loading
+263 −239
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ nsMsgMailboxParser::nsMsgMailboxParser() : nsMsgLineBuffer(NULL, PR_FALSE)

nsMsgMailboxParser::~nsMsgMailboxParser()
{
	XP_FREE(m_mailboxName);
	PR_FREEIF(m_mailboxName);
}

void nsMsgMailboxParser::UpdateStatusText ()
@@ -1223,187 +1223,23 @@ int nsParseMailMessageState::FinalizeHeaders()



#ifdef NEW_MAIL_HANDLED
int ParseNewMailState::MarkFilteredMessageRead(nsMsgHdr *msgHdr)
nsParseNewMailState::nsParseNewMailState(MSG_Master *master, nsFilePath &folder)
{
	if (m_mailDB)
		m_mailDB->MarkHdrRead(msgHdr, TRUE, NULL);
	else
		msgHdr->OrFlags(kIsRead);
	return 0;
}

int ParseNewMailState::MoveIncorporatedMessage(nsMsgHdr *mailHdr, 
											   nsMailDatabase *sourceDB, 
											   char *destFolder,
											   MSG_Filter *filter)
{
	int err = 0;
	XP_File		destFid;
	XP_File		sourceFid = m_file;
//	SetMaster(master);
	m_mailboxName = PL_strdup(folder);

	// Make sure no one else is writing into this folder
	MSG_FolderInfo *lockedFolder = m_mailMaster->FindMailFolder (destFolder, FALSE /*create*/);
	if (lockedFolder && (err = lockedFolder->AcquireSemaphore (this)) != 0)
		return err;

	if (sourceFid == 0)
	{
		sourceFid = XP_FileOpen(m_mailboxName,
										xpMailFolder, XP_FILE_READ_BIN);
	}
	XP_ASSERT(sourceFid != 0);
	if (sourceFid == 0)
	{
#ifdef DEBUG_bienvenu
		XP_ASSERT(FALSE);
#endif
		if (lockedFolder)
			lockedFolder->ReleaseSemaphore (this);

		return MK_MSG_FOLDER_UNREADABLE;	// ### dmb
	}

	XP_FileSeek (sourceFid, mailHdr->GetMessageOffset(), SEEK_SET);
	int newMsgPos;

	destFid = XP_FileOpen(destFolder, xpMailFolder, XP_FILE_APPEND_BIN);

	if (!destFid) 
	{
#ifdef DEBUG_bienvenu
		XP_ASSERT(FALSE);
#endif
		if (lockedFolder)
			lockedFolder->ReleaseSemaphore (this);
		XP_FileClose (sourceFid);
		return  MK_MSG_ERROR_WRITING_MAIL_FOLDER;
	}

	if (!XP_FileSeek (destFid, 0, SEEK_END))
	{
		newMsgPos = ftell (destFid);
	}
	else
	{
		XP_ASSERT(FALSE);
		if (lockedFolder)
			lockedFolder->ReleaseSemaphore (this);
		XP_FileClose (destFid);
		XP_FileClose (sourceFid);
		return  MK_MSG_ERROR_WRITING_MAIL_FOLDER;
	}

	nsMailDatabase *mailDb = NULL;
	// don't force upgrade in place - open the db here before we start writing to the 
	// destination file because XP_Stat can return file size including bytes written...
	MsgERR msgErr = nsMailDatabase::Open (destFolder, TRUE, &mailDb);	
	PRUint32 length = mailHdr->GetByteLength();

	m_ibuffer_size = 10240;
	m_ibuffer = NULL;

	while (!m_ibuffer && (m_ibuffer_size >= 512))
	{
		m_ibuffer = (char *) XP_ALLOC(m_ibuffer_size);
		if (m_ibuffer == NULL)
			m_ibuffer_size /= 2;
	}
	XP_ASSERT(m_ibuffer != NULL);
	while ((length > 0) && m_ibuffer)
	{
		PRUint32 nRead = XP_FileRead (m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size  : length, sourceFid);
		if (nRead == 0)
			break;
		
		// we must monitor the number of bytes actually written to the file. (mscott)
		if (XP_FileWrite (m_ibuffer, nRead, destFid) != nRead) 
		{
			XP_FileClose(sourceFid);
			XP_FileClose(destFid);     

			// truncate  destination file in case message was partially written
			XP_FileTruncate(destFolder,xpMailFolder,newMsgPos);

			if (lockedFolder)
				lockedFolder->ReleaseSemaphore(this);

			if (mailDb)
				mailDb->Close();

			return MK_MSG_ERROR_WRITING_MAIL_FOLDER;   // caller (ApplyFilters) currently ignores error conditions
		}
	// the new mail parser isn't going to get the stream input, it seems, so we can't use
	// the OnStartBinding mechanism the mailbox parser uses. So, let's open the db right now.
	nsMailDatabase::Open(folder, PR_TRUE, &m_mailDB, PR_FALSE);

		length -= nRead;
	}
	
	XP_ASSERT(length == 0);

	// if we have made it this far then the message has successfully been written to the new folder
	// now add the header to the mailDb.
	if (eSUCCESS == msgErr)
	{
		nsMsgHdr *newHdr = new nsMsgHdr();	
		if (newHdr)
		{
			newHdr->CopyFromMsgHdr (mailHdr, sourceDB->GetDB(), mailDb->GetDB());
			// set new byte offset, since the offset in the old file is certainly wrong
			newHdr->SetMessageKey (newMsgPos); 
			newHdr->OrFlags(kNew);

			msgErr = mailDb->AddHdrToDB (newHdr, NULL, m_updateAsWeGo);
		}
	}
	else
	{
		if (mailDb)
		{
			mailDb->Close();
			mailDb = NULL;
		}
	}

	XP_FileClose(sourceFid);
	XP_FileClose(destFid);
	int truncRet = XP_FileTruncate(m_mailboxName, xpMailFolder, mailHdr->GetMessageOffset());
	XP_ASSERT(truncRet >= 0);

	if (lockedFolder)
		lockedFolder->ReleaseSemaphore (this);

	// tell outgoing parser that we've truncated the Inbox
	m_parseMsgState->Init(mailHdr->GetMessageOffset());
	MSG_FolderInfo *folder = m_mailMaster->FindMailFolder(destFolder, FALSE);

	if (folder)
		folder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);

	if (mailDb != NULL)
	{
		// update the folder size so we won't reparse.
		UpdateDBFolderInfo(mailDb, destFolder);
		if (folder != NULL)
			folder->SummaryChanged();

		mailDb->Close();
	}
	// We are logging the hit with the old mailHdr, which should work, as long
	// as LogRuleHit doesn't assume the new hdr.
	if (m_filterList->IsLoggingEnabled())
		LogRuleHit(filter, mailHdr);

	return err;

}

ParseNewMailState::ParseNewMailState(MSG_Master *master, MSG_FolderInfoMail
									 *folder) :
	nsMsgMailboxParser(folder->GetPathname())
{
	SetMaster(master);
#ifdef DOING_FILTERS
	if (MSG_FilterList::Open(master, filterInbox, NULL, folder, &m_filterList)
		!= FilterError_Success)
		m_filterList = NULL;

	m_logFile = NULL;
#endif
#ifdef DOING_MDN
	if (m_filterList)
	{
		const char *folderName = NULL;
@@ -1424,7 +1260,6 @@ ParseNewMailState::ParseNewMailState(MSG_Master *master, MSG_FolderInfoMail
				XP_FREE(defaultFolderName);
			}
		}

		if (folderName)
		{
			MSG_Filter *newFilter = new MSG_Filter(filterInboxRule, "receipt");
@@ -1453,29 +1288,109 @@ ParseNewMailState::ParseNewMailState(MSG_Master *master, MSG_FolderInfoMail
			}
		}
	}
	m_logFile = NULL;
#endif DOING_MDN
	m_usingTempDB = FALSE;
	m_tmpdbName = NULL;
	m_disableFilters = FALSE;
}

ParseNewMailState::~ParseNewMailState()
nsParseNewMailState::~nsParseNewMailState()
{
#ifdef DOING_FILTERS
	if (m_filterList != NULL)
		MSG_CancelFilterList(m_filterList);
	if (m_logFile != NULL)
		XP_FileClose(m_logFile);
#endif
	if (m_mailDB)
		m_mailDB->Close();
	if (m_usingTempDB)
//	if (m_usingTempDB)
//	{
//		XP_FileRemove(m_tmpdbName, xpMailFolderSummary);
//	}
	PR_FREEIF(m_tmpdbName);
#ifdef DOING_FILTERS
	JSFilter_cleanup();
#endif
}


// This gets called for every message because libnet calls IncorporateBegin,
// IncorporateWrite (once or more), and IncorporateComplete for every message.
void nsParseNewMailState::DoneParsingFolder()
{
	PRBool moved = FALSE;
/* End of file.  Flush out any partial line remaining in the buffer. */
	if (m_ibuffer_fp > 0) 
	{
		XP_FileRemove(m_tmpdbName, xpMailFolderSummary);
		ParseFolderLine(m_ibuffer, m_ibuffer_fp);
		m_ibuffer_fp = 0;
	}
	FREEIF(m_tmpdbName);
	JSFilter_cleanup();
	PublishMsgHeader();
	if (!moved && m_mailDB != NULL)	// finished parsing, so flush db folder info 
		UpdateDBFolderInfo();

#ifdef HAVE_FOLDERINFO
	if (m_folder != NULL)
		m_folder->SummaryChanged();
#endif

	/* We're done reading the folder - we don't need these things
	 any more. */
	PR_FREEIF (m_ibuffer);
	m_ibuffer_size = 0;
	PR_FREEIF (m_obuffer);
	m_obuffer_size = 0;
}

XP_File ParseNewMailState::GetLogFile ()
PRInt32 nsParseNewMailState::PublishMsgHeader()
{
	PRBool		moved = FALSE;

	FinishHeader();
	
	if (m_newMsgHdr)
	{
		FolderTypeSpecificTweakMsgHeader(m_newMsgHdr);
#ifdef DOING_FILTERS
		if (!m_disableFilters) {
			ApplyFilters(&moved);
		}
#endif // DOING_FILTERS
		if (!moved)
		{
			if (m_mailDB)
			{
				PRUint32 newFlags;
				m_newMsgHdr->OrFlags(MSG_FLAG_NEW, &newFlags);

//				m_mailDB->AddHdrToDB (m_newMsgHdr, NULL,
//									  m_updateAsWeGo);
			}
#ifdef HAVE_FOLDERINFO
			if (m_folder)
				m_folder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);
#endif

		}		// if it was moved by imap filter, m_parseMsgState->m_newMsgHdr == NULL
		else if (m_newMsgHdr)
		{
			m_newMsgHdr->Release();
		}
		m_newMsgHdr = NULL;
	}
	return 0;
}

void	nsParseNewMailState::SetUsingTempDB(PRBool usingTempDB, char *tmpDBName)
{
	m_usingTempDB = usingTempDB;
	m_tmpdbName = tmpDBName;
}

#ifdef DOING_FILTERS

XP_File nsParseNewMailState::GetLogFile ()
{
	// This log file is used by regular filters and JS filters
	if (m_logFile == NULL)
@@ -1483,7 +1398,7 @@ XP_File ParseNewMailState::GetLogFile ()
	return m_logFile;
}

void ParseNewMailState::LogRuleHit(MSG_Filter *filter, nsMsgHdr *msgHdr)
void nsParseNewMailState::LogRuleHit(MSG_Filter *filter, nsMsgHdr *msgHdr)
{
	char	*filterName = "";
	time_t	date;
@@ -1524,14 +1439,14 @@ void ParseNewMailState::LogRuleHit(MSG_Filter *filter, nsMsgHdr *msgHdr)
	}
}

MSG_FolderInfoMail *ParseNewMailState::GetTrashFolder()
MSG_FolderInfoMail *nsParseNewMailState::GetTrashFolder()
{
	MSG_FolderInfo *foundTrash = NULL;
	GetMaster()->GetLocalMailFolderTree()->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, &foundTrash, 1);
	return foundTrash ? foundTrash->GetMailFolderInfo() : (MSG_FolderInfoMail *)NULL;
}

void ParseNewMailState::ApplyFilters(PRBool *pMoved)
void nsParseNewMailState::ApplyFilters(PRBool *pMoved)
{
	MSG_Filter	*filter;
	PRInt32		filterCount = 0;
@@ -1694,75 +1609,184 @@ void ParseNewMailState::ApplyFilters(PRBool *pMoved)
		*pMoved = msgMoved;
}

// This gets called for every message because libnet calls IncorporateBegin,
// IncorporateWrite (once or more), and IncorporateComplete for every message.
void ParseNewMailState::DoneParsingFolder()
int nsParseNewMailState::MarkFilteredMessageRead(nsMsgHdr *msgHdr)
{
	PRBool moved = FALSE;
/* End of file.  Flush out any partial line remaining in the buffer. */
	if (m_ibuffer_fp > 0) 
	if (m_mailDB)
		m_mailDB->MarkHdrRead(msgHdr, TRUE, NULL);
	else
		msgHdr->OrFlags(kIsRead);
	return 0;
}

int nsParseNewMailState::MoveIncorporatedMessage(nsMsgHdr *mailHdr, 
											   nsMailDatabase *sourceDB, 
											   char *destFolder,
											   MSG_Filter *filter)
{
		m_parseMsgState->ParseFolderLine(m_ibuffer, m_ibuffer_fp);
		m_ibuffer_fp = 0;
	int err = 0;
	XP_File		destFid;
	XP_File		sourceFid = m_file;

	// Make sure no one else is writing into this folder
	MSG_FolderInfo *lockedFolder = m_mailMaster->FindMailFolder (destFolder, FALSE /*create*/);
	if (lockedFolder && (err = lockedFolder->AcquireSemaphore (this)) != 0)
		return err;

	if (sourceFid == 0)
	{
		sourceFid = XP_FileOpen(m_mailboxName,
										xpMailFolder, XP_FILE_READ_BIN);
	}
	PublishMsgHeader();
	if (!moved && m_mailDB != NULL)	// finished parsing, so flush db folder info 
		UpdateDBFolderInfo();
	XP_ASSERT(sourceFid != 0);
	if (sourceFid == 0)
	{
#ifdef DEBUG_bienvenu
		XP_ASSERT(FALSE);
#endif
		if (lockedFolder)
			lockedFolder->ReleaseSemaphore (this);

	if (m_folder != NULL)
		m_folder->SummaryChanged();
		return MK_MSG_FOLDER_UNREADABLE;	// ### dmb
	}

	/* We're done reading the folder - we don't need these things
	 any more. */
	FREEIF (m_ibuffer);
	m_ibuffer_size = 0;
	FREEIF (m_obuffer);
	m_obuffer_size = 0;
	XP_FileSeek (sourceFid, mailHdr->GetMessageOffset(), SEEK_SET);
	int newMsgPos;

	destFid = XP_FileOpen(destFolder, xpMailFolder, XP_FILE_APPEND_BIN);

	if (!destFid) 
	{
#ifdef DEBUG_bienvenu
		XP_ASSERT(FALSE);
#endif
		if (lockedFolder)
			lockedFolder->ReleaseSemaphore (this);
		XP_FileClose (sourceFid);
		return  MK_MSG_ERROR_WRITING_MAIL_FOLDER;
	}

PRInt32 ParseNewMailState::PublishMsgHeader()
	if (!XP_FileSeek (destFid, 0, SEEK_END))
	{
	PRBool		moved = FALSE;
		newMsgPos = ftell (destFid);
	}
	else
	{
		XP_ASSERT(FALSE);
		if (lockedFolder)
			lockedFolder->ReleaseSemaphore (this);
		XP_FileClose (destFid);
		XP_FileClose (sourceFid);
		return  MK_MSG_ERROR_WRITING_MAIL_FOLDER;
	}

	m_parseMsgState->FinishHeader();
	nsMailDatabase *mailDb = NULL;
	// don't force upgrade in place - open the db here before we start writing to the 
	// destination file because XP_Stat can return file size including bytes written...
	MsgERR msgErr = nsMailDatabase::Open (destFolder, TRUE, &mailDb);	
	PRUint32 length = mailHdr->GetByteLength();

	if (m_parseMsgState->m_newMsgHdr)
	m_ibuffer_size = 10240;
	m_ibuffer = NULL;

	while (!m_ibuffer && (m_ibuffer_size >= 512))
	{
		FolderTypeSpecificTweakMsgHeader(m_parseMsgState->m_newMsgHdr);
		if (!m_disableFilters) {
			ApplyFilters(&moved);
		m_ibuffer = (char *) XP_ALLOC(m_ibuffer_size);
		if (m_ibuffer == NULL)
			m_ibuffer_size /= 2;
	}
		if (!moved)
	XP_ASSERT(m_ibuffer != NULL);
	while ((length > 0) && m_ibuffer)
	{
			if (m_mailDB)
		PRUint32 nRead = XP_FileRead (m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size  : length, sourceFid);
		if (nRead == 0)
			break;
		
		// we must monitor the number of bytes actually written to the file. (mscott)
		if (XP_FileWrite (m_ibuffer, nRead, destFid) != nRead) 
		{
				m_parseMsgState->m_newMsgHdr->OrFlags(kNew);
				m_mailDB->AddHdrToDB (m_parseMsgState->m_newMsgHdr, NULL,
									  m_updateAsWeGo);
			XP_FileClose(sourceFid);
			XP_FileClose(destFid);     

			// truncate  destination file in case message was partially written
			XP_FileTruncate(destFolder,xpMailFolder,newMsgPos);

			if (lockedFolder)
				lockedFolder->ReleaseSemaphore(this);

			if (mailDb)
				mailDb->Close();

			return MK_MSG_ERROR_WRITING_MAIL_FOLDER;   // caller (ApplyFilters) currently ignores error conditions
		}
			if (m_folder)
				m_folder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);
			
		length -= nRead;
	}
	
		}		// if it was moved by imap filter, m_parseMsgState->m_newMsgHdr == NULL
		else if (m_parseMsgState->m_newMsgHdr)
	XP_ASSERT(length == 0);

	// if we have made it this far then the message has successfully been written to the new folder
	// now add the header to the mailDb.
	if (eSUCCESS == msgErr)
	{
			m_parseMsgState->m_newMsgHdr->unrefer();
		nsMsgHdr *newHdr = new nsMsgHdr();	
		if (newHdr)
		{
			newHdr->CopyFromMsgHdr (mailHdr, sourceDB->GetDB(), mailDb->GetDB());
			// set new byte offset, since the offset in the old file is certainly wrong
			newHdr->SetMessageKey (newMsgPos); 
			newHdr->OrFlags(kNew);

			msgErr = mailDb->AddHdrToDB (newHdr, NULL, m_updateAsWeGo);
		}
		m_parseMsgState->m_newMsgHdr = NULL;
	}
	return 0;
	else
	{
		if (mailDb)
		{
			mailDb->Close();
			mailDb = NULL;
		}
	}

void	ParseNewMailState::SetUsingTempDB(PRBool usingTempDB, char *tmpDBName)
	XP_FileClose(sourceFid);
	XP_FileClose(destFid);
	int truncRet = XP_FileTruncate(m_mailboxName, xpMailFolder, mailHdr->GetMessageOffset());
	XP_ASSERT(truncRet >= 0);

	if (lockedFolder)
		lockedFolder->ReleaseSemaphore (this);

	// tell outgoing parser that we've truncated the Inbox
	m_parseMsgState->Init(mailHdr->GetMessageOffset());
	MSG_FolderInfo *folder = m_mailMaster->FindMailFolder(destFolder, FALSE);

	if (folder)
		folder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);

	if (mailDb != NULL)
	{
	m_usingTempDB = usingTempDB;
	m_tmpdbName = tmpDBName;
		// update the folder size so we won't reparse.
		UpdateDBFolderInfo(mailDb, destFolder);
		if (folder != NULL)
			folder->SummaryChanged();

		mailDb->Close();
	}
	// We are logging the hit with the old mailHdr, which should work, as long
	// as LogRuleHit doesn't assume the new hdr.
	if (m_filterList->IsLoggingEnabled())
		LogRuleHit(filter, mailHdr);

	return err;

}
#endif // DOING_FILTERS

#ifdef IMAP_NEW_MAIL_HANDLED

ParseIMAPMailboxState::ParseIMAPMailboxState(MSG_Master *master, MSG_IMAPHost *host, MSG_FolderInfoMail *folder,
											 MSG_UrlQueue *urlQueue, TImapFlagAndUidState *flagStateAdopted)
											: ParseNewMailState(master, folder), fUrlQueue(urlQueue)
											: nsParseNewMailState(master, folder), fUrlQueue(urlQueue)
{
 	MSG_FolderInfoContainer *imapContainer =  m_mailMaster->GetImapMailFolderTreeForHost(host->GetHostName());
 	MSG_FolderInfo *filteredFolder = imapContainer->FindMailPathname(folder->GetPathname());
@@ -1910,7 +1934,7 @@ MSG_FolderInfoMail *ParseIMAPMailboxState::GetTrashFolder()
void ParseIMAPMailboxState::ApplyFilters(PRBool *pMoved)
{
 	if (fParsingInbox && !(GetCurrentMsg()->GetFlags() & kIsRead) )
 		ParseNewMailState::ApplyFilters(pMoved);
 		nsParseNewMailState::ApplyFilters(pMoved);
 	else
 		*pMoved = FALSE;
 	
@@ -2184,4 +2208,4 @@ void ParseOutgoingMessage::FlushOutputBuffer()
	}
}

#endif /* NEW_MAIL_HANDLED */
#endif /* IMAP_NEW_MAIL_HANDLED */
+24 −28
Original line number Diff line number Diff line
@@ -26,24 +26,23 @@
#include "nsMsgLineBuffer.h"
#include "nsMsgRFC822Parser.h"

class nsFilePath;
class nsByteArray;
class nsMailDatabase;
class nsMsgHdr;
class nsOutputFileStream;
class nsInputFileStream;
class MSG_Filter;
class MSG_Master;
class MSG_FolderInfoMail;
class MSG_FilterList;

/*
class MSG_Master;
class MailDB;
class MSG_Pane;
class MSG_FolderPane;
class MailMessageHdr;
struct MSG_FilterList;
struct MSG_Filter;
struct MSG_Rule;
class MailMessageHdr;
class MSG_UrlQueue;
class TImapFlagAndUidState;
class MSG_FolderInfoContainer;
class MSG_FolderInfoMail;
class MSG_IMAPHost;
*/

@@ -100,14 +99,8 @@ public:
	PRUint32			m_headerstartpos;

	nsByteArray		m_headers;
//	char			*m_headers;
//	PRUint32			m_headers_fp;
//	PRUint32			m_headers_size;

	nsByteArray		m_envelope;
//	char			*m_envelope;
//	PRUint32			m_envelope_fp;
//	PRUint32			m_envelope_size;

	struct message_header m_message_id;
	struct message_header m_references;
@@ -232,18 +225,17 @@ private:

};

#ifdef NEW_MAIL_HANDLED

class ParseNewMailState : public ParseMailboxState 
class nsParseNewMailState : public nsMsgMailboxParser 
{
public:
	ParseNewMailState(MSG_Master *master, MSG_FolderInfoMail *folder);
	virtual ~ParseNewMailState();
	nsParseNewMailState(MSG_Master *master, nsFilePath &folder);
	virtual ~nsParseNewMailState();
	virtual void	DoneParsingFolder();
	virtual void	SetUsingTempDB(PRBool usingTempDB, char *tmpDBName);

	void DisableFilters() {m_disableFilters = TRUE;}

#ifdef DOING_FILTERS
	// from jsmsg.cpp
	friend void JSMailFilter_MoveMessage(ParseNewMailState *state, 
										 nsMsgHdr *msgHdr, 
@@ -251,10 +243,11 @@ public:
										 const char *folder, 
										 MSG_Filter *filter,
										 PRBool *pMoved);
	XP_File GetLogFile();

	nsInputFileStream *GetLogFile();
#endif // DOING_FILTERS
protected:
	virtual PRInt32	PublishMsgHeader();
#ifdef DOING_FILTERS
	virtual void	ApplyFilters(PRBool *pMoved);
	virtual MSG_FolderInfoMail *GetTrashFolder();
	virtual int		MoveIncorporatedMessage(nsMsgHdr *mailHdr, 
@@ -264,12 +257,15 @@ protected:
	virtual	int			MarkFilteredMessageRead(nsMsgHdr *msgHdr);
			void		LogRuleHit(MSG_Filter *filter, nsMsgHdr *msgHdr);
	MSG_FilterList		*m_filterList;
	XP_File			m_logFile;
	nsOutputFileStream	*m_logFile;
#endif // DOING_FILTERS
	char				*m_tmpdbName;				// Temporary filename of new database
	PRBool				m_usingTempDB;
	PRBool				m_disableFilters;
};

#ifdef IMAP_NEW_MAIL_HANDLED


class ParseIMAPMailboxState : public ParseNewMailState 
{
+13 −26
Original line number Diff line number Diff line
@@ -387,7 +387,7 @@ NS_IMETHODIMP nsPop3Protocol::OnStopBinding(nsIURL* aURL, nsresult aStatus,
    return NS_OK; // for now
}

nsPop3Protocol::nsPop3Protocol(nsIURL* aURL, nsITransport* aTransport)
nsPop3Protocol::nsPop3Protocol(nsIURL* aURL, nsITransport* aTransport) : nsMsgLineBuffer(NULL, FALSE)
{
    nsresult rv = 0;

@@ -2038,15 +2038,6 @@ nsPop3Protocol::SendRetr()
}


extern PRInt32 msg_LineBuffer (const char *net_buffer, PRInt32 net_buffer_size,
						   char **bufferP, PRUint32 *buffer_sizeP,
						   PRUint32 *buffer_fpP,
						   PRBool convert_newlines_p,
						   PRInt32 (*per_line_fn) (char *line, PRUint32
                                   line_length, void *closure),
               void *closure);


static PRInt32 gPOP3parsed_bytes, gPOP3size;
static PRBool gPOP3dotFix, gPOP3AssumedEnd;

@@ -2175,10 +2166,7 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
            m_pop3ConData->obuffer_size = 1024;
            m_pop3ConData->obuffer_fp = 0;
        }
        status = msg_LineBuffer(buffer, buffer_size,
                                &m_pop3ConData->obuffer, &m_pop3ConData->obuffer_size,
                                &m_pop3ConData->obuffer_fp, PR_FALSE,
                                RetrHandleLine, (void *) this);
        status = BufferInput(buffer, buffer_size);
    }
    if (status < 0)
    {
@@ -2296,16 +2284,15 @@ nsPop3Protocol::TopResponse(nsIInputStream* inputStream, PRUint32 length)


PRInt32
nsPop3Protocol::RetrHandleLine(char *line, PRUint32 line_length, void *closure)
nsPop3Protocol::HandleLine(char *line, PRUint32 line_length)
{
    nsPop3Protocol* p3p = (nsPop3Protocol *) closure;
    int status;
    
    PR_ASSERT(p3p->m_pop3ConData->msg_closure);
    if (!p3p->m_pop3ConData->msg_closure)
    PR_ASSERT(m_pop3ConData->msg_closure);
    if (!m_pop3ConData->msg_closure)
        return -1;
    
    if (p3p->m_pop3ConData->sender_info && !p3p->m_pop3ConData->seenFromHeader)
    if (m_pop3ConData->sender_info && !m_pop3ConData->seenFromHeader)
    {
        if (line_length > 6 && !XP_MEMCMP("From: ", line, 6))
        {
@@ -2317,16 +2304,16 @@ nsPop3Protocol::RetrHandleLine(char *line, PRUint32 line_length, void *closure)
             */
            char ch = line[line_length-1];
            line[line_length-1] = 0;
            p3p->m_pop3ConData->seenFromHeader = PR_TRUE;
            if (PL_strstr(line, p3p->m_pop3ConData->sender_info) == NULL)
                p3p->m_nsIPop3Sink->SetSenderAuthedFlag(p3p->m_pop3ConData->msg_closure,
            m_pop3ConData->seenFromHeader = PR_TRUE;
            if (PL_strstr(line, m_pop3ConData->sender_info) == NULL)
                m_nsIPop3Sink->SetSenderAuthedFlag(m_pop3ConData->msg_closure,
                                                     PR_FALSE);
            line[line_length-1] = ch;
        }
    }
    
    status =
        p3p->m_nsIPop3Sink->IncorporateWrite(p3p->m_pop3ConData->msg_closure, 
        m_nsIPop3Sink->IncorporateWrite(m_pop3ConData->msg_closure, 
                                             line, line_length);
    
    if ((status >= 0) &&
@@ -2335,12 +2322,12 @@ nsPop3Protocol::RetrHandleLine(char *line, PRUint32 line_length, void *closure)
    {
        gPOP3AssumedEnd = PR_TRUE;	/* in case byte count from server is */
                                    /* wrong, mark we may have had the end */ 
        if (!gPOP3dotFix || p3p->m_pop3ConData->truncating_cur_msg ||
        if (!gPOP3dotFix || m_pop3ConData->truncating_cur_msg ||
            (gPOP3parsed_bytes >= (gPOP3size -3))) 
        {
            status = 
                p3p->m_nsIPop3Sink->IncorporateComplete(p3p->m_pop3ConData->msg_closure);
            p3p->m_pop3ConData->msg_closure = 0;
                m_nsIPop3Sink->IncorporateComplete(m_pop3ConData->msg_closure);
            m_pop3ConData->msg_closure = 0;
        }
    }
    
+3 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "nsIInputStream.h"
#include "nsIPop3URL.h"
#include "nsIPop3Sink.h"
#include "nsMsgLineBuffer.h"

#include "rosetta.h"
#include HG09893
@@ -291,7 +292,7 @@ typedef struct _Pop3ConData {
    char *sender_info;
} Pop3ConData;

class nsPop3Protocol : public nsIStreamListener
class nsPop3Protocol : public nsIStreamListener, public nsMsgLineBuffer
{
public:
    nsPop3Protocol(nsIURL* aURL, nsITransport* aTransport);
@@ -398,7 +399,7 @@ private:
    PRInt32 SendXsender();
    PRInt32 XsenderResponse();
    PRInt32 SendRetr();
    static PRInt32 RetrHandleLine(char *line, PRUint32 line_length, void* closure);
    PRInt32 HandleLine(char *line, PRUint32 line_length);

    PRInt32 RetrResponse(nsIInputStream* inputStream, 
                         PRUint32 length);
+36 −7
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "nscore.h"
#include <stdio.h>
#include <time.h>
#include "nsParseMailbox.h"

#ifdef XP_MAC
#  define LINEBREAK             "\015"
@@ -51,6 +52,7 @@ nsPop3Sink::nsPop3Sink()
    m_outputBuffer = nsnull;
    m_outputBufferSize = 0;
    m_mailDirectory = 0;
	m_newMailParser = NULL;
#ifdef DEBUG
    m_fileCounter = 0;
#endif
@@ -61,6 +63,8 @@ nsPop3Sink::~nsPop3Sink()
    PR_FREEIF(m_accountUrl);
    PR_FREEIF(m_outputBuffer);
    PR_FREEIF(m_mailDirectory);
	if (m_newMailParser)
		delete m_newMailParser;
}

nsresult
@@ -121,6 +125,9 @@ nsPop3Sink::BeginMailDelivery(PRBool* aBool)
    nsFilePath filePath(path);
    m_outFileStream = new nsOutputFileStream(filePath, 
                                             PR_WRONLY | PR_CREATE_FILE | PR_APPEND);

	// create a new mail parser
	m_newMailParser = new nsParseNewMailState(NULL, filePath);
    PR_FREEIF(path);

#ifdef DEBUG
@@ -140,6 +147,12 @@ nsPop3Sink::EndMailDelivery()
        delete m_outFileStream;
        m_outFileStream = 0;
    }
	if (m_newMailParser)
	{
		delete m_newMailParser;
		m_newMailParser = NULL;
	}

#ifdef DEBUG
    printf("End mail message delivery.\n");
#endif 
@@ -178,9 +191,9 @@ nsPop3Sink::IncorporateBegin(const char* uidlString,
    
    char *dummyEnvelope = GetDummyEnvelope();

    *m_outFileStream << dummyEnvelope;
    *m_outFileStream << "X-Mozilla-Status: 8000\r\n";
    *m_outFileStream << "X-Mozilla-Status2: 00000000\r\n";
    WriteLineToMailbox(dummyEnvelope);
    WriteLineToMailbox("X-Mozilla-Status: 8000\r\n");
    WriteLineToMailbox("X-Mozilla-Status2: 00000000\r\n");

    return NS_OK;
}
@@ -254,8 +267,25 @@ nsPop3Sink::IncorporateWrite(void* closure,
#ifdef DEBUG
        printf("%s\n", m_outputBuffer);
#endif 
		WriteLineToMailbox (m_outputBuffer);
		// Is this where we should hook up the new mail parser? Is this block a line, or a real block?
		// I think it's a real line. We're also not escaping lines that start with "From ", which is
		// a potentially horrible bug...Should this be done here, or in the mailbox parser? I vote for
		// here. Also, we're writing out the mozilla-status line in IncorporateBegin, but we need to 
		// pass that along to the mailbox parser so that the mozilla-status offset is handled correctly.
		// And what about uidl? Don't we need to be able to write out an X-UIDL header?
    }
    return NS_OK;
}

nsresult nsPop3Sink::WriteLineToMailbox(char *buffer)
{
	if (buffer)
	{
		if (m_newMailParser)
			m_newMailParser->ParseFolderLine(buffer, PL_strlen(buffer));
		if (m_outFileStream)
            *m_outFileStream << m_outputBuffer;
			*m_outFileStream << buffer;
	}
	return NS_OK;
}
@@ -275,8 +305,7 @@ nsPop3Sink::IncorporateComplete(void* closure)
nsresult
nsPop3Sink::IncorporateAbort(void* closure, PRInt32 status)
{
    if (m_outFileStream)
        *m_outFileStream << LINEBREAK;
	WriteLineToMailbox(LINEBREAK);

#ifdef DEBUG
    printf("Incorporate message abort.\n");
Loading