diff options
Diffstat (limited to 'mailnews/import/src/ImportOutFile.cpp')
-rw-r--r-- | mailnews/import/src/ImportOutFile.cpp | 299 |
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; +} + |