diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mailnews/import/src/ImportOutFile.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mailnews/import/src/ImportOutFile.cpp')
-rw-r--r-- | comm/mailnews/import/src/ImportOutFile.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/comm/mailnews/import/src/ImportOutFile.cpp b/comm/mailnews/import/src/ImportOutFile.cpp new file mode 100644 index 0000000000..3622b56ad7 --- /dev/null +++ b/comm/mailnews/import/src/ImportOutFile.cpp @@ -0,0 +1,257 @@ +/* -*- 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 "nscore.h" +#include "nsString.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; +} |