Backout part of 2f79b0b939ed that's unrelated. a=Standard8
/* -*- 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;
}