/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "msgCore.h" // precompiled header... #include "nsPop3Sink.h" #include "prprf.h" #include "prlog.h" #include "nscore.h" #include #include #include "nsParseMailbox.h" #include "nsIMsgLocalMailFolder.h" #include "nsIMsgIncomingServer.h" #include "nsLocalUtils.h" #include "nsMsgLocalFolderHdrs.h" #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later... #include "nsMsgMessageFlags.h" #include "nsMailHeaders.h" #include "nsIMsgAccountManager.h" #include "nsIPop3Protocol.h" #include "nsLocalMailFolder.h" #include "nsIInputStream.h" #include "nsIPrefBranch.h" #include "nsIPrefService.h" #include "nsDirectoryServiceDefs.h" #include "nsIPromptService.h" #include "nsIDocShell.h" #include "mozIDOMWindow.h" #include "nsEmbedCID.h" #include "nsMsgUtils.h" #include "nsServiceManagerUtils.h" #include "nsISupportsPrimitives.h" #include "nsIObserverService.h" #include "nsIPop3Service.h" #include "mozilla/Logging.h" #include "mozilla/Services.h" /* for logging to Error Console */ #include "nsIScriptError.h" mozilla::LazyLogModule POP3LOGMODULE("POP3"); #define POP3LOG(str) "sink: [this=%p] " str, this NS_IMPL_ISUPPORTS(nsPop3Sink, nsIPop3Sink) nsPop3Sink::nsPop3Sink() { m_biffState = 0; m_numNewMessages = 0; m_numNewMessagesInFolder = 0; m_numMsgsDownloaded = 0; m_senderAuthed = false; m_outFileStream = nullptr; m_uidlDownload = false; m_buildMessageUri = false; } nsPop3Sink::~nsPop3Sink() { MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("Calling ReleaseFolderLock from ~nsPop3Sink"))); ReleaseFolderLock(); } partialRecord::partialRecord() : m_msgDBHdr(nullptr) {} partialRecord::~partialRecord() {} // Walk through all the messages in this folder and look for any // PARTIAL messages. For each of those, dig through the mailbox and // find the Account that the message belongs to. If that Account // matches the current Account, then look for the Uidl and save // this message for later processing. nsresult nsPop3Sink::FindPartialMessages() { nsCOMPtr messages; bool hasMore = false; bool isOpen = false; nsLocalFolderScanState folderScanState; nsCOMPtr db; nsCOMPtr localFolder = do_QueryInterface(m_folder); m_folder->GetMsgDatabase(getter_AddRefs(db)); if (!localFolder || !db) return NS_ERROR_FAILURE; // we need it to grub through the folder nsresult rv = db->EnumerateMessages(getter_AddRefs(messages)); if (messages) messages->HasMoreElements(&hasMore); while (hasMore && NS_SUCCEEDED(rv)) { uint32_t flags = 0; nsCOMPtr msgDBHdr; rv = messages->GetNext(getter_AddRefs(msgDBHdr)); if (!NS_SUCCEEDED(rv)) break; msgDBHdr->GetFlags(&flags); if (flags & nsMsgMessageFlags::Partial) { // Open the various streams we need to seek and read from the mailbox if (!isOpen) { rv = localFolder->GetFolderScanState(&folderScanState); if (NS_SUCCEEDED(rv)) isOpen = true; else break; } rv = localFolder->GetUidlFromFolder(&folderScanState, msgDBHdr); if (!NS_SUCCEEDED(rv)) break; // If we got the uidl, see if this partial message belongs to this // account. Add it to the array if so... if (folderScanState.m_uidl && m_accountKey.Equals(folderScanState.m_accountKey, nsCaseInsensitiveCStringComparator)) { partialRecord* partialMsg = new partialRecord(); if (partialMsg) { partialMsg->m_uidl = folderScanState.m_uidl; partialMsg->m_msgDBHdr = msgDBHdr; m_partialMsgsArray.AppendElement(partialMsg); } } } messages->HasMoreElements(&hasMore); } if (isOpen && folderScanState.m_inputStream) folderScanState.m_inputStream->Close(); return rv; } // For all the partial messages saved by FindPartialMessages, // ask the protocol handler if they still exist on the server. // Any messages that don't exist any more are deleted from the // msgDB. void nsPop3Sink::CheckPartialMessages(nsIPop3Protocol* protocol) { uint32_t count = m_partialMsgsArray.Length(); bool deleted = false; for (uint32_t i = 0; i < count; i++) { partialRecord* partialMsg; bool found = true; partialMsg = m_partialMsgsArray.ElementAt(i); protocol->CheckMessage(partialMsg->m_uidl.get(), &found); if (!found && partialMsg->m_msgDBHdr) { if (m_newMailParser) m_newMailParser->m_mailDB->DeleteHeader(partialMsg->m_msgDBHdr, nullptr, false, true); deleted = true; } delete partialMsg; } m_partialMsgsArray.Clear(); if (deleted) { nsCOMPtr localFolder = do_QueryInterface(m_folder); if (localFolder) localFolder->NotifyDelete(); } } nsresult nsPop3Sink::BeginMailDelivery(bool uidlDownload, nsIMsgWindow* aMsgWindow, bool* aBool) { nsresult rv; nsCOMPtr server = do_QueryInterface(m_popServer); if (!server) return NS_ERROR_UNEXPECTED; m_window = aMsgWindow; nsCOMPtr acctMgr = do_GetService("@mozilla.org/messenger/account-manager;1", &rv); nsCOMPtr account; NS_ENSURE_SUCCESS(rv, rv); acctMgr->FindAccountForServer(server, getter_AddRefs(account)); if (account) account->GetKey(m_accountKey); bool isLocked; nsCOMPtr supports = do_QueryInterface(static_cast(this)); NS_ENSURE_STATE(m_folder); m_folder->GetLocked(&isLocked); if (!isLocked) { MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("BeginMailDelivery acquiring semaphore"))); m_folder->AcquireSemaphore(supports); } else { MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("BeginMailDelivery folder locked"))); return NS_MSG_FOLDER_BUSY; } m_uidlDownload = uidlDownload; if (!uidlDownload) FindPartialMessages(); m_folder->GetNumNewMessages(false, &m_numNewMessagesInFolder); #ifdef DEBUG printf("Begin mail message delivery.\n"); #endif nsCOMPtr pop3Service( do_GetService("@mozilla.org/messenger/popservice;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); pop3Service->NotifyDownloadStarted(m_folder); if (aBool) *aBool = true; return NS_OK; } nsresult nsPop3Sink::EndMailDelivery(nsIPop3Protocol* protocol) { CheckPartialMessages(protocol); if (m_newMailParser) { if (m_outFileStream) m_outFileStream->Flush(); // try this. m_newMailParser->OnStopRequest(nullptr, NS_OK); m_newMailParser->EndMsgDownload(); } if (m_outFileStream) { m_outFileStream->Close(); m_outFileStream = nullptr; } // tell the parser to mark the db valid *after* closing the mailbox. if (m_newMailParser) m_newMailParser->UpdateDBFolderInfo(); MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("Calling ReleaseFolderLock from EndMailDelivery"))); nsresult rv = ReleaseFolderLock(); NS_ASSERTION(NS_SUCCEEDED(rv), "folder lock not released successfully"); bool filtersRun; m_folder->CallFilterPlugins(nullptr, &filtersRun); // ??? do we need msgWindow? int32_t numNewMessagesInFolder; // if filters have marked msgs read or deleted, the num new messages count // will go negative by the number of messages marked read or deleted, // so if we add that number to the number of msgs downloaded, that will give // us the number of actual new messages. m_folder->GetNumNewMessages(false, &numNewMessagesInFolder); m_numNewMessages -= (m_numNewMessagesInFolder - numNewMessagesInFolder); m_folder->SetNumNewMessages( m_numNewMessages); // we'll adjust this for spam later if (!filtersRun && m_numNewMessages > 0) { nsCOMPtr server; m_folder->GetServer(getter_AddRefs(server)); if (server) { server->SetPerformingBiff(true); m_folder->SetBiffState(m_biffState); server->SetPerformingBiff(false); } } // note that size on disk has possibly changed. nsCOMPtr localFolder = do_QueryInterface(m_folder); if (localFolder) (void)localFolder->RefreshSizeOnDisk(); nsCOMPtr server = do_QueryInterface(m_popServer); if (server) { nsCOMPtr filterList; rv = server->GetFilterList(nullptr, getter_AddRefs(filterList)); NS_ENSURE_SUCCESS(rv, rv); if (filterList) (void)filterList->FlushLogIfNecessary(); } // fix for bug #161999 // we should update the summary totals for the folder (inbox) // in case it's not the open folder m_folder->UpdateSummaryTotals(true); // check if the folder open in this window is not the current folder, and if // it has new message, in which case we need to try to run the filter plugin. if (m_newMailParser) { nsCOMPtr msgWindow; m_newMailParser->GetMsgWindow(getter_AddRefs(msgWindow)); // this breaks down if it's biff downloading new mail because // there's no msgWindow... if (msgWindow) { nsCOMPtr openFolder; (void)msgWindow->GetOpenFolder(getter_AddRefs(openFolder)); if (openFolder && openFolder != m_folder) { // only call filter plugins if folder is a local folder, because only // local folders get messages filtered into them synchronously by pop3. nsCOMPtr localFolder = do_QueryInterface(openFolder); if (localFolder) { bool hasNew, isLocked; (void)openFolder->GetHasNewMessages(&hasNew); if (hasNew) { // if the open folder is locked, we shouldn't run the spam filters // on it because someone is using the folder. see 218433. // Ideally, the filter plugin code would try to grab the folder lock // and hold onto it until done, but that's more difficult and I // think this will actually fix the problem. openFolder->GetLocked(&isLocked); if (!isLocked) openFolder->CallFilterPlugins(nullptr, &filtersRun); } } } } } #ifdef DEBUG printf("End mail message delivery.\n"); #endif nsCOMPtr pop3Service( do_GetService("@mozilla.org/messenger/popservice;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); pop3Service->NotifyDownloadCompleted(m_folder, m_numNewMessages); return NS_OK; } nsresult nsPop3Sink::ReleaseFolderLock() { nsresult result = NS_OK; if (!m_folder) return result; bool haveSemaphore; nsCOMPtr supports = do_QueryInterface(static_cast(this)); result = m_folder->TestSemaphore(supports, &haveSemaphore); MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("ReleaseFolderLock haveSemaphore = %s"), haveSemaphore ? "TRUE" : "FALSE")); if (NS_SUCCEEDED(result) && haveSemaphore) result = m_folder->ReleaseSemaphore(supports); return result; } nsresult nsPop3Sink::AbortMailDelivery(nsIPop3Protocol* protocol) { CheckPartialMessages(protocol); // ### PS TODO - discard any new message? if (m_outFileStream) { m_outFileStream->Close(); m_outFileStream = nullptr; } /* tell the parser to mark the db valid *after* closing the mailbox. we have truncated the inbox, so berkeley mailbox and msf file are in sync*/ if (m_newMailParser) m_newMailParser->UpdateDBFolderInfo(); MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("Calling ReleaseFolderLock from AbortMailDelivery"))); nsresult rv = ReleaseFolderLock(); NS_ASSERTION(NS_SUCCEEDED(rv), "folder lock not released successfully"); #ifdef DEBUG printf("Abort mail message delivery.\n"); #endif nsCOMPtr pop3Service( do_GetService("@mozilla.org/messenger/popservice;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); pop3Service->NotifyDownloadCompleted(m_folder, 0); return NS_OK; } NS_IMETHODIMP nsPop3Sink::IncorporateBegin(const char* uidlString, uint32_t flags) { #ifdef DEBUG printf("Incorporate message begin:\n"); if (uidlString) printf("uidl string: %s\n", uidlString); #endif nsresult rv; nsCOMPtr newHdr; nsCOMPtr server = do_QueryInterface(m_popServer); if (!server) return NS_ERROR_UNEXPECTED; rv = server->GetMsgStore(getter_AddRefs(m_msgStore)); NS_ENSURE_SUCCESS(rv, rv); rv = m_msgStore->GetNewMsgOutputStream(m_folder, getter_AddRefs(newHdr), getter_AddRefs(m_outFileStream)); NS_ENSURE_SUCCESS(rv, rv); // create a new mail parser if (!m_newMailParser) m_newMailParser = new nsParseNewMailState; NS_ENSURE_TRUE(m_newMailParser, NS_ERROR_OUT_OF_MEMORY); if (m_uidlDownload) m_newMailParser->DisableFilters(); nsCOMPtr serverFolder; rv = GetServerFolder(getter_AddRefs(serverFolder)); if (NS_FAILED(rv)) return rv; rv = m_newMailParser->Init(serverFolder, m_folder, m_window, newHdr, m_outFileStream); // If we failed to initialize the parser, then just don't use it!!! // We can still continue without one. if (NS_FAILED(rv)) { m_newMailParser = nullptr; rv = NS_OK; } nsCString outputString(GetDummyEnvelope()); rv = WriteLineToMailbox(outputString); NS_ENSURE_SUCCESS(rv, rv); // Write out account-key before UIDL so the code that looks for // UIDL will find the account first and know it can stop looking // once it finds the UIDL line. if (!m_accountKey.IsEmpty()) { outputString.AssignLiteral(HEADER_X_MOZILLA_ACCOUNT_KEY ": "); outputString.Append(m_accountKey); outputString.AppendLiteral(MSG_LINEBREAK); rv = WriteLineToMailbox(outputString); NS_ENSURE_SUCCESS(rv, rv); } if (uidlString) { outputString.AssignLiteral("X-UIDL: "); outputString.Append(uidlString); outputString.AppendLiteral(MSG_LINEBREAK); rv = WriteLineToMailbox(outputString); NS_ENSURE_SUCCESS(rv, rv); } // WriteLineToMailbox("X-Mozilla-Status: 8000" MSG_LINEBREAK); char* statusLine = PR_smprintf(X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, flags); outputString.Assign(statusLine); rv = WriteLineToMailbox(outputString); PR_smprintf_free(statusLine); NS_ENSURE_SUCCESS(rv, rv); rv = WriteLineToMailbox("X-Mozilla-Status2: 00000000"_ns MSG_LINEBREAK); NS_ENSURE_SUCCESS(rv, rv); // leave space for 60 bytes worth of keys/tags rv = WriteLineToMailbox(nsLiteralCString(X_MOZILLA_KEYWORDS)); return NS_OK; } NS_IMETHODIMP nsPop3Sink::SetPopServer(nsIPop3IncomingServer* server) { m_popServer = server; return NS_OK; } NS_IMETHODIMP nsPop3Sink::GetPopServer(nsIPop3IncomingServer** aServer) { NS_ENSURE_ARG_POINTER(aServer); NS_IF_ADDREF(*aServer = m_popServer); return NS_OK; } NS_IMETHODIMP nsPop3Sink::GetFolder(nsIMsgFolder** aFolder) { NS_ENSURE_ARG_POINTER(aFolder); NS_IF_ADDREF(*aFolder = m_folder); return NS_OK; } NS_IMETHODIMP nsPop3Sink::SetFolder(nsIMsgFolder* aFolder) { m_folder = aFolder; return NS_OK; } nsresult nsPop3Sink::GetServerFolder(nsIMsgFolder** aFolder) { NS_ENSURE_ARG_POINTER(aFolder); if (m_popServer) { // not sure what this is used for - might be wrong if we have a deferred // account. nsCOMPtr incomingServer = do_QueryInterface(m_popServer); if (incomingServer) return incomingServer->GetRootFolder(aFolder); } *aFolder = nullptr; return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsPop3Sink::SetMsgsToDownload(uint32_t aNumMessages) { m_numNewMessages = aNumMessages; return NS_OK; } char* nsPop3Sink::GetDummyEnvelope(void) { static char result[75]; char* ct; time_t now = time((time_t*)0); #if defined(XP_WIN) if (now < 0 || now > 0x7FFFFFFF) now = 0x7FFFFFFF; #endif ct = ctime(&now); PR_ASSERT(ct[24] == '\r' || ct[24] == '\n'); ct[24] = 0; /* This value must be in ctime() format, with English abbreviations. strftime("... %c ...") is no good, because it is localized. */ PL_strcpy(result, "From - "); PL_strcpy(result + 7, ct); PL_strcpy(result + 7 + 24, MSG_LINEBREAK); return result; } nsresult nsPop3Sink::IncorporateWrite(const char* block, int32_t length) { m_outputBuffer.Truncate(); if (!strncmp(block, "From ", 5)) m_outputBuffer.Assign('>'); m_outputBuffer.Append(block); return WriteLineToMailbox(m_outputBuffer); } nsresult nsPop3Sink::WriteLineToMailbox(const nsACString& buffer) { if (!buffer.IsEmpty()) { uint32_t bufferLen = buffer.Length(); if (m_newMailParser) m_newMailParser->HandleLine(buffer.BeginReading(), bufferLen); // The following (!m_outFileStream etc) was added to make sure that we don't // write somewhere where for some reason or another we can't write to and // lose the messages See bug 62480 NS_ENSURE_TRUE(m_outFileStream, NS_ERROR_OUT_OF_MEMORY); // To remove seeking to the end for each line to be written, remove the // following line. See bug 1116055 for details. #define SEEK_TO_END #ifdef SEEK_TO_END // seek to the end in case someone else has sought elsewhere in our stream. nsCOMPtr seekableOutStream = do_QueryInterface(m_outFileStream); if (seekableOutStream) { int64_t before_seek_pos; nsresult rv2 = seekableOutStream->Tell(&before_seek_pos); MOZ_ASSERT(NS_SUCCEEDED(rv2), "seekableOutStream->Tell(&before_seek_pos) failed"); // XXX Handle error such as network error for remote file system. seekableOutStream->Seek(nsISeekableStream::NS_SEEK_END, 0); int64_t after_seek_pos; nsresult rv3 = seekableOutStream->Tell(&after_seek_pos); MOZ_ASSERT(NS_SUCCEEDED(rv3), "seekableOutStream->Tell(&after_seek_pos) failed"); if (NS_SUCCEEDED(rv2) && NS_SUCCEEDED(rv3)) { if (before_seek_pos != after_seek_pos) { nsString folderName; if (m_folder) m_folder->GetPrettyName(folderName); // This merits a console message, it's poor man's telemetry. MsgLogToConsole4( u"Unexpected file position change detected"_ns + (folderName.IsEmpty() ? EmptyString() : u" in folder "_ns) + (folderName.IsEmpty() ? EmptyString() : folderName) + u". " "If you can reliably reproduce this, please report the " "steps you used to dev-apps-thunderbird@lists.mozilla.org " "or to bug 1308335 at bugzilla.mozilla.org. " "Resolving this problem will allow speeding up message " "downloads."_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, nsIScriptError::errorFlag); # ifdef DEBUG // Debugging, see bug 1116055. if (!folderName.IsEmpty()) { fprintf(stderr, "(seekdebug) WriteLineToMailbox() detected an unexpected " "file position change in folder %s.\n", NS_ConvertUTF16toUTF8(folderName).get()); } else { fprintf(stderr, "(seekdebug) WriteLineToMailbox() detected an unexpected " "file position change.\n"); } fprintf(stderr, "(seekdebug) before_seek_pos=0x%016llx, " "after_seek_pos=0x%016llx\n", (long long unsigned int)before_seek_pos, (long long unsigned int)after_seek_pos); # endif } } } #endif uint32_t bytesWritten; nsresult rv = m_outFileStream->Write(buffer.BeginReading(), bufferLen, &bytesWritten); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(bytesWritten == bufferLen, NS_ERROR_FAILURE); } return NS_OK; } NS_IMETHODIMP nsPop3Sink::IncorporateComplete(nsIMsgWindow* aMsgWindow, int32_t aSize) { if (m_buildMessageUri && !m_baseMessageUri.IsEmpty() && m_newMailParser && m_newMailParser->m_newMsgHdr) { nsMsgKey msgKey; m_newMailParser->m_newMsgHdr->GetMessageKey(&msgKey); m_messageUri.Truncate(); nsBuildLocalMessageURI(m_baseMessageUri, msgKey, m_messageUri); } nsresult rv = WriteLineToMailbox(nsLiteralCString(MSG_LINEBREAK)); NS_ENSURE_SUCCESS(rv, rv); bool leaveOnServer = false; m_popServer->GetLeaveMessagesOnServer(&leaveOnServer); // We need to flush the output stream, in case mail filters move // the new message, which relies on all the data being flushed. rv = m_outFileStream->Flush(); // Make sure the message is written to the disk NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(m_newMailParser, "could not get m_newMailParser"); if (m_newMailParser) { // PublishMsgHdr clears m_newMsgHdr, so we need a comptr to // hold onto it. nsCOMPtr hdr = m_newMailParser->m_newMsgHdr; NS_ASSERTION(hdr, "m_newMailParser->m_newMsgHdr wasn't set"); if (!hdr) return NS_ERROR_FAILURE; nsCOMPtr localFolder = do_QueryInterface(m_folder); // If a header already exists for this message (for example, when // getting a complete message when a partial exists), then update the new // header from the old. nsCOMPtr oldMsgHdr; if (!m_origMessageUri.IsEmpty() && localFolder) { rv = GetMsgDBHdrFromURI(m_origMessageUri, getter_AddRefs(oldMsgHdr)); if (NS_SUCCEEDED(rv) && oldMsgHdr) { localFolder->UpdateNewMsgHdr(oldMsgHdr, hdr); } } m_msgStore->FinishNewMessage(m_outFileStream, hdr); m_newMailParser->PublishMsgHeader(aMsgWindow); m_newMailParser->ApplyForwardAndReplyFilter(aMsgWindow); if (aSize) hdr->SetUint32Property("onlineSize", aSize); if (oldMsgHdr) { // We had the partial message, but got the full now. nsCOMPtr oldMsgFolder; rv = oldMsgHdr->GetFolder(getter_AddRefs(oldMsgFolder)); NS_ENSURE_SUCCESS(rv, rv); nsCString oldURI; rv = oldMsgFolder->GetUriForMsg(oldMsgHdr, oldURI); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr newMsgFolder; rv = hdr->GetFolder(getter_AddRefs(newMsgFolder)); NS_ENSURE_SUCCESS(rv, rv); nsCString newURI; rv = newMsgFolder->GetUriForMsg(hdr, newURI); NS_ENSURE_SUCCESS(rv, rv); // Delete old header before notifying. nsCOMPtr db; rv = m_folder->GetMsgDatabase(getter_AddRefs(db)); NS_ENSURE_SUCCESS(rv, rv); rv = db->DeleteHeader(oldMsgHdr, nullptr, false, true); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr obsServ = mozilla::services::GetObserverService(); nsCOMPtr origUri = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { origUri->SetData(NS_ConvertUTF8toUTF16(oldURI)); obsServ->NotifyObservers(origUri, "message-content-updated", NS_ConvertUTF8toUTF16(newURI).get()); } } } #ifdef DEBUG printf("Incorporate message complete.\n"); #endif nsCOMPtr pop3Service( do_GetService("@mozilla.org/messenger/popservice;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); pop3Service->NotifyDownloadProgress(m_folder, ++m_numMsgsDownloaded, m_numNewMessages); return NS_OK; } NS_IMETHODIMP nsPop3Sink::IncorporateAbort(bool uidlDownload) { NS_ENSURE_STATE(m_outFileStream); nsresult rv = m_outFileStream->Close(); NS_ENSURE_SUCCESS(rv, rv); if (m_msgStore && m_newMailParser && m_newMailParser->m_newMsgHdr) { m_msgStore->DiscardNewMessage(m_outFileStream, m_newMailParser->m_newMsgHdr); } #ifdef DEBUG printf("Incorporate message abort.\n"); #endif return rv; } nsresult nsPop3Sink::SetBiffStateAndUpdateFE(uint32_t aBiffState, int32_t numNewMessages, bool notify) { m_biffState = aBiffState; if (m_newMailParser) numNewMessages -= m_newMailParser->m_numNotNewMessages; if (notify && m_folder && numNewMessages > 0 && numNewMessages != m_numNewMessages && aBiffState == nsIMsgFolder::nsMsgBiffState_NewMail) { m_folder->SetNumNewMessages(numNewMessages); m_folder->SetBiffState(aBiffState); } m_numNewMessages = numNewMessages; return NS_OK; } NS_IMETHODIMP nsPop3Sink::GetBuildMessageUri(bool* bVal) { NS_ENSURE_ARG_POINTER(bVal); *bVal = m_buildMessageUri; return NS_OK; } NS_IMETHODIMP nsPop3Sink::SetBuildMessageUri(bool bVal) { m_buildMessageUri = bVal; return NS_OK; } NS_IMETHODIMP nsPop3Sink::GetMessageUri(nsACString& messageUri) { NS_ENSURE_TRUE(!m_messageUri.IsEmpty(), NS_ERROR_FAILURE); messageUri = m_messageUri; return NS_OK; } NS_IMETHODIMP nsPop3Sink::SetMessageUri(const nsACString& messageUri) { m_messageUri = messageUri; return NS_OK; } NS_IMETHODIMP nsPop3Sink::GetBaseMessageUri(nsACString& baseMessageUri) { NS_ENSURE_TRUE(!m_baseMessageUri.IsEmpty(), NS_ERROR_FAILURE); baseMessageUri = m_baseMessageUri; return NS_OK; } NS_IMETHODIMP nsPop3Sink::SetBaseMessageUri(const nsACString& baseMessageUri) { m_baseMessageUri = baseMessageUri; return NS_OK; } NS_IMETHODIMP nsPop3Sink::GetOrigMessageUri(nsACString& aOrigMessageUri) { aOrigMessageUri.Assign(m_origMessageUri); return NS_OK; } NS_IMETHODIMP nsPop3Sink::SetOrigMessageUri(const nsACString& aOrigMessageUri) { m_origMessageUri.Assign(aOrigMessageUri); return NS_OK; }