12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci********************************************************************** 52e5b6d6dSopenharmony_ci* Copyright (C) 2002-2016, International Business Machines 62e5b6d6dSopenharmony_ci* Corporation and others. All Rights Reserved. 72e5b6d6dSopenharmony_ci********************************************************************** 82e5b6d6dSopenharmony_ci* file name: ucnv_u7.c 92e5b6d6dSopenharmony_ci* encoding: UTF-8 102e5b6d6dSopenharmony_ci* tab size: 8 (not used) 112e5b6d6dSopenharmony_ci* indentation:4 122e5b6d6dSopenharmony_ci* 132e5b6d6dSopenharmony_ci* created on: 2002jul01 142e5b6d6dSopenharmony_ci* created by: Markus W. Scherer 152e5b6d6dSopenharmony_ci* 162e5b6d6dSopenharmony_ci* UTF-7 converter implementation. Used to be in ucnv_utf.c. 172e5b6d6dSopenharmony_ci*/ 182e5b6d6dSopenharmony_ci 192e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 202e5b6d6dSopenharmony_ci 212e5b6d6dSopenharmony_ci#if !UCONFIG_NO_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_ci#include "cmemory.h" 242e5b6d6dSopenharmony_ci#include "unicode/ucnv.h" 252e5b6d6dSopenharmony_ci#include "ucnv_bld.h" 262e5b6d6dSopenharmony_ci#include "ucnv_cnv.h" 272e5b6d6dSopenharmony_ci#include "uassert.h" 282e5b6d6dSopenharmony_ci 292e5b6d6dSopenharmony_ci/* UTF-7 -------------------------------------------------------------------- */ 302e5b6d6dSopenharmony_ci 312e5b6d6dSopenharmony_ci/* 322e5b6d6dSopenharmony_ci * UTF-7 is a stateful encoding of Unicode. 332e5b6d6dSopenharmony_ci * It is defined in RFC 2152. (http://www.ietf.org/rfc/rfc2152.txt) 342e5b6d6dSopenharmony_ci * It was intended for use in Internet email systems, using in its bytewise 352e5b6d6dSopenharmony_ci * encoding only a subset of 7-bit US-ASCII. 362e5b6d6dSopenharmony_ci * UTF-7 is deprecated in favor of UTF-8/16/32 and SCSU, but still 372e5b6d6dSopenharmony_ci * occasionally used. 382e5b6d6dSopenharmony_ci * 392e5b6d6dSopenharmony_ci * For converting Unicode to UTF-7, the RFC allows to encode some US-ASCII 402e5b6d6dSopenharmony_ci * characters directly or in base64. Especially, the characters in set O 412e5b6d6dSopenharmony_ci * as defined in the RFC (see below) may be encoded directly but are not 422e5b6d6dSopenharmony_ci * allowed in, e.g., email headers. 432e5b6d6dSopenharmony_ci * By default, the ICU UTF-7 converter encodes set O directly. 442e5b6d6dSopenharmony_ci * By choosing the option "version=1", set O will be escaped instead. 452e5b6d6dSopenharmony_ci * For example: 462e5b6d6dSopenharmony_ci * utf7Converter=ucnv_open("UTF-7,version=1"); 472e5b6d6dSopenharmony_ci * 482e5b6d6dSopenharmony_ci * For details about email headers see RFC 2047. 492e5b6d6dSopenharmony_ci */ 502e5b6d6dSopenharmony_ci 512e5b6d6dSopenharmony_ci/* 522e5b6d6dSopenharmony_ci * Tests for US-ASCII characters belonging to character classes 532e5b6d6dSopenharmony_ci * defined in UTF-7. 542e5b6d6dSopenharmony_ci * 552e5b6d6dSopenharmony_ci * Set D (directly encoded characters) consists of the following 562e5b6d6dSopenharmony_ci * characters: the upper and lower case letters A through Z 572e5b6d6dSopenharmony_ci * and a through z, the 10 digits 0-9, and the following nine special 582e5b6d6dSopenharmony_ci * characters (note that "+" and "=" are omitted): 592e5b6d6dSopenharmony_ci * '(),-./:? 602e5b6d6dSopenharmony_ci * 612e5b6d6dSopenharmony_ci * Set O (optional direct characters) consists of the following 622e5b6d6dSopenharmony_ci * characters (note that "\" and "~" are omitted): 632e5b6d6dSopenharmony_ci * !"#$%&*;<=>@[]^_`{|} 642e5b6d6dSopenharmony_ci * 652e5b6d6dSopenharmony_ci * According to the rules in RFC 2152, the byte values for the following 662e5b6d6dSopenharmony_ci * US-ASCII characters are not used in UTF-7 and are therefore illegal: 672e5b6d6dSopenharmony_ci * - all C0 control codes except for CR LF TAB 682e5b6d6dSopenharmony_ci * - BACKSLASH 692e5b6d6dSopenharmony_ci * - TILDE 702e5b6d6dSopenharmony_ci * - DEL 712e5b6d6dSopenharmony_ci * - all codes beyond US-ASCII, i.e. all >127 722e5b6d6dSopenharmony_ci */ 732e5b6d6dSopenharmony_ci#define inSetD(c) \ 742e5b6d6dSopenharmony_ci ((uint8_t)((c)-97)<26 || (uint8_t)((c)-65)<26 || /* letters */ \ 752e5b6d6dSopenharmony_ci (uint8_t)((c)-48)<10 || /* digits */ \ 762e5b6d6dSopenharmony_ci (uint8_t)((c)-39)<3 || /* '() */ \ 772e5b6d6dSopenharmony_ci (uint8_t)((c)-44)<4 || /* ,-./ */ \ 782e5b6d6dSopenharmony_ci (c)==58 || (c)==63 /* :? */ \ 792e5b6d6dSopenharmony_ci ) 802e5b6d6dSopenharmony_ci 812e5b6d6dSopenharmony_ci#define inSetO(c) \ 822e5b6d6dSopenharmony_ci ((uint8_t)((c)-33)<6 || /* !"#$%& */ \ 832e5b6d6dSopenharmony_ci (uint8_t)((c)-59)<4 || /* ;<=> */ \ 842e5b6d6dSopenharmony_ci (uint8_t)((c)-93)<4 || /* ]^_` */ \ 852e5b6d6dSopenharmony_ci (uint8_t)((c)-123)<3 || /* {|} */ \ 862e5b6d6dSopenharmony_ci (c)==42 || (c)==64 || (c)==91 /* *@[ */ \ 872e5b6d6dSopenharmony_ci ) 882e5b6d6dSopenharmony_ci 892e5b6d6dSopenharmony_ci#define isCRLFTAB(c) ((c)==13 || (c)==10 || (c)==9) 902e5b6d6dSopenharmony_ci#define isCRLFSPTAB(c) ((c)==32 || (c)==13 || (c)==10 || (c)==9) 912e5b6d6dSopenharmony_ci 922e5b6d6dSopenharmony_ci#define PLUS 43 932e5b6d6dSopenharmony_ci#define MINUS 45 942e5b6d6dSopenharmony_ci#define BACKSLASH 92 952e5b6d6dSopenharmony_ci#define TILDE 126 962e5b6d6dSopenharmony_ci 972e5b6d6dSopenharmony_ci/* legal byte values: all US-ASCII graphic characters from space to before tilde, and CR LF TAB */ 982e5b6d6dSopenharmony_ci#define isLegalUTF7(c) (((uint8_t)((c)-32)<94 && (c)!=BACKSLASH) || isCRLFTAB(c)) 992e5b6d6dSopenharmony_ci 1002e5b6d6dSopenharmony_ci/* encode directly sets D and O and CR LF SP TAB */ 1012e5b6d6dSopenharmony_cistatic const UBool encodeDirectlyMaximum[128]={ 1022e5b6d6dSopenharmony_ci /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 1032e5b6d6dSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1042e5b6d6dSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1052e5b6d6dSopenharmony_ci 1062e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1072e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1082e5b6d6dSopenharmony_ci 1092e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1102e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1112e5b6d6dSopenharmony_ci 1122e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1132e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 1142e5b6d6dSopenharmony_ci}; 1152e5b6d6dSopenharmony_ci 1162e5b6d6dSopenharmony_ci/* encode directly set D and CR LF SP TAB but not set O */ 1172e5b6d6dSopenharmony_cistatic const UBool encodeDirectlyRestricted[128]={ 1182e5b6d6dSopenharmony_ci /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 1192e5b6d6dSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1202e5b6d6dSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1212e5b6d6dSopenharmony_ci 1222e5b6d6dSopenharmony_ci 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1232e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1242e5b6d6dSopenharmony_ci 1252e5b6d6dSopenharmony_ci 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1262e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1272e5b6d6dSopenharmony_ci 1282e5b6d6dSopenharmony_ci 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1292e5b6d6dSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 1302e5b6d6dSopenharmony_ci}; 1312e5b6d6dSopenharmony_ci 1322e5b6d6dSopenharmony_cistatic const uint8_t 1332e5b6d6dSopenharmony_citoBase64[64]={ 1342e5b6d6dSopenharmony_ci /* A-Z */ 1352e5b6d6dSopenharmony_ci 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 1362e5b6d6dSopenharmony_ci 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 1372e5b6d6dSopenharmony_ci /* a-z */ 1382e5b6d6dSopenharmony_ci 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 1392e5b6d6dSopenharmony_ci 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 1402e5b6d6dSopenharmony_ci /* 0-9 */ 1412e5b6d6dSopenharmony_ci 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 1422e5b6d6dSopenharmony_ci /* +/ */ 1432e5b6d6dSopenharmony_ci 43, 47 1442e5b6d6dSopenharmony_ci}; 1452e5b6d6dSopenharmony_ci 1462e5b6d6dSopenharmony_cistatic const int8_t 1472e5b6d6dSopenharmony_cifromBase64[128]={ 1482e5b6d6dSopenharmony_ci /* C0 controls, -1 for legal ones (CR LF TAB), -3 for illegal ones */ 1492e5b6d6dSopenharmony_ci -3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3, 1502e5b6d6dSopenharmony_ci -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 1512e5b6d6dSopenharmony_ci 1522e5b6d6dSopenharmony_ci /* general punctuation with + and / and a special value (-2) for - */ 1532e5b6d6dSopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -2, -1, 63, 1542e5b6d6dSopenharmony_ci /* digits */ 1552e5b6d6dSopenharmony_ci 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, 1562e5b6d6dSopenharmony_ci 1572e5b6d6dSopenharmony_ci /* A-Z */ 1582e5b6d6dSopenharmony_ci -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1592e5b6d6dSopenharmony_ci 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -3, -1, -1, -1, 1602e5b6d6dSopenharmony_ci 1612e5b6d6dSopenharmony_ci /* a-z */ 1622e5b6d6dSopenharmony_ci -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 1632e5b6d6dSopenharmony_ci 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -3, -3 1642e5b6d6dSopenharmony_ci}; 1652e5b6d6dSopenharmony_ci 1662e5b6d6dSopenharmony_ci/* 1672e5b6d6dSopenharmony_ci * converter status values: 1682e5b6d6dSopenharmony_ci * 1692e5b6d6dSopenharmony_ci * toUnicodeStatus: 1702e5b6d6dSopenharmony_ci * 24 inDirectMode (boolean) 1712e5b6d6dSopenharmony_ci * 23..16 base64Counter (-1..7) 1722e5b6d6dSopenharmony_ci * 15..0 bits (up to 14 bits incoming base64) 1732e5b6d6dSopenharmony_ci * 1742e5b6d6dSopenharmony_ci * fromUnicodeStatus: 1752e5b6d6dSopenharmony_ci * 31..28 version (0: set O direct 1: set O escaped) 1762e5b6d6dSopenharmony_ci * 24 inDirectMode (boolean) 1772e5b6d6dSopenharmony_ci * 23..16 base64Counter (0..2) 1782e5b6d6dSopenharmony_ci * 7..0 bits (6 bits outgoing base64) 1792e5b6d6dSopenharmony_ci * 1802e5b6d6dSopenharmony_ci */ 1812e5b6d6dSopenharmony_ci 1822e5b6d6dSopenharmony_ciU_CDECL_BEGIN 1832e5b6d6dSopenharmony_cistatic void U_CALLCONV 1842e5b6d6dSopenharmony_ci_UTF7Reset(UConverter *cnv, UConverterResetChoice choice) { 1852e5b6d6dSopenharmony_ci if(choice<=UCNV_RESET_TO_UNICODE) { 1862e5b6d6dSopenharmony_ci /* reset toUnicode */ 1872e5b6d6dSopenharmony_ci cnv->toUnicodeStatus=0x1000000; /* inDirectMode=true */ 1882e5b6d6dSopenharmony_ci cnv->toULength=0; 1892e5b6d6dSopenharmony_ci } 1902e5b6d6dSopenharmony_ci if(choice!=UCNV_RESET_TO_UNICODE) { 1912e5b6d6dSopenharmony_ci /* reset fromUnicode */ 1922e5b6d6dSopenharmony_ci cnv->fromUnicodeStatus=(cnv->fromUnicodeStatus&0xf0000000)|0x1000000; /* keep version, inDirectMode=true */ 1932e5b6d6dSopenharmony_ci } 1942e5b6d6dSopenharmony_ci} 1952e5b6d6dSopenharmony_ci 1962e5b6d6dSopenharmony_cistatic void U_CALLCONV 1972e5b6d6dSopenharmony_ci_UTF7Open(UConverter *cnv, 1982e5b6d6dSopenharmony_ci UConverterLoadArgs *pArgs, 1992e5b6d6dSopenharmony_ci UErrorCode *pErrorCode) { 2002e5b6d6dSopenharmony_ci (void)pArgs; 2012e5b6d6dSopenharmony_ci if(UCNV_GET_VERSION(cnv)<=1) { 2022e5b6d6dSopenharmony_ci /* TODO(markus): Should just use cnv->options rather than copying the version number. */ 2032e5b6d6dSopenharmony_ci cnv->fromUnicodeStatus=UCNV_GET_VERSION(cnv)<<28; 2042e5b6d6dSopenharmony_ci _UTF7Reset(cnv, UCNV_RESET_BOTH); 2052e5b6d6dSopenharmony_ci } else { 2062e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 2072e5b6d6dSopenharmony_ci } 2082e5b6d6dSopenharmony_ci} 2092e5b6d6dSopenharmony_ci 2102e5b6d6dSopenharmony_cistatic void U_CALLCONV 2112e5b6d6dSopenharmony_ci_UTF7ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, 2122e5b6d6dSopenharmony_ci UErrorCode *pErrorCode) { 2132e5b6d6dSopenharmony_ci UConverter *cnv; 2142e5b6d6dSopenharmony_ci const uint8_t *source, *sourceLimit; 2152e5b6d6dSopenharmony_ci UChar *target; 2162e5b6d6dSopenharmony_ci const UChar *targetLimit; 2172e5b6d6dSopenharmony_ci int32_t *offsets; 2182e5b6d6dSopenharmony_ci 2192e5b6d6dSopenharmony_ci uint8_t *bytes; 2202e5b6d6dSopenharmony_ci uint8_t byteIndex; 2212e5b6d6dSopenharmony_ci 2222e5b6d6dSopenharmony_ci int32_t length, targetCapacity; 2232e5b6d6dSopenharmony_ci 2242e5b6d6dSopenharmony_ci /* UTF-7 state */ 2252e5b6d6dSopenharmony_ci uint16_t bits; 2262e5b6d6dSopenharmony_ci int8_t base64Counter; 2272e5b6d6dSopenharmony_ci UBool inDirectMode; 2282e5b6d6dSopenharmony_ci 2292e5b6d6dSopenharmony_ci int8_t base64Value; 2302e5b6d6dSopenharmony_ci 2312e5b6d6dSopenharmony_ci int32_t sourceIndex, nextSourceIndex; 2322e5b6d6dSopenharmony_ci 2332e5b6d6dSopenharmony_ci uint8_t b; 2342e5b6d6dSopenharmony_ci /* set up the local pointers */ 2352e5b6d6dSopenharmony_ci cnv=pArgs->converter; 2362e5b6d6dSopenharmony_ci 2372e5b6d6dSopenharmony_ci source=(const uint8_t *)pArgs->source; 2382e5b6d6dSopenharmony_ci sourceLimit=(const uint8_t *)pArgs->sourceLimit; 2392e5b6d6dSopenharmony_ci target=pArgs->target; 2402e5b6d6dSopenharmony_ci targetLimit=pArgs->targetLimit; 2412e5b6d6dSopenharmony_ci offsets=pArgs->offsets; 2422e5b6d6dSopenharmony_ci /* get the state machine state */ 2432e5b6d6dSopenharmony_ci { 2442e5b6d6dSopenharmony_ci uint32_t status=cnv->toUnicodeStatus; 2452e5b6d6dSopenharmony_ci inDirectMode=(UBool)((status>>24)&1); 2462e5b6d6dSopenharmony_ci base64Counter=(int8_t)(status>>16); 2472e5b6d6dSopenharmony_ci bits=(uint16_t)status; 2482e5b6d6dSopenharmony_ci } 2492e5b6d6dSopenharmony_ci bytes=cnv->toUBytes; 2502e5b6d6dSopenharmony_ci byteIndex=cnv->toULength; 2512e5b6d6dSopenharmony_ci 2522e5b6d6dSopenharmony_ci /* sourceIndex=-1 if the current character began in the previous buffer */ 2532e5b6d6dSopenharmony_ci sourceIndex=byteIndex==0 ? 0 : -1; 2542e5b6d6dSopenharmony_ci nextSourceIndex=0; 2552e5b6d6dSopenharmony_ci 2562e5b6d6dSopenharmony_ci if(inDirectMode) { 2572e5b6d6dSopenharmony_cidirectMode: 2582e5b6d6dSopenharmony_ci /* 2592e5b6d6dSopenharmony_ci * In Direct Mode, most US-ASCII characters are encoded directly, i.e., 2602e5b6d6dSopenharmony_ci * with their US-ASCII byte values. 2612e5b6d6dSopenharmony_ci * Backslash and Tilde and most control characters are not allowed in UTF-7. 2622e5b6d6dSopenharmony_ci * A plus sign starts Unicode (or "escape") Mode. 2632e5b6d6dSopenharmony_ci * 2642e5b6d6dSopenharmony_ci * In Direct Mode, only the sourceIndex is used. 2652e5b6d6dSopenharmony_ci */ 2662e5b6d6dSopenharmony_ci byteIndex=0; 2672e5b6d6dSopenharmony_ci length=(int32_t)(sourceLimit-source); 2682e5b6d6dSopenharmony_ci targetCapacity=(int32_t)(targetLimit-target); 2692e5b6d6dSopenharmony_ci if(length>targetCapacity) { 2702e5b6d6dSopenharmony_ci length=targetCapacity; 2712e5b6d6dSopenharmony_ci } 2722e5b6d6dSopenharmony_ci while(length>0) { 2732e5b6d6dSopenharmony_ci b=*source++; 2742e5b6d6dSopenharmony_ci if(!isLegalUTF7(b)) { 2752e5b6d6dSopenharmony_ci /* illegal */ 2762e5b6d6dSopenharmony_ci bytes[0]=b; 2772e5b6d6dSopenharmony_ci byteIndex=1; 2782e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 2792e5b6d6dSopenharmony_ci break; 2802e5b6d6dSopenharmony_ci } else if(b!=PLUS) { 2812e5b6d6dSopenharmony_ci /* write directly encoded character */ 2822e5b6d6dSopenharmony_ci *target++=b; 2832e5b6d6dSopenharmony_ci if(offsets!=NULL) { 2842e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 2852e5b6d6dSopenharmony_ci } 2862e5b6d6dSopenharmony_ci } else /* PLUS */ { 2872e5b6d6dSopenharmony_ci /* switch to Unicode mode */ 2882e5b6d6dSopenharmony_ci nextSourceIndex=++sourceIndex; 2892e5b6d6dSopenharmony_ci inDirectMode=false; 2902e5b6d6dSopenharmony_ci byteIndex=0; 2912e5b6d6dSopenharmony_ci bits=0; 2922e5b6d6dSopenharmony_ci base64Counter=-1; 2932e5b6d6dSopenharmony_ci goto unicodeMode; 2942e5b6d6dSopenharmony_ci } 2952e5b6d6dSopenharmony_ci --length; 2962e5b6d6dSopenharmony_ci } 2972e5b6d6dSopenharmony_ci if(source<sourceLimit && target>=targetLimit) { 2982e5b6d6dSopenharmony_ci /* target is full */ 2992e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 3002e5b6d6dSopenharmony_ci } 3012e5b6d6dSopenharmony_ci } else { 3022e5b6d6dSopenharmony_ciunicodeMode: 3032e5b6d6dSopenharmony_ci /* 3042e5b6d6dSopenharmony_ci * In Unicode (or "escape") Mode, UTF-16BE is base64-encoded. 3052e5b6d6dSopenharmony_ci * The base64 sequence ends with any character that is not in the base64 alphabet. 3062e5b6d6dSopenharmony_ci * A terminating minus sign is consumed. 3072e5b6d6dSopenharmony_ci * 3082e5b6d6dSopenharmony_ci * In Unicode Mode, the sourceIndex has the index to the start of the current 3092e5b6d6dSopenharmony_ci * base64 bytes, while nextSourceIndex is precisely parallel to source, 3102e5b6d6dSopenharmony_ci * keeping the index to the following byte. 3112e5b6d6dSopenharmony_ci * Note that in 2 out of 3 cases, UChars overlap within a base64 byte. 3122e5b6d6dSopenharmony_ci */ 3132e5b6d6dSopenharmony_ci while(source<sourceLimit) { 3142e5b6d6dSopenharmony_ci if(target<targetLimit) { 3152e5b6d6dSopenharmony_ci bytes[byteIndex++]=b=*source++; 3162e5b6d6dSopenharmony_ci ++nextSourceIndex; 3172e5b6d6dSopenharmony_ci base64Value = -3; /* initialize as illegal */ 3182e5b6d6dSopenharmony_ci if(b>=126 || (base64Value=fromBase64[b])==-3 || base64Value==-1) { 3192e5b6d6dSopenharmony_ci /* either 3202e5b6d6dSopenharmony_ci * base64Value==-1 for any legal character except base64 and minus sign, or 3212e5b6d6dSopenharmony_ci * base64Value==-3 for illegal characters: 3222e5b6d6dSopenharmony_ci * 1. In either case, leave Unicode mode. 3232e5b6d6dSopenharmony_ci * 2.1. If we ended with an incomplete UChar or none after the +, then 3242e5b6d6dSopenharmony_ci * generate an error for the preceding erroneous sequence and deal with 3252e5b6d6dSopenharmony_ci * the current (possibly illegal) character next time through. 3262e5b6d6dSopenharmony_ci * 2.2. Else the current char comes after a complete UChar, which was already 3272e5b6d6dSopenharmony_ci * pushed to the output buf, so: 3282e5b6d6dSopenharmony_ci * 2.2.1. If the current char is legal, just save it for processing next time. 3292e5b6d6dSopenharmony_ci * It may be for example, a plus which we need to deal with in direct mode. 3302e5b6d6dSopenharmony_ci * 2.2.2. Else if the current char is illegal, we might as well deal with it here. 3312e5b6d6dSopenharmony_ci */ 3322e5b6d6dSopenharmony_ci inDirectMode=true; 3332e5b6d6dSopenharmony_ci if(base64Counter==-1) { 3342e5b6d6dSopenharmony_ci /* illegal: + immediately followed by something other than base64 or minus sign */ 3352e5b6d6dSopenharmony_ci /* include the plus sign in the reported sequence, but not the subsequent char */ 3362e5b6d6dSopenharmony_ci --source; 3372e5b6d6dSopenharmony_ci bytes[0]=PLUS; 3382e5b6d6dSopenharmony_ci byteIndex=1; 3392e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 3402e5b6d6dSopenharmony_ci break; 3412e5b6d6dSopenharmony_ci } else if(bits!=0) { 3422e5b6d6dSopenharmony_ci /* bits are illegally left over, a UChar is incomplete */ 3432e5b6d6dSopenharmony_ci /* don't include current char (legal or illegal) in error seq */ 3442e5b6d6dSopenharmony_ci --source; 3452e5b6d6dSopenharmony_ci --byteIndex; 3462e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 3472e5b6d6dSopenharmony_ci break; 3482e5b6d6dSopenharmony_ci } else { 3492e5b6d6dSopenharmony_ci /* previous UChar was complete */ 3502e5b6d6dSopenharmony_ci if(base64Value==-3) { 3512e5b6d6dSopenharmony_ci /* current character is illegal, deal with it here */ 3522e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 3532e5b6d6dSopenharmony_ci break; 3542e5b6d6dSopenharmony_ci } else { 3552e5b6d6dSopenharmony_ci /* un-read the current character in case it is a plus sign */ 3562e5b6d6dSopenharmony_ci --source; 3572e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex-1; 3582e5b6d6dSopenharmony_ci goto directMode; 3592e5b6d6dSopenharmony_ci } 3602e5b6d6dSopenharmony_ci } 3612e5b6d6dSopenharmony_ci } else if(base64Value>=0) { 3622e5b6d6dSopenharmony_ci /* collect base64 bytes into UChars */ 3632e5b6d6dSopenharmony_ci switch(base64Counter) { 3642e5b6d6dSopenharmony_ci case -1: /* -1 is immediately after the + */ 3652e5b6d6dSopenharmony_ci case 0: 3662e5b6d6dSopenharmony_ci bits=base64Value; 3672e5b6d6dSopenharmony_ci base64Counter=1; 3682e5b6d6dSopenharmony_ci break; 3692e5b6d6dSopenharmony_ci case 1: 3702e5b6d6dSopenharmony_ci case 3: 3712e5b6d6dSopenharmony_ci case 4: 3722e5b6d6dSopenharmony_ci case 6: 3732e5b6d6dSopenharmony_ci bits=(uint16_t)((bits<<6)|base64Value); 3742e5b6d6dSopenharmony_ci ++base64Counter; 3752e5b6d6dSopenharmony_ci break; 3762e5b6d6dSopenharmony_ci case 2: 3772e5b6d6dSopenharmony_ci *target++=(UChar)((bits<<4)|(base64Value>>2)); 3782e5b6d6dSopenharmony_ci if(offsets!=NULL) { 3792e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 3802e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex-1; 3812e5b6d6dSopenharmony_ci } 3822e5b6d6dSopenharmony_ci bytes[0]=b; /* keep this byte in case an error occurs */ 3832e5b6d6dSopenharmony_ci byteIndex=1; 3842e5b6d6dSopenharmony_ci bits=(uint16_t)(base64Value&3); 3852e5b6d6dSopenharmony_ci base64Counter=3; 3862e5b6d6dSopenharmony_ci break; 3872e5b6d6dSopenharmony_ci case 5: 3882e5b6d6dSopenharmony_ci *target++=(UChar)((bits<<2)|(base64Value>>4)); 3892e5b6d6dSopenharmony_ci if(offsets!=NULL) { 3902e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 3912e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex-1; 3922e5b6d6dSopenharmony_ci } 3932e5b6d6dSopenharmony_ci bytes[0]=b; /* keep this byte in case an error occurs */ 3942e5b6d6dSopenharmony_ci byteIndex=1; 3952e5b6d6dSopenharmony_ci bits=(uint16_t)(base64Value&15); 3962e5b6d6dSopenharmony_ci base64Counter=6; 3972e5b6d6dSopenharmony_ci break; 3982e5b6d6dSopenharmony_ci case 7: 3992e5b6d6dSopenharmony_ci *target++=(UChar)((bits<<6)|base64Value); 4002e5b6d6dSopenharmony_ci if(offsets!=NULL) { 4012e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 4022e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex; 4032e5b6d6dSopenharmony_ci } 4042e5b6d6dSopenharmony_ci byteIndex=0; 4052e5b6d6dSopenharmony_ci bits=0; 4062e5b6d6dSopenharmony_ci base64Counter=0; 4072e5b6d6dSopenharmony_ci break; 4082e5b6d6dSopenharmony_ci default: 4092e5b6d6dSopenharmony_ci /* will never occur */ 4102e5b6d6dSopenharmony_ci break; 4112e5b6d6dSopenharmony_ci } 4122e5b6d6dSopenharmony_ci } else /*base64Value==-2*/ { 4132e5b6d6dSopenharmony_ci /* minus sign terminates the base64 sequence */ 4142e5b6d6dSopenharmony_ci inDirectMode=true; 4152e5b6d6dSopenharmony_ci if(base64Counter==-1) { 4162e5b6d6dSopenharmony_ci /* +- i.e. a minus immediately following a plus */ 4172e5b6d6dSopenharmony_ci *target++=PLUS; 4182e5b6d6dSopenharmony_ci if(offsets!=NULL) { 4192e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 4202e5b6d6dSopenharmony_ci } 4212e5b6d6dSopenharmony_ci } else { 4222e5b6d6dSopenharmony_ci /* absorb the minus and leave the Unicode Mode */ 4232e5b6d6dSopenharmony_ci if(bits!=0) { 4242e5b6d6dSopenharmony_ci /* bits are illegally left over, a UChar is incomplete */ 4252e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 4262e5b6d6dSopenharmony_ci break; 4272e5b6d6dSopenharmony_ci } 4282e5b6d6dSopenharmony_ci } 4292e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex; 4302e5b6d6dSopenharmony_ci goto directMode; 4312e5b6d6dSopenharmony_ci } 4322e5b6d6dSopenharmony_ci } else { 4332e5b6d6dSopenharmony_ci /* target is full */ 4342e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 4352e5b6d6dSopenharmony_ci break; 4362e5b6d6dSopenharmony_ci } 4372e5b6d6dSopenharmony_ci } 4382e5b6d6dSopenharmony_ci } 4392e5b6d6dSopenharmony_ci 4402e5b6d6dSopenharmony_ci if(U_SUCCESS(*pErrorCode) && pArgs->flush && source==sourceLimit && bits==0) { 4412e5b6d6dSopenharmony_ci /* 4422e5b6d6dSopenharmony_ci * if we are in Unicode mode, then the byteIndex might not be 0, 4432e5b6d6dSopenharmony_ci * but that is ok if bits==0 4442e5b6d6dSopenharmony_ci * -> we set byteIndex=0 at the end of the stream to avoid a truncated error 4452e5b6d6dSopenharmony_ci * (not true for IMAP-mailbox-name where we must end in direct mode) 4462e5b6d6dSopenharmony_ci */ 4472e5b6d6dSopenharmony_ci byteIndex=0; 4482e5b6d6dSopenharmony_ci } 4492e5b6d6dSopenharmony_ci 4502e5b6d6dSopenharmony_ci /* set the converter state back into UConverter */ 4512e5b6d6dSopenharmony_ci cnv->toUnicodeStatus=((uint32_t)inDirectMode<<24)|((uint32_t)((uint8_t)base64Counter)<<16)|(uint32_t)bits; 4522e5b6d6dSopenharmony_ci cnv->toULength=byteIndex; 4532e5b6d6dSopenharmony_ci 4542e5b6d6dSopenharmony_ci /* write back the updated pointers */ 4552e5b6d6dSopenharmony_ci pArgs->source=(const char *)source; 4562e5b6d6dSopenharmony_ci pArgs->target=target; 4572e5b6d6dSopenharmony_ci pArgs->offsets=offsets; 4582e5b6d6dSopenharmony_ci return; 4592e5b6d6dSopenharmony_ci} 4602e5b6d6dSopenharmony_ci 4612e5b6d6dSopenharmony_cistatic void U_CALLCONV 4622e5b6d6dSopenharmony_ci_UTF7FromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, 4632e5b6d6dSopenharmony_ci UErrorCode *pErrorCode) { 4642e5b6d6dSopenharmony_ci UConverter *cnv; 4652e5b6d6dSopenharmony_ci const UChar *source, *sourceLimit; 4662e5b6d6dSopenharmony_ci uint8_t *target, *targetLimit; 4672e5b6d6dSopenharmony_ci int32_t *offsets; 4682e5b6d6dSopenharmony_ci 4692e5b6d6dSopenharmony_ci int32_t length, targetCapacity, sourceIndex; 4702e5b6d6dSopenharmony_ci UChar c; 4712e5b6d6dSopenharmony_ci 4722e5b6d6dSopenharmony_ci /* UTF-7 state */ 4732e5b6d6dSopenharmony_ci const UBool *encodeDirectly; 4742e5b6d6dSopenharmony_ci uint8_t bits; 4752e5b6d6dSopenharmony_ci int8_t base64Counter; 4762e5b6d6dSopenharmony_ci UBool inDirectMode; 4772e5b6d6dSopenharmony_ci 4782e5b6d6dSopenharmony_ci /* set up the local pointers */ 4792e5b6d6dSopenharmony_ci cnv=pArgs->converter; 4802e5b6d6dSopenharmony_ci 4812e5b6d6dSopenharmony_ci /* set up the local pointers */ 4822e5b6d6dSopenharmony_ci source=pArgs->source; 4832e5b6d6dSopenharmony_ci sourceLimit=pArgs->sourceLimit; 4842e5b6d6dSopenharmony_ci target=(uint8_t *)pArgs->target; 4852e5b6d6dSopenharmony_ci targetLimit=(uint8_t *)pArgs->targetLimit; 4862e5b6d6dSopenharmony_ci offsets=pArgs->offsets; 4872e5b6d6dSopenharmony_ci 4882e5b6d6dSopenharmony_ci /* get the state machine state */ 4892e5b6d6dSopenharmony_ci { 4902e5b6d6dSopenharmony_ci uint32_t status=cnv->fromUnicodeStatus; 4912e5b6d6dSopenharmony_ci encodeDirectly= status<0x10000000 ? encodeDirectlyMaximum : encodeDirectlyRestricted; 4922e5b6d6dSopenharmony_ci inDirectMode=(UBool)((status>>24)&1); 4932e5b6d6dSopenharmony_ci base64Counter=(int8_t)(status>>16); 4942e5b6d6dSopenharmony_ci bits=(uint8_t)status; 4952e5b6d6dSopenharmony_ci U_ASSERT(bits<=UPRV_LENGTHOF(toBase64)); 4962e5b6d6dSopenharmony_ci } 4972e5b6d6dSopenharmony_ci 4982e5b6d6dSopenharmony_ci /* UTF-7 always encodes UTF-16 code units, therefore we need only a simple sourceIndex */ 4992e5b6d6dSopenharmony_ci sourceIndex=0; 5002e5b6d6dSopenharmony_ci 5012e5b6d6dSopenharmony_ci if(inDirectMode) { 5022e5b6d6dSopenharmony_cidirectMode: 5032e5b6d6dSopenharmony_ci length=(int32_t)(sourceLimit-source); 5042e5b6d6dSopenharmony_ci targetCapacity=(int32_t)(targetLimit-target); 5052e5b6d6dSopenharmony_ci if(length>targetCapacity) { 5062e5b6d6dSopenharmony_ci length=targetCapacity; 5072e5b6d6dSopenharmony_ci } 5082e5b6d6dSopenharmony_ci while(length>0) { 5092e5b6d6dSopenharmony_ci c=*source++; 5102e5b6d6dSopenharmony_ci /* currently always encode CR LF SP TAB directly */ 5112e5b6d6dSopenharmony_ci if(c<=127 && encodeDirectly[c]) { 5122e5b6d6dSopenharmony_ci /* encode directly */ 5132e5b6d6dSopenharmony_ci *target++=(uint8_t)c; 5142e5b6d6dSopenharmony_ci if(offsets!=NULL) { 5152e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 5162e5b6d6dSopenharmony_ci } 5172e5b6d6dSopenharmony_ci } else if(c==PLUS) { 5182e5b6d6dSopenharmony_ci /* output +- for + */ 5192e5b6d6dSopenharmony_ci *target++=PLUS; 5202e5b6d6dSopenharmony_ci if(target<targetLimit) { 5212e5b6d6dSopenharmony_ci *target++=MINUS; 5222e5b6d6dSopenharmony_ci if(offsets!=NULL) { 5232e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 5242e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 5252e5b6d6dSopenharmony_ci } 5262e5b6d6dSopenharmony_ci /* realign length and targetCapacity */ 5272e5b6d6dSopenharmony_ci goto directMode; 5282e5b6d6dSopenharmony_ci } else { 5292e5b6d6dSopenharmony_ci if(offsets!=NULL) { 5302e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 5312e5b6d6dSopenharmony_ci } 5322e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=MINUS; 5332e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 5342e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 5352e5b6d6dSopenharmony_ci break; 5362e5b6d6dSopenharmony_ci } 5372e5b6d6dSopenharmony_ci } else { 5382e5b6d6dSopenharmony_ci /* un-read this character and switch to Unicode Mode */ 5392e5b6d6dSopenharmony_ci --source; 5402e5b6d6dSopenharmony_ci *target++=PLUS; 5412e5b6d6dSopenharmony_ci if(offsets!=NULL) { 5422e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 5432e5b6d6dSopenharmony_ci } 5442e5b6d6dSopenharmony_ci inDirectMode=false; 5452e5b6d6dSopenharmony_ci base64Counter=0; 5462e5b6d6dSopenharmony_ci goto unicodeMode; 5472e5b6d6dSopenharmony_ci } 5482e5b6d6dSopenharmony_ci --length; 5492e5b6d6dSopenharmony_ci } 5502e5b6d6dSopenharmony_ci if(source<sourceLimit && target>=targetLimit) { 5512e5b6d6dSopenharmony_ci /* target is full */ 5522e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 5532e5b6d6dSopenharmony_ci } 5542e5b6d6dSopenharmony_ci } else { 5552e5b6d6dSopenharmony_ciunicodeMode: 5562e5b6d6dSopenharmony_ci while(source<sourceLimit) { 5572e5b6d6dSopenharmony_ci if(target<targetLimit) { 5582e5b6d6dSopenharmony_ci c=*source++; 5592e5b6d6dSopenharmony_ci if(c<=127 && encodeDirectly[c]) { 5602e5b6d6dSopenharmony_ci /* encode directly */ 5612e5b6d6dSopenharmony_ci inDirectMode=true; 5622e5b6d6dSopenharmony_ci 5632e5b6d6dSopenharmony_ci /* trick: back out this character to make this easier */ 5642e5b6d6dSopenharmony_ci --source; 5652e5b6d6dSopenharmony_ci 5662e5b6d6dSopenharmony_ci /* terminate the base64 sequence */ 5672e5b6d6dSopenharmony_ci if(base64Counter!=0) { 5682e5b6d6dSopenharmony_ci /* write remaining bits for the previous character */ 5692e5b6d6dSopenharmony_ci *target++=toBase64[bits]; 5702e5b6d6dSopenharmony_ci if(offsets!=NULL) { 5712e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 5722e5b6d6dSopenharmony_ci } 5732e5b6d6dSopenharmony_ci } 5742e5b6d6dSopenharmony_ci if(fromBase64[c]!=-1) { 5752e5b6d6dSopenharmony_ci /* need to terminate with a minus */ 5762e5b6d6dSopenharmony_ci if(target<targetLimit) { 5772e5b6d6dSopenharmony_ci *target++=MINUS; 5782e5b6d6dSopenharmony_ci if(offsets!=NULL) { 5792e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 5802e5b6d6dSopenharmony_ci } 5812e5b6d6dSopenharmony_ci } else { 5822e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=MINUS; 5832e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 5842e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 5852e5b6d6dSopenharmony_ci break; 5862e5b6d6dSopenharmony_ci } 5872e5b6d6dSopenharmony_ci } 5882e5b6d6dSopenharmony_ci goto directMode; 5892e5b6d6dSopenharmony_ci } else { 5902e5b6d6dSopenharmony_ci /* 5912e5b6d6dSopenharmony_ci * base64 this character: 5922e5b6d6dSopenharmony_ci * Output 2 or 3 base64 bytes for the remaining bits of the previous character 5932e5b6d6dSopenharmony_ci * and the bits of this character, each implicitly in UTF-16BE. 5942e5b6d6dSopenharmony_ci * 5952e5b6d6dSopenharmony_ci * Here, bits is an 8-bit variable because only 6 bits need to be kept from one 5962e5b6d6dSopenharmony_ci * character to the next. The actual 2 or 4 bits are shifted to the left edge 5972e5b6d6dSopenharmony_ci * of the 6-bits field 5..0 to make the termination of the base64 sequence easier. 5982e5b6d6dSopenharmony_ci */ 5992e5b6d6dSopenharmony_ci switch(base64Counter) { 6002e5b6d6dSopenharmony_ci case 0: 6012e5b6d6dSopenharmony_ci *target++=toBase64[c>>10]; 6022e5b6d6dSopenharmony_ci if(target<targetLimit) { 6032e5b6d6dSopenharmony_ci *target++=toBase64[(c>>4)&0x3f]; 6042e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6052e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6062e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6072e5b6d6dSopenharmony_ci } 6082e5b6d6dSopenharmony_ci } else { 6092e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6102e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6112e5b6d6dSopenharmony_ci } 6122e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=toBase64[(c>>4)&0x3f]; 6132e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 6142e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 6152e5b6d6dSopenharmony_ci } 6162e5b6d6dSopenharmony_ci bits=(uint8_t)((c&15)<<2); 6172e5b6d6dSopenharmony_ci base64Counter=1; 6182e5b6d6dSopenharmony_ci break; 6192e5b6d6dSopenharmony_ci case 1: 6202e5b6d6dSopenharmony_ci *target++=toBase64[bits|(c>>14)]; 6212e5b6d6dSopenharmony_ci if(target<targetLimit) { 6222e5b6d6dSopenharmony_ci *target++=toBase64[(c>>8)&0x3f]; 6232e5b6d6dSopenharmony_ci if(target<targetLimit) { 6242e5b6d6dSopenharmony_ci *target++=toBase64[(c>>2)&0x3f]; 6252e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6262e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6272e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6282e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6292e5b6d6dSopenharmony_ci } 6302e5b6d6dSopenharmony_ci } else { 6312e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6322e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6332e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6342e5b6d6dSopenharmony_ci } 6352e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=toBase64[(c>>2)&0x3f]; 6362e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 6372e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 6382e5b6d6dSopenharmony_ci } 6392e5b6d6dSopenharmony_ci } else { 6402e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6412e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6422e5b6d6dSopenharmony_ci } 6432e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=toBase64[(c>>8)&0x3f]; 6442e5b6d6dSopenharmony_ci cnv->charErrorBuffer[1]=toBase64[(c>>2)&0x3f]; 6452e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=2; 6462e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 6472e5b6d6dSopenharmony_ci } 6482e5b6d6dSopenharmony_ci bits=(uint8_t)((c&3)<<4); 6492e5b6d6dSopenharmony_ci base64Counter=2; 6502e5b6d6dSopenharmony_ci break; 6512e5b6d6dSopenharmony_ci case 2: 6522e5b6d6dSopenharmony_ci *target++=toBase64[bits|(c>>12)]; 6532e5b6d6dSopenharmony_ci if(target<targetLimit) { 6542e5b6d6dSopenharmony_ci *target++=toBase64[(c>>6)&0x3f]; 6552e5b6d6dSopenharmony_ci if(target<targetLimit) { 6562e5b6d6dSopenharmony_ci *target++=toBase64[c&0x3f]; 6572e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6582e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6592e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6602e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6612e5b6d6dSopenharmony_ci } 6622e5b6d6dSopenharmony_ci } else { 6632e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6642e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 6652e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6662e5b6d6dSopenharmony_ci } 6672e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=toBase64[c&0x3f]; 6682e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 6692e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 6702e5b6d6dSopenharmony_ci } 6712e5b6d6dSopenharmony_ci } else { 6722e5b6d6dSopenharmony_ci if(offsets!=NULL) { 6732e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 6742e5b6d6dSopenharmony_ci } 6752e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=toBase64[(c>>6)&0x3f]; 6762e5b6d6dSopenharmony_ci cnv->charErrorBuffer[1]=toBase64[c&0x3f]; 6772e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=2; 6782e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 6792e5b6d6dSopenharmony_ci } 6802e5b6d6dSopenharmony_ci bits=0; 6812e5b6d6dSopenharmony_ci base64Counter=0; 6822e5b6d6dSopenharmony_ci break; 6832e5b6d6dSopenharmony_ci default: 6842e5b6d6dSopenharmony_ci /* will never occur */ 6852e5b6d6dSopenharmony_ci break; 6862e5b6d6dSopenharmony_ci } 6872e5b6d6dSopenharmony_ci } 6882e5b6d6dSopenharmony_ci } else { 6892e5b6d6dSopenharmony_ci /* target is full */ 6902e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 6912e5b6d6dSopenharmony_ci break; 6922e5b6d6dSopenharmony_ci } 6932e5b6d6dSopenharmony_ci } 6942e5b6d6dSopenharmony_ci } 6952e5b6d6dSopenharmony_ci 6962e5b6d6dSopenharmony_ci if(pArgs->flush && source>=sourceLimit) { 6972e5b6d6dSopenharmony_ci /* flush remaining bits to the target */ 6982e5b6d6dSopenharmony_ci if(!inDirectMode) { 6992e5b6d6dSopenharmony_ci if (base64Counter!=0) { 7002e5b6d6dSopenharmony_ci if(target<targetLimit) { 7012e5b6d6dSopenharmony_ci *target++=toBase64[bits]; 7022e5b6d6dSopenharmony_ci if(offsets!=NULL) { 7032e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 7042e5b6d6dSopenharmony_ci } 7052e5b6d6dSopenharmony_ci } else { 7062e5b6d6dSopenharmony_ci cnv->charErrorBuffer[cnv->charErrorBufferLength++]=toBase64[bits]; 7072e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 7082e5b6d6dSopenharmony_ci } 7092e5b6d6dSopenharmony_ci } 7102e5b6d6dSopenharmony_ci /* Add final MINUS to terminate unicodeMode */ 7112e5b6d6dSopenharmony_ci if(target<targetLimit) { 7122e5b6d6dSopenharmony_ci *target++=MINUS; 7132e5b6d6dSopenharmony_ci if(offsets!=NULL) { 7142e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 7152e5b6d6dSopenharmony_ci } 7162e5b6d6dSopenharmony_ci } else { 7172e5b6d6dSopenharmony_ci cnv->charErrorBuffer[cnv->charErrorBufferLength++]=MINUS; 7182e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 7192e5b6d6dSopenharmony_ci } 7202e5b6d6dSopenharmony_ci } 7212e5b6d6dSopenharmony_ci /* reset the state for the next conversion */ 7222e5b6d6dSopenharmony_ci cnv->fromUnicodeStatus=(cnv->fromUnicodeStatus&0xf0000000)|0x1000000; /* keep version, inDirectMode=true */ 7232e5b6d6dSopenharmony_ci } else { 7242e5b6d6dSopenharmony_ci /* set the converter state back into UConverter */ 7252e5b6d6dSopenharmony_ci cnv->fromUnicodeStatus= 7262e5b6d6dSopenharmony_ci (cnv->fromUnicodeStatus&0xf0000000)| /* keep version*/ 7272e5b6d6dSopenharmony_ci ((uint32_t)inDirectMode<<24)|((uint32_t)base64Counter<<16)|(uint32_t)bits; 7282e5b6d6dSopenharmony_ci } 7292e5b6d6dSopenharmony_ci 7302e5b6d6dSopenharmony_ci /* write back the updated pointers */ 7312e5b6d6dSopenharmony_ci pArgs->source=source; 7322e5b6d6dSopenharmony_ci pArgs->target=(char *)target; 7332e5b6d6dSopenharmony_ci pArgs->offsets=offsets; 7342e5b6d6dSopenharmony_ci return; 7352e5b6d6dSopenharmony_ci} 7362e5b6d6dSopenharmony_ci 7372e5b6d6dSopenharmony_cistatic const char * U_CALLCONV 7382e5b6d6dSopenharmony_ci_UTF7GetName(const UConverter *cnv) { 7392e5b6d6dSopenharmony_ci switch(cnv->fromUnicodeStatus>>28) { 7402e5b6d6dSopenharmony_ci case 1: 7412e5b6d6dSopenharmony_ci return "UTF-7,version=1"; 7422e5b6d6dSopenharmony_ci default: 7432e5b6d6dSopenharmony_ci return "UTF-7"; 7442e5b6d6dSopenharmony_ci } 7452e5b6d6dSopenharmony_ci} 7462e5b6d6dSopenharmony_ciU_CDECL_END 7472e5b6d6dSopenharmony_ci 7482e5b6d6dSopenharmony_cistatic const UConverterImpl _UTF7Impl={ 7492e5b6d6dSopenharmony_ci UCNV_UTF7, 7502e5b6d6dSopenharmony_ci 7512e5b6d6dSopenharmony_ci NULL, 7522e5b6d6dSopenharmony_ci NULL, 7532e5b6d6dSopenharmony_ci 7542e5b6d6dSopenharmony_ci _UTF7Open, 7552e5b6d6dSopenharmony_ci NULL, 7562e5b6d6dSopenharmony_ci _UTF7Reset, 7572e5b6d6dSopenharmony_ci 7582e5b6d6dSopenharmony_ci _UTF7ToUnicodeWithOffsets, 7592e5b6d6dSopenharmony_ci _UTF7ToUnicodeWithOffsets, 7602e5b6d6dSopenharmony_ci _UTF7FromUnicodeWithOffsets, 7612e5b6d6dSopenharmony_ci _UTF7FromUnicodeWithOffsets, 7622e5b6d6dSopenharmony_ci NULL, 7632e5b6d6dSopenharmony_ci 7642e5b6d6dSopenharmony_ci NULL, 7652e5b6d6dSopenharmony_ci _UTF7GetName, 7662e5b6d6dSopenharmony_ci NULL, /* we don't need writeSub() because we never call a callback at fromUnicode() */ 7672e5b6d6dSopenharmony_ci NULL, 7682e5b6d6dSopenharmony_ci ucnv_getCompleteUnicodeSet, 7692e5b6d6dSopenharmony_ci 7702e5b6d6dSopenharmony_ci NULL, 7712e5b6d6dSopenharmony_ci NULL 7722e5b6d6dSopenharmony_ci}; 7732e5b6d6dSopenharmony_ci 7742e5b6d6dSopenharmony_cistatic const UConverterStaticData _UTF7StaticData={ 7752e5b6d6dSopenharmony_ci sizeof(UConverterStaticData), 7762e5b6d6dSopenharmony_ci "UTF-7", 7772e5b6d6dSopenharmony_ci 0, /* TODO CCSID for UTF-7 */ 7782e5b6d6dSopenharmony_ci UCNV_IBM, UCNV_UTF7, 7792e5b6d6dSopenharmony_ci 1, 4, 7802e5b6d6dSopenharmony_ci { 0x3f, 0, 0, 0 }, 1, /* the subchar is not used */ 7812e5b6d6dSopenharmony_ci false, false, 7822e5b6d6dSopenharmony_ci 0, 7832e5b6d6dSopenharmony_ci 0, 7842e5b6d6dSopenharmony_ci { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */ 7852e5b6d6dSopenharmony_ci}; 7862e5b6d6dSopenharmony_ci 7872e5b6d6dSopenharmony_ciconst UConverterSharedData _UTF7Data= 7882e5b6d6dSopenharmony_ci UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF7StaticData, &_UTF7Impl); 7892e5b6d6dSopenharmony_ci 7902e5b6d6dSopenharmony_ci/* IMAP mailbox name encoding ----------------------------------------------- */ 7912e5b6d6dSopenharmony_ci 7922e5b6d6dSopenharmony_ci/* 7932e5b6d6dSopenharmony_ci * RFC 2060: INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 7942e5b6d6dSopenharmony_ci * http://www.ietf.org/rfc/rfc2060.txt 7952e5b6d6dSopenharmony_ci * 7962e5b6d6dSopenharmony_ci * 5.1.3. Mailbox International Naming Convention 7972e5b6d6dSopenharmony_ci * 7982e5b6d6dSopenharmony_ci * By convention, international mailbox names are specified using a 7992e5b6d6dSopenharmony_ci * modified version of the UTF-7 encoding described in [UTF-7]. The 8002e5b6d6dSopenharmony_ci * purpose of these modifications is to correct the following problems 8012e5b6d6dSopenharmony_ci * with UTF-7: 8022e5b6d6dSopenharmony_ci * 8032e5b6d6dSopenharmony_ci * 1) UTF-7 uses the "+" character for shifting; this conflicts with 8042e5b6d6dSopenharmony_ci * the common use of "+" in mailbox names, in particular USENET 8052e5b6d6dSopenharmony_ci * newsgroup names. 8062e5b6d6dSopenharmony_ci * 8072e5b6d6dSopenharmony_ci * 2) UTF-7's encoding is BASE64 which uses the "/" character; this 8082e5b6d6dSopenharmony_ci * conflicts with the use of "/" as a popular hierarchy delimiter. 8092e5b6d6dSopenharmony_ci * 8102e5b6d6dSopenharmony_ci * 3) UTF-7 prohibits the unencoded usage of "\"; this conflicts with 8112e5b6d6dSopenharmony_ci * the use of "\" as a popular hierarchy delimiter. 8122e5b6d6dSopenharmony_ci * 8132e5b6d6dSopenharmony_ci * 4) UTF-7 prohibits the unencoded usage of "~"; this conflicts with 8142e5b6d6dSopenharmony_ci * the use of "~" in some servers as a home directory indicator. 8152e5b6d6dSopenharmony_ci * 8162e5b6d6dSopenharmony_ci * 5) UTF-7 permits multiple alternate forms to represent the same 8172e5b6d6dSopenharmony_ci * string; in particular, printable US-ASCII characters can be 8182e5b6d6dSopenharmony_ci * represented in encoded form. 8192e5b6d6dSopenharmony_ci * 8202e5b6d6dSopenharmony_ci * In modified UTF-7, printable US-ASCII characters except for "&" 8212e5b6d6dSopenharmony_ci * represent themselves; that is, characters with octet values 0x20-0x25 8222e5b6d6dSopenharmony_ci * and 0x27-0x7e. The character "&" (0x26) is represented by the two- 8232e5b6d6dSopenharmony_ci * octet sequence "&-". 8242e5b6d6dSopenharmony_ci * 8252e5b6d6dSopenharmony_ci * All other characters (octet values 0x00-0x1f, 0x7f-0xff, and all 8262e5b6d6dSopenharmony_ci * Unicode 16-bit octets) are represented in modified BASE64, with a 8272e5b6d6dSopenharmony_ci * further modification from [UTF-7] that "," is used instead of "/". 8282e5b6d6dSopenharmony_ci * Modified BASE64 MUST NOT be used to represent any printing US-ASCII 8292e5b6d6dSopenharmony_ci * character which can represent itself. 8302e5b6d6dSopenharmony_ci * 8312e5b6d6dSopenharmony_ci * "&" is used to shift to modified BASE64 and "-" to shift back to US- 8322e5b6d6dSopenharmony_ci * ASCII. All names start in US-ASCII, and MUST end in US-ASCII (that 8332e5b6d6dSopenharmony_ci * is, a name that ends with a Unicode 16-bit octet MUST end with a "- 8342e5b6d6dSopenharmony_ci * "). 8352e5b6d6dSopenharmony_ci * 8362e5b6d6dSopenharmony_ci * For example, here is a mailbox name which mixes English, Japanese, 8372e5b6d6dSopenharmony_ci * and Chinese text: ~peter/mail/&ZeVnLIqe-/&U,BTFw- 8382e5b6d6dSopenharmony_ci */ 8392e5b6d6dSopenharmony_ci 8402e5b6d6dSopenharmony_ci/* 8412e5b6d6dSopenharmony_ci * Tests for US-ASCII characters belonging to character classes 8422e5b6d6dSopenharmony_ci * defined in UTF-7. 8432e5b6d6dSopenharmony_ci * 8442e5b6d6dSopenharmony_ci * Set D (directly encoded characters) consists of the following 8452e5b6d6dSopenharmony_ci * characters: the upper and lower case letters A through Z 8462e5b6d6dSopenharmony_ci * and a through z, the 10 digits 0-9, and the following nine special 8472e5b6d6dSopenharmony_ci * characters (note that "+" and "=" are omitted): 8482e5b6d6dSopenharmony_ci * '(),-./:? 8492e5b6d6dSopenharmony_ci * 8502e5b6d6dSopenharmony_ci * Set O (optional direct characters) consists of the following 8512e5b6d6dSopenharmony_ci * characters (note that "\" and "~" are omitted): 8522e5b6d6dSopenharmony_ci * !"#$%&*;<=>@[]^_`{|} 8532e5b6d6dSopenharmony_ci * 8542e5b6d6dSopenharmony_ci * According to the rules in RFC 2152, the byte values for the following 8552e5b6d6dSopenharmony_ci * US-ASCII characters are not used in UTF-7 and are therefore illegal: 8562e5b6d6dSopenharmony_ci * - all C0 control codes except for CR LF TAB 8572e5b6d6dSopenharmony_ci * - BACKSLASH 8582e5b6d6dSopenharmony_ci * - TILDE 8592e5b6d6dSopenharmony_ci * - DEL 8602e5b6d6dSopenharmony_ci * - all codes beyond US-ASCII, i.e. all >127 8612e5b6d6dSopenharmony_ci */ 8622e5b6d6dSopenharmony_ci 8632e5b6d6dSopenharmony_ci/* uses '&' not '+' to start a base64 sequence */ 8642e5b6d6dSopenharmony_ci#define AMPERSAND 0x26 8652e5b6d6dSopenharmony_ci#define COMMA 0x2c 8662e5b6d6dSopenharmony_ci#define SLASH 0x2f 8672e5b6d6dSopenharmony_ci 8682e5b6d6dSopenharmony_ci/* legal byte values: all US-ASCII graphic characters 0x20..0x7e */ 8692e5b6d6dSopenharmony_ci#define isLegalIMAP(c) (0x20<=(c) && (c)<=0x7e) 8702e5b6d6dSopenharmony_ci 8712e5b6d6dSopenharmony_ci/* direct-encode all of printable ASCII 0x20..0x7e except '&' 0x26 */ 8722e5b6d6dSopenharmony_ci#define inSetDIMAP(c) (isLegalIMAP(c) && c!=AMPERSAND) 8732e5b6d6dSopenharmony_ci 8742e5b6d6dSopenharmony_ci#define TO_BASE64_IMAP(n) ((n)<63 ? toBase64[n] : COMMA) 8752e5b6d6dSopenharmony_ci#define FROM_BASE64_IMAP(c) ((c)==COMMA ? 63 : (c)==SLASH ? -1 : fromBase64[c]) 8762e5b6d6dSopenharmony_ci 8772e5b6d6dSopenharmony_ci/* 8782e5b6d6dSopenharmony_ci * converter status values: 8792e5b6d6dSopenharmony_ci * 8802e5b6d6dSopenharmony_ci * toUnicodeStatus: 8812e5b6d6dSopenharmony_ci * 24 inDirectMode (boolean) 8822e5b6d6dSopenharmony_ci * 23..16 base64Counter (-1..7) 8832e5b6d6dSopenharmony_ci * 15..0 bits (up to 14 bits incoming base64) 8842e5b6d6dSopenharmony_ci * 8852e5b6d6dSopenharmony_ci * fromUnicodeStatus: 8862e5b6d6dSopenharmony_ci * 24 inDirectMode (boolean) 8872e5b6d6dSopenharmony_ci * 23..16 base64Counter (0..2) 8882e5b6d6dSopenharmony_ci * 7..0 bits (6 bits outgoing base64) 8892e5b6d6dSopenharmony_ci * 8902e5b6d6dSopenharmony_ci * ignore bits 31..25 8912e5b6d6dSopenharmony_ci */ 8922e5b6d6dSopenharmony_ci 8932e5b6d6dSopenharmony_ciU_CDECL_BEGIN 8942e5b6d6dSopenharmony_cistatic void U_CALLCONV 8952e5b6d6dSopenharmony_ci_IMAPToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, 8962e5b6d6dSopenharmony_ci UErrorCode *pErrorCode) { 8972e5b6d6dSopenharmony_ci UConverter *cnv; 8982e5b6d6dSopenharmony_ci const uint8_t *source, *sourceLimit; 8992e5b6d6dSopenharmony_ci UChar *target; 9002e5b6d6dSopenharmony_ci const UChar *targetLimit; 9012e5b6d6dSopenharmony_ci int32_t *offsets; 9022e5b6d6dSopenharmony_ci 9032e5b6d6dSopenharmony_ci uint8_t *bytes; 9042e5b6d6dSopenharmony_ci uint8_t byteIndex; 9052e5b6d6dSopenharmony_ci 9062e5b6d6dSopenharmony_ci int32_t length, targetCapacity; 9072e5b6d6dSopenharmony_ci 9082e5b6d6dSopenharmony_ci /* UTF-7 state */ 9092e5b6d6dSopenharmony_ci uint16_t bits; 9102e5b6d6dSopenharmony_ci int8_t base64Counter; 9112e5b6d6dSopenharmony_ci UBool inDirectMode; 9122e5b6d6dSopenharmony_ci 9132e5b6d6dSopenharmony_ci int8_t base64Value; 9142e5b6d6dSopenharmony_ci 9152e5b6d6dSopenharmony_ci int32_t sourceIndex, nextSourceIndex; 9162e5b6d6dSopenharmony_ci 9172e5b6d6dSopenharmony_ci UChar c; 9182e5b6d6dSopenharmony_ci uint8_t b; 9192e5b6d6dSopenharmony_ci 9202e5b6d6dSopenharmony_ci /* set up the local pointers */ 9212e5b6d6dSopenharmony_ci cnv=pArgs->converter; 9222e5b6d6dSopenharmony_ci 9232e5b6d6dSopenharmony_ci source=(const uint8_t *)pArgs->source; 9242e5b6d6dSopenharmony_ci sourceLimit=(const uint8_t *)pArgs->sourceLimit; 9252e5b6d6dSopenharmony_ci target=pArgs->target; 9262e5b6d6dSopenharmony_ci targetLimit=pArgs->targetLimit; 9272e5b6d6dSopenharmony_ci offsets=pArgs->offsets; 9282e5b6d6dSopenharmony_ci /* get the state machine state */ 9292e5b6d6dSopenharmony_ci { 9302e5b6d6dSopenharmony_ci uint32_t status=cnv->toUnicodeStatus; 9312e5b6d6dSopenharmony_ci inDirectMode=(UBool)((status>>24)&1); 9322e5b6d6dSopenharmony_ci base64Counter=(int8_t)(status>>16); 9332e5b6d6dSopenharmony_ci bits=(uint16_t)status; 9342e5b6d6dSopenharmony_ci } 9352e5b6d6dSopenharmony_ci bytes=cnv->toUBytes; 9362e5b6d6dSopenharmony_ci byteIndex=cnv->toULength; 9372e5b6d6dSopenharmony_ci 9382e5b6d6dSopenharmony_ci /* sourceIndex=-1 if the current character began in the previous buffer */ 9392e5b6d6dSopenharmony_ci sourceIndex=byteIndex==0 ? 0 : -1; 9402e5b6d6dSopenharmony_ci nextSourceIndex=0; 9412e5b6d6dSopenharmony_ci 9422e5b6d6dSopenharmony_ci if(inDirectMode) { 9432e5b6d6dSopenharmony_cidirectMode: 9442e5b6d6dSopenharmony_ci /* 9452e5b6d6dSopenharmony_ci * In Direct Mode, US-ASCII characters are encoded directly, i.e., 9462e5b6d6dSopenharmony_ci * with their US-ASCII byte values. 9472e5b6d6dSopenharmony_ci * An ampersand starts Unicode (or "escape") Mode. 9482e5b6d6dSopenharmony_ci * 9492e5b6d6dSopenharmony_ci * In Direct Mode, only the sourceIndex is used. 9502e5b6d6dSopenharmony_ci */ 9512e5b6d6dSopenharmony_ci byteIndex=0; 9522e5b6d6dSopenharmony_ci length=(int32_t)(sourceLimit-source); 9532e5b6d6dSopenharmony_ci targetCapacity=(int32_t)(targetLimit-target); 9542e5b6d6dSopenharmony_ci if(length>targetCapacity) { 9552e5b6d6dSopenharmony_ci length=targetCapacity; 9562e5b6d6dSopenharmony_ci } 9572e5b6d6dSopenharmony_ci while(length>0) { 9582e5b6d6dSopenharmony_ci b=*source++; 9592e5b6d6dSopenharmony_ci if(!isLegalIMAP(b)) { 9602e5b6d6dSopenharmony_ci /* illegal */ 9612e5b6d6dSopenharmony_ci bytes[0]=b; 9622e5b6d6dSopenharmony_ci byteIndex=1; 9632e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 9642e5b6d6dSopenharmony_ci break; 9652e5b6d6dSopenharmony_ci } else if(b!=AMPERSAND) { 9662e5b6d6dSopenharmony_ci /* write directly encoded character */ 9672e5b6d6dSopenharmony_ci *target++=b; 9682e5b6d6dSopenharmony_ci if(offsets!=NULL) { 9692e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 9702e5b6d6dSopenharmony_ci } 9712e5b6d6dSopenharmony_ci } else /* AMPERSAND */ { 9722e5b6d6dSopenharmony_ci /* switch to Unicode mode */ 9732e5b6d6dSopenharmony_ci nextSourceIndex=++sourceIndex; 9742e5b6d6dSopenharmony_ci inDirectMode=false; 9752e5b6d6dSopenharmony_ci byteIndex=0; 9762e5b6d6dSopenharmony_ci bits=0; 9772e5b6d6dSopenharmony_ci base64Counter=-1; 9782e5b6d6dSopenharmony_ci goto unicodeMode; 9792e5b6d6dSopenharmony_ci } 9802e5b6d6dSopenharmony_ci --length; 9812e5b6d6dSopenharmony_ci } 9822e5b6d6dSopenharmony_ci if(source<sourceLimit && target>=targetLimit) { 9832e5b6d6dSopenharmony_ci /* target is full */ 9842e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 9852e5b6d6dSopenharmony_ci } 9862e5b6d6dSopenharmony_ci } else { 9872e5b6d6dSopenharmony_ciunicodeMode: 9882e5b6d6dSopenharmony_ci /* 9892e5b6d6dSopenharmony_ci * In Unicode (or "escape") Mode, UTF-16BE is base64-encoded. 9902e5b6d6dSopenharmony_ci * The base64 sequence ends with any character that is not in the base64 alphabet. 9912e5b6d6dSopenharmony_ci * A terminating minus sign is consumed. 9922e5b6d6dSopenharmony_ci * US-ASCII must not be base64-ed. 9932e5b6d6dSopenharmony_ci * 9942e5b6d6dSopenharmony_ci * In Unicode Mode, the sourceIndex has the index to the start of the current 9952e5b6d6dSopenharmony_ci * base64 bytes, while nextSourceIndex is precisely parallel to source, 9962e5b6d6dSopenharmony_ci * keeping the index to the following byte. 9972e5b6d6dSopenharmony_ci * Note that in 2 out of 3 cases, UChars overlap within a base64 byte. 9982e5b6d6dSopenharmony_ci */ 9992e5b6d6dSopenharmony_ci while(source<sourceLimit) { 10002e5b6d6dSopenharmony_ci if(target<targetLimit) { 10012e5b6d6dSopenharmony_ci bytes[byteIndex++]=b=*source++; 10022e5b6d6dSopenharmony_ci ++nextSourceIndex; 10032e5b6d6dSopenharmony_ci if(b>0x7e) { 10042e5b6d6dSopenharmony_ci /* illegal - test other illegal US-ASCII values by base64Value==-3 */ 10052e5b6d6dSopenharmony_ci inDirectMode=true; 10062e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 10072e5b6d6dSopenharmony_ci break; 10082e5b6d6dSopenharmony_ci } else if((base64Value=FROM_BASE64_IMAP(b))>=0) { 10092e5b6d6dSopenharmony_ci /* collect base64 bytes into UChars */ 10102e5b6d6dSopenharmony_ci switch(base64Counter) { 10112e5b6d6dSopenharmony_ci case -1: /* -1 is immediately after the & */ 10122e5b6d6dSopenharmony_ci case 0: 10132e5b6d6dSopenharmony_ci bits=base64Value; 10142e5b6d6dSopenharmony_ci base64Counter=1; 10152e5b6d6dSopenharmony_ci break; 10162e5b6d6dSopenharmony_ci case 1: 10172e5b6d6dSopenharmony_ci case 3: 10182e5b6d6dSopenharmony_ci case 4: 10192e5b6d6dSopenharmony_ci case 6: 10202e5b6d6dSopenharmony_ci bits=(uint16_t)((bits<<6)|base64Value); 10212e5b6d6dSopenharmony_ci ++base64Counter; 10222e5b6d6dSopenharmony_ci break; 10232e5b6d6dSopenharmony_ci case 2: 10242e5b6d6dSopenharmony_ci c=(UChar)((bits<<4)|(base64Value>>2)); 10252e5b6d6dSopenharmony_ci if(isLegalIMAP(c)) { 10262e5b6d6dSopenharmony_ci /* illegal */ 10272e5b6d6dSopenharmony_ci inDirectMode=true; 10282e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 10292e5b6d6dSopenharmony_ci goto endloop; 10302e5b6d6dSopenharmony_ci } 10312e5b6d6dSopenharmony_ci *target++=c; 10322e5b6d6dSopenharmony_ci if(offsets!=NULL) { 10332e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 10342e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex-1; 10352e5b6d6dSopenharmony_ci } 10362e5b6d6dSopenharmony_ci bytes[0]=b; /* keep this byte in case an error occurs */ 10372e5b6d6dSopenharmony_ci byteIndex=1; 10382e5b6d6dSopenharmony_ci bits=(uint16_t)(base64Value&3); 10392e5b6d6dSopenharmony_ci base64Counter=3; 10402e5b6d6dSopenharmony_ci break; 10412e5b6d6dSopenharmony_ci case 5: 10422e5b6d6dSopenharmony_ci c=(UChar)((bits<<2)|(base64Value>>4)); 10432e5b6d6dSopenharmony_ci if(isLegalIMAP(c)) { 10442e5b6d6dSopenharmony_ci /* illegal */ 10452e5b6d6dSopenharmony_ci inDirectMode=true; 10462e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 10472e5b6d6dSopenharmony_ci goto endloop; 10482e5b6d6dSopenharmony_ci } 10492e5b6d6dSopenharmony_ci *target++=c; 10502e5b6d6dSopenharmony_ci if(offsets!=NULL) { 10512e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 10522e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex-1; 10532e5b6d6dSopenharmony_ci } 10542e5b6d6dSopenharmony_ci bytes[0]=b; /* keep this byte in case an error occurs */ 10552e5b6d6dSopenharmony_ci byteIndex=1; 10562e5b6d6dSopenharmony_ci bits=(uint16_t)(base64Value&15); 10572e5b6d6dSopenharmony_ci base64Counter=6; 10582e5b6d6dSopenharmony_ci break; 10592e5b6d6dSopenharmony_ci case 7: 10602e5b6d6dSopenharmony_ci c=(UChar)((bits<<6)|base64Value); 10612e5b6d6dSopenharmony_ci if(isLegalIMAP(c)) { 10622e5b6d6dSopenharmony_ci /* illegal */ 10632e5b6d6dSopenharmony_ci inDirectMode=true; 10642e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 10652e5b6d6dSopenharmony_ci goto endloop; 10662e5b6d6dSopenharmony_ci } 10672e5b6d6dSopenharmony_ci *target++=c; 10682e5b6d6dSopenharmony_ci if(offsets!=NULL) { 10692e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 10702e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex; 10712e5b6d6dSopenharmony_ci } 10722e5b6d6dSopenharmony_ci byteIndex=0; 10732e5b6d6dSopenharmony_ci bits=0; 10742e5b6d6dSopenharmony_ci base64Counter=0; 10752e5b6d6dSopenharmony_ci break; 10762e5b6d6dSopenharmony_ci default: 10772e5b6d6dSopenharmony_ci /* will never occur */ 10782e5b6d6dSopenharmony_ci break; 10792e5b6d6dSopenharmony_ci } 10802e5b6d6dSopenharmony_ci } else if(base64Value==-2) { 10812e5b6d6dSopenharmony_ci /* minus sign terminates the base64 sequence */ 10822e5b6d6dSopenharmony_ci inDirectMode=true; 10832e5b6d6dSopenharmony_ci if(base64Counter==-1) { 10842e5b6d6dSopenharmony_ci /* &- i.e. a minus immediately following an ampersand */ 10852e5b6d6dSopenharmony_ci *target++=AMPERSAND; 10862e5b6d6dSopenharmony_ci if(offsets!=NULL) { 10872e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 10882e5b6d6dSopenharmony_ci } 10892e5b6d6dSopenharmony_ci } else { 10902e5b6d6dSopenharmony_ci /* absorb the minus and leave the Unicode Mode */ 10912e5b6d6dSopenharmony_ci if(bits!=0 || (base64Counter!=0 && base64Counter!=3 && base64Counter!=6)) { 10922e5b6d6dSopenharmony_ci /* bits are illegally left over, a UChar is incomplete */ 10932e5b6d6dSopenharmony_ci /* base64Counter other than 0, 3, 6 means non-minimal zero-padding, also illegal */ 10942e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 10952e5b6d6dSopenharmony_ci break; 10962e5b6d6dSopenharmony_ci } 10972e5b6d6dSopenharmony_ci } 10982e5b6d6dSopenharmony_ci sourceIndex=nextSourceIndex; 10992e5b6d6dSopenharmony_ci goto directMode; 11002e5b6d6dSopenharmony_ci } else { 11012e5b6d6dSopenharmony_ci if(base64Counter==-1) { 11022e5b6d6dSopenharmony_ci /* illegal: & immediately followed by something other than base64 or minus sign */ 11032e5b6d6dSopenharmony_ci /* include the ampersand in the reported sequence */ 11042e5b6d6dSopenharmony_ci --sourceIndex; 11052e5b6d6dSopenharmony_ci bytes[0]=AMPERSAND; 11062e5b6d6dSopenharmony_ci bytes[1]=b; 11072e5b6d6dSopenharmony_ci byteIndex=2; 11082e5b6d6dSopenharmony_ci } 11092e5b6d6dSopenharmony_ci /* base64Value==-1 for characters that are illegal only in Unicode mode */ 11102e5b6d6dSopenharmony_ci /* base64Value==-3 for illegal characters */ 11112e5b6d6dSopenharmony_ci /* illegal */ 11122e5b6d6dSopenharmony_ci inDirectMode=true; 11132e5b6d6dSopenharmony_ci *pErrorCode=U_ILLEGAL_CHAR_FOUND; 11142e5b6d6dSopenharmony_ci break; 11152e5b6d6dSopenharmony_ci } 11162e5b6d6dSopenharmony_ci } else { 11172e5b6d6dSopenharmony_ci /* target is full */ 11182e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 11192e5b6d6dSopenharmony_ci break; 11202e5b6d6dSopenharmony_ci } 11212e5b6d6dSopenharmony_ci } 11222e5b6d6dSopenharmony_ci } 11232e5b6d6dSopenharmony_ciendloop: 11242e5b6d6dSopenharmony_ci 11252e5b6d6dSopenharmony_ci /* 11262e5b6d6dSopenharmony_ci * the end of the input stream and detection of truncated input 11272e5b6d6dSopenharmony_ci * are handled by the framework, but here we must check if we are in Unicode 11282e5b6d6dSopenharmony_ci * mode and byteIndex==0 because we must end in direct mode 11292e5b6d6dSopenharmony_ci * 11302e5b6d6dSopenharmony_ci * conditions: 11312e5b6d6dSopenharmony_ci * successful 11322e5b6d6dSopenharmony_ci * in Unicode mode and byteIndex==0 11332e5b6d6dSopenharmony_ci * end of input and no truncated input 11342e5b6d6dSopenharmony_ci */ 11352e5b6d6dSopenharmony_ci if( U_SUCCESS(*pErrorCode) && 11362e5b6d6dSopenharmony_ci !inDirectMode && byteIndex==0 && 11372e5b6d6dSopenharmony_ci pArgs->flush && source>=sourceLimit 11382e5b6d6dSopenharmony_ci ) { 11392e5b6d6dSopenharmony_ci if(base64Counter==-1) { 11402e5b6d6dSopenharmony_ci /* & at the very end of the input */ 11412e5b6d6dSopenharmony_ci /* make the ampersand the reported sequence */ 11422e5b6d6dSopenharmony_ci bytes[0]=AMPERSAND; 11432e5b6d6dSopenharmony_ci byteIndex=1; 11442e5b6d6dSopenharmony_ci } 11452e5b6d6dSopenharmony_ci /* else if(base64Counter!=-1) byteIndex remains 0 because there is no particular byte sequence */ 11462e5b6d6dSopenharmony_ci 11472e5b6d6dSopenharmony_ci inDirectMode=true; /* avoid looping */ 11482e5b6d6dSopenharmony_ci *pErrorCode=U_TRUNCATED_CHAR_FOUND; 11492e5b6d6dSopenharmony_ci } 11502e5b6d6dSopenharmony_ci 11512e5b6d6dSopenharmony_ci /* set the converter state back into UConverter */ 11522e5b6d6dSopenharmony_ci cnv->toUnicodeStatus=((uint32_t)inDirectMode<<24)|((uint32_t)((uint8_t)base64Counter)<<16)|(uint32_t)bits; 11532e5b6d6dSopenharmony_ci cnv->toULength=byteIndex; 11542e5b6d6dSopenharmony_ci 11552e5b6d6dSopenharmony_ci /* write back the updated pointers */ 11562e5b6d6dSopenharmony_ci pArgs->source=(const char *)source; 11572e5b6d6dSopenharmony_ci pArgs->target=target; 11582e5b6d6dSopenharmony_ci pArgs->offsets=offsets; 11592e5b6d6dSopenharmony_ci return; 11602e5b6d6dSopenharmony_ci} 11612e5b6d6dSopenharmony_ci 11622e5b6d6dSopenharmony_cistatic void U_CALLCONV 11632e5b6d6dSopenharmony_ci_IMAPFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, 11642e5b6d6dSopenharmony_ci UErrorCode *pErrorCode) { 11652e5b6d6dSopenharmony_ci UConverter *cnv; 11662e5b6d6dSopenharmony_ci const UChar *source, *sourceLimit; 11672e5b6d6dSopenharmony_ci uint8_t *target, *targetLimit; 11682e5b6d6dSopenharmony_ci int32_t *offsets; 11692e5b6d6dSopenharmony_ci 11702e5b6d6dSopenharmony_ci int32_t length, targetCapacity, sourceIndex; 11712e5b6d6dSopenharmony_ci UChar c; 11722e5b6d6dSopenharmony_ci uint8_t b; 11732e5b6d6dSopenharmony_ci 11742e5b6d6dSopenharmony_ci /* UTF-7 state */ 11752e5b6d6dSopenharmony_ci uint8_t bits; 11762e5b6d6dSopenharmony_ci int8_t base64Counter; 11772e5b6d6dSopenharmony_ci UBool inDirectMode; 11782e5b6d6dSopenharmony_ci 11792e5b6d6dSopenharmony_ci /* set up the local pointers */ 11802e5b6d6dSopenharmony_ci cnv=pArgs->converter; 11812e5b6d6dSopenharmony_ci 11822e5b6d6dSopenharmony_ci /* set up the local pointers */ 11832e5b6d6dSopenharmony_ci source=pArgs->source; 11842e5b6d6dSopenharmony_ci sourceLimit=pArgs->sourceLimit; 11852e5b6d6dSopenharmony_ci target=(uint8_t *)pArgs->target; 11862e5b6d6dSopenharmony_ci targetLimit=(uint8_t *)pArgs->targetLimit; 11872e5b6d6dSopenharmony_ci offsets=pArgs->offsets; 11882e5b6d6dSopenharmony_ci 11892e5b6d6dSopenharmony_ci /* get the state machine state */ 11902e5b6d6dSopenharmony_ci { 11912e5b6d6dSopenharmony_ci uint32_t status=cnv->fromUnicodeStatus; 11922e5b6d6dSopenharmony_ci inDirectMode=(UBool)((status>>24)&1); 11932e5b6d6dSopenharmony_ci base64Counter=(int8_t)(status>>16); 11942e5b6d6dSopenharmony_ci bits=(uint8_t)status; 11952e5b6d6dSopenharmony_ci } 11962e5b6d6dSopenharmony_ci 11972e5b6d6dSopenharmony_ci /* UTF-7 always encodes UTF-16 code units, therefore we need only a simple sourceIndex */ 11982e5b6d6dSopenharmony_ci sourceIndex=0; 11992e5b6d6dSopenharmony_ci 12002e5b6d6dSopenharmony_ci if(inDirectMode) { 12012e5b6d6dSopenharmony_cidirectMode: 12022e5b6d6dSopenharmony_ci length=(int32_t)(sourceLimit-source); 12032e5b6d6dSopenharmony_ci targetCapacity=(int32_t)(targetLimit-target); 12042e5b6d6dSopenharmony_ci if(length>targetCapacity) { 12052e5b6d6dSopenharmony_ci length=targetCapacity; 12062e5b6d6dSopenharmony_ci } 12072e5b6d6dSopenharmony_ci while(length>0) { 12082e5b6d6dSopenharmony_ci c=*source++; 12092e5b6d6dSopenharmony_ci /* encode 0x20..0x7e except '&' directly */ 12102e5b6d6dSopenharmony_ci if(inSetDIMAP(c)) { 12112e5b6d6dSopenharmony_ci /* encode directly */ 12122e5b6d6dSopenharmony_ci *target++=(uint8_t)c; 12132e5b6d6dSopenharmony_ci if(offsets!=NULL) { 12142e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 12152e5b6d6dSopenharmony_ci } 12162e5b6d6dSopenharmony_ci } else if(c==AMPERSAND) { 12172e5b6d6dSopenharmony_ci /* output &- for & */ 12182e5b6d6dSopenharmony_ci *target++=AMPERSAND; 12192e5b6d6dSopenharmony_ci if(target<targetLimit) { 12202e5b6d6dSopenharmony_ci *target++=MINUS; 12212e5b6d6dSopenharmony_ci if(offsets!=NULL) { 12222e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 12232e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 12242e5b6d6dSopenharmony_ci } 12252e5b6d6dSopenharmony_ci /* realign length and targetCapacity */ 12262e5b6d6dSopenharmony_ci goto directMode; 12272e5b6d6dSopenharmony_ci } else { 12282e5b6d6dSopenharmony_ci if(offsets!=NULL) { 12292e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 12302e5b6d6dSopenharmony_ci } 12312e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=MINUS; 12322e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 12332e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 12342e5b6d6dSopenharmony_ci break; 12352e5b6d6dSopenharmony_ci } 12362e5b6d6dSopenharmony_ci } else { 12372e5b6d6dSopenharmony_ci /* un-read this character and switch to Unicode Mode */ 12382e5b6d6dSopenharmony_ci --source; 12392e5b6d6dSopenharmony_ci *target++=AMPERSAND; 12402e5b6d6dSopenharmony_ci if(offsets!=NULL) { 12412e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 12422e5b6d6dSopenharmony_ci } 12432e5b6d6dSopenharmony_ci inDirectMode=false; 12442e5b6d6dSopenharmony_ci base64Counter=0; 12452e5b6d6dSopenharmony_ci goto unicodeMode; 12462e5b6d6dSopenharmony_ci } 12472e5b6d6dSopenharmony_ci --length; 12482e5b6d6dSopenharmony_ci } 12492e5b6d6dSopenharmony_ci if(source<sourceLimit && target>=targetLimit) { 12502e5b6d6dSopenharmony_ci /* target is full */ 12512e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 12522e5b6d6dSopenharmony_ci } 12532e5b6d6dSopenharmony_ci } else { 12542e5b6d6dSopenharmony_ciunicodeMode: 12552e5b6d6dSopenharmony_ci while(source<sourceLimit) { 12562e5b6d6dSopenharmony_ci if(target<targetLimit) { 12572e5b6d6dSopenharmony_ci c=*source++; 12582e5b6d6dSopenharmony_ci if(isLegalIMAP(c)) { 12592e5b6d6dSopenharmony_ci /* encode directly */ 12602e5b6d6dSopenharmony_ci inDirectMode=true; 12612e5b6d6dSopenharmony_ci 12622e5b6d6dSopenharmony_ci /* trick: back out this character to make this easier */ 12632e5b6d6dSopenharmony_ci --source; 12642e5b6d6dSopenharmony_ci 12652e5b6d6dSopenharmony_ci /* terminate the base64 sequence */ 12662e5b6d6dSopenharmony_ci if(base64Counter!=0) { 12672e5b6d6dSopenharmony_ci /* write remaining bits for the previous character */ 12682e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(bits); 12692e5b6d6dSopenharmony_ci if(offsets!=NULL) { 12702e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 12712e5b6d6dSopenharmony_ci } 12722e5b6d6dSopenharmony_ci } 12732e5b6d6dSopenharmony_ci /* need to terminate with a minus */ 12742e5b6d6dSopenharmony_ci if(target<targetLimit) { 12752e5b6d6dSopenharmony_ci *target++=MINUS; 12762e5b6d6dSopenharmony_ci if(offsets!=NULL) { 12772e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 12782e5b6d6dSopenharmony_ci } 12792e5b6d6dSopenharmony_ci } else { 12802e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=MINUS; 12812e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 12822e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 12832e5b6d6dSopenharmony_ci break; 12842e5b6d6dSopenharmony_ci } 12852e5b6d6dSopenharmony_ci goto directMode; 12862e5b6d6dSopenharmony_ci } else { 12872e5b6d6dSopenharmony_ci /* 12882e5b6d6dSopenharmony_ci * base64 this character: 12892e5b6d6dSopenharmony_ci * Output 2 or 3 base64 bytes for the remaining bits of the previous character 12902e5b6d6dSopenharmony_ci * and the bits of this character, each implicitly in UTF-16BE. 12912e5b6d6dSopenharmony_ci * 12922e5b6d6dSopenharmony_ci * Here, bits is an 8-bit variable because only 6 bits need to be kept from one 12932e5b6d6dSopenharmony_ci * character to the next. The actual 2 or 4 bits are shifted to the left edge 12942e5b6d6dSopenharmony_ci * of the 6-bits field 5..0 to make the termination of the base64 sequence easier. 12952e5b6d6dSopenharmony_ci */ 12962e5b6d6dSopenharmony_ci switch(base64Counter) { 12972e5b6d6dSopenharmony_ci case 0: 12982e5b6d6dSopenharmony_ci b=(uint8_t)(c>>10); 12992e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13002e5b6d6dSopenharmony_ci if(target<targetLimit) { 13012e5b6d6dSopenharmony_ci b=(uint8_t)((c>>4)&0x3f); 13022e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13032e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13042e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13052e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13062e5b6d6dSopenharmony_ci } 13072e5b6d6dSopenharmony_ci } else { 13082e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13092e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13102e5b6d6dSopenharmony_ci } 13112e5b6d6dSopenharmony_ci b=(uint8_t)((c>>4)&0x3f); 13122e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=TO_BASE64_IMAP(b); 13132e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 13142e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 13152e5b6d6dSopenharmony_ci } 13162e5b6d6dSopenharmony_ci bits=(uint8_t)((c&15)<<2); 13172e5b6d6dSopenharmony_ci base64Counter=1; 13182e5b6d6dSopenharmony_ci break; 13192e5b6d6dSopenharmony_ci case 1: 13202e5b6d6dSopenharmony_ci b=(uint8_t)(bits|(c>>14)); 13212e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13222e5b6d6dSopenharmony_ci if(target<targetLimit) { 13232e5b6d6dSopenharmony_ci b=(uint8_t)((c>>8)&0x3f); 13242e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13252e5b6d6dSopenharmony_ci if(target<targetLimit) { 13262e5b6d6dSopenharmony_ci b=(uint8_t)((c>>2)&0x3f); 13272e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13282e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13292e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13302e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13312e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13322e5b6d6dSopenharmony_ci } 13332e5b6d6dSopenharmony_ci } else { 13342e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13352e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13362e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13372e5b6d6dSopenharmony_ci } 13382e5b6d6dSopenharmony_ci b=(uint8_t)((c>>2)&0x3f); 13392e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=TO_BASE64_IMAP(b); 13402e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 13412e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 13422e5b6d6dSopenharmony_ci } 13432e5b6d6dSopenharmony_ci } else { 13442e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13452e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13462e5b6d6dSopenharmony_ci } 13472e5b6d6dSopenharmony_ci b=(uint8_t)((c>>8)&0x3f); 13482e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=TO_BASE64_IMAP(b); 13492e5b6d6dSopenharmony_ci b=(uint8_t)((c>>2)&0x3f); 13502e5b6d6dSopenharmony_ci cnv->charErrorBuffer[1]=TO_BASE64_IMAP(b); 13512e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=2; 13522e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 13532e5b6d6dSopenharmony_ci } 13542e5b6d6dSopenharmony_ci bits=(uint8_t)((c&3)<<4); 13552e5b6d6dSopenharmony_ci base64Counter=2; 13562e5b6d6dSopenharmony_ci break; 13572e5b6d6dSopenharmony_ci case 2: 13582e5b6d6dSopenharmony_ci b=(uint8_t)(bits|(c>>12)); 13592e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13602e5b6d6dSopenharmony_ci if(target<targetLimit) { 13612e5b6d6dSopenharmony_ci b=(uint8_t)((c>>6)&0x3f); 13622e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13632e5b6d6dSopenharmony_ci if(target<targetLimit) { 13642e5b6d6dSopenharmony_ci b=(uint8_t)(c&0x3f); 13652e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(b); 13662e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13672e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13682e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13692e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13702e5b6d6dSopenharmony_ci } 13712e5b6d6dSopenharmony_ci } else { 13722e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13732e5b6d6dSopenharmony_ci *offsets++=sourceIndex; 13742e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13752e5b6d6dSopenharmony_ci } 13762e5b6d6dSopenharmony_ci b=(uint8_t)(c&0x3f); 13772e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=TO_BASE64_IMAP(b); 13782e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=1; 13792e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 13802e5b6d6dSopenharmony_ci } 13812e5b6d6dSopenharmony_ci } else { 13822e5b6d6dSopenharmony_ci if(offsets!=NULL) { 13832e5b6d6dSopenharmony_ci *offsets++=sourceIndex++; 13842e5b6d6dSopenharmony_ci } 13852e5b6d6dSopenharmony_ci b=(uint8_t)((c>>6)&0x3f); 13862e5b6d6dSopenharmony_ci cnv->charErrorBuffer[0]=TO_BASE64_IMAP(b); 13872e5b6d6dSopenharmony_ci b=(uint8_t)(c&0x3f); 13882e5b6d6dSopenharmony_ci cnv->charErrorBuffer[1]=TO_BASE64_IMAP(b); 13892e5b6d6dSopenharmony_ci cnv->charErrorBufferLength=2; 13902e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 13912e5b6d6dSopenharmony_ci } 13922e5b6d6dSopenharmony_ci bits=0; 13932e5b6d6dSopenharmony_ci base64Counter=0; 13942e5b6d6dSopenharmony_ci break; 13952e5b6d6dSopenharmony_ci default: 13962e5b6d6dSopenharmony_ci /* will never occur */ 13972e5b6d6dSopenharmony_ci break; 13982e5b6d6dSopenharmony_ci } 13992e5b6d6dSopenharmony_ci } 14002e5b6d6dSopenharmony_ci } else { 14012e5b6d6dSopenharmony_ci /* target is full */ 14022e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 14032e5b6d6dSopenharmony_ci break; 14042e5b6d6dSopenharmony_ci } 14052e5b6d6dSopenharmony_ci } 14062e5b6d6dSopenharmony_ci } 14072e5b6d6dSopenharmony_ci 14082e5b6d6dSopenharmony_ci if(pArgs->flush && source>=sourceLimit) { 14092e5b6d6dSopenharmony_ci /* flush remaining bits to the target */ 14102e5b6d6dSopenharmony_ci if(!inDirectMode) { 14112e5b6d6dSopenharmony_ci if(base64Counter!=0) { 14122e5b6d6dSopenharmony_ci if(target<targetLimit) { 14132e5b6d6dSopenharmony_ci *target++=TO_BASE64_IMAP(bits); 14142e5b6d6dSopenharmony_ci if(offsets!=NULL) { 14152e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 14162e5b6d6dSopenharmony_ci } 14172e5b6d6dSopenharmony_ci } else { 14182e5b6d6dSopenharmony_ci cnv->charErrorBuffer[cnv->charErrorBufferLength++]=TO_BASE64_IMAP(bits); 14192e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 14202e5b6d6dSopenharmony_ci } 14212e5b6d6dSopenharmony_ci } 14222e5b6d6dSopenharmony_ci /* need to terminate with a minus */ 14232e5b6d6dSopenharmony_ci if(target<targetLimit) { 14242e5b6d6dSopenharmony_ci *target++=MINUS; 14252e5b6d6dSopenharmony_ci if(offsets!=NULL) { 14262e5b6d6dSopenharmony_ci *offsets++=sourceIndex-1; 14272e5b6d6dSopenharmony_ci } 14282e5b6d6dSopenharmony_ci } else { 14292e5b6d6dSopenharmony_ci cnv->charErrorBuffer[cnv->charErrorBufferLength++]=MINUS; 14302e5b6d6dSopenharmony_ci *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 14312e5b6d6dSopenharmony_ci } 14322e5b6d6dSopenharmony_ci } 14332e5b6d6dSopenharmony_ci /* reset the state for the next conversion */ 14342e5b6d6dSopenharmony_ci cnv->fromUnicodeStatus=(cnv->fromUnicodeStatus&0xf0000000)|0x1000000; /* keep version, inDirectMode=true */ 14352e5b6d6dSopenharmony_ci } else { 14362e5b6d6dSopenharmony_ci /* set the converter state back into UConverter */ 14372e5b6d6dSopenharmony_ci cnv->fromUnicodeStatus= 14382e5b6d6dSopenharmony_ci (cnv->fromUnicodeStatus&0xf0000000)| /* keep version*/ 14392e5b6d6dSopenharmony_ci ((uint32_t)inDirectMode<<24)|((uint32_t)base64Counter<<16)|(uint32_t)bits; 14402e5b6d6dSopenharmony_ci } 14412e5b6d6dSopenharmony_ci 14422e5b6d6dSopenharmony_ci /* write back the updated pointers */ 14432e5b6d6dSopenharmony_ci pArgs->source=source; 14442e5b6d6dSopenharmony_ci pArgs->target=(char *)target; 14452e5b6d6dSopenharmony_ci pArgs->offsets=offsets; 14462e5b6d6dSopenharmony_ci return; 14472e5b6d6dSopenharmony_ci} 14482e5b6d6dSopenharmony_ciU_CDECL_END 14492e5b6d6dSopenharmony_ci 14502e5b6d6dSopenharmony_cistatic const UConverterImpl _IMAPImpl={ 14512e5b6d6dSopenharmony_ci UCNV_IMAP_MAILBOX, 14522e5b6d6dSopenharmony_ci 14532e5b6d6dSopenharmony_ci NULL, 14542e5b6d6dSopenharmony_ci NULL, 14552e5b6d6dSopenharmony_ci 14562e5b6d6dSopenharmony_ci _UTF7Open, 14572e5b6d6dSopenharmony_ci NULL, 14582e5b6d6dSopenharmony_ci _UTF7Reset, 14592e5b6d6dSopenharmony_ci 14602e5b6d6dSopenharmony_ci _IMAPToUnicodeWithOffsets, 14612e5b6d6dSopenharmony_ci _IMAPToUnicodeWithOffsets, 14622e5b6d6dSopenharmony_ci _IMAPFromUnicodeWithOffsets, 14632e5b6d6dSopenharmony_ci _IMAPFromUnicodeWithOffsets, 14642e5b6d6dSopenharmony_ci NULL, 14652e5b6d6dSopenharmony_ci 14662e5b6d6dSopenharmony_ci NULL, 14672e5b6d6dSopenharmony_ci NULL, 14682e5b6d6dSopenharmony_ci NULL, /* we don't need writeSub() because we never call a callback at fromUnicode() */ 14692e5b6d6dSopenharmony_ci NULL, 14702e5b6d6dSopenharmony_ci ucnv_getCompleteUnicodeSet, 14712e5b6d6dSopenharmony_ci NULL, 14722e5b6d6dSopenharmony_ci NULL 14732e5b6d6dSopenharmony_ci}; 14742e5b6d6dSopenharmony_ci 14752e5b6d6dSopenharmony_cistatic const UConverterStaticData _IMAPStaticData={ 14762e5b6d6dSopenharmony_ci sizeof(UConverterStaticData), 14772e5b6d6dSopenharmony_ci "IMAP-mailbox-name", 14782e5b6d6dSopenharmony_ci 0, /* TODO CCSID for IMAP-mailbox-name */ 14792e5b6d6dSopenharmony_ci UCNV_IBM, UCNV_IMAP_MAILBOX, 14802e5b6d6dSopenharmony_ci 1, 4, 14812e5b6d6dSopenharmony_ci { 0x3f, 0, 0, 0 }, 1, /* the subchar is not used */ 14822e5b6d6dSopenharmony_ci false, false, 14832e5b6d6dSopenharmony_ci 0, 14842e5b6d6dSopenharmony_ci 0, 14852e5b6d6dSopenharmony_ci { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */ 14862e5b6d6dSopenharmony_ci}; 14872e5b6d6dSopenharmony_ci 14882e5b6d6dSopenharmony_ciconst UConverterSharedData _IMAPData= 14892e5b6d6dSopenharmony_ci UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_IMAPStaticData, &_IMAPImpl); 14902e5b6d6dSopenharmony_ci 14912e5b6d6dSopenharmony_ci#endif 1492