зеркало из https://github.com/mozilla/gecko-dev.git
make pop3 protocol use mailbox parse and line buffer
This commit is contained in:
Родитель
3a6a2f17b3
Коммит
bdab3045e5
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче