make pop3 protocol use mailbox parse and line buffer

This commit is contained in:
bienvenu%netscape.com 1999-02-17 00:09:22 +00:00
Родитель 7fc4f1aeff
Коммит bbc1349b8c
10 изменённых файлов: 362 добавлений и 503 удалений

Просмотреть файл

@ -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;
}
// SetMaster(master);
m_mailboxName = PL_strdup(folder);
int ParseNewMailState::MoveIncorporatedMessage(nsMsgHdr *mailHdr,
nsMailDatabase *sourceDB,
char *destFolder,
MSG_Filter *filter)
{
int err = 0;
XP_File destFid;
XP_File sourceFid = m_file;
// 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);
// 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
}
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)
{
XP_FileRemove(m_tmpdbName, xpMailFolderSummary);
}
FREEIF(m_tmpdbName);
// if (m_usingTempDB)
// {
// XP_FileRemove(m_tmpdbName, xpMailFolderSummary);
// }
PR_FREEIF(m_tmpdbName);
#ifdef DOING_FILTERS
JSFilter_cleanup();
#endif
}
XP_File ParseNewMailState::GetLogFile ()
// 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)
{
ParseFolderLine(m_ibuffer, m_ibuffer_fp);
m_ibuffer_fp = 0;
}
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;
}
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)
{
m_parseMsgState->ParseFolderLine(m_ibuffer, m_ibuffer_fp);
m_ibuffer_fp = 0;
}
PublishMsgHeader();
if (!moved && m_mailDB != NULL) // finished parsing, so flush db folder info
UpdateDBFolderInfo();
if (m_folder != NULL)
m_folder->SummaryChanged();
/* 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;
}
PRInt32 ParseNewMailState::PublishMsgHeader()
{
PRBool moved = FALSE;
m_parseMsgState->FinishHeader();
if (m_parseMsgState->m_newMsgHdr)
{
FolderTypeSpecificTweakMsgHeader(m_parseMsgState->m_newMsgHdr);
if (!m_disableFilters) {
ApplyFilters(&moved);
}
if (!moved)
{
if (m_mailDB)
{
m_parseMsgState->m_newMsgHdr->OrFlags(kNew);
m_mailDB->AddHdrToDB (m_parseMsgState->m_newMsgHdr, NULL,
m_updateAsWeGo);
}
if (m_folder)
m_folder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);
} // if it was moved by imap filter, m_parseMsgState->m_newMsgHdr == NULL
else if (m_parseMsgState->m_newMsgHdr)
{
m_parseMsgState->m_newMsgHdr->unrefer();
}
m_parseMsgState->m_newMsgHdr = NULL;
}
if (m_mailDB)
m_mailDB->MarkHdrRead(msgHdr, TRUE, NULL);
else
msgHdr->OrFlags(kIsRead);
return 0;
}
void ParseNewMailState::SetUsingTempDB(PRBool usingTempDB, char *tmpDBName)
int nsParseNewMailState::MoveIncorporatedMessage(nsMsgHdr *mailHdr,
nsMailDatabase *sourceDB,
char *destFolder,
MSG_Filter *filter)
{
m_usingTempDB = usingTempDB;
m_tmpdbName = tmpDBName;
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);
}
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
}
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;
}
#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 */

Просмотреть файл

@ -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,25 +243,29 @@ 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,
nsMailDatabase *sourceDB,
char *destFolder,
MSG_Filter *filter);
virtual int MarkFilteredMessageRead(nsMsgHdr *msgHdr);
void LogRuleHit(MSG_Filter *filter, nsMsgHdr *msgHdr);
MSG_FilterList *m_filterList;
XP_File m_logFile;
char *m_tmpdbName; // Temporary filename of new database
PRBool m_usingTempDB;
PRBool m_disableFilters;
virtual int MarkFilteredMessageRead(nsMsgHdr *msgHdr);
void LogRuleHit(MSG_Filter *filter, nsMsgHdr *msgHdr);
MSG_FilterList *m_filterList;
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
{

Просмотреть файл

@ -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;
}
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -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,12 +267,29 @@ nsPop3Sink::IncorporateWrite(void* closure,
#ifdef DEBUG
printf("%s\n", m_outputBuffer);
#endif
if (m_outFileStream)
*m_outFileStream << m_outputBuffer;
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 << buffer;
}
return NS_OK;
}
nsresult
nsPop3Sink::IncorporateComplete(void* closure)
{
@ -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");

Просмотреть файл

@ -28,6 +28,8 @@
#include "plstr.h"
#include "prenv.h"
class nsParseNewMailState;
class nsPop3Sink : public nsIPop3Sink
{
public:
@ -56,6 +58,9 @@ public:
static char* GetDummyEnvelope(void);
protected:
nsresult WriteLineToMailbox(char *buffer);
PRBool m_authed;
char* m_accountUrl;
PRUint32 m_biffState;
@ -63,6 +68,7 @@ protected:
char* m_outputBuffer;
PRInt32 m_outputBufferSize;
char* m_mailDirectory;
nsParseNewMailState *m_newMailParser;
#ifdef DEBUG
PRInt32 m_fileCounter;
#endif

Просмотреть файл

@ -45,6 +45,7 @@ MYLIBS= \
$(DIST)\lib\libplc21.lib \
$(DIST)\lib\msglocal.lib \
$(DIST)\lib\msgcore.lib \
$(DIST)\lib\rdfbase_s.lib \
$(DIST)\lib\xplib.lib \
$(DIST)\lib\mailnews.lib \
$(NULL)

Просмотреть файл

@ -131,7 +131,7 @@ protected:
void InitializeProtocol(const char * urlSpec);
PRBool m_protocolInitialized;
nsParseMailboxProtocol *m_mailboxParser;
nsMsgMailboxParser *m_mailboxParser;
};
nsMailboxParserTestDriver::nsMailboxParserTestDriver()
@ -203,7 +203,7 @@ void nsMailboxParserTestDriver::InitializeTestDriver()
scanf("%s", fileName);
// now prompt for the local mail folder directory .....
printf("Enter local mail folder directory [%s]: ", m_mailDirectory);
m_mailboxParser = new nsParseMailboxProtocol(fileName);
m_mailboxParser = new nsMsgMailboxParser;
}
// prints the userPrompt and then reads in the user data. Assumes urlData has already been allocated.

Просмотреть файл

@ -43,8 +43,11 @@ MYLIBS= \
$(DIST)\lib\raptorwidget.lib \
$(DIST)\lib\netlib.lib \
$(DIST)\lib\libplc21.lib \
$(DIST)\lib\rdfbase_s.lib \
$(DIST)\lib\msglocal.lib \
$(DIST)\lib\msgcore.lib \
$(DIST)\lib\xplib.lib \
$(DIST)\lib\mailnews.lib \
$(NULL)
LLIBS= $(MYLIBS) \

Просмотреть файл

@ -191,198 +191,10 @@ char *MSG_UnEscapeSearchUrl (const char *commandSpecificData)
}
/* Buffer management.
Why do I feel like I've written this a hundred times before?
*/
int
msg_GrowBuffer (PRUint32 desired_size, PRUint32 element_size, PRUint32 quantum,
char **buffer, PRUint32 *size)
{
if (*size <= desired_size)
{
char *new_buf;
PRUint32 increment = desired_size - *size;
if (increment < quantum) /* always grow by a minimum of N bytes */
increment = quantum;
#ifdef TESTFORWIN16
if (((*size + increment) * (element_size / sizeof(char))) >= 64000)
{
/* Make sure we don't choke on WIN16 */
XP_ASSERT(0);
return MK_OUT_OF_MEMORY;
}
#endif /* DEBUG */
new_buf = (*buffer
? (char *) PR_REALLOC (*buffer, (*size + increment)
* (element_size / sizeof(char)))
: (char *) PR_MALLOC ((*size + increment)
* (element_size / sizeof(char))));
if (! new_buf)
return MK_OUT_OF_MEMORY;
*buffer = new_buf;
*size += increment;
}
return 0;
}
/* Take the given buffer, tweak the newlines at the end if necessary, and
send it off to the given routine. We are guaranteed that the given
buffer has allocated space for at least one more character at the end. */
static PRInt32
msg_convert_and_send_buffer(char* buf, PRUint32 length, PRBool convert_newlines_p,
PRInt32 (*per_line_fn) (char *line,
PRUint32 line_length,
void *closure),
void *closure)
{
/* Convert the line terminator to the native form.
*/
char* newline;
PR_ASSERT(buf && length > 0);
if (!buf || length <= 0) return -1;
newline = buf + length;
PR_ASSERT(newline[-1] == CR || newline[-1] == LF);
if (newline[-1] != CR && newline[-1] != LF) return -1;
/* update count of bytes parsed adding/removing CR or LF*/
NET_POP3TooEarlyForEnd(length);
if (!convert_newlines_p)
{
}
#if (LINEBREAK_LEN == 1)
else if ((newline - buf) >= 2 &&
newline[-2] == CR &&
newline[-1] == LF)
{
/* CRLF -> CR or LF */
buf [length - 2] = LINEBREAK[0];
length--;
}
else if (newline > buf + 1 &&
newline[-1] != LINEBREAK[0])
{
/* CR -> LF or LF -> CR */
buf [length - 1] = LINEBREAK[0];
}
#else
else if (((newline - buf) >= 2 && newline[-2] != CR) ||
((newline - buf) >= 1 && newline[-1] != LF))
{
/* LF -> CRLF or CR -> CRLF */
length++;
buf[length - 2] = LINEBREAK[0];
buf[length - 1] = LINEBREAK[1];
}
#endif
return (*per_line_fn)(buf, length, closure);
}
/* SI::BUFFERED-STREAM-MIXIN
Why do I feel like I've written this a hundred times before?
*/
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)
{
int status = 0;
if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == CR &&
net_buffer_size > 0 && net_buffer[0] != LF) {
/* The last buffer ended with a CR. The new buffer does not start
with a LF. This old buffer should be shipped out and discarded. */
PR_ASSERT(*buffer_sizeP > *buffer_fpP);
if (*buffer_sizeP <= *buffer_fpP) return -1;
status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP,
convert_newlines_p,
per_line_fn, closure);
if (status < 0) return status;
*buffer_fpP = 0;
}
while (net_buffer_size > 0)
{
const char *net_buffer_end = net_buffer + net_buffer_size;
const char *newline = 0;
const char *s;
for (s = net_buffer; s < net_buffer_end; s++)
{
/* Move forward in the buffer until the first newline.
Stop when we see CRLF, CR, or LF, or the end of the buffer.
*But*, if we see a lone CR at the *very end* of the buffer,
treat this as if we had reached the end of the buffer without
seeing a line terminator. This is to catch the case of the
buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n".
*/
if (*s == CR || *s == LF)
{
newline = s;
if (newline[0] == CR)
{
if (s == net_buffer_end - 1)
{
/* CR at end - wait for the next character. */
newline = 0;
break;
}
else if (newline[1] == LF)
/* CRLF seen; swallow both. */
newline++;
}
newline++;
break;
}
}
/* Ensure room in the net_buffer and append some or all of the current
chunk of data to it. */
{
const char *end = (newline ? newline : net_buffer_end);
PRUint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1;
if (desired_size >= (*buffer_sizeP))
{
status = msg_GrowBuffer (desired_size, sizeof(char), 1024,
bufferP, buffer_sizeP);
if (status < 0) return status;
}
memcpy ((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer));
(*buffer_fpP) += (end - net_buffer);
}
/* Now *bufferP contains either a complete line, or as complete
a line as we have read so far.
If we have a line, process it, and then remove it from `*bufferP'.
Then go around the loop again, until we drain the incoming data.
*/
if (!newline)
return 0;
status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP,
convert_newlines_p,
per_line_fn, closure);
if (status < 0) return status;
net_buffer_size -= (newline - net_buffer);
net_buffer = newline;
(*buffer_fpP) = 0;
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////////
// This function is used to load and prepare an pop3 url which can be run by