From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- comm/mailnews/intl/nsUnicodeToUTF7.cpp | 302 +++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 comm/mailnews/intl/nsUnicodeToUTF7.cpp (limited to 'comm/mailnews/intl/nsUnicodeToUTF7.cpp') diff --git a/comm/mailnews/intl/nsUnicodeToUTF7.cpp b/comm/mailnews/intl/nsUnicodeToUTF7.cpp new file mode 100644 index 0000000000..ab9d1cf895 --- /dev/null +++ b/comm/mailnews/intl/nsUnicodeToUTF7.cpp @@ -0,0 +1,302 @@ +/* -*- 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 "nsUnicodeToUTF7.h" +#include + +//---------------------------------------------------------------------- +// Global functions and data [declaration] + +#define ENC_DIRECT 0 +#define ENC_BASE64 1 + +//---------------------------------------------------------------------- +// Class nsBasicUTF7Encoder [implementation] + +nsBasicUTF7Encoder::nsBasicUTF7Encoder(char aLastChar, char aEscChar) { + mLastChar = aLastChar; + mEscChar = aEscChar; + Reset(); +} + +nsresult nsBasicUTF7Encoder::ShiftEncoding(int32_t aEncoding, char* aDest, + int32_t* aDestLength) { + if (aEncoding == mEncoding) { + *aDestLength = 0; + return NS_OK; + } + + nsresult res = NS_OK; + char* dest = aDest; + char* destEnd = aDest + *aDestLength; + + if (mEncStep != 0) { + if (dest >= destEnd) return NS_OK_UENC_MOREOUTPUT; + *(dest++) = ValueToChar(mEncBits); + mEncStep = 0; + mEncBits = 0; + } + + if (dest >= destEnd) { + res = NS_OK_UENC_MOREOUTPUT; + } else { + switch (aEncoding) { + case 0: + *(dest++) = '-'; + mEncStep = 0; + mEncBits = 0; + break; + case 1: + *(dest++) = mEscChar; + break; + } + mEncoding = aEncoding; + } + + *aDestLength = dest - aDest; + return res; +} + +nsresult nsBasicUTF7Encoder::EncodeDirect(const char16_t* aSrc, + int32_t* aSrcLength, char* aDest, + int32_t* aDestLength) { + nsresult res = NS_OK; + const char16_t* src = aSrc; + const char16_t* srcEnd = aSrc + *aSrcLength; + char* dest = aDest; + char* destEnd = aDest + *aDestLength; + char16_t ch; + + while (src < srcEnd) { + ch = *src; + + // stop when we reach Unicode chars + if (!DirectEncodable(ch)) break; + + if (ch == mEscChar) { + // special case for the escape char + if (destEnd - dest < 1) { + res = NS_OK_UENC_MOREOUTPUT; + break; + } else { + *dest++ = (char)ch; + *dest++ = (char)'-'; + src++; + } + } else { + // classic direct encoding + if (dest >= destEnd) { + res = NS_OK_UENC_MOREOUTPUT; + break; + } else { + *dest++ = (char)ch; + src++; + } + } + } + + *aSrcLength = src - aSrc; + *aDestLength = dest - aDest; + return res; +} + +nsresult nsBasicUTF7Encoder::EncodeBase64(const char16_t* aSrc, + int32_t* aSrcLength, char* aDest, + int32_t* aDestLength) { + nsresult res = NS_OK; + const char16_t* src = aSrc; + const char16_t* srcEnd = aSrc + *aSrcLength; + char* dest = aDest; + char* destEnd = aDest + *aDestLength; + char16_t ch; + uint32_t value; + + while (src < srcEnd) { + ch = *src; + + // stop when we reach printable US-ASCII chars + if (DirectEncodable(ch)) break; + + switch (mEncStep) { + case 0: + if (destEnd - dest < 2) { + res = NS_OK_UENC_MOREOUTPUT; + break; + } + value = ch >> 10; + *(dest++) = ValueToChar(value); + value = (ch >> 4) & 0x3f; + *(dest++) = ValueToChar(value); + mEncBits = (ch & 0x0f) << 2; + break; + case 1: + if (destEnd - dest < 3) { + res = NS_OK_UENC_MOREOUTPUT; + break; + } + value = mEncBits + (ch >> 14); + *(dest++) = ValueToChar(value); + value = (ch >> 8) & 0x3f; + *(dest++) = ValueToChar(value); + value = (ch >> 2) & 0x3f; + *(dest++) = ValueToChar(value); + mEncBits = (ch & 0x03) << 4; + break; + case 2: + if (destEnd - dest < 3) { + res = NS_OK_UENC_MOREOUTPUT; + break; + } + value = mEncBits + (ch >> 12); + *(dest++) = ValueToChar(value); + value = (ch >> 6) & 0x3f; + *(dest++) = ValueToChar(value); + value = ch & 0x3f; + *(dest++) = ValueToChar(value); + mEncBits = 0; + break; + } + + if (res != NS_OK) break; + + src++; + (++mEncStep) %= 3; + } + + *aSrcLength = src - aSrc; + *aDestLength = dest - aDest; + return res; +} + +char nsBasicUTF7Encoder::ValueToChar(uint32_t aValue) { + if (aValue < 26) + return (char)('A' + aValue); + else if (aValue < 26 + 26) + return (char)('a' + aValue - 26); + else if (aValue < 26 + 26 + 10) + return (char)('0' + aValue - 26 - 26); + else if (aValue == 26 + 26 + 10) + return '+'; + else if (aValue == 26 + 26 + 10 + 1) + return mLastChar; + else + return -1; +} + +bool nsBasicUTF7Encoder::DirectEncodable(char16_t aChar) { + // spec says: printable US-ASCII chars + if ((aChar >= 0x20) && (aChar <= 0x7e)) + return true; + else + return false; +} + +//---------------------------------------------------------------------- +// Subclassing of nsEncoderSupport class [implementation] + +NS_IMETHODIMP nsBasicUTF7Encoder::ConvertNoBuffNoErr(const char16_t* aSrc, + int32_t* aSrcLength, + char* aDest, + int32_t* aDestLength) { + nsresult res = NS_OK; + const char16_t* src = aSrc; + const char16_t* srcEnd = aSrc + *aSrcLength; + char* dest = aDest; + char* destEnd = aDest + *aDestLength; + int32_t bcr, bcw; + char16_t ch; + int32_t enc; + + while (src < srcEnd) { + // find the encoding for the next char + ch = *src; + if (DirectEncodable(ch)) + enc = ENC_DIRECT; + else + enc = ENC_BASE64; + + // if necessary, shift into the required encoding + bcw = destEnd - dest; + res = ShiftEncoding(enc, dest, &bcw); + dest += bcw; + if (res != NS_OK) break; + + // now encode (as much as you can) + bcr = srcEnd - src; + bcw = destEnd - dest; + if (enc == ENC_DIRECT) + res = EncodeDirect(src, &bcr, dest, &bcw); + else + res = EncodeBase64(src, &bcr, dest, &bcw); + src += bcr; + dest += bcw; + + if (res != NS_OK) break; + } + + *aSrcLength = src - aSrc; + *aDestLength = dest - aDest; + return res; +} + +NS_IMETHODIMP nsBasicUTF7Encoder::FinishNoBuff(char* aDest, + int32_t* aDestLength) { + return ShiftEncoding(ENC_DIRECT, aDest, aDestLength); +} + +NS_IMETHODIMP nsBasicUTF7Encoder::Reset() { + mEncoding = ENC_DIRECT; + mEncBits = 0; + mEncStep = 0; + return NS_OK; +} + +//---------------------------------------------------------------------- +// Class nsUnicodeToUTF7 [implementation] + +nsUnicodeToUTF7::nsUnicodeToUTF7() : nsBasicUTF7Encoder('/', '+') {} + +bool nsUnicodeToUTF7::DirectEncodable(char16_t aChar) { + if ((aChar >= 'A') && (aChar <= 'Z')) + return true; + else if ((aChar >= 'a') && (aChar <= 'z')) + return true; + else if ((aChar >= '0') && (aChar <= '9')) + return true; + else if ((aChar >= 39) && (aChar <= 41)) + return true; + else if ((aChar >= 44) && (aChar <= 47)) + return true; + else if (aChar == 58) + return true; + else if (aChar == 63) + return true; + else if (aChar == ' ') + return true; + else if (aChar == 9) + return true; + else if (aChar == 13) + return true; + else if (aChar == 10) + return true; + else if (aChar == 60) + return true; // '<' + else if (aChar == 33) + return true; // '!' + else if (aChar == 34) + return true; // '"' + else if (aChar == 62) + return true; // '>' + else if (aChar == 61) + return true; // '=' + else if (aChar == 59) + return true; // ';' + else if (aChar == 91) + return true; // '[' + else if (aChar == 93) + return true; // ']' + else + return false; +} -- cgit v1.2.3