summaryrefslogtreecommitdiffstats
path: root/mailnews/import/src/ImportOutFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/import/src/ImportOutFile.cpp')
-rw-r--r--mailnews/import/src/ImportOutFile.cpp299
1 files changed, 299 insertions, 0 deletions
diff --git a/mailnews/import/src/ImportOutFile.cpp b/mailnews/import/src/ImportOutFile.cpp
new file mode 100644
index 000000000..beeb8903a
--- /dev/null
+++ b/mailnews/import/src/ImportOutFile.cpp
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "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 '????'
+#define kMacTextFile 'TEXT'
+#else
+#define kMacNoCreator 0
+#define kMacTextFile 0
+#endif
+*/
+
+ImportOutFile::ImportOutFile()
+{
+ m_ownsFileAndBuffer = false;
+ m_pos = 0;
+ m_pBuf = nullptr;
+ m_bufSz = 0;
+ m_pTrans = nullptr;
+ m_pTransOut = nullptr;
+ m_pTransBuf = nullptr;
+}
+
+ImportOutFile::ImportOutFile(nsIFile *pFile, uint8_t * pBuf, uint32_t sz)
+{
+ m_pTransBuf = nullptr;
+ m_pTransOut = nullptr;
+ m_pTrans = nullptr;
+ m_ownsFileAndBuffer = false;
+ InitOutFile(pFile, pBuf, sz);
+}
+
+ImportOutFile::~ImportOutFile()
+{
+ if (m_ownsFileAndBuffer)
+ {
+ Flush();
+ delete [] m_pBuf;
+ }
+
+ delete m_pTrans;
+ delete m_pTransOut;
+ delete [] m_pTransBuf;
+}
+
+bool ImportOutFile::Set8bitTranslator(nsImportTranslator *pTrans)
+{
+ if (!Flush())
+ return false;
+
+ m_engaged = false;
+ m_pTrans = pTrans;
+ m_supports8to7 = pTrans->Supports8bitEncoding();
+
+
+ return true;
+}
+
+bool ImportOutFile::End8bitTranslation(bool *pEngaged, nsCString& useCharset, nsCString& encoding)
+{
+ if (!m_pTrans)
+ return false;
+
+
+ bool bResult = Flush();
+ if (m_supports8to7 && m_pTransOut) {
+ if (bResult)
+ bResult = m_pTrans->FinishConvertToFile(m_pTransOut);
+ if (bResult)
+ bResult = Flush();
+ }
+
+ if (m_supports8to7) {
+ m_pTrans->GetCharset(useCharset);
+ m_pTrans->GetEncoding(encoding);
+ }
+ else
+ useCharset.Truncate();
+ *pEngaged = m_engaged;
+ delete m_pTrans;
+ m_pTrans = nullptr;
+ delete m_pTransOut;
+ m_pTransOut = nullptr;
+ delete [] m_pTransBuf;
+ m_pTransBuf = nullptr;
+
+ return bResult;
+}
+
+bool ImportOutFile::InitOutFile(nsIFile *pFile, uint32_t bufSz)
+{
+ if (!bufSz)
+ bufSz = 32 * 1024;
+ if (!m_pBuf)
+ m_pBuf = new uint8_t[ bufSz];
+
+ if (!m_outputStream)
+ {
+ nsresult rv;
+ 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;
+ m_pBuf = nullptr;
+ return false;
+ }
+ }
+ m_pFile = pFile;
+ m_ownsFileAndBuffer = true;
+ m_pos = 0;
+ m_bufSz = bufSz;
+ return true;
+}
+
+void ImportOutFile::InitOutFile(nsIFile *pFile, uint8_t * pBuf, uint32_t sz)
+{
+ m_ownsFileAndBuffer = false;
+ m_pFile = pFile;
+ m_pBuf = pBuf;
+ m_bufSz = sz;
+ m_pos = 0;
+}
+
+
+
+bool ImportOutFile::Flush(void)
+{
+ if (!m_pos)
+ return true;
+
+ uint32_t transLen;
+ bool duddleyDoWrite = false;
+
+ // handle translations if appropriate
+ if (m_pTrans) {
+ if (m_engaged && m_supports8to7) {
+ // Markers can get confused by this crap!!!
+ // TLR: FIXME: Need to update the markers based on
+ // the difference between the translated len and untranslated len
+
+ if (!m_pTrans->ConvertToFile( m_pBuf, m_pos, m_pTransOut, &transLen))
+ return false;
+ if (!m_pTransOut->Flush())
+ return false;
+ // now update our buffer...
+ if (transLen < m_pos) {
+ memcpy(m_pBuf, m_pBuf + transLen, m_pos - transLen);
+ }
+ m_pos -= transLen;
+ }
+ else if (m_engaged) {
+ // does not actually support translation!
+ duddleyDoWrite = true;
+ }
+ else {
+ // should we engage?
+ uint8_t * pChar = m_pBuf;
+ uint32_t len = m_pos;
+ while (len) {
+ if (!ImportCharSet::IsUSAscii(*pChar))
+ break;
+ pChar++;
+ len--;
+ }
+ if (len) {
+ m_engaged = true;
+ if (m_supports8to7) {
+ // allocate our translation output buffer and file...
+ m_pTransBuf = new uint8_t[m_bufSz];
+ m_pTransOut = new ImportOutFile(m_pFile, m_pTransBuf, m_bufSz);
+ return Flush();
+ }
+ else
+ duddleyDoWrite = true;
+ }
+ else {
+ duddleyDoWrite = true;
+ }
+ }
+ }
+ else
+ duddleyDoWrite = true;
+
+ if (duddleyDoWrite) {
+ uint32_t written = 0;
+ nsresult rv = m_outputStream->Write((const char *)m_pBuf, (int32_t)m_pos, &written);
+ if (NS_FAILED(rv) || ((uint32_t)written != m_pos))
+ return false;
+ m_pos = 0;
+ }
+
+ return true;
+}
+
+bool ImportOutFile::WriteU8NullTerm(const uint8_t * pSrc, bool includeNull)
+{
+ while (*pSrc) {
+ if (m_pos >= m_bufSz) {
+ if (!Flush())
+ return false;
+ }
+ *(m_pBuf + m_pos) = *pSrc;
+ m_pos++;
+ pSrc++;
+ }
+ if (includeNull) {
+ if (m_pos >= m_bufSz) {
+ if (!Flush())
+ return false;
+ }
+ *(m_pBuf + m_pos) = 0;
+ m_pos++;
+ }
+
+ return true;
+}
+
+bool ImportOutFile::SetMarker(int markerID)
+{
+ if (!Flush()) {
+ return false;
+ }
+
+ if (markerID < kMaxMarkers) {
+ int64_t pos = 0;
+ if (m_outputStream)
+ {
+ // do we need to flush for the seek to give us the right pos?
+ m_outputStream->Flush();
+ nsresult rv;
+ nsCOMPtr <nsISeekableStream> seekStream = do_QueryInterface(m_outputStream, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+ rv = seekStream->Tell(&pos);
+ if (NS_FAILED(rv)) {
+ IMPORT_LOG0("*** Error, Tell failed on output stream\n");
+ return false;
+ }
+ }
+ m_markers[markerID] = (uint32_t)pos + m_pos;
+ }
+
+ return true;
+}
+
+void ImportOutFile::ClearMarker(int markerID)
+{
+ if (markerID < kMaxMarkers)
+ m_markers[markerID] = 0;
+}
+
+bool ImportOutFile::WriteStrAtMarker(int markerID, const char *pStr)
+{
+ if (markerID >= kMaxMarkers)
+ return false;
+
+ if (!Flush())
+ return false;
+ int64_t pos;
+ m_outputStream->Flush();
+ nsresult rv;
+ nsCOMPtr <nsISeekableStream> seekStream = do_QueryInterface(m_outputStream, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+ rv = seekStream->Tell(&pos);
+ if (NS_FAILED(rv))
+ return false;
+ rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, (int32_t) m_markers[markerID]);
+ if (NS_FAILED(rv))
+ return false;
+ uint32_t written;
+ rv = m_outputStream->Write(pStr, strlen(pStr), &written);
+ if (NS_FAILED(rv))
+ return false;
+
+ rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, pos);
+ if (NS_FAILED(rv))
+ return false;
+
+ return true;
+}
+