use buffered file i/o to help perf with profiles on networked file systems, and get us back to 2.0 filespec perf, r=bienvenu, sr=standard8, with a few code tweaks by bienvenu bug 539389
authorneil@parkwaycc.co.uk <neil@httl.net>
Tue, 13 Apr 2010 14:58:43 -0700
changeset 5435 596957726d36e2239672f355dd34b60ae0e91b3e
parent 5434 af361d0593eae83685d2b01c29b915eb0435e45d
child 5436 9ecee87ecb58c14bffd6e6c8a68eba6487e9dc7a
push idunknown
push userunknown
push dateunknown
reviewersbienvenu, standard8, with
bugs539389
use buffered file i/o to help perf with profiles on networked file systems, and get us back to 2.0 filespec perf, r=bienvenu, sr=standard8, with a few code tweaks by bienvenu bug 539389
mailnews/addrbook/src/nsAbManager.cpp
mailnews/base/search/src/nsMsgFilterList.cpp
mailnews/base/src/nsMessenger.cpp
mailnews/base/src/nsMsgAccountManager.cpp
mailnews/base/src/nsMsgFolderCompactor.cpp
mailnews/base/src/nsSpamSettings.cpp
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/base/util/nsMsgMailNewsUrl.cpp
mailnews/base/util/nsMsgUtils.cpp
mailnews/base/util/nsMsgUtils.h
mailnews/compose/public/nsIURLFetcher.idl
mailnews/compose/src/nsMsgAttachmentHandler.cpp
mailnews/compose/src/nsMsgAttachmentHandler.h
mailnews/compose/src/nsMsgSend.cpp
mailnews/compose/src/nsMsgSendLater.cpp
mailnews/compose/src/nsURLFetcher.cpp
mailnews/compose/src/nsURLFetcher.h
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/imap/src/nsImapOfflineSync.cpp
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/test/unit/test_imapFilterActions.js
mailnews/import/applemail/src/nsAppleMailImport.cpp
mailnews/import/eudora/src/nsEudoraMailbox.cpp
mailnews/import/oexpress/nsOE5File.cpp
mailnews/import/oexpress/nsOEMailbox.cpp
mailnews/import/outlook/src/nsOutlookMail.cpp
mailnews/import/src/ImportOutFile.cpp
mailnews/import/src/Makefile.in
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsMailboxProtocol.cpp
mailnews/local/src/nsParseMailbox.cpp
mailnews/local/src/nsPop3Protocol.cpp
mailnews/mime/src/mimedrft.cpp
mailnews/mime/src/mimemrel.cpp
mailnews/mime/src/mimepbuf.cpp
mailnews/news/src/nsNntpIncomingServer.cpp
--- a/mailnews/addrbook/src/nsAbManager.cpp
+++ b/mailnews/addrbook/src/nsAbManager.cpp
@@ -598,20 +598,20 @@ nsresult
 nsAbManager::ExportDirectoryToDelimitedText(nsIAbDirectory *aDirectory, const char *aDelim, PRUint32 aDelimLen, nsILocalFile *aLocalFile)
 {
   nsCOMPtr <nsISimpleEnumerator> cardsEnumerator;
   nsCOMPtr <nsIAbCard> card;
 
   nsresult rv;
 
   nsCOMPtr <nsIOutputStream> outputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream),
-                                   aLocalFile,
-                                   PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
-                                   0664);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(outputStream),
+                                      aLocalFile,
+                                      PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
+                                      0664);
 
   // the desired file may be read only
   if (NS_FAILED(rv))
     return rv;
 
   PRUint32 i;
   PRUint32 writeCount;
   PRUint32 length;
@@ -779,20 +779,20 @@ nsresult
 nsAbManager::ExportDirectoryToLDIF(nsIAbDirectory *aDirectory, nsILocalFile *aLocalFile)
 {
   nsCOMPtr <nsISimpleEnumerator> cardsEnumerator;
   nsCOMPtr <nsIAbCard> card;
 
   nsresult rv;
 
   nsCOMPtr <nsIOutputStream> outputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream),
-                                   aLocalFile,
-                                   PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
-                                   0664);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(outputStream),
+                                      aLocalFile,
+                                      PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
+                                      0664);
 
   // the desired file may be read only
   if (NS_FAILED(rv))
     return rv;
 
   // Get the default attribute map for ldap. We use the default attribute
   // map rather than one for a specific server because if people want an
   // ldif export using a servers specific schema, then they can use ldapsearch
--- a/mailnews/base/search/src/nsMsgFilterList.cpp
+++ b/mailnews/base/search/src/nsMsgFilterList.cpp
@@ -276,20 +276,20 @@ nsMsgFilterList::GetLogStream(nsIOutputS
   nsresult rv;
 
   if (!m_logStream) {
     nsCOMPtr <nsILocalFile> logFile;
     rv = GetLogFile(getter_AddRefs(logFile));
     NS_ENSURE_SUCCESS(rv,rv);
 
     // append to the end of the log file
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_logStream),
-                                   logFile,
-                                   PR_CREATE_FILE | PR_WRONLY | PR_APPEND,
-                                   0600);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(m_logStream),
+                                        logFile,
+                                        PR_CREATE_FILE | PR_WRONLY | PR_APPEND,
+                                        0600);
     NS_ENSURE_SUCCESS(rv,rv);
 
     if (!m_logStream)
       return NS_ERROR_FAILURE;
 
     PRInt64 fileSize;
     rv = logFile->GetFileSize(&fileSize);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/mailnews/base/src/nsMessenger.cpp
+++ b/mailnews/base/src/nsMessenger.cpp
@@ -1834,17 +1834,17 @@ nsresult nsSaveMsgListener::InitializeDo
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsSaveMsgListener::OnStartRequest(nsIRequest* request, nsISupports* aSupport)
 {
   if (m_file)
-    NS_NewLocalFileOutputStream(getter_AddRefs(m_outputStream), m_file, -1, 00600);
+    MsgNewBufferedFileOutputStream(getter_AddRefs(m_outputStream), m_file, -1, 00600);
   if (!m_outputStream)
   {
     mCanceled = PR_TRUE;
     if (m_messenger)
       m_messenger->Alert("saveAttachmentFailed");
   }
   return NS_OK;
 }
@@ -2864,21 +2864,17 @@ nsDelAttachListener::StartProcessing(nsM
   // The file is removed in the destructor.
   rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR, "nsmail.tmp",
                                        getter_AddRefs(mMsgFile));
   NS_ENSURE_SUCCESS(rv,rv);
 
   rv = mMsgFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
   NS_ENSURE_SUCCESS(rv,rv);
 
-  nsCOMPtr<nsIOutputStream> fileOutputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOutputStream), mMsgFile, -1, 00600);
-  NS_ENSURE_SUCCESS(rv,rv);
-  rv = NS_NewBufferedOutputStream(getter_AddRefs(mMsgFileStream), fileOutputStream, FOUR_K);
-  NS_ENSURE_SUCCESS(rv,rv);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mMsgFileStream), mMsgFile, -1, 00600);
 
   // create the additional header for data conversion. This will tell the stream converter
   // which MIME emitter we want to use, and it will tell the MIME emitter which attachments
   // should be deleted.
   const char * partId;
   const char * nextField;
   nsCAutoString sHeader("attach&del=");
   nsCAutoString detachToHeader("&detachTo=");
--- a/mailnews/base/src/nsMsgAccountManager.cpp
+++ b/mailnews/base/src/nsMsgAccountManager.cpp
@@ -3198,20 +3198,20 @@ nsMsgAccountManager::saveVirtualFolders(
       NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
       PRUint32 vfCount;
       virtualFolders->GetLength(&vfCount);
       nsIOutputStream *outputStream = * (nsIOutputStream **) data;
       if (!outputStream)
       {
         nsCOMPtr<nsILocalFile> file;
         GetVirtualFoldersFile(file);
-        rv = NS_NewLocalFileOutputStream(&outputStream,
-                                         file,
-                                         PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
-                                         0664);
+        rv = MsgNewBufferedFileOutputStream(&outputStream,
+                                            file,
+                                            PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
+                                            0664);
         NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
         * (nsIOutputStream **) data = outputStream;
         WriteLineToOutputStream("version=", "1", outputStream);
 
       }
       for (PRUint32 folderIndex = 0; folderIndex < vfCount; folderIndex++)
       {
         nsCOMPtr <nsIRDFResource> folderRes (do_QueryElementAt(virtualFolders, folderIndex));
--- a/mailnews/base/src/nsMsgFolderCompactor.cpp
+++ b/mailnews/base/src/nsMsgFolderCompactor.cpp
@@ -308,17 +308,17 @@ nsFolderCompactState::Init(nsIMsgFolder 
   {
     CleanupTempFilesAfterError();
     return rv;
   }
 
   m_size = m_keyArray.Length();
   m_curIndex = 0;
   
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_fileStream), m_file, -1, 00600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(m_fileStream), m_file, -1, 00600);
   if (NS_FAILED(rv)) 
     m_folder->ThrowAlertMsg("compactFolderWriteFailed", m_window);
   else
     rv = GetMessageServiceFromURI(nsDependentCString(baseMsgUri),
                                 getter_AddRefs(m_messageService));
   if (NS_FAILED(rv))
   {
     m_status = rv;
--- a/mailnews/base/src/nsSpamSettings.cpp
+++ b/mailnews/base/src/nsSpamSettings.cpp
@@ -240,20 +240,20 @@ nsSpamSettings::GetLogStream(nsIOutputSt
 
   nsresult rv;
 
   if (!mLogStream) {
     nsCOMPtr <nsILocalFile> logFile = do_QueryInterface(mLogFile, &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
     // append to the end of the log file
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(mLogStream),
-                                   logFile,
-                                   PR_CREATE_FILE | PR_WRONLY | PR_APPEND,
-                                   0600);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mLogStream),
+                                        logFile,
+                                        PR_CREATE_FILE | PR_WRONLY | PR_APPEND,
+                                        0600);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PRInt64 fileSize;
     rv = logFile->GetFileSize(&fileSize);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PRUint32 fileLen;
     LL_L2UI(fileLen, fileSize);
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -871,17 +871,17 @@ NS_IMETHODIMP nsMsgDBFolder::GetOfflineS
         if (NS_FAILED(rv))
           return rv;
       }
     }
 #endif
   nsCOMPtr <nsILocalFile> localPath;
   rv = GetFilePath(getter_AddRefs(localPath));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = NS_NewLocalFileOutputStream(outputStream, localPath, PR_WRONLY | PR_CREATE_FILE, 00600);
+  rv = MsgNewBufferedFileOutputStream(outputStream, localPath, PR_WRONLY | PR_CREATE_FILE, 00600);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr <nsISeekableStream> seekable = do_QueryInterface(*outputStream);
   if (seekable)
     seekable->Seek(nsISeekableStream::NS_SEEK_END, 0);
   return rv;
 }
 
@@ -1587,17 +1587,17 @@ nsresult nsMsgDBFolder::WriteStartOfNewL
   {
     seekable->Tell(&curStorePos);
     m_offlineHeader->SetMessageOffset(curStorePos);
   }
   m_tempMessageStream->Write(result.get(), result.Length(),
                              &writeCount);
   if (seekable)
   {
-    seekable->Seek(PR_SEEK_CUR, 0); // seeking causes a flush, w/o syncing
+    m_tempMessageStream->Flush();
     seekable->Tell(&curStorePos);
     m_offlineHeader->SetStatusOffset((PRUint32) curStorePos);
   }
 
   NS_NAMED_LITERAL_CSTRING(MozillaStatus, "X-Mozilla-Status: 0001" MSG_LINEBREAK);
   m_tempMessageStream->Write(MozillaStatus.get(), MozillaStatus.Length(),
                              &writeCount);
   m_bytesAddedToLocalMsg += writeCount;
@@ -1639,17 +1639,17 @@ nsresult nsMsgDBFolder::EndNewOfflineMes
 
   m_offlineHeader->GetMessageKey(&messageKey);
   if (m_tempMessageStream)
     seekable = do_QueryInterface(m_tempMessageStream);
 
   mDatabase->MarkOffline(messageKey, PR_TRUE, nsnull);
   if (seekable)
   {
-    seekable->Seek(PR_SEEK_CUR, 0); // seeking causes a flush, w/o syncing
+    m_tempMessageStream->Flush();
     PRInt64 tellPos;
     seekable->Tell(&tellPos);
     curStorePos = tellPos;
 
     // N.B. This only works if we've set the offline flag for the message,
     // so be careful about moving the call to MarkOffline above.
     m_offlineHeader->GetMessageOffset(&messageOffset);
     curStorePos -= messageOffset;
--- a/mailnews/base/util/nsMsgMailNewsUrl.cpp
+++ b/mailnews/base/util/nsMsgMailNewsUrl.cpp
@@ -931,18 +931,18 @@ nsresult nsMsgSaveAsListener::SetupMsgWr
   // object, thus creating an empty file. Actual save operations for
   // IMAP and NNTP use this nsMsgSaveAsListener here, though, so we
   // have to close the stream before deleting the file, else data
   // would still be written happily into a now non-existing file.
   // (Windows doesn't care, btw, just unixoids do...)
   aFile->Remove(PR_FALSE);
 
   nsCOMPtr <nsILocalFile> localFile = do_QueryInterface(aFile);
-  nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_outputStream),
-                                            localFile, -1, 00600);
+  nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(m_outputStream),
+                                               localFile, -1, 00600);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (m_outputStream && addDummyEnvelope)
   {
     nsCAutoString result;
     PRUint32 writeCount;
 
     time_t now = time((time_t*) 0);
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -95,16 +95,18 @@
 static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
 static NS_DEFINE_CID(kCMailboxUrl, NS_MAILBOXURL_CID);
 static NS_DEFINE_CID(kCNntpUrlCID, NS_NNTPURL_CID);
 
 #define ILLEGAL_FOLDER_CHARS ";#"
 #define ILLEGAL_FOLDER_CHARS_AS_FIRST_LETTER "."
 #define ILLEGAL_FOLDER_CHARS_AS_LAST_LETTER  ".~ "
 
+#define FOUR_K 4096
+
 nsresult GetMessageServiceContractIDForURI(const char *uri, nsCString &contractID)
 {
   nsresult rv = NS_OK;
   //Find protocol
   nsCAutoString uriStr(uri);
   PRInt32 pos = uriStr.FindChar(':');
   if (pos == -1)
     return NS_ERROR_FAILURE;
@@ -1323,16 +1325,28 @@ nsresult MsgReopenFileStream(nsILocalFil
 {
   nsMsgFileStream *msgFileStream = static_cast<nsMsgFileStream *>(fileStream);
   if (msgFileStream)
     return msgFileStream->InitWithFile(file);
   else
     return NS_ERROR_FAILURE;
 }
 
+nsresult MsgNewBufferedFileOutputStream(nsIOutputStream **aResult,
+                                        nsIFile* aFile,
+                                        PRInt32 aIOFlags,
+                                        PRInt32 aPerm)
+{
+  nsCOMPtr<nsIOutputStream> stream;
+  nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile, aIOFlags, aPerm);
+  if (NS_SUCCEEDED(rv))
+    rv = NS_NewBufferedOutputStream(aResult, stream, FOUR_K);
+  return rv;
+}
+
 PRBool MsgFindKeyword(const nsCString &keyword, nsCString &keywords, PRInt32 *aStartOfKeyword, PRInt32 *aLength)
 {
 #ifdef MOZILLA_INTERNAL_API
 // nsTString_CharT::Find(const nsCString& aString,
 //                       PRBool aIgnoreCase=PR_FALSE,
 //                       PRInt32 aOffset=0,
 //                       PRInt32 aCount=-1 ) const;
 #define FIND_KEYWORD(keywords,keyword,offset) ((keywords).Find((keyword), PR_FALSE, (offset)))
--- a/mailnews/base/util/nsMsgUtils.h
+++ b/mailnews/base/util/nsMsgUtils.h
@@ -198,16 +198,19 @@ NS_MSG_BASE nsresult GetSummaryFileLocat
 NS_MSG_BASE nsresult GetSpecialDirectoryWithFileName(const char* specialDirName,
                                                      const char* fileName,
                                                      nsIFile** result);
 
 NS_MSG_BASE nsresult MsgGetFileStream(nsILocalFile *file, nsIOutputStream **fileStream);
 
 NS_MSG_BASE nsresult MsgReopenFileStream(nsILocalFile *file, nsIInputStream *fileStream);
 
+// Automatically creates an output stream with a 4K buffer
+NS_MSG_BASE nsresult MsgNewBufferedFileOutputStream(nsIOutputStream **aResult, nsIFile *aFile, PRInt32 aIOFlags = -1, PRInt32 aPerm = -1);
+
 // fills in the position of the passed in keyword in the passed in keyword list
 // and returns false if the keyword isn't present
 NS_MSG_BASE PRBool MsgFindKeyword(const nsCString &keyword, nsCString &keywords, PRInt32 *aStartOfKeyword, PRInt32 *aLength);
 
 NS_MSG_BASE PRBool MsgHostDomainIsTrusted(nsCString &host, nsCString &trustedMailDomains);
 
 NS_MSG_BASE nsresult FolderUriFromDirInProfile(nsILocalFile *aLocalPath, nsACString &mailboxUri);
 
--- a/mailnews/compose/public/nsIURLFetcher.idl
+++ b/mailnews/compose/public/nsIURLFetcher.idl
@@ -57,12 +57,12 @@ typedef nsresult (*nsAttachSaveCompletio
 native nsAttachSaveCompletionCallback(nsAttachSaveCompletionCallback);
 
 
 [noscript, uuid(3ef12571-d41f-48ce-9d55-086e6d3c9bc0)]
 interface nsIURLFetcher : nsISupports
 {
   boolean stillRunning();
 
-  void fireURLRequest(in nsIURI aURL, in nsILocalFile localFile, in nsIFileOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
+  void fireURLRequest(in nsIURI aURL, in nsILocalFile localFile, in nsIOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
 
-  void initialize(in nsILocalFile localFile, in nsIFileOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
+  void initialize(in nsILocalFile localFile, in nsIOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
 };
--- a/mailnews/compose/src/nsMsgAttachmentHandler.cpp
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.cpp
@@ -556,35 +556,33 @@ nsMsgAttachmentHandler::SnarfMsgAttachme
     PR_Free(m_override_type);
     m_override_type = PL_strdup(MESSAGE_RFC822);
     if (!mTmpFile)
     {
       rv = NS_ERROR_FAILURE;
       goto done;
     }
 
-    nsCOMPtr<nsIOutputStream> outputStream;
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, -1, 00600);
-    if (NS_FAILED(rv) || !outputStream)
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mOutFile), mTmpFile, -1, 00600);
+    if (NS_FAILED(rv) || !mOutFile)
     {
       if (m_mime_delivery_state)
       {
         nsCOMPtr<nsIMsgSendReport> sendReport;
         m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport));
         if (sendReport)
         {
           nsAutoString error_msg;
           nsMsgBuildMessageWithTmpFile(mTmpFile, error_msg);
           sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
         }
       }
       rv =  NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
       goto done;
     }
-    mOutFile = do_QueryInterface(outputStream);
 
     nsCOMPtr<nsIURLFetcher> fetcher = do_CreateInstance(NS_URLFETCHER_CONTRACTID, &rv);
     if (NS_FAILED(rv) || !fetcher)
     {
       if (NS_SUCCEEDED(rv))
         rv =  NS_ERROR_UNEXPECTED;
       goto done;
     }
@@ -686,36 +684,34 @@ nsMsgAttachmentHandler::SnarfAttachment(
   // First, get as file spec and create the stream for the
   // temp file where we will save this data
   nsCOMPtr <nsIFile> tmpFile;
   nsresult rv = nsMsgCreateTempFile("nsmail.tmp", getter_AddRefs(tmpFile));
   NS_ENSURE_SUCCESS(rv, rv);
   mTmpFile = do_QueryInterface(tmpFile);
   mDeleteFile = PR_TRUE;
 
-  nsCOMPtr<nsIOutputStream> outputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, -1, 00600);
-  if (NS_FAILED(rv) || !outputStream)
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mOutFile), mTmpFile, -1, 00600);
+  if (NS_FAILED(rv) || !mOutFile)
   {
     if (m_mime_delivery_state)
     {
       nsCOMPtr<nsIMsgSendReport> sendReport;
       m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport));
       if (sendReport)
       {
         nsAutoString error_msg;
         nsMsgBuildMessageWithTmpFile(mTmpFile, error_msg);
         sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
       }
     }
     mTmpFile->Remove(PR_FALSE);
     mTmpFile = nsnull;
     return NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
   }
-  mOutFile = do_QueryInterface(outputStream);
 
   nsCString sourceURISpec;
   mURL->GetSpec(sourceURISpec);
 #ifdef XP_MACOSX
   if (!m_bogus_attachment && StringBeginsWith(sourceURISpec, NS_LITERAL_CSTRING("file://")))
   {
     // Unescape the path (i.e. un-URLify it) before making a FSSpec
     nsCAutoString filePath;
--- a/mailnews/compose/src/nsMsgAttachmentHandler.h
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.h
@@ -123,17 +123,17 @@ private:
   nsresult ConvertToZipFile(nsILocalFileMac *aSourceFile);
   PRBool HasResourceFork(FSSpec *fsSpec);
 #endif
 
   //
 public:
   nsCOMPtr <nsIURI> mURL;
   nsCOMPtr <nsILocalFile>        mTmpFile;         // The temp file to which we save it 
-  nsCOMPtr<nsIFileOutputStream>  mOutFile;          
+  nsCOMPtr<nsIOutputStream>  mOutFile;          
   nsIRequest            *mRequest;          // The live request used while fetching an attachment
   nsMsgCompFields       *mCompFields;       // Message composition fields for the sender
   PRBool                m_bogus_attachment; // This is to catch problem children...
   
 #ifdef XP_MACOSX
   // if we need to encode this file into for example an appledouble, or zip file,
   // this file is our working file. currently only needed on mac.
   nsCOMPtr<nsILocalFile> mEncodedWorkingFile;
--- a/mailnews/compose/src/nsMsgSend.cpp
+++ b/mailnews/compose/src/nsMsgSend.cpp
@@ -623,17 +623,17 @@ nsMsgComposeAndSend::GatherMimeAttachmen
     // a text/plain message, so we will write the HTML out to a disk file,
     // fire off another URL request for this local disk file and that will
     // take care of the conversion...
     //
     rv = nsMsgCreateTempFile("nsemail.html", getter_AddRefs(mHTMLFile));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIOutputStream> tempfile;
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(tempfile), mHTMLFile, -1, 00600);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(tempfile), mHTMLFile, -1, 00600);
     if (NS_FAILED(rv))
     {
       if (mSendReport)
       {
         nsAutoString error_msg;
         nsMsgBuildMessageWithTmpFile(mTempFile, error_msg);
         mSendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
       }
@@ -702,17 +702,17 @@ nsMsgComposeAndSend::GatherMimeAttachmen
   mComposeBundle->GetStringFromID(NS_MSG_ASSEMBLING_MSG, getter_Copies(msg));
   SetStatusMessage( msg );
 
   /* First, open the message file.
   */
   rv = nsMsgCreateTempFile("nsemail.eml", getter_AddRefs(mTempFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(mOutputFile), mTempFile, -1, 00600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mOutputFile), mTempFile, -1, 00600);
   if (NS_FAILED(rv))
   {
     status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
     if (mSendReport)
     {
       nsAutoString error_msg;
       nsMsgBuildMessageWithTmpFile(mTempFile, error_msg);
       mSendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
@@ -4480,17 +4480,17 @@ nsMsgComposeAndSend::MimeDoFCC(nsIFile  
 
   //
   // Create the file that will be used for the copy service!
   //
   nsresult rv = nsMsgCreateTempFile("nscopy.tmp", getter_AddRefs(mCopyFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIOutputStream> tempOutfile;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(tempOutfile), mCopyFile, -1, 00600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(tempOutfile), mCopyFile, -1, 00600);
   if (NS_FAILED(rv))
   {
     if (mSendReport)
     {
       nsAutoString error_msg;
       nsMsgBuildMessageWithTmpFile(mCopyFile, error_msg);
       mSendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
     }
--- a/mailnews/compose/src/nsMsgSendLater.cpp
+++ b/mailnews/compose/src/nsMsgSendLater.cpp
@@ -1188,17 +1188,17 @@ nsMsgSendLater::DeliverQueuedLine(char *
     }
     
     if (line[0] == '\r' || line[0] == '\n' || line[0] == 0)
     {
       // End of headers.  Now parse them; open the temp file;
       // and write the appropriate subset of the headers out. 
       m_inhead = PR_FALSE;
 
-      nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(mOutFile), mTempFile, -1, 00600);
+      nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mOutFile), mTempFile, -1, 00600);
       if (NS_FAILED(rv))
         return NS_MSG_ERROR_WRITING_FILE;
 
       nsresult status = BuildHeaders();
       if (NS_FAILED(status))
         return status;
 
       PRUint32 n;
--- a/mailnews/compose/src/nsURLFetcher.cpp
+++ b/mailnews/compose/src/nsURLFetcher.cpp
@@ -327,32 +327,32 @@ nsURLFetcher::OnStopRequest(nsIRequest *
     mCallback (aStatus, mContentType, mCharset, mTotalWritten, nsnull, mTagData);
 
   // Time to return...
   return NS_OK;
 }
 
 nsresult 
 nsURLFetcher::Initialize(nsILocalFile *localFile, 
-                         nsIFileOutputStream *outputStream,
+                         nsIOutputStream *outputStream,
                          nsAttachSaveCompletionCallback cb, 
                          void *tagData)
 {
   if (!outputStream || !localFile)
     return NS_ERROR_INVALID_ARG;
 
   mOutStream = outputStream;
   mLocalFile = localFile;
   mCallback = cb;     //JFD: Please, no more callback, use a listener...
   mTagData = tagData; //JFD: TODO, WE SHOULD USE A NSCOMPTR to hold this stuff!!!
   return NS_OK;
 }
 
 nsresult
-nsURLFetcher::FireURLRequest(nsIURI *aURL, nsILocalFile *localFile, nsIFileOutputStream *outputStream, 
+nsURLFetcher::FireURLRequest(nsIURI *aURL, nsILocalFile *localFile, nsIOutputStream *outputStream, 
                              nsAttachSaveCompletionCallback cb, void *tagData)
 {
   nsresult rv;
 
   rv = Initialize(localFile, outputStream, cb, tagData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   //check to see if aURL is a local file or not
--- a/mailnews/compose/src/nsURLFetcher.h
+++ b/mailnews/compose/src/nsURLFetcher.h
@@ -82,17 +82,17 @@ public:
 
   // Methods for nsIWebProgressListener
   NS_DECL_NSIWEBPROGRESSLISTENER
 
 protected:
   nsresult InsertConverter(const char * aContentType);
 
 private:
-  nsCOMPtr<nsIFileOutputStream>   mOutStream;               // the output file stream
+  nsCOMPtr<nsIOutputStream>       mOutStream;               // the output file stream
   nsCOMPtr<nsILocalFile>          mLocalFile;               // the output file itself
   nsCOMPtr<nsIStreamListener>     mConverter;               // the stream converter, if needed
   nsCString                  mConverterContentType;    // The content type of the converter
   PRBool                          mStillRunning;  // Are we still running?
   PRInt32                         mTotalWritten;  // Size counter variable
   char                            *mBuffer;                 // Buffer used for reading the data
   PRUint32                        mBufferSize;              // Buffer size;
   nsCString                  mContentType;             // The content type retrieved from the server
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -3229,20 +3229,17 @@ NS_IMETHODIMP nsImapMailFolder::BeginCop
                                         getter_AddRefs(m_copyState->m_tmpFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // create a unique file, since multiple copies may be open on multiple folders
   rv = m_copyState->m_tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
 
   nsCOMPtr<nsIOutputStream> fileOutputStream;
   nsCOMPtr <nsILocalFile> localFile = do_QueryInterface(m_copyState->m_tmpFile);
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOutputStream), localFile, -1, 00600);
-  NS_ENSURE_SUCCESS(rv,rv);
-  rv = NS_NewBufferedOutputStream(getter_AddRefs(m_copyState->m_msgFileStream), fileOutputStream, FOUR_K);
-  NS_ENSURE_SUCCESS(rv,rv);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(m_copyState->m_msgFileStream), localFile, -1, 00600);
 
   if (!m_copyState->m_dataBuffer)
     m_copyState->m_dataBuffer = (char*) PR_CALLOC(COPY_BUFFER_SIZE+1);
   NS_ENSURE_TRUE(m_copyState->m_dataBuffer, NS_ERROR_OUT_OF_MEMORY);
   m_copyState->m_dataBufferSize = COPY_BUFFER_SIZE;
   return NS_OK;
 }
 
@@ -4374,17 +4371,17 @@ void nsImapMailFolder::TweakHeaderFlags(
 
 NS_IMETHODIMP
 nsImapMailFolder::SetupMsgWriteStream(nsIFile * aFile, PRBool addDummyEnvelope)
 {
   nsresult rv;
   aFile->Remove(PR_FALSE);
   nsCOMPtr<nsILocalFile>  localFile = do_QueryInterface(aFile, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_tempMessageStream), localFile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 00700);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(m_tempMessageStream), localFile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 00700);
   if (m_tempMessageStream && addDummyEnvelope)
   {
     nsCAutoString result;
     char *ct;
     PRUint32 writeCount;
     time_t now = time ((time_t*) 0);
     ct = ctime(&now);
     ct[24] = 0;
--- a/mailnews/imap/src/nsImapOfflineSync.cpp
+++ b/mailnews/imap/src/nsImapOfflineSync.cpp
@@ -391,17 +391,17 @@ nsImapOfflineSync::ProcessAppendMsgOpera
                                                   "nscpmsg.txt",
                                                   getter_AddRefs(tmpFile))))
       return;
 
     if (NS_FAILED(tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600)))
       return;
 
     nsCOMPtr <nsIOutputStream> outputStream;
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), tmpFile, PR_WRONLY | PR_CREATE_FILE, 00600);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(outputStream), tmpFile, PR_WRONLY | PR_CREATE_FILE, 00600);
     if (NS_SUCCEEDED(rv) && outputStream)
     {
       nsCString moveDestination;
       currentOp->GetDestinationFolderURI(getter_Copies(moveDestination));
       nsCOMPtr<nsIRDFService> rdf(do_GetService(kRDFServiceCID, &rv));
       nsCOMPtr<nsIRDFResource> res;
       if (NS_FAILED(rv)) return ; // ### return error code.
       rv = rdf->GetResource(moveDestination, getter_AddRefs(res));
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -1735,16 +1735,29 @@ PRBool nsImapProtocol::ProcessCurrentURL
   // The URL has now been processed
     if ((!logonFailed && GetConnectionStatus() < 0) || DeathSignalReceived())
          HandleCurrentUrlError();
 
   }
   else if (!logonFailed)
       HandleCurrentUrlError();
 
+// if we are set up as a channel, we should notify our channel listener that we are stopping...
+// so pass in ourself as the channel and not the underlying socket or file channel the protocol
+// happens to be using
+  if (m_channelListener)
+  {
+      nsCOMPtr<nsIRequest> request = do_QueryInterface(m_mockChannel);
+      NS_ASSERTION(request, "no request");
+      if (request) {
+        nsresult status;
+        request->GetStatus(&status);
+        rv = m_channelListener->OnStopRequest(request, m_channelContext, status);
+      }
+  }
   if (mailnewsurl && m_imapMailFolderSink)
   {
     rv = GetServerStateParser().LastCommandSuccessful() && !logonFailed ?
           NS_OK : NS_ERROR_FAILURE;
     // we are done with this url.
     m_imapMailFolderSink->SetUrlState(this, mailnewsurl, PR_FALSE, rv);
      // doom the cache entry
     if (NS_FAILED(rv) && DeathSignalReceived() && m_mockChannel)
@@ -1752,29 +1765,16 @@ PRBool nsImapProtocol::ProcessCurrentURL
   }
   else
     NS_ASSERTION(PR_FALSE, "missing url or sink");
 
   // disable timeouts before caching connection.
   if (m_transport)
     m_transport->SetTimeout(nsISocketTransport::TIMEOUT_READ_WRITE, PR_UINT32_MAX);
 
-// if we are set up as a channel, we should notify our channel listener that we are stopping...
-// so pass in ourself as the channel and not the underlying socket or file channel the protocol
-// happens to be using
-  if (m_channelListener)
-  {
-      nsCOMPtr<nsIRequest> request = do_QueryInterface(m_mockChannel);
-      NS_ASSERTION(request, "no request");
-      if (request) {
-        nsresult status;
-        request->GetStatus(&status);
-        rv = m_channelListener->OnStopRequest(request, m_channelContext, status);
-      }
-  }
   SetFlag(IMAP_CLEAN_UP_URL_STATE);
 
   nsCOMPtr <nsISupports> copyState;
   if (m_runningUrl)
     m_runningUrl->GetCopyState(getter_AddRefs(copyState));
   // this is so hokey...we MUST clear any local references to the url
   // BEFORE calling ReleaseUrlState
   mailnewsurl = nsnull;
--- a/mailnews/imap/test/unit/test_imapFilterActions.js
+++ b/mailnews/imap/test/unit/test_imapFilterActions.js
@@ -753,16 +753,17 @@ function testCounts(aHasNew, aUnreadDelt
   db().getNewList(countOut, arrayOut);
   let dbNew = countOut.value ? countOut.value : 0;
   let folderNewFlag = gIMAPInbox.getFlag(Ci.nsMsgFolderFlags.GotNew);
   dump(" hasNew: " + hasNew +
        " unread: " + unread +
        " folderNew: " + folderNew +
        " folderNewFlag: " + folderNewFlag +
        " dbNew: " + dbNew +
+       " prevUnread " + gPreviousUnread +
        "\n");
   do_check_eq(aHasNew, hasNew);
   do_check_eq(aUnreadDelta, unread - gPreviousUnread);
   gPreviousUnread = unread;
   // This seems to be reset for each folder update.
   //
   // This check seems to be failing in SeaMonkey builds, yet I can see no ill
   // effects of this in the actual program. Fixing this is complex because of
--- a/mailnews/import/applemail/src/nsAppleMailImport.cpp
+++ b/mailnews/import/applemail/src/nsAppleMailImport.cpp
@@ -46,16 +46,17 @@
 #include "nsIImportService.h"
 #include "nsIImportMailboxDescriptor.h"
 #include "nsIImportGeneric.h"
 #include "nsILocalFile.h"
 #include "nsIStringBundle.h"
 #include "nsIProxyObjectManager.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsNetUtil.h"
+#include "nsMsgUtils.h"
 
 #include "nsEmlxHelperUtils.h"
 #include "nsAppleMailImport.h"
 
 PRLogModuleInfo *APPLEMAILLOGMODULE = nsnull;
 
 // some hard-coded strings
 #define DEFAULT_MAIL_FOLDER "~/Library/Mail/"
@@ -562,17 +563,17 @@ NS_IMETHODIMP nsAppleMailImportMail::Imp
     if (NS_FAILED(rv)) {
       ReportStatus(APPLEMAILIMPORT_MAILBOX_CONVERTERROR, mailboxName, errorLog);
       SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
       return NS_ERROR_FAILURE;
     }
 
     // prepare an outstream to the destination file
     nsCOMPtr<nsIOutputStream> outStream;
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), aDestination);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(outStream), aDestination);
     if (!outStream || NS_FAILED(rv)) {
       ReportStatus(APPLEMAILIMPORT_MAILBOX_CONVERTERROR, mailboxName, errorLog);
       SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
       return NS_ERROR_FAILURE;
     }
 
     PRBool hasMore = PR_FALSE;
     while (NS_SUCCEEDED(directoryEnumerator->HasMoreElements(&hasMore)) && hasMore) {
--- a/mailnews/import/eudora/src/nsEudoraMailbox.cpp
+++ b/mailnews/import/eudora/src/nsEudoraMailbox.cpp
@@ -260,17 +260,17 @@ nsresult nsEudoraMailbox::ImportMailbox(
 
   // First, get the index file for this mailbox
   rv = FindTOCFile( pSrc, getter_AddRefs( tocFile), &deleteToc);
   if (NS_SUCCEEDED( rv) && tocFile)
         {
     IMPORT_LOG0( "Reading euroda toc file: ");
     DUMP_FILENAME( tocFile, PR_TRUE);
 
-                rv = NS_NewLocalFileOutputStream(getter_AddRefs(mailOutputStream), pDst);
+                rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mailOutputStream), pDst);
                 NS_ENSURE_SUCCESS(rv, rv);
     // Read the toc and import the messages
     rv = ImportMailboxUsingTOC( pBytes, pAbort, srcInputStream, tocFile, mailOutputStream, pMsgCount);
 
     // clean up
     if (deleteToc)
       DeleteFile( tocFile);
 
--- a/mailnews/import/oexpress/nsOE5File.cpp
+++ b/mailnews/import/oexpress/nsOE5File.cpp
@@ -277,17 +277,17 @@ nsresult nsOE5File::ImportMailbox( PRUin
   PRInt32    msgCount = 0;
   if (pCount)
     *pCount = 0;
 
   nsCOMPtr <nsIInputStream> inputStream;
   rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), inFile);
   if (NS_FAILED( rv)) return( rv);
   nsCOMPtr <nsIOutputStream> outputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), pDestination, -1, 0600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(outputStream), pDestination, -1, 0600);
   if (NS_FAILED( rv))
     return( rv);
 
   PRUint32 *  pIndex;
   PRUint32  indexSize;
   PRUint32 *  pFlags;
   PRUint64  *  pTime;
 
--- a/mailnews/import/oexpress/nsOEMailbox.cpp
+++ b/mailnews/import/oexpress/nsOEMailbox.cpp
@@ -38,16 +38,17 @@
 #include "nsOEMailbox.h"
 
 #include "OEDebugLog.h"
 #include "msgCore.h"
 #include "prprf.h"
 #include "nsMsgLocalFolderHdrs.h"
 #include "nsNetUtil.h"
 #include "nsISeekableStream.h"
+#include "nsMsgUtils.h"
 
 class CMbxScanner {
 public:
   CMbxScanner( nsString& name, nsIFile * mbxFile, nsIFile * dstFile);
   ~CMbxScanner();
 
   virtual PRBool  Initialize( void);
   virtual PRBool  DoWork( PRBool *pAbort, PRUint32 *pDone, PRUint32 *pCount);
@@ -242,17 +243,17 @@ PRBool CMbxScanner::Initialize( void)
 
   m_mbxFile->GetFileSize( &m_mbxFileSize);
   // open the mailbox file...
   if (NS_FAILED( NS_NewLocalFileInputStream(getter_AddRefs(m_mbxFileInputStream), m_mbxFile))) {
     CleanUp();
     return( PR_FALSE);
   }
 
-  if (NS_FAILED(NS_NewLocalFileOutputStream(getter_AddRefs(m_dstFileOutputStream), m_dstFile, -1, 0600))) {
+  if (NS_FAILED(MsgNewBufferedFileOutputStream(getter_AddRefs(m_dstFileOutputStream), m_dstFile, -1, 0600))) {
     CleanUp();
     return( PR_FALSE);
   }
 
   return( PR_TRUE);
 }
 
 
--- a/mailnews/import/outlook/src/nsOutlookMail.cpp
+++ b/mailnews/import/outlook/src/nsOutlookMail.cpp
@@ -421,17 +421,17 @@ nsresult nsOutlookMail::ImportMailbox( P
   int      attachCount;
   ULONG    totalCount;
   PRFloat64  doneCalc;
   nsCString  fromLine;
   int      fromLen;
   PRBool    lostAttach = PR_FALSE;
 
   nsCOMPtr<nsIOutputStream> destOutputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(destOutputStream), pDest, -1, 0600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(destOutputStream), pDest, -1, 0600);
   NS_ENSURE_SUCCESS(rv, rv);
 
   while (!done) {
     if (!contents.GetNext( &cbEid, &lpEid, &oType, &done)) {
       IMPORT_LOG1( "*** Error iterating mailbox: %S\n", pName);
       return( NS_ERROR_FAILURE);
     }
 
--- a/mailnews/import/src/ImportOutFile.cpp
+++ b/mailnews/import/src/ImportOutFile.cpp
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nscore.h"
 #include "nsStringGlue.h"
 #include "prio.h"
 #include "nsNetUtil.h"
 #include "nsISeekableStream.h"
+#include "nsMsgUtils.h"
 #include "ImportOutFile.h"
 #include "ImportCharSet.h"
 
 #include "ImportDebug.h"
 
 /*
 #ifdef _MAC
 #define  kMacNoCreator    '????'
@@ -138,17 +139,17 @@ PRBool ImportOutFile::InitOutFile( nsIFi
     bufSz = 32 * 1024;
   if (!m_pBuf) {
     m_pBuf = new PRUint8[ bufSz];
   }
 
   // m_fH = UFile::CreateFile( oFile, kMacNoCreator, kMacTextFile);
         if (!m_outputStream)
         {
-          nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_outputStream),
+          nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(m_outputStream),
                                    pFile,
                                    PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
                                    0644);
 
     if (NS_FAILED( rv))
                 {
       IMPORT_LOG0( "Couldn't create outfile\n");
       delete [] m_pBuf;
--- a/mailnews/import/src/Makefile.in
+++ b/mailnews/import/src/Makefile.in
@@ -50,16 +50,17 @@ ifndef MOZ_INCOMPLETE_EXTERNAL_LINKAGE
 MOZILLA_INTERNAL_API = 1
 endif
 
 REQUIRES	= xpcom \
 		  string \
 		  addrbook \
 		  uconv \
 		  msgbase \
+		  msgbaseutil \
 		  intl \
 		  necko \
 		  rdf \
 		  unicharutil \
 		  $(NULL)
 
 
 
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -1571,17 +1571,17 @@ nsMsgLocalMailFolder::InitCopyState(nsIS
   mCopyState->m_dataBuffer = (char*) PR_CALLOC(COPY_BUFFER_SIZE+1);
   NS_ENSURE_TRUE(mCopyState->m_dataBuffer, NS_ERROR_OUT_OF_MEMORY);
 
   mCopyState->m_dataBufferSize = COPY_BUFFER_SIZE;
   mCopyState->m_destDB = msgDB;
 
   //Before we continue we should verify that there is enough diskspace.
   //XXX How do we do this?
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs( mCopyState->m_fileStream), path, PR_WRONLY | PR_CREATE_FILE, 00600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mCopyState->m_fileStream), path, PR_WRONLY | PR_CREATE_FILE, 00600);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(mCopyState->m_fileStream);
   //The new key is the end of the file
   seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
   mCopyState->m_srcSupport = do_QueryInterface(aSupport, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   mCopyState->m_messages = messages;
   mCopyState->m_curCopyIndex = 0;
@@ -2599,26 +2599,35 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndC
   nsCOMPtr <nsISeekableStream> seekableStream;
   if (mCopyState)
   {
     NS_ASSERTION(mCopyState->m_leftOver == 0, "whoops, something wrong with previous copy");
     mCopyState->m_leftOver = 0; // reset to 0.
     // need to reset this in case we're move/copying multiple msgs.
     mCopyState->m_fromLineSeen = PR_FALSE;
 
-    // flush the copied message. Seeking causes a flush, w/o syncing. We need
-    // a flush+sync at the end to get the file size and time updated correctly.
+    // flush the copied message. We need a close at the end to get the
+    // file size and time updated correctly.
     if (mCopyState->m_fileStream)
     {
-      // we need this for the m_dummyEnvelopeNeeded code below.
       seekableStream = do_QueryInterface(mCopyState->m_fileStream);
+      if (mCopyState->m_dummyEnvelopeNeeded)
+      {
+        PRUint32 bytesWritten;
+        seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
+        mCopyState->m_fileStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &bytesWritten);
+        if (mCopyState->m_parseMsgState)
+          mCopyState->m_parseMsgState->ParseAFolderLine(CRLF, MSG_LINEBREAK_LEN);
+      }
+      // flush the copied message. We need a close at the end to get the
+      // file size and time updated correctly.
       if (multipleCopiesFinished)
-        mCopyState->m_fileStream->Flush();
+        mCopyState->m_fileStream->Close();
       else
-        seekableStream->Seek(nsISeekableStream::NS_SEEK_CUR, 0);
+        mCopyState->m_fileStream->Flush();
     }
   }
   //Copy the header to the new database
   if (copySucceeded && mCopyState->m_message)
   {
     //  CopyMessages() goes here, and CopyFileMessages() with metadata to save;
     nsCOMPtr<nsIMsgDBHdr> newHdr;
     if (!mCopyState->m_parseMsgState)
@@ -2654,25 +2663,16 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndC
         mCopyState->m_message->GetMessageKey(&aKey);
         mCopyState->m_message->GetStatusOffset(&statusOffset);
         localUndoTxn->AddSrcKey(aKey);
         localUndoTxn->AddSrcStatusOffset(statusOffset);
         localUndoTxn->AddDstKey(mCopyState->m_curDstKey);
       }
     }
   }
-  if (mCopyState->m_dummyEnvelopeNeeded)
-  {
-    PRUint32 bytesWritten;
-    seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
-    mCopyState->m_fileStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &bytesWritten);
-    if (mCopyState->m_parseMsgState)
-      mCopyState->m_parseMsgState->ParseAFolderLine(CRLF, MSG_LINEBREAK_LEN);
-  }
-
   nsCOMPtr<nsIMsgDBHdr> newHdr;
   // CopyFileMessage() and CopyMessages() from servers other than mailbox
   if (mCopyState->m_parseMsgState)
   {
     nsCOMPtr<nsIMsgDatabase> msgDb;
     mCopyState->m_parseMsgState->FinishHeader();
     GetDatabaseWOReparse(getter_AddRefs(msgDb));
     if (msgDb)
--- a/mailnews/local/src/nsMailboxProtocol.cpp
+++ b/mailnews/local/src/nsMailboxProtocol.cpp
@@ -60,16 +60,17 @@
 #include "nspr.h"
 
 PRLogModuleInfo *MAILBOX;
 #include "nsIFileStreams.h"
 #include "nsIStreamTransportService.h"
 #include "nsIStreamConverterService.h"
 #include "nsIIOService.h"
 #include "nsNetUtil.h"
+#include "nsMsgUtils.h"
 #include "nsIMsgWindow.h"
 #include "nsIMimeHeaders.h"
 
 #include "nsIMsgMdnGenerator.h"
 
 /* the output_buffer_size must be larger than the largest possible line
  * 2000 seems good for news
  *
@@ -499,17 +500,17 @@ nsresult nsMailboxProtocol::LoadUrl(nsIU
           // to be the name of our save message to disk file. Since save message to disk
           // urls are run without a docshell to display the msg into, we won't be trying
           // to display the message after we write it to disk...
           {
             nsCOMPtr<nsIMsgMessageUrl> messageUrl = do_QueryInterface(m_runningUrl, &rv);
             if (NS_SUCCEEDED(rv))
             {
               messageUrl->GetMessageFile(getter_AddRefs(m_tempMessageFile));
-              NS_NewLocalFileOutputStream(getter_AddRefs(m_msgFileOutputStream), m_tempMessageFile, -1, 00600);
+              MsgNewBufferedFileOutputStream(getter_AddRefs(m_msgFileOutputStream), m_tempMessageFile, -1, 00600);
 
               PRBool addDummyEnvelope = PR_FALSE;
               messageUrl->GetAddDummyEnvelope(&addDummyEnvelope);
               if (addDummyEnvelope)
                 SetFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
               else
                 ClearFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
             }
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -2359,17 +2359,17 @@ nsresult nsParseNewMailState::EndMsgDown
 nsresult nsParseNewMailState::AppendMsgFromFile(nsIInputStream *fileStream,
                                                 PRUint32 offset, PRUint32 length,
                                                 nsILocalFile *destFile)
 {
   nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(fileStream);
   seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
 
   nsCOMPtr <nsIOutputStream> destFileStream;
-  NS_NewLocalFileOutputStream(getter_AddRefs(destFileStream), destFile, PR_RDWR | PR_CREATE_FILE, 00600);
+  MsgNewBufferedFileOutputStream(getter_AddRefs(destFileStream), destFile, PR_RDWR | PR_CREATE_FILE, 00600);
 
   if (!destFileStream)
   {
 #ifdef DEBUG_bienvenu
     NS_ASSERTION(PR_FALSE, "out of memory");
 #endif
     return  NS_MSG_ERROR_WRITING_MAIL_FOLDER;
   }
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -368,17 +368,17 @@ net_pop3_write_state(Pop3UidlHost* host,
 
   mailDirectory->Clone(getter_AddRefs(clonedDirectory));
   if (!clonedDirectory)
     return;
   nsCOMPtr <nsILocalFile> popState = do_QueryInterface(clonedDirectory);
   popState->AppendNative(NS_LITERAL_CSTRING("popstate.dat"));
 
   nsCOMPtr<nsIOutputStream> fileOutputStream;
-  nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOutputStream), popState, -1, 00600);
+  nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(fileOutputStream), popState, -1, 00600);
   if (NS_FAILED(rv))
     return;
 
   const char tmpBuffer[] =
     "# POP3 State File" MSG_LINEBREAK
     "# This is a generated file!  Do not edit." MSG_LINEBREAK
     MSG_LINEBREAK;
 
--- a/mailnews/mime/src/mimedrft.cpp
+++ b/mailnews/mime/src/mimedrft.cpp
@@ -1944,17 +1944,17 @@ mime_decompose_file_init_fn ( void *stre
   PR_FREEIF(workURLSpec);
   if (!tmpFile)
     return MIME_OUT_OF_MEMORY;
 
   mdd->tmpFile = do_QueryInterface(tmpFile);
 
   newAttachment->tmp_file = mdd->tmpFile;
 
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(mdd->tmpFileStream), tmpFile,PR_WRONLY | PR_CREATE_FILE, 00600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mdd->tmpFileStream), tmpFile,PR_WRONLY | PR_CREATE_FILE, 00600);
   if (NS_FAILED(rv))
     return MIME_UNABLE_TO_OPEN_TMP_FILE;
 
   // For now, we are always going to decode all of the attachments
   // for the message. This way, we have native data
   if (creatingMsgBody)
   {
     MimeDecoderData *(*fn) (nsresult (*) (const char*, PRInt32, void*), void*) = 0;
--- a/mailnews/mime/src/mimemrel.cpp
+++ b/mailnews/mime/src/mimemrel.cpp
@@ -672,17 +672,17 @@ MimeMultipartRelated_parse_child_line (M
      make a file buffer. */
   if (!relobj->head_buffer && !relobj->file_buffer)
   {
     nsCOMPtr <nsIFile> file;
     rv = nsMsgCreateTempFile("nsma", getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
     relobj->file_buffer = do_QueryInterface(file);
 
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(relobj->output_file_stream), relobj->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(relobj->output_file_stream), relobj->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   PR_ASSERT(relobj->head_buffer || relobj->output_file_stream);
 
 
   /* If this line will fit in the memory buffer, put it there.
    */
@@ -700,17 +700,17 @@ MimeMultipartRelated_parse_child_line (M
       if (!relobj->file_buffer)
       {
         nsCOMPtr <nsIFile> file;
         rv = nsMsgCreateTempFile("nsma", getter_AddRefs(file));
         NS_ENSURE_SUCCESS(rv, rv);
         relobj->file_buffer = do_QueryInterface(file);
       }
 
-      nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(relobj->output_file_stream), relobj->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
+      nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(relobj->output_file_stream), relobj->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (relobj->head_buffer && relobj->head_buffer_fp)
       {
         PRUint32 bytesWritten;
         status = relobj->output_file_stream->Write(relobj->head_buffer,
                                                    relobj->head_buffer_fp,
                                                    &bytesWritten);
--- a/mailnews/mime/src/mimepbuf.cpp
+++ b/mailnews/mime/src/mimepbuf.cpp
@@ -37,16 +37,17 @@
 #include "nsCOMPtr.h"
 #include "mimepbuf.h"
 #include "mimemoz2.h"
 #include "prmem.h"
 #include "prio.h"
 #include "plstr.h"
 #include "nsMimeStringResources.h"
 #include "nsNetUtil.h"
+#include "nsMsgUtils.h"
 //
 // External Defines...
 //
 extern nsresult
 nsMsgCreateTempFile(const char *tFileName, nsIFile **tFile);
 
 /* See mimepbuf.h for a description of the mission of this file.
 
@@ -196,17 +197,17 @@ MimePartBufferWrite (MimePartBufferData 
     make a file buffer. */
   if (!data->part_buffer && !data->file_buffer)
   {
     nsCOMPtr <nsIFile> tmpFile;
     nsresult rv = nsMsgCreateTempFile("nsma", getter_AddRefs(tmpFile));
     NS_ENSURE_SUCCESS(rv, MIME_UNABLE_TO_OPEN_TMP_FILE);
     data->file_buffer = do_QueryInterface(tmpFile);
 
-    rv = NS_NewLocalFileOutputStream(getter_AddRefs( data->output_file_stream), data->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
+    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(data->output_file_stream), data->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ASSERTION(data->part_buffer || data->output_file_stream, "no part_buffer or file_stream");
 
   /* If this buf will fit in the memory buffer, put it there.
     */
   if (data->part_buffer &&
@@ -229,17 +230,17 @@ MimePartBufferWrite (MimePartBufferData 
       {
         nsCOMPtr <nsIFile> tmpFile;
         rv = nsMsgCreateTempFile("nsma", getter_AddRefs(tmpFile));
         NS_ENSURE_SUCCESS(rv, MIME_UNABLE_TO_OPEN_TMP_FILE);
         data->file_buffer = do_QueryInterface(tmpFile);
 
       }
 
-      rv = NS_NewLocalFileOutputStream(getter_AddRefs( data->output_file_stream), data->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
+      rv = MsgNewBufferedFileOutputStream(getter_AddRefs(data->output_file_stream), data->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
       NS_ENSURE_SUCCESS(rv, MIME_UNABLE_TO_OPEN_TMP_FILE);
 
       if (data->part_buffer && data->part_buffer_fp)
       {
         PRUint32 bytesWritten;
         nsresult rv = data->output_file_stream->Write(data->part_buffer,
                                                  data->part_buffer_fp, &bytesWritten);
         NS_ENSURE_SUCCESS(rv, rv);
--- a/mailnews/news/src/nsNntpIncomingServer.cpp
+++ b/mailnews/news/src/nsNntpIncomingServer.cpp
@@ -337,17 +337,17 @@ nsNntpIncomingServer::WriteNewsrcFile()
 #ifdef DEBUG_NEWS
         printf("write newsrc file for %s\n", hostname.get());
 #endif
         nsCOMPtr <nsILocalFile> newsrcFile;
         rv = GetNewsrcFilePath(getter_AddRefs(newsrcFile));
         if (NS_FAILED(rv)) return rv;
 
         nsCOMPtr<nsIOutputStream> newsrcStream;
-        nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(newsrcStream), newsrcFile, -1, 00600);
+        nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(newsrcStream), newsrcFile, -1, 00600);
         if (NS_FAILED(rv))
           return rv;
 
         nsCOMPtr<nsISimpleEnumerator> subFolders;
         nsCOMPtr<nsIMsgFolder> rootFolder;
         rv = GetRootFolder(getter_AddRefs(rootFolder));
         if (NS_FAILED(rv)) return rv;
 
@@ -835,17 +835,17 @@ nsNntpIncomingServer::WriteHostInfoFile(
 
   nsCString hostname;
   nsresult rv = GetHostName(hostname);
   NS_ENSURE_SUCCESS(rv,rv);
 
   if (!mHostInfoFile)
     return NS_ERROR_UNEXPECTED;
   nsCOMPtr<nsIOutputStream> hostInfoStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(hostInfoStream), mHostInfoFile, -1, 00600);
+  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(hostInfoStream), mHostInfoFile, -1, 00600);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // todo, missing some formatting, see the 4.x code
   nsCAutoString header("# News host information file.");
   WriteLine(hostInfoStream, header);
   header.Assign("# This is a generated file!  Do not edit.");
   WriteLine(hostInfoStream, header);
   header.Truncate();