• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "text_coder.h"
17 #include "iconv.h"
18 #include "mms_charset.h"
19 #include "securec.h"
20 #include "telephony_log_wrapper.h"
21 
22 namespace OHOS {
23 namespace Telephony {
24 using msg_encode_type_t = uint8_t;
25 using namespace std;
26 static constexpr uint8_t GSM7_DEFLIST_LEN = 128;
27 static constexpr uint8_t UCS2_LEN_MIN = 2;
28 static constexpr uint32_t UCS2_LEN_MAX = INT_MAX / sizeof(WCHAR);
29 
30 const WCHAR GSM7_BIT_TO_UC_S2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC, 0x00F2, 0x00C7,
31     0x000A, 216, 0x00F8, 0x000D, 0x00C5, 0x00E5, 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8, 0x03A3,
32     0x0398, 0x039E, 0x001B, 0x00C6, 0x00E6, 0x00DF, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026,
33     0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034,
34     0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x00A1, 0x0041, 0x0042,
35     0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
36     0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6, 0x00D1, 0x00DC,
37     0x00A7, 0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C,
38     0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A,
39     0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0 };
40 
TextCoder()41 TextCoder::TextCoder()
42 {
43     InitExtCharMap();
44     InitGsm7bitDefMap();
45     InitGsm7bitExtMap();
46     InitTurkishMap();
47     InitSpanishMap();
48     InitPortuMap();
49     InitReplaceCharMap();
50 }
51 
~TextCoder()52 TextCoder::~TextCoder()
53 {
54     extCharMap_.clear();
55     gsm7bitDefMap_.clear();
56     gsm7bitExtMap_.clear();
57     turkishMap_.clear();
58     spanishMap_.clear();
59     portuMap_.clear();
60     replaceCharMap_.clear();
61 }
62 
Instance()63 TextCoder &TextCoder::Instance()
64 {
65     static TextCoder instance;
66     return instance;
67 }
68 
InitExtCharMap()69 void TextCoder::InitExtCharMap()
70 {
71     extCharMap_.clear();
72     extCharMap_ = { { 0x000C, MSG_GSM7EXT_CHAR }, { 0x005B, MSG_GSM7EXT_CHAR }, { 0x005C, MSG_GSM7EXT_CHAR },
73         { 0x005D, MSG_GSM7EXT_CHAR }, { 0x005E, MSG_GSM7EXT_CHAR }, { 0x007B, MSG_GSM7EXT_CHAR },
74         { 0x007C, MSG_GSM7EXT_CHAR }, { 0x007D, MSG_GSM7EXT_CHAR }, { 0x007E, MSG_GSM7EXT_CHAR },
75         { 0x20AC, MSG_GSM7EXT_CHAR }, { 0x00E7, MSG_TURKISH_CHAR }, { 0x011E, MSG_TURKISH_CHAR },
76         { 0x011F, MSG_TURKISH_CHAR }, { 0x01E6, MSG_TURKISH_CHAR }, { 0x01E7, MSG_TURKISH_CHAR },
77         { 0x0130, MSG_TURKISH_CHAR }, { 0x0131, MSG_TURKISH_CHAR }, { 0x015E, MSG_TURKISH_CHAR },
78         { 0x015F, MSG_TURKISH_CHAR }, { 0x00C1, MSG_SPANISH_CHAR }, { 0x00E1, MSG_SPANISH_CHAR },
79         { 0x00CD, MSG_SPANISH_CHAR }, { 0x00ED, MSG_SPANISH_CHAR }, { 0x00D3, MSG_SPANISH_CHAR },
80         { 0x00F3, MSG_SPANISH_CHAR }, { 0x00DA, MSG_SPANISH_CHAR }, { 0x00FA, MSG_SPANISH_CHAR },
81         { 0x00D4, MSG_PORTUGUESE_CHAR }, { 0x00F4, MSG_PORTUGUESE_CHAR }, { 0x00CA, MSG_PORTUGUESE_CHAR },
82         { 0x00EA, MSG_PORTUGUESE_CHAR }, { 0x00C0, MSG_PORTUGUESE_CHAR }, { 0x00E7, MSG_PORTUGUESE_CHAR },
83         { 0x00C3, MSG_PORTUGUESE_CHAR }, { 0x00E3, MSG_PORTUGUESE_CHAR }, { 0x00D5, MSG_PORTUGUESE_CHAR },
84         { 0x00F5, MSG_PORTUGUESE_CHAR }, { 0x00C2, MSG_PORTUGUESE_CHAR }, { 0x00E2, MSG_PORTUGUESE_CHAR } };
85 }
86 
InitGsm7bitDefMap()87 void TextCoder::InitGsm7bitDefMap()
88 {
89     gsm7bitDefMap_.clear();
90     for (uint8_t i = 0; i < GSM7_DEFLIST_LEN; i++) {
91         gsm7bitDefMap_[GSM7_BIT_TO_UC_S2[i]] = i;
92     }
93 }
94 
InitGsm7bitExtMap()95 void TextCoder::InitGsm7bitExtMap()
96 {
97     gsm7bitExtMap_.clear();
98     gsm7bitExtMap_ = { { 0x005B, 0x3C }, { 0x005D, 0x3E }, { 0x007B, 0x28 }, { 0x007D, 0x29 }, { 0x000C, 0x0A },
99         { 0x005C, 0x2F }, { 0x005E, 0x14 }, { 0x007C, 0x40 }, { 0x007E, 0x3D }, { 0x20AC, 0x65 } };
100 }
101 
InitTurkishMap()102 void TextCoder::InitTurkishMap()
103 {
104     // Turkish
105     turkishMap_.clear();
106     turkishMap_ = { { 0x005B, 0x3C }, { 0x005D, 0x3E }, { 0x007B, 0x28 }, { 0x007D, 0x29 }, { 0x000C, 0x0A },
107         { 0x005C, 0x2F }, { 0x005E, 0x14 }, { 0x007C, 0x40 }, { 0x007E, 0x3D }, { 0x20AC, 0x65 }, { 0x00E7, 0x63 },
108         { 0x011E, 0x47 }, { 0x011F, 0x67 }, { 0x01E6, 0x47 }, { 0x01E7, 0x67 }, { 0x0130, 0x49 }, { 0x0131, 0x69 },
109         { 0x015E, 0x53 }, { 0x015F, 0x73 } };
110 }
111 
InitSpanishMap()112 void TextCoder::InitSpanishMap()
113 {
114     // Spanish
115     spanishMap_.clear();
116     spanishMap_ = { { 0x005B, 0x3C }, { 0x005D, 0x3E }, { 0x007B, 0x28 }, { 0x007D, 0x29 }, { 0x000C, 0x0A },
117         { 0x005C, 0x2F }, { 0x005E, 0x14 }, { 0x007C, 0x40 }, { 0x007E, 0x3D }, { 0x20AC, 0x65 }, { 0x00C1, 0x41 },
118         { 0x00E1, 0x61 }, { 0x00CD, 0x49 }, { 0x00ED, 0x69 }, { 0x00D3, 0x4F }, { 0x00F3, 0x6F }, { 0x00DA, 0x55 },
119         { 0x00FA, 0x75 } };
120 }
121 
InitPortuMap()122 void TextCoder::InitPortuMap()
123 {
124     // Portuguese
125     portuMap_.clear();
126     portuMap_ = { { 0x005B, 0x3C }, { 0x005D, 0x3E }, { 0x007B, 0x28 }, { 0x007D, 0x29 }, { 0x000C, 0x0A },
127         { 0x005C, 0x2F }, { 0x005E, 0x14 }, { 0x007C, 0x40 }, { 0x007E, 0x3D }, { 0x20AC, 0x65 }, { 0x00D4, 0x0B },
128         { 0x00F4, 0x0C }, { 0x00C1, 0x0E }, { 0x00E1, 0x0F }, { 0x00CA, 0x1F }, { 0x00EA, 0x05 }, { 0x00C0, 0x41 },
129         { 0x00E7, 0x09 }, { 0x00CD, 0x49 }, { 0x00ED, 0x69 }, { 0x00D3, 0x4F }, { 0x00F3, 0x6F }, { 0x00DA, 0x55 },
130         { 0x00FA, 0x75 }, { 0x00C3, 0x61 }, { 0x00E3, 0x7B }, { 0x00D5, 0x5C }, { 0x00F5, 0x7C }, { 0x00C2, 0x61 },
131         { 0x00E2, 0x7F }, { 0x03A6, 0x12 }, { 0x0393, 0x13 }, { 0x03A9, 0x15 }, { 0x03A0, 0x16 }, { 0x03A8, 0x17 },
132         { 0x03A3, 0x18 }, { 0x0398, 0x19 } };
133 }
134 
InitReplaceCharMap()135 void TextCoder::InitReplaceCharMap()
136 {
137     // character replacement table
138     replaceCharMap_.clear();
139     replaceCharMap_ = { { 0x00E0, 0x61 }, { 0x00E1, 0x61 }, { 0x00E2, 0x61 }, { 0x00E3, 0x61 }, { 0x00E4, 0x61 },
140         { 0x00E5, 0x61 }, { 0x00E6, 0x61 }, { 0x0101, 0x61 }, { 0x0103, 0x61 }, { 0x0105, 0x61 }, { 0x01CE, 0x61 },
141         { 0x00C0, 0x41 }, { 0x00C1, 0x41 }, { 0x00C2, 0x41 }, { 0x00C3, 0x41 }, { 0x00C4, 0x41 }, { 0x00C5, 0x41 },
142         { 0x00C6, 0x41 }, { 0x0100, 0x41 }, { 0x0102, 0x41 }, { 0x0104, 0x41 }, { 0x01CD, 0x41 }, { 0x00E7, 0x63 },
143         { 0x0107, 0x63 }, { 0x0109, 0x63 }, { 0x010B, 0x63 }, { 0x010D, 0x63 }, { 0x00C7, 0x43 }, { 0x0106, 0x43 },
144         { 0x0108, 0x43 }, { 0x010A, 0x43 }, { 0x010C, 0x43 }, { 0x010F, 0x64 }, { 0x0111, 0x64 }, { 0x010E, 0x44 },
145         { 0x0110, 0x44 }, { 0x00E8, 0x65 }, { 0x00E9, 0x65 }, { 0x00EA, 0x65 }, { 0x00EB, 0x65 }, { 0x0113, 0x65 },
146         { 0x0115, 0x65 }, { 0x0117, 0x65 }, { 0x0119, 0x65 }, { 0x011B, 0x65 }, { 0x0259, 0x65 }, { 0x00C8, 0x45 },
147         { 0x00C9, 0x45 }, { 0x00CA, 0x45 }, { 0x00CB, 0x45 }, { 0x0112, 0x45 }, { 0x0114, 0x45 }, { 0x0116, 0x45 },
148         { 0x0118, 0x45 }, { 0x011A, 0x45 }, { 0x018F, 0x45 }, { 0x011D, 0x67 }, { 0x011F, 0x67 }, { 0x0121, 0x67 },
149         { 0x0123, 0x67 }, { 0x01E7, 0x67 }, { 0x01F5, 0x67 }, { 0x1E21, 0x67 }, { 0x011C, 0x47 }, { 0x011E, 0x47 },
150         { 0x0120, 0x47 }, { 0x0122, 0x47 }, { 0x01E6, 0x47 }, { 0x01F4, 0x47 }, { 0x1E20, 0x47 }, { 0x00EC, 0x69 },
151         { 0x00ED, 0x69 }, { 0x00EE, 0x69 }, { 0x00EF, 0x69 }, { 0x0129, 0x69 }, { 0x012B, 0x69 }, { 0x012D, 0x69 },
152         { 0x012F, 0x69 }, { 0x01D0, 0x69 }, { 0x0131, 0x69 }, { 0x00CC, 0x49 }, { 0x00CD, 0x49 }, { 0x00CE, 0x49 },
153         { 0x00CF, 0x49 }, { 0x0128, 0x49 }, { 0x012A, 0x49 }, { 0x012C, 0x49 }, { 0x012E, 0x49 }, { 0x0130, 0x49 },
154         { 0x0137, 0x6B }, { 0x0136, 0x4B }, { 0x013A, 0x6C }, { 0x013C, 0x6C }, { 0x013E, 0x6C }, { 0x0140, 0x6C },
155         { 0x0142, 0x6C }, { 0x0139, 0x4C }, { 0x013B, 0x4C }, { 0x013D, 0x4C }, { 0x013F, 0x4C }, { 0x0141, 0x4C },
156         { 0x00F1, 0x6E }, { 0x0144, 0x6E }, { 0x0146, 0x6E }, { 0x0148, 0x6E }, { 0x00D1, 0x4E }, { 0x0143, 0x4E },
157         { 0x0145, 0x4E }, { 0x0147, 0x4E }, { 0x00F2, 0x6F }, { 0x00F3, 0x6F }, { 0x00F4, 0x6F }, { 0x00F5, 0x6F },
158         { 0x00F6, 0x6F }, { 0x00F8, 0x6F }, { 0x014D, 0x6F }, { 0x014F, 0x6F }, { 0x01D2, 0x6F }, { 0x01EB, 0x6F },
159         { 0x0151, 0x6F }, { 0x0153, 0x6F }, { 0x00D2, 0x4F }, { 0x00D3, 0x4F }, { 0x00D4, 0x4F }, { 0x00D5, 0x4F },
160         { 0x00D6, 0x4F }, { 216, 0x4F }, { 0x014C, 0x4F }, { 0x014E, 0x4F }, { 0x01D1, 0x4F }, { 0x01EA, 0x4F },
161         { 0x0150, 0x4F }, { 0x0152, 0x4F }, { 0x0155, 0x72 }, { 0x0157, 0x72 }, { 0x0159, 0x72 }, { 0x0154, 0x52 },
162         { 0x0156, 0x52 }, { 0x0158, 0x52 }, { 0x015B, 0x73 }, { 0x015D, 0x73 }, { 0x015F, 0x73 }, { 0x0161, 0x73 },
163         { 0x015A, 0x53 }, { 0x015C, 0x53 }, { 0x015E, 0x53 }, { 0x0160, 0x53 }, { 0x00FE, 0x74 }, { 0x0163, 0x74 },
164         { 0x0165, 0x74 }, { 0x0167, 0x74 }, { 0x021B, 0x74 }, { 0x00DE, 0x54 }, { 0x0162, 0x54 }, { 0x0164, 0x54 },
165         { 0x0166, 0x54 }, { 0x00F9, 0x75 }, { 0x00FA, 0x75 }, { 0x00FB, 0x75 }, { 0x00FC, 0x75 }, { 0x0169, 0x75 },
166         { 0x016B, 0x75 }, { 0x016D, 0x75 }, { 0x016F, 0x75 }, { 0x0171, 0x75 }, { 0x0173, 0x75 }, { 0x01D4, 0x75 },
167         { 0x00D9, 0x55 }, { 0x00DA, 0x55 }, { 0x00DB, 0x55 }, { 0x00DC, 0x55 }, { 0x0168, 0x55 }, { 0x016A, 0x55 },
168         { 0x016C, 0x55 }, { 0x016E, 0x55 }, { 0x0170, 0x55 }, { 0x0172, 0x55 }, { 0x01D3, 0x55 }, { 0x00FD, 0x79 },
169         { 0x00FF, 0x79 }, { 0x0177, 0x79 }, { 0x0233, 0x79 }, { 0x1EF3, 0x79 }, { 0x1EF9, 0x79 }, { 0x00DD, 0x59 },
170         { 0x0176, 0x59 }, { 0x0178, 0x59 }, { 0x0232, 0x59 }, { 0x1EF2, 0x59 }, { 0x1EF8, 0x59 }, { 0x017A, 0x7A },
171         { 0x017C, 0x7A }, { 0x017E, 0x7A }, { 0x0179, 0x5A }, { 0x017B, 0x5A }, { 0x017D, 0x5A } };
172 }
173 
GetEncodeString(std::string & encodeString,uint32_t charset,uint32_t valLength,const std::string & strEncodeString)174 bool TextCoder::GetEncodeString(
175     std::string &encodeString, uint32_t charset, uint32_t valLength, const std::string &strEncodeString)
176 {
177     std::string strToCodeset("UTF-8");
178     std::string strFromCodeset;
179     auto charSetInstance = DelayedSingleton<MmsCharSet>::GetInstance();
180     if (charSetInstance == nullptr || (!charSetInstance->GetCharSetStrFromInt(strFromCodeset, charset))) {
181         strFromCodeset = "UTF-8";
182     }
183     iconv_t cd = iconv_open(strToCodeset.c_str(), strFromCodeset.c_str());
184     if (cd == reinterpret_cast<iconv_t>(-1)) {
185         TELEPHONY_LOGE("GetEncodeString iconv_open failed");
186         return false;
187     }
188     size_t inLen = static_cast<size_t>(valLength);
189     auto outBufSize = strEncodeString.size() * 4;
190     std::unique_ptr<char[]> outBufPtr = std::make_unique<char[]>(outBufSize);
191     char *outBuf = outBufPtr.get();
192     char *inBuf = const_cast<char*>(strEncodeString.c_str());
193     size_t err = iconv(cd, &inBuf, &inLen, &outBuf, &outBufSize);
194     iconv_close(cd);
195     if (static_cast<int>(err) == -1) {
196         TELEPHONY_LOGE("iconv conversion failed");
197         return false;
198     }
199     encodeString = std::string(outBufPtr.get(), outBuf - outBufPtr.get());
200     return true;
201 }
202 
203 /**
204  * @brief Utf8ToGsm7bit
205  * max # of Ucs2 chars, NOT bytes. when all utf8 chars are only one byte,
206  * Ucs2Length is maxUcs2 Length. otherwise (ex: 2 bytes of UTF8 is one char)
207  * Ucs2Length must be  less than utf8Length
208  */
Utf8ToGsm7bit(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,MSG_LANGUAGE_ID_T & langId)209 int TextCoder::Utf8ToGsm7bit(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, MSG_LANGUAGE_ID_T &langId)
210 {
211     if (srcLength == -1 && src) {
212         // null terminated string
213         srcLength = strlen(reinterpret_cast<const char *>(src));
214     }
215     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
216         TELEPHONY_LOGE("text is null");
217         return 0;
218     }
219 
220     int maxUcs2Length = srcLength;
221     if (static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
222         TELEPHONY_LOGE("src over size");
223         return 0;
224     }
225     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
226     if (ucs2Text == nullptr) {
227         TELEPHONY_LOGE("make_unique error");
228         return 0;
229     }
230     WCHAR *pUcs2Text = ucs2Text.get();
231     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
232         TELEPHONY_LOGE("memset_s error");
233         return 0;
234     }
235 
236     TELEPHONY_LOGI("srcLength = %{public}d", srcLength);
237     int ucs2Length = Utf8ToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength);
238     return Ucs2ToGsm7bit(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length, langId);
239 }
240 
Utf8ToUcs2(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)241 int TextCoder::Utf8ToUcs2(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
242 {
243     if (srcLength == -1 && src) {
244         // null terminated string
245         srcLength = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(src)));
246     }
247     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
248         TELEPHONY_LOGE("text is null");
249         return 0;
250     }
251 
252     size_t textLen = static_cast<size_t>(srcLength);
253     auto unicodeTemp = reinterpret_cast<uint8_t *>(dest);
254     size_t remainedLength = static_cast<size_t>(maxLength);
255     iconv_t cd = iconv_open("UTF16BE", "UTF8");
256     if (cd == reinterpret_cast<iconv_t>(-1)) {
257         TELEPHONY_LOGE("Utf8ToUcs2-iconv_open is error");
258         return 0;
259     }
260     size_t err = iconv(cd, reinterpret_cast<char **>(const_cast<uint8_t **>(&src)), &textLen,
261         reinterpret_cast<char **>(&unicodeTemp), &remainedLength);
262     iconv_close(cd);
263     return (static_cast<int>(err) == -1) ? -1 : (maxLength - static_cast<int>(remainedLength));
264 }
265 
GsmUtf8ToAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,DataCodingScheme & scheme,SmsCodingNationalType codingNationalType,MSG_LANGUAGE_ID_T & langId)266 int TextCoder::GsmUtf8ToAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength,
267     DataCodingScheme &scheme, SmsCodingNationalType codingNationalType, MSG_LANGUAGE_ID_T &langId)
268 {
269     int maxUcs2Length = srcLength;
270     if (maxUcs2Length <= 0 || static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
271         TELEPHONY_LOGE("src over size");
272         return 0;
273     }
274     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
275     if (ucs2Text == nullptr) {
276         TELEPHONY_LOGE("GsmUtf8ToAuto make_unique error");
277         return 0;
278     }
279     WCHAR *pUcs2Text = ucs2Text.get();
280     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
281         TELEPHONY_LOGE("GsmUtf8ToAuto memset_s error");
282         return 0;
283     }
284     int ucs2Length = Utf8ToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength);
285     int tempTextLen = 0;
286     if (ucs2Length < 0) {
287         scheme = DATA_CODING_8BIT;
288         tempTextLen = (srcLength > maxLength) ? maxLength : srcLength;
289         if (memcpy_s(dest, tempTextLen, src, tempTextLen) != EOK) {
290             TELEPHONY_LOGE("GsmUtf8ToAuto memcpy_s error");
291         }
292         return tempTextLen;
293     }
294     bool unknown = false;
295     int length = Ucs2ToGsm7bitAuto(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length,
296         unknown, codingNationalType);
297     if (unknown) {
298         scheme = DATA_CODING_UCS2;
299         if (ucs2Length <= 0) {
300             return length;
301         }
302         tempTextLen = (ucs2Length > maxLength) ? maxLength : ucs2Length;
303         if (memcpy_s(dest, tempTextLen, pUcs2Text, tempTextLen) != EOK) {
304             TELEPHONY_LOGE("memcpy_s error");
305         }
306         return tempTextLen;
307     }
308     langId = static_cast<MSG_LANGUAGE_ID_T>(codingNationalType);
309     scheme = DATA_CODING_7BIT;
310     return length;
311 }
312 
CdmaUtf8ToAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,DataCodingScheme & scheme)313 int TextCoder::CdmaUtf8ToAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, DataCodingScheme &scheme)
314 {
315     int maxUcs2Length = srcLength;
316     if (maxUcs2Length <= 0 || static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
317         TELEPHONY_LOGE("CdmaUtf8ToAuto src over size");
318         return 0;
319     }
320     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
321     if (ucs2Text == nullptr) {
322         TELEPHONY_LOGE("CdmaUtf8ToAuto make_unique error");
323         return 0;
324     }
325     WCHAR *pUcs2Text = ucs2Text.get();
326     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
327         TELEPHONY_LOGE("CdmaUtf8ToAuto memset_s error");
328         return 0;
329     }
330     int ucs2Length = Utf8ToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength);
331     int tempTextLen = 0;
332     if (ucs2Length < 0) {
333         scheme = DATA_CODING_8BIT;
334         tempTextLen = (srcLength > maxLength) ? maxLength : srcLength;
335         if (memcpy_s(dest, tempTextLen, src, tempTextLen) != EOK) {
336             TELEPHONY_LOGE("memcpy_s error");
337         }
338         return tempTextLen;
339     }
340     bool unknown = false;
341     int gsm7bitLength = Ucs2ToAscii(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length, unknown);
342     if (unknown) {
343         scheme = DATA_CODING_UCS2;
344         if (ucs2Length <= 0) {
345             return gsm7bitLength;
346         }
347         tempTextLen = (ucs2Length > maxLength) ? maxLength : ucs2Length;
348         if (memcpy_s(dest, tempTextLen, pUcs2Text, tempTextLen) != EOK) {
349             TELEPHONY_LOGE("memcpy_s error");
350         }
351         return tempTextLen;
352     }
353     scheme = DATA_CODING_ASCII7BIT;
354     return gsm7bitLength;
355 }
356 
357 /**
358  * @brief Gsm7bitToUtf8
359  * max # of Ucs2 chars, NOT bytes. when all gsm7 chars are only one byte(-there is no extension)
360  * Ucs2Length is maxUcs2 Length. otherwise(ex: gsm7 char starts with 0x1b)
361  * Ucs2Length must be less than gsm7 length
362  */
Gsm7bitToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,const MsgLangInfo & langInfo)363 int TextCoder::Gsm7bitToUtf8(
364     uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, const MsgLangInfo &langInfo)
365 {
366     int maxUcs2Length = srcLength;
367     if (maxUcs2Length <= 0 || static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
368         TELEPHONY_LOGE("Gsm7bitToUtf8 src over size");
369         return 0;
370     }
371     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
372     if (ucs2Text == nullptr) {
373         TELEPHONY_LOGE("Gsm7bitToUtf8 make_unique error");
374         return 0;
375     }
376     WCHAR *pUcs2Text = ucs2Text.get();
377     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
378         TELEPHONY_LOGE("Gsm7bitToUtf8 memset_s error");
379         return 0;
380     }
381     TELEPHONY_LOGI("max dest Length = %{public}d, srcLength = %{public}d", maxLength, srcLength);
382     int ucs2Length =
383         Gsm7bitToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength, langInfo);
384     if (ucs2Length > maxLength) {
385         // Usually, maxLength is a large number, like 1530, 4200. But when you decode the address, maxLength is only 21.
386         // (according to section 9/1/2/5 in 3gpp 23040). When the code is converted to UCS2, the length is doubled,
387         // that is, the length is greater than maxUcs2Length * sizeof(WCHAR) should be considered a failure.
388         // If the value of maxLength is large(1530 4200), and the first condition is met, this condition is also met,
389         // and there is no impact.
390         if (ucs2Length > static_cast<int>(maxUcs2Length * sizeof(WCHAR))) {
391             TELEPHONY_LOGI("src over size, ucs2Length = %{public}d, maxLength = %{public}d", ucs2Length,
392                 static_cast<int>(maxUcs2Length * sizeof(WCHAR)));
393             return 0;
394         }
395     }
396     return Ucs2ToUtf8(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length);
397 }
398 
Ucs2ToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)399 int TextCoder::Ucs2ToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
400 {
401     if (srcLength == -1 && src) {
402         TELEPHONY_LOGE("stcLength == -1 && src branch");
403         // null terminated string
404         srcLength = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(src)));
405     }
406     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
407         TELEPHONY_LOGE("text is null");
408         return 0;
409     }
410 
411     size_t  textLen = static_cast<size_t >(srcLength);
412     size_t  remainedLength = static_cast<size_t >(maxLength);
413     iconv_t cd = iconv_open("UTF8", "UTF16BE");
414     if (cd == reinterpret_cast<iconv_t>(-1)) {
415         TELEPHONY_LOGE("Ucs2ToUtf8 iconv_open is error");
416         return 0;
417     }
418     size_t err = iconv(cd, reinterpret_cast<char **>(const_cast<uint8_t **>(&src)),
419         reinterpret_cast<size_t *>(&textLen), reinterpret_cast<char **>(&dest),
420         reinterpret_cast<size_t *>(&remainedLength));
421     iconv_close(cd);
422     if (static_cast<int>(err) == -1) {
423         TELEPHONY_LOGE("Ucs2ToUtf8-iconv result is err");
424         return 0;
425     }
426     int length = maxLength - static_cast<int>(remainedLength);
427     if (length < 0 || length >= maxLength) {
428         return 0;
429     }
430     return length;
431 }
432 
EuckrToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)433 int TextCoder::EuckrToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
434 {
435     if (srcLength == -1 && src) {
436         // null terminated string
437         srcLength = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(src)));
438     }
439     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
440         TELEPHONY_LOGE("text is null");
441         return 0;
442     }
443 
444     size_t remainedLength = static_cast<size_t>(maxLength);
445     size_t textLen = static_cast<size_t>(srcLength);
446     iconv_t cd = iconv_open("UTF8", "EUCKR");
447     if (cd == reinterpret_cast<iconv_t>(-1)) {
448         TELEPHONY_LOGE("EuckrToUtf8 iconv_open is error");
449         return 0;
450     }
451     size_t err = iconv(cd, reinterpret_cast<char **>(const_cast<uint8_t **>(&src)),
452         reinterpret_cast<size_t *>(&textLen), reinterpret_cast<char **>(&dest),
453         reinterpret_cast<size_t *>(&remainedLength));
454     if (static_cast<int>(err) == -1) {
455         TELEPHONY_LOGE("EuckrToUtf8 iconv result is err");
456         return 0;
457     }
458     int utf8Length = maxLength - static_cast<int>(remainedLength);
459     if (utf8Length < 0 || utf8Length >= maxLength) {
460         return 0;
461     }
462     dest[utf8Length] = 0x00;
463     return utf8Length;
464 }
465 
ShiftjisToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength) const466 int TextCoder::ShiftjisToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength) const
467 {
468     if (srcLength == -1 && src) {
469         // null terminated string
470         srcLength = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(src)));
471     }
472     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
473         TELEPHONY_LOGE("text is null");
474         return 0;
475     }
476 
477     size_t textLen = static_cast<size_t>(srcLength);
478     size_t remainedLength = static_cast<size_t>(maxLength);
479     iconv_t cd = iconv_open("UTF8", "SHIFT-JIS");
480     if (cd == reinterpret_cast<iconv_t>(-1)) {
481         TELEPHONY_LOGE("ShiftjisToUtf8 iconv_open is error");
482         return 0;
483     }
484     size_t err = iconv(cd, reinterpret_cast<char **>(const_cast<uint8_t **>(&src)),
485         reinterpret_cast<size_t *>(&textLen), reinterpret_cast<char **>(&dest),
486         reinterpret_cast<size_t *>(&remainedLength));
487     iconv_close(cd);
488     if (static_cast<int>(err) == -1) {
489         TELEPHONY_LOGE("ShiftjisToUtf8 iconv result is err");
490         return 0;
491     }
492     int utf8Length = maxLength - static_cast<int>(remainedLength);
493     if (utf8Length < 0 || utf8Length >= maxLength) {
494         return 0;
495     }
496     dest[utf8Length] = 0x00;
497     return utf8Length;
498 }
499 
Ucs2ToGsm7bit(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,MSG_LANGUAGE_ID_T & langId)500 int TextCoder::Ucs2ToGsm7bit(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, MSG_LANGUAGE_ID_T &langId)
501 {
502     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
503         TELEPHONY_LOGE("text is null");
504         return -1;
505     }
506     int outTextLen = 0;
507     int remainLen = 0;
508     uint16_t inText = 0;
509     uint8_t currType = GetLangType(src, srcLength);
510     std::map<uint16_t, uint8_t>::iterator itChar;
511     for (int index = 0; index < (srcLength - 1); index += UCS2_LEN_MIN) {
512         inText = src[index];
513         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
514         itChar = gsm7bitDefMap_.find(inText); // check gsm7bit default char
515         if (itChar != gsm7bitDefMap_.end()) {
516             dest[outTextLen++] = static_cast<uint8_t>(itChar->second);
517         } else {
518             switch (currType) {
519                 case MSG_GSM7EXT_CHAR:
520                     remainLen = maxLength - outTextLen;
521                     outTextLen += FindGsm7bitExt(&dest[outTextLen], remainLen, inText);
522                     break;
523                 case MSG_TURKISH_CHAR:
524                     langId = MSG_ID_TURKISH_LANG;
525                     remainLen = maxLength - outTextLen;
526                     outTextLen += FindTurkish(&dest[outTextLen], remainLen, inText);
527                     break;
528                 case MSG_SPANISH_CHAR:
529                     langId = MSG_ID_SPANISH_LANG;
530                     remainLen = maxLength - outTextLen;
531                     outTextLen += FindSpanish(&dest[outTextLen], remainLen, inText);
532                     break;
533                 case MSG_PORTUGUESE_CHAR:
534                     langId = MSG_ID_PORTUGUESE_LANG;
535                     remainLen = maxLength - outTextLen;
536                     outTextLen += FindPortu(&dest[outTextLen], remainLen, inText);
537                     break;
538                 default:
539                     dest[outTextLen] = FindReplaceChar(inText);
540                     break;
541             }
542             outTextLen++;
543         }
544         // prevent buffer overflow
545         if (maxLength <= outTextLen) {
546             TELEPHONY_LOGE("buffer overflow");
547             break;
548         }
549     }
550     return outTextLen;
551 }
552 
Get7BitCodingExtMap(SmsCodingNationalType codingNationalType) const553 std::map<uint16_t, uint8_t> TextCoder::Get7BitCodingExtMap(SmsCodingNationalType codingNationalType) const
554 {
555     std::map<uint16_t, uint8_t> extMap = gsm7bitExtMap_;
556     switch (codingNationalType) {
557         case SMS_CODING_NATIONAL_TYPE_DEFAULT:
558             extMap = gsm7bitExtMap_;
559             break;
560         case SMS_CODING_NATIONAL_TYPE_TURKISH:
561             extMap = turkishMap_;
562             break;
563         case SMS_CODING_NATIONAL_TYPE_SPANISH:
564             extMap = spanishMap_;
565             break;
566         case SMS_CODING_NATIONAL_TYPE_PORTUGUESE:
567             extMap = portuMap_;
568             break;
569         default:
570             extMap = gsm7bitExtMap_;
571             break;
572     }
573     return extMap;
574 }
575 
Ucs2ToGsm7bitAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,bool & unknown,SmsCodingNationalType codingNationalType)576 int TextCoder::Ucs2ToGsm7bitAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength,
577     bool &unknown, SmsCodingNationalType codingNationalType)
578 {
579     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
580         TELEPHONY_LOGE("text is null");
581         return -1;
582     }
583 
584     std::map<uint16_t, uint8_t> extMap = Get7BitCodingExtMap(codingNationalType);
585     int outTextLen = 0;
586     std::map<uint16_t, uint8_t>::iterator itChar;
587     std::map<uint16_t, uint8_t>::iterator itExt;
588     uint16_t inText;
589     for (int i = 0; i < srcLength - 1; i += UCS2_LEN_MIN) {
590         inText = src[i];
591         inText = ((inText << 0x08) & 0xFF00) | src[i + 1];
592         itChar = gsm7bitDefMap_.find(inText); // check gsm7bit default char
593         if (itChar != gsm7bitDefMap_.end()) {
594             dest[outTextLen++] = static_cast<uint8_t>(itChar->second);
595         } else {
596             itExt = extMap.find(inText);
597             if (itExt == extMap.end()) {
598                 TELEPHONY_LOGI("Abnormal character is included. inText : [%{public}04x]", inText);
599                 unknown = true;
600                 return 0;
601             }
602             if (maxLength <= outTextLen + 1) {
603                 TELEPHONY_LOGE("buffer overflow.");
604                 break;
605             }
606             dest[outTextLen++] = 0x1B;
607             dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
608         }
609         // prevent buffer overflow
610         if (maxLength <= outTextLen) {
611             TELEPHONY_LOGE("buffer overflow");
612             break;
613         }
614     }
615     return outTextLen;
616 }
617 
Ucs2ToAscii(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,bool & unknown)618 int TextCoder::Ucs2ToAscii(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, bool &unknown)
619 {
620     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
621         TELEPHONY_LOGE("text is null");
622         return -1;
623     }
624 
625     int outTextLen = 0;
626     std::map<uint16_t, uint8_t>::iterator itChar;
627     std::map<uint16_t, uint8_t>::iterator itExt;
628     uint16_t inText;
629     for (int index = 0; index < srcLength - 1; index += UCS2_LEN_MIN) {
630         inText = src[index];
631         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
632         // check default char
633         if (inText > 0x007f) {
634             TELEPHONY_LOGI("abnormal character is included [%{public}04x]", inText);
635             unknown = true;
636             return 0;
637         }
638         dest[outTextLen++] = static_cast<uint8_t>(inText);
639         // prevent buffer overflow
640         if (maxLength <= outTextLen) {
641             TELEPHONY_LOGE("buffer overflow");
642             break;
643         }
644     }
645     return outTextLen;
646 }
647 
GetLangType(const uint8_t * src,int srcLength)648 uint8_t TextCoder::GetLangType(const uint8_t *src, int srcLength)
649 {
650     if (srcLength <= 0 || src == nullptr) {
651         TELEPHONY_LOGE("text is null");
652         return MSG_DEFAULT_CHAR;
653     }
654 
655     std::map<uint16_t, uint8_t>::iterator itExt;
656     uint8_t currType = MSG_DEFAULT_CHAR;
657     uint8_t newType = MSG_DEFAULT_CHAR;
658     uint16_t inText;
659     for (int index = 0; index < (srcLength - 1); index += UCS2_LEN_MIN) {
660         inText = src[index];
661         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
662         itExt = extCharMap_.find(inText);
663         if (itExt == extCharMap_.end()) {
664             continue;
665         }
666         newType = static_cast<uint8_t>(itExt->second);
667         if (newType >= currType) {
668             bool isTurkisk = (inText == 0x00e7 && currType <= MSG_TURKISH_CHAR);
669             currType = isTurkisk ? MSG_TURKISH_CHAR : newType;
670         }
671     }
672     TELEPHONY_LOGI("charType : [%{public}hhu]", currType);
673     return currType;
674 }
675 
FindGsm7bitExt(uint8_t * dest,int maxLength,const uint16_t inText)676 int TextCoder::FindGsm7bitExt(uint8_t *dest, int maxLength, const uint16_t inText)
677 {
678     int outTextLen = 0;
679     if (dest == nullptr || maxLength <= 0) {
680         TELEPHONY_LOGE("Invalid parameter.");
681         return outTextLen;
682     }
683 
684     auto itExt = gsm7bitExtMap_.find(inText);
685     if (itExt == gsm7bitExtMap_.end()) {
686         dest[outTextLen++] = FindReplaceChar(inText);
687         return outTextLen;
688     }
689     // prevent buffer overflow
690     if (maxLength <= outTextLen + 1) {
691         TELEPHONY_LOGE("FindGsm7bitExt buffer overflow");
692         return outTextLen;
693     }
694     dest[outTextLen++] = 0x1B;
695     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
696     return outTextLen;
697 }
698 
FindTurkish(uint8_t * dest,int maxLength,const uint16_t inText)699 int TextCoder::FindTurkish(uint8_t *dest, int maxLength, const uint16_t inText)
700 {
701     int outTextLen = 0;
702     if (dest == nullptr || maxLength <= 0) {
703         TELEPHONY_LOGE("Invalid parameter.");
704         return outTextLen;
705     }
706 
707     auto itExt = turkishMap_.find(inText);
708     if (itExt == turkishMap_.end()) {
709         dest[outTextLen++] = FindReplaceChar(inText);
710         return outTextLen;
711     }
712     // prevent buffer overflow
713     if (maxLength <= outTextLen + 1) {
714         TELEPHONY_LOGE("FindTurkish buffer overflow");
715         return outTextLen;
716     }
717     dest[outTextLen++] = 0x1B;
718     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
719     return outTextLen;
720 }
721 
FindSpanish(uint8_t * dest,int maxLength,const uint16_t inText)722 int TextCoder::FindSpanish(uint8_t *dest, int maxLength, const uint16_t inText)
723 {
724     int outTextLen = 0;
725     if (dest == nullptr || maxLength <= 0) {
726         TELEPHONY_LOGE("Invalid parameter.");
727         return outTextLen;
728     }
729 
730     auto itExt = spanishMap_.find(inText);
731     if (itExt == spanishMap_.end()) {
732         dest[outTextLen++] = FindReplaceChar(inText);
733         return outTextLen;
734     }
735     // prevent buffer overflow
736     if (maxLength <= outTextLen + 1) {
737         TELEPHONY_LOGE("FindSpanish buffer overflow");
738         return outTextLen;
739     }
740     dest[outTextLen++] = 0x1B;
741     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
742     return outTextLen;
743 }
744 
FindPortu(uint8_t * dest,int maxLength,const uint16_t inText)745 int TextCoder::FindPortu(uint8_t *dest, int maxLength, const uint16_t inText)
746 {
747     int outTextLen = 0;
748     if (dest == nullptr || maxLength <= 0) {
749         TELEPHONY_LOGE("Invalid parameter.");
750         return outTextLen;
751     }
752 
753     auto itExt = portuMap_.find(inText);
754     if (itExt == portuMap_.end()) {
755         dest[outTextLen++] = FindReplaceChar(inText);
756         return outTextLen;
757     }
758     // prevent buffer overflow
759     if (maxLength <= outTextLen + 1) {
760         TELEPHONY_LOGE("FindPortu buffer overflow");
761         return outTextLen;
762     }
763     dest[outTextLen++] = 0x1B;
764     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
765     return outTextLen;
766 }
767 
FindReplaceChar(const uint16_t inText)768 uint8_t TextCoder::FindReplaceChar(const uint16_t inText)
769 {
770     uint8_t result = 0;
771     auto itReplace = replaceCharMap_.find(inText);
772     if (itReplace != replaceCharMap_.end()) {
773         result = static_cast<uint8_t>(itReplace->second);
774     } else {
775         result = 0x3F;
776     }
777     return result;
778 }
779 
Gsm7bitToUcs2(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,const MsgLangInfo & langInfo)780 int TextCoder::Gsm7bitToUcs2(
781     uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, const MsgLangInfo &langInfo)
782 {
783     if (srcLength == 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
784         TELEPHONY_LOGE("text is null");
785         return -1;
786     }
787 
788     int outTextLen = 0;
789     uint8_t lowerByte = 0;
790     uint8_t upperByte = 0;
791     uint16_t result = 0;
792     for (int i = 0; i < srcLength && maxLength > UCS2_LEN_MIN; i++) {
793         if (src[i] >= 0x80) {
794             TELEPHONY_LOGE("a_pTextString[%{public}d]=%{public}x, The alpha isn't the gsm 7bit code", i, src[i]);
795             return -1;
796         }
797         if (langInfo.bLockingShift) {
798             TELEPHONY_LOGI("National Language Locking Shift [%{public}d]", langInfo.lockingLang);
799             if (langInfo.lockingLang == MSG_ID_TURKISH_LANG) {
800                 i += EscapeTurkishLockingToUcs2(&src[i], (srcLength - i), langInfo, result);
801                 lowerByte = static_cast<uint8_t>(result & 0x00FF);
802                 upperByte = static_cast<uint8_t>(result >> 0x08);
803             } else if (langInfo.lockingLang == MSG_ID_PORTUGUESE_LANG) {
804                 i += EscapePortuLockingToUcs2(&src[i], (srcLength - i), langInfo, result);
805                 lowerByte = static_cast<uint8_t>(result & 0x00FF);
806                 upperByte = static_cast<uint8_t>(result >> 0x08);
807             }
808         } else {
809             i += EscapeGsm7bitToUcs2(&src[i], (srcLength - i), langInfo, result);
810             lowerByte = static_cast<uint8_t>(result & 0x00FF);
811             upperByte = static_cast<uint8_t>(result >> 0x08);
812         }
813         dest[outTextLen++] = upperByte;
814         dest[outTextLen++] = lowerByte;
815         maxLength -= 0x02;
816     }
817     dest[outTextLen] = '\0';
818 
819     return outTextLen;
820 }
821 
EscapeTurkishLockingToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)822 int TextCoder::EscapeTurkishLockingToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
823 {
824     int index = 0;
825     if (src == nullptr || srcLen <= 0) {
826         return index;
827     }
828     // Turkish National Language Locking Shift Table
829     const WCHAR turkishLockingToUcs2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x20AC, 0x00E9, 0x00F9, 0x00EC, 0x00F2,
830         0x00C7, 0x000A, 0x011E, 0x011F, 0x000D, 0x00C5, 0x00E5, 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0,
831         0x03A8, 0x03A3, 0x0398, 0x039E, 0x001B, 0x015E, 0x015F, 0x00DF, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4,
832         0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032,
833         0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0130,
834         0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E,
835         0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6,
836         0x00D1, 0x00DC, 0x00A7, 0x00E7, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
837         0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
838         0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0 };
839     // Check Escape
840     if (turkishLockingToUcs2[src[index]] == 0x001B) {
841         index++;
842         if (index >= srcLen) {
843             return index;
844         }
845         result = EscapeToUcs2(src[index], langInfo);
846     } else {
847         // TURKISH
848         result = turkishLockingToUcs2[src[index]];
849     }
850     return index;
851 }
852 
EscapePortuLockingToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)853 int TextCoder::EscapePortuLockingToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
854 {
855     int index = 0;
856     if (src == nullptr || srcLen <= 0) {
857         return index;
858     }
859     // Portuguese National Language Locking Shift Table
860     const WCHAR portuLockingToUcs2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00EA, 0x00E9, 0x00FA, 0x00ED, 0x00F3, 0x00E7,
861         0x000A, 0x00D4, 0x00F4, 0x000D, 0x00C1, 0x00E1, 0x0394, 0x005F, 0x0020, 0x00C7, 0x00C0, 0x0020, 0x005E, 0x005C,
862         0x20AC, 0x00D3, 0x007C, 0x001B, 0x00C2, 0x00E2, 0x00CA, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025,
863         0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033,
864         0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x00CD, 0x0041,
865         0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
866         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C3, 0x00D5, 0x00DA,
867         0x00DC, 0x00A7, 0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
868         0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
869         0x007A, 0x00E3, 0x00F5, 0x0020, 0x00FC, 0x00E0 };
870     if (portuLockingToUcs2[src[index]] == 0x001B) {
871         index++;
872         if (index >= srcLen) {
873             return index;
874         }
875         result = EscapeToUcs2(src[index], langInfo);
876     } else {
877         // PORTUGUESE
878         result = portuLockingToUcs2[src[index]];
879     }
880     return index;
881 }
882 
EscapeGsm7bitToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)883 int TextCoder::EscapeGsm7bitToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
884 {
885     int index = 0;
886     if (src == nullptr || srcLen <= 0) {
887         return index;
888     }
889     if (GSM7_BIT_TO_UC_S2[src[index]] == 0x001B) {
890         index++;
891         if (index >= srcLen) {
892             return index;
893         }
894         result = EscapeToUcs2(src[index], langInfo);
895     } else {
896         result = GSM7_BIT_TO_UC_S2[src[index]];
897     }
898     return index;
899 }
900 
EscapeToUcs2(const uint8_t srcText,const MsgLangInfo & langInfo)901 uint16_t TextCoder::EscapeToUcs2(const uint8_t srcText, const MsgLangInfo &langInfo)
902 {
903     uint16_t result = 0;
904     if (langInfo.bSingleShift) {
905         TELEPHONY_LOGI("National Language Single Shift [%{public}d]", langInfo.singleLang);
906         switch (langInfo.singleLang) {
907             case MSG_ID_TURKISH_LANG:
908                 GetTurkishSingleToUcs2(srcText, result);
909                 break;
910             case MSG_ID_SPANISH_LANG:
911                 GetSpanishSingleToUcs2(srcText, result);
912                 break;
913             case MSG_ID_PORTUGUESE_LANG:
914                 GetPortuSingleToUcs2(srcText, result);
915                 break;
916             default:
917                 GetGsm7BitExtToUcs2(srcText, result);
918                 break;
919         }
920     } else {
921         GetGsm7BitExtToUcs2(srcText, result);
922     }
923     return result;
924 }
925 
GetUCS2Value(uint32_t charset)926 WCHAR TextCoder::GetUCS2Value(uint32_t charset)
927 {
928     if (charset < 0 || charset >= GSM7_DEFLIST_LEN) {
929         return 0;
930     }
931     return GSM7_BIT_TO_UC_S2[charset];
932 }
933 
GetTurkishSingleToUcs2(const uint8_t & srcText,uint16_t & result)934 void TextCoder::GetTurkishSingleToUcs2(const uint8_t &srcText, uint16_t &result)
935 {
936     // Turkish National Language Single Shift Table
937     const WCHAR turkishSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
938         0x0020, 0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020,
939         0x0020, 0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
940         0x0020, 0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020,
941         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C,
942         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x011E, 0x0020, 0x0130, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
943         0x0020, 0x0020, 0x0020, 0x0020, 0x015E, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
944         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00E7, 0x0020, 0x20AC, 0x0020, 0x011F, 0x0020, 0x0131, 0x0020,
945         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x015F, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
946         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
947     result = turkishSingleToUcs2[srcText];
948 }
949 
GetSpanishSingleToUcs2(const uint8_t & srcText,uint16_t & result)950 void TextCoder::GetSpanishSingleToUcs2(const uint8_t &srcText, uint16_t &result)
951 {
952     // Spanish National Language Single Shift Table
953     const WCHAR spanishSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
954         0x00E7, 0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020,
955         0x0020, 0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
956         0x0020, 0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020,
957         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C,
958         0x00C1, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
959         0x00D3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00DA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
960         0x0020, 0x0020, 0x0020, 0x0020, 0x00E1, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x00ED, 0x0020,
961         0x0020, 0x0020, 0x0020, 0x0020, 0x00F3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00FA, 0x0020, 0x0020, 0x0020,
962         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
963     result = spanishSingleToUcs2[srcText];
964 }
965 
GetGsm7BitExtToUcs2(const uint8_t & srcText,uint16_t & result)966 void TextCoder::GetGsm7BitExtToUcs2(const uint8_t &srcText, uint16_t &result)
967 {
968     // GSM 7 bit Default Alphabet Extension Table
969     const WCHAR gsm7BitExtToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
970         0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020, 0x0020,
971         0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
972         0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020, 0x0020,
973         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C, 0x0020,
974         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
975         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
976         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
977         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
978         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
979     result = gsm7BitExtToUcs2[srcText];
980 }
981 
GetPortuSingleToUcs2(const uint8_t & srcText,uint16_t & result)982 void TextCoder::GetPortuSingleToUcs2(const uint8_t &srcText, uint16_t &result)
983 {
984     // Portuguese National Language Single Shift Table
985     const WCHAR portuSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00EA, 0x0020, 0x0020, 0x0020, 0x00E7,
986         0x000C, 0x00D4, 0x00F4, 0x0020, 0x00C1, 0x00E1, 0x0020, 0x0020, 0x03A6, 0x0393, 0x005E, 0x03A9, 0x03A0, 0x03A8,
987         0x03A3, 0x0398, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x00CA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
988         0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020, 0x0020,
989         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C, 0x00C0,
990         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00D3,
991         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00DA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00C3, 0x00D5, 0x0020,
992         0x0020, 0x0020, 0x0020, 0x00C2, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x00ED, 0x0020, 0x0020,
993         0x0020, 0x0020, 0x0020, 0x00F3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00FA, 0x0020, 0x0020, 0x0020, 0x0020,
994         0x0020, 0x00E3, 0x00F5, 0x0020, 0x0020, 0x00E2 };
995     result = portuSingleToUcs2[srcText];
996 }
997 
998 } // namespace Telephony
999 } // namespace OHOS
1000