summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/import/src/nsImportTranslator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/import/src/nsImportTranslator.cpp')
-rw-r--r--comm/mailnews/import/src/nsImportTranslator.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/comm/mailnews/import/src/nsImportTranslator.cpp b/comm/mailnews/import/src/nsImportTranslator.cpp
new file mode 100644
index 0000000000..f988e7035d
--- /dev/null
+++ b/comm/mailnews/import/src/nsImportTranslator.cpp
@@ -0,0 +1,308 @@
+/* -*- 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 "ImportOutFile.h"
+#include "nsImportTranslator.h"
+
+#include "ImportCharSet.h"
+
+bool nsImportTranslator::ConvertToFile(const uint8_t* pIn, uint32_t inLen,
+ ImportOutFile* pOutFile,
+ uint32_t* pProcessed) {
+ if (pProcessed) *pProcessed = inLen;
+ return (pOutFile->WriteData(pIn, inLen));
+}
+
+void CMHTranslator::ConvertBuffer(const uint8_t* pIn, uint32_t inLen,
+ uint8_t* pOut) {
+ while (inLen) {
+ if (!ImportCharSet::IsUSAscii(*pIn) ||
+ ImportCharSet::Is822SpecialChar(*pIn) ||
+ ImportCharSet::Is822CtlChar(*pIn) ||
+ (*pIn == ImportCharSet::cSpaceChar) || (*pIn == '*') ||
+ (*pIn == '\'') || (*pIn == '%')) {
+ // needs to be encode as %hex val
+ *pOut = '%';
+ pOut++;
+ ImportCharSet::ByteToHex(*pIn, pOut);
+ pOut += 2;
+ } else {
+ *pOut = *pIn;
+ pOut++;
+ }
+ pIn++;
+ inLen--;
+ }
+ *pOut = 0;
+}
+
+bool CMHTranslator::ConvertToFile(const uint8_t* pIn, uint32_t inLen,
+ ImportOutFile* pOutFile,
+ uint32_t* pProcessed) {
+ uint8_t hex[2];
+ while (inLen) {
+ if (!ImportCharSet::IsUSAscii(*pIn) ||
+ ImportCharSet::Is822SpecialChar(*pIn) ||
+ ImportCharSet::Is822CtlChar(*pIn) ||
+ (*pIn == ImportCharSet::cSpaceChar) || (*pIn == '*') ||
+ (*pIn == '\'') || (*pIn == '%')) {
+ // needs to be encode as %hex val
+ if (!pOutFile->WriteByte('%')) return false;
+ ImportCharSet::ByteToHex(*pIn, hex);
+ if (!pOutFile->WriteData(hex, 2)) return false;
+ } else {
+ if (!pOutFile->WriteByte(*pIn)) return false;
+ }
+ pIn++;
+ inLen--;
+ }
+
+ if (pProcessed) *pProcessed = inLen;
+
+ return true;
+}
+
+bool C2047Translator::ConvertToFileQ(const uint8_t* pIn, uint32_t inLen,
+ ImportOutFile* pOutFile,
+ uint32_t* pProcessed) {
+ if (!inLen) return true;
+
+ int maxLineLen = 64;
+ int curLineLen = m_startLen;
+ bool startLine = true;
+
+ uint8_t hex[2];
+ while (inLen) {
+ if (startLine) {
+ if (!pOutFile->WriteStr(" =?")) return false;
+ if (!pOutFile->WriteStr(m_charset.get())) return false;
+ if (!pOutFile->WriteStr("?q?")) return false;
+ curLineLen += (6 + m_charset.Length());
+ startLine = false;
+ }
+
+ if (!ImportCharSet::IsUSAscii(*pIn) ||
+ ImportCharSet::Is822SpecialChar(*pIn) ||
+ ImportCharSet::Is822CtlChar(*pIn) ||
+ (*pIn == ImportCharSet::cSpaceChar) || (*pIn == '?') || (*pIn == '=')) {
+ // needs to be encode as =hex val
+ if (!pOutFile->WriteByte('=')) return false;
+ ImportCharSet::ByteToHex(*pIn, hex);
+ if (!pOutFile->WriteData(hex, 2)) return false;
+ curLineLen += 3;
+ } else {
+ if (!pOutFile->WriteByte(*pIn)) return false;
+ curLineLen++;
+ }
+ pIn++;
+ inLen--;
+ if (curLineLen > maxLineLen) {
+ if (!pOutFile->WriteStr("?=")) return false;
+ if (inLen) {
+ if (!pOutFile->WriteStr("\x0D\x0A ")) return false;
+ }
+
+ startLine = true;
+ curLineLen = 0;
+ }
+ }
+
+ if (!startLine) {
+ // end the encoding!
+ if (!pOutFile->WriteStr("?=")) return false;
+ }
+
+ if (pProcessed) *pProcessed = inLen;
+
+ return true;
+}
+
+bool C2047Translator::ConvertToFile(const uint8_t* pIn, uint32_t inLen,
+ ImportOutFile* pOutFile,
+ uint32_t* pProcessed) {
+ if (m_useQuotedPrintable)
+ return ConvertToFileQ(pIn, inLen, pOutFile, pProcessed);
+
+ if (!inLen) return true;
+
+ int maxLineLen = 64;
+ int curLineLen = m_startLen;
+ bool startLine = true;
+ int encodeMax;
+ uint8_t* pEncoded = new uint8_t[maxLineLen * 2];
+
+ while (inLen) {
+ if (startLine) {
+ if (!pOutFile->WriteStr(" =?")) {
+ delete[] pEncoded;
+ return false;
+ }
+ if (!pOutFile->WriteStr(m_charset.get())) {
+ delete[] pEncoded;
+ return false;
+ }
+ if (!pOutFile->WriteStr("?b?")) {
+ delete[] pEncoded;
+ return false;
+ }
+ curLineLen += (6 + m_charset.Length());
+ startLine = false;
+ }
+ encodeMax = maxLineLen - curLineLen;
+ encodeMax *= 3;
+ encodeMax /= 4;
+ if ((uint32_t)encodeMax > inLen) encodeMax = (int)inLen;
+
+ // encode the line, end the line
+ // then continue. Update curLineLen, pIn, startLine, and inLen
+ UMimeEncode::ConvertBuffer(pIn, encodeMax, pEncoded, maxLineLen, maxLineLen,
+ "\x0D\x0A");
+
+ if (!pOutFile->WriteStr((const char*)pEncoded)) {
+ delete[] pEncoded;
+ return false;
+ }
+
+ pIn += encodeMax;
+ inLen -= encodeMax;
+ startLine = true;
+ curLineLen = 0;
+ if (!pOutFile->WriteStr("?=")) {
+ delete[] pEncoded;
+ return false;
+ }
+ if (inLen) {
+ if (!pOutFile->WriteStr("\x0D\x0A ")) {
+ delete[] pEncoded;
+ return false;
+ }
+ }
+ }
+
+ delete[] pEncoded;
+
+ if (pProcessed) *pProcessed = inLen;
+
+ return true;
+}
+
+uint32_t UMimeEncode::GetBufferSize(uint32_t inBytes) {
+ // it takes 4 base64 bytes to represent 3 regular bytes
+ inBytes += 3;
+ inBytes /= 3;
+ inBytes *= 4;
+ // This should be plenty, but just to be safe
+ inBytes += 4;
+
+ // now allow for end of line characters
+ inBytes += ((inBytes + 39) / 40) * 4;
+
+ return inBytes;
+}
+
+static uint8_t gBase64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+uint32_t UMimeEncode::ConvertBuffer(const uint8_t* pIn, uint32_t inLen,
+ uint8_t* pOut, uint32_t maxLen,
+ uint32_t firstLineLen,
+ const char* pEolStr) {
+ uint32_t pos = 0;
+ uint32_t len = 0;
+ uint32_t lineLen = 0;
+ uint32_t maxLine = firstLineLen;
+ int eolLen = 0;
+ if (pEolStr) eolLen = strlen(pEolStr);
+
+ while ((pos + 2) < inLen) {
+ // Encode 3 bytes
+ *pOut = gBase64[*pIn >> 2];
+ pOut++;
+ len++;
+ lineLen++;
+ *pOut = gBase64[(((*pIn) & 0x3) << 4) | (((*(pIn + 1)) & 0xF0) >> 4)];
+ pIn++;
+ pOut++;
+ len++;
+ lineLen++;
+ *pOut = gBase64[(((*pIn) & 0xF) << 2) | (((*(pIn + 1)) & 0xC0) >> 6)];
+ pIn++;
+ pOut++;
+ len++;
+ lineLen++;
+ *pOut = gBase64[(*pIn) & 0x3F];
+ pIn++;
+ pOut++;
+ len++;
+ lineLen++;
+ pos += 3;
+ if (lineLen >= maxLine) {
+ lineLen = 0;
+ maxLine = maxLen;
+ if (pEolStr) {
+ memcpy(pOut, pEolStr, eolLen);
+ pOut += eolLen;
+ len += eolLen;
+ }
+ }
+ }
+
+ if ((pos < inLen) && ((lineLen + 3) > maxLine)) {
+ lineLen = 0;
+ maxLine = maxLen;
+ if (pEolStr) {
+ memcpy(pOut, pEolStr, eolLen);
+ pOut += eolLen;
+ len += eolLen;
+ }
+ }
+
+ if (pos < inLen) {
+ // Get the last few bytes!
+ *pOut = gBase64[*pIn >> 2];
+ pOut++;
+ len++;
+ pos++;
+ if (pos < inLen) {
+ *pOut = gBase64[(((*pIn) & 0x3) << 4) | (((*(pIn + 1)) & 0xF0) >> 4)];
+ pIn++;
+ pOut++;
+ pos++;
+ len++;
+ if (pos < inLen) {
+ // Should be dead code!! (Then why is it here doofus?)
+ *pOut = gBase64[(((*pIn) & 0xF) << 2) | (((*(pIn + 1)) & 0xC0) >> 6)];
+ pIn++;
+ pOut++;
+ len++;
+ *pOut = gBase64[(*pIn) & 0x3F];
+ pos++;
+ pOut++;
+ len++;
+ } else {
+ *pOut = gBase64[(((*pIn) & 0xF) << 2)];
+ pOut++;
+ len++;
+ *pOut = '=';
+ pOut++;
+ len++;
+ }
+ } else {
+ *pOut = gBase64[(((*pIn) & 0x3) << 4)];
+ pOut++;
+ len++;
+ *pOut = '=';
+ pOut++;
+ len++;
+ *pOut = '=';
+ pOut++;
+ len++;
+ }
+ }
+
+ *pOut = 0;
+
+ return len;
+}