From 302bf1b523012e11b60425d6eee1221ebc2724eb Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Sun, 3 Nov 2019 00:17:46 -0400 Subject: Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1 --- mailnews/intl/nsUnicodeToUTF7.cpp | 298 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 mailnews/intl/nsUnicodeToUTF7.cpp (limited to 'mailnews/intl/nsUnicodeToUTF7.cpp') diff --git a/mailnews/intl/nsUnicodeToUTF7.cpp b/mailnews/intl/nsUnicodeToUTF7.cpp new file mode 100644 index 000000000..5db623a17 --- /dev/null +++ b/mailnews/intl/nsUnicodeToUTF7.cpp @@ -0,0 +1,298 @@ +/* -*- 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) +: nsEncoderSupport(5) +{ + 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 nsEncoderSupport::Reset(); +} + +//---------------------------------------------------------------------- +// 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