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 "glib.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 
Base64Encode(const std::string & src,std::string & dest)174 void TextCoder::Base64Encode(const std::string &src, std::string &dest)
175 {
176     gchar *encode_data = g_base64_encode((guchar *)src.data(), src.length());
177     if (encode_data == nullptr) {
178         return;
179     }
180     gsize out_len = 0;
181     out_len = strlen(encode_data);
182     std::string temp(encode_data, out_len);
183     dest = temp;
184 
185     if (encode_data != nullptr) {
186         g_free(encode_data);
187     }
188 }
189 
Base64Decode(const std::string & src,std::string & dest)190 void TextCoder::Base64Decode(const std::string &src, std::string &dest)
191 {
192     gsize out_len = 0;
193     gchar *decodeData = reinterpret_cast<gchar *>(g_base64_decode(src.data(), &out_len));
194     if (decodeData == nullptr) {
195         return;
196     }
197     std::string temp(decodeData, out_len);
198     dest = temp;
199 
200     if (decodeData != nullptr) {
201         g_free(decodeData);
202     }
203 }
204 
GetEncodeString(std::string & encodeString,uint32_t charset,uint32_t valLength,const std::string & strEncodeString)205 bool TextCoder::GetEncodeString(
206     std::string &encodeString, uint32_t charset, uint32_t valLength, const std::string &strEncodeString)
207 {
208     bool ret = false;
209     gchar *pDest = nullptr;
210     gsize bytes_read = 0;
211     gsize bytes_written = 0;
212     GError *error = nullptr;
213     std::string strToCodeset("UTF-8");
214     std::string strFromCodeset;
215     auto charSetInstance = DelayedSingleton<MmsCharSet>::GetInstance();
216     if (charSetInstance == nullptr || (!charSetInstance->GetCharSetStrFromInt(strFromCodeset, charset))) {
217         strFromCodeset = "UTF-8";
218     }
219     pDest = g_convert(strEncodeString.c_str(), valLength, strToCodeset.c_str(), strFromCodeset.c_str(), &bytes_read,
220         &bytes_written, &error);
221     if (!error) {
222         encodeString = std::string(pDest, bytes_written);
223         ret = true;
224     } else {
225         TELEPHONY_LOGE("EncodeString charset convert fail.");
226         ret = false;
227     }
228     if (pDest != nullptr) {
229         g_free(pDest);
230     }
231     return ret;
232 }
233 
234 /**
235  * @brief Utf8ToGsm7bit
236  * max # of Ucs2 chars, NOT bytes. when all utf8 chars are only one byte,
237  * Ucs2Length is maxUcs2 Length. otherwise (ex: 2 bytes of UTF8 is one char)
238  * Ucs2Length must be  less than utf8Length
239  */
Utf8ToGsm7bit(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,MSG_LANGUAGE_ID_T & langId)240 int TextCoder::Utf8ToGsm7bit(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, MSG_LANGUAGE_ID_T &langId)
241 {
242     if (srcLength == -1 && src) {
243         // null terminated string
244         srcLength = strlen(reinterpret_cast<const gchar *>(src));
245     }
246     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
247         TELEPHONY_LOGE("text is null");
248         return 0;
249     }
250 
251     int maxUcs2Length = srcLength;
252     if (static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
253         TELEPHONY_LOGE("src over size");
254         return 0;
255     }
256     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
257     if (ucs2Text == nullptr) {
258         TELEPHONY_LOGE("make_unique error");
259         return 0;
260     }
261     WCHAR *pUcs2Text = ucs2Text.get();
262     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
263         TELEPHONY_LOGE("memset_s error");
264         return 0;
265     }
266 
267     TELEPHONY_LOGI("srcLength = %{public}d", srcLength);
268     int ucs2Length = Utf8ToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength);
269     return Ucs2ToGsm7bit(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length, langId);
270 }
271 
Utf8ToUcs2(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)272 int TextCoder::Utf8ToUcs2(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
273 {
274     if (srcLength == -1 && src) {
275         // null terminated string
276         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
277     }
278     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
279         TELEPHONY_LOGE("text is null");
280         return 0;
281     }
282 
283     gsize textLen = static_cast<gsize>(srcLength);
284     auto unicodeTemp = reinterpret_cast<uint8_t *>(dest);
285     gsize remainedLength = static_cast<gsize>(maxLength);
286     uint32_t err = 0;
287     GIConv cd = g_iconv_open("UTF16BE", "UTF8");
288     if (cd != nullptr) {
289         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
290             reinterpret_cast<gchar **>(&unicodeTemp), reinterpret_cast<gsize *>(&remainedLength));
291     }
292     g_iconv_close(cd);
293     return (err != 0) ? -1 : (maxLength - static_cast<int>(remainedLength));
294 }
295 
GsmUtf8ToAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,DataCodingScheme & scheme,SmsCodingNationalType codingNationalType,MSG_LANGUAGE_ID_T & langId)296 int TextCoder::GsmUtf8ToAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength,
297     DataCodingScheme &scheme, SmsCodingNationalType codingNationalType, MSG_LANGUAGE_ID_T &langId)
298 {
299     int maxUcs2Length = srcLength;
300     if (maxUcs2Length <= 0 || static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
301         TELEPHONY_LOGE("src over size");
302         return 0;
303     }
304     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
305     if (ucs2Text == nullptr) {
306         TELEPHONY_LOGE("GsmUtf8ToAuto make_unique error");
307         return 0;
308     }
309     WCHAR *pUcs2Text = ucs2Text.get();
310     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
311         TELEPHONY_LOGE("GsmUtf8ToAuto memset_s error");
312         return 0;
313     }
314     int ucs2Length = Utf8ToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength);
315     int tempTextLen = 0;
316     if (ucs2Length < 0) {
317         scheme = DATA_CODING_8BIT;
318         tempTextLen = (srcLength > maxLength) ? maxLength : srcLength;
319         if (memcpy_s(dest, tempTextLen, src, tempTextLen) != EOK) {
320             TELEPHONY_LOGE("GsmUtf8ToAuto memcpy_s error");
321         }
322         return tempTextLen;
323     }
324     bool unknown = false;
325     int length = Ucs2ToGsm7bitAuto(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length,
326         unknown, codingNationalType);
327     if (unknown) {
328         scheme = DATA_CODING_UCS2;
329         if (ucs2Length <= 0) {
330             return length;
331         }
332         tempTextLen = (ucs2Length > maxLength) ? maxLength : ucs2Length;
333         if (memcpy_s(dest, tempTextLen, pUcs2Text, tempTextLen) != EOK) {
334             TELEPHONY_LOGE("memcpy_s error");
335         }
336         return tempTextLen;
337     }
338     langId = static_cast<MSG_LANGUAGE_ID_T>(codingNationalType);
339     scheme = DATA_CODING_7BIT;
340     return length;
341 }
342 
CdmaUtf8ToAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,DataCodingScheme & scheme)343 int TextCoder::CdmaUtf8ToAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, DataCodingScheme &scheme)
344 {
345     int maxUcs2Length = srcLength;
346     if (maxUcs2Length <= 0 || static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
347         TELEPHONY_LOGE("CdmaUtf8ToAuto src over size");
348         return 0;
349     }
350     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
351     if (ucs2Text == nullptr) {
352         TELEPHONY_LOGE("CdmaUtf8ToAuto make_unique error");
353         return 0;
354     }
355     WCHAR *pUcs2Text = ucs2Text.get();
356     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
357         TELEPHONY_LOGE("CdmaUtf8ToAuto memset_s error");
358         return 0;
359     }
360     int ucs2Length = Utf8ToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength);
361     int tempTextLen = 0;
362     if (ucs2Length < 0) {
363         scheme = DATA_CODING_8BIT;
364         tempTextLen = (srcLength > maxLength) ? maxLength : srcLength;
365         if (memcpy_s(dest, tempTextLen, src, tempTextLen) != EOK) {
366             TELEPHONY_LOGE("memcpy_s error");
367         }
368         return tempTextLen;
369     }
370     bool unknown = false;
371     int gsm7bitLength = Ucs2ToAscii(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length, unknown);
372     if (unknown) {
373         scheme = DATA_CODING_UCS2;
374         if (ucs2Length <= 0) {
375             return gsm7bitLength;
376         }
377         tempTextLen = (ucs2Length > maxLength) ? maxLength : ucs2Length;
378         if (memcpy_s(dest, tempTextLen, pUcs2Text, tempTextLen) != EOK) {
379             TELEPHONY_LOGE("memcpy_s error");
380         }
381         return tempTextLen;
382     }
383     scheme = DATA_CODING_ASCII7BIT;
384     return gsm7bitLength;
385 }
386 
387 /**
388  * @brief Gsm7bitToUtf8
389  * max # of Ucs2 chars, NOT bytes. when all gsm7 chars are only one byte(-there is no extension)
390  * Ucs2Length is maxUcs2 Length. otherwise(ex: gsm7 char starts with 0x1b)
391  * Ucs2Length must be less than gsm7 length
392  */
Gsm7bitToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,const MsgLangInfo & langInfo)393 int TextCoder::Gsm7bitToUtf8(
394     uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, const MsgLangInfo &langInfo)
395 {
396     int maxUcs2Length = srcLength;
397     if (maxUcs2Length <= 0 || static_cast<uint32_t>(maxUcs2Length) >= UCS2_LEN_MAX) {
398         TELEPHONY_LOGE("Gsm7bitToUtf8 src over size");
399         return 0;
400     }
401     std::unique_ptr<WCHAR[]> ucs2Text = std::make_unique<WCHAR[]>(maxUcs2Length);
402     if (ucs2Text == nullptr) {
403         TELEPHONY_LOGE("Gsm7bitToUtf8 make_unique error");
404         return 0;
405     }
406     WCHAR *pUcs2Text = ucs2Text.get();
407     if (memset_s(pUcs2Text, maxUcs2Length * sizeof(WCHAR), 0x00, maxUcs2Length * sizeof(WCHAR)) != EOK) {
408         TELEPHONY_LOGE("Gsm7bitToUtf8 memset_s error");
409         return 0;
410     }
411     TELEPHONY_LOGI("max dest Length = %{public}d, srcLength = %{public}d", maxLength, srcLength);
412     int ucs2Length =
413         Gsm7bitToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength, langInfo);
414     if (ucs2Length > maxLength) {
415         // Usually, maxLength is a large number, like 1530, 4200. But when you decode the address, maxLength is only 21.
416         // (according to section 9/1/2/5 in 3gpp 23040). When the code is converted to UCS2, the length is doubled,
417         // that is, the length is greater than maxUcs2Length * sizeof(WCHAR) should be considered a failure.
418         // If the value of maxLength is large(1530 4200), and the first condition is met, this condition is also met,
419         // and there is no impact.
420         if (ucs2Length > static_cast<int>(maxUcs2Length * sizeof(WCHAR))) {
421             TELEPHONY_LOGI("src over size, ucs2Length = %{public}d, maxLength = %{public}d", ucs2Length,
422                 static_cast<int>(maxUcs2Length * sizeof(WCHAR)));
423             return 0;
424         }
425     }
426     return Ucs2ToUtf8(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length);
427 }
428 
Ucs2ToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)429 int TextCoder::Ucs2ToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
430 {
431     if (srcLength == -1 && src) {
432         TELEPHONY_LOGE("stcLength == -1 && src branch");
433         // null terminated string
434         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
435     }
436     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
437         TELEPHONY_LOGE("text is null");
438         return 0;
439     }
440 
441     gsize textLen = static_cast<gsize>(srcLength);
442     uint32_t err = 0;
443     gsize remainedLength = static_cast<gsize>(maxLength);
444     GIConv cd = g_iconv_open("UTF8", "UTF16BE");
445     if (cd != nullptr) {
446         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
447             reinterpret_cast<gchar **>(&dest), reinterpret_cast<gsize *>(&remainedLength));
448     }
449     g_iconv_close(cd);
450     if (err != 0) {
451         TELEPHONY_LOGE("g_iconv result is %{public}u", err);
452     }
453     int length = maxLength - static_cast<int>(remainedLength);
454     if (length < 0 || length >= maxLength) {
455         return 0;
456     }
457     return length;
458 }
459 
EuckrToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)460 int TextCoder::EuckrToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
461 {
462     if (srcLength == -1 && src) {
463         // null terminated string
464         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
465     }
466     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
467         TELEPHONY_LOGE("text is null");
468         return 0;
469     }
470 
471     gsize remainedLength = static_cast<gsize>(maxLength);
472     gsize textLen = static_cast<gsize>(srcLength);
473     uint32_t err = 0;
474     GIConv cd = g_iconv_open("UTF8", "EUCKR");
475     if (cd != nullptr) {
476         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
477             reinterpret_cast<gchar **>(&dest), reinterpret_cast<gsize *>(&remainedLength));
478     }
479     g_iconv_close(cd);
480     if (err != 0) {
481         TELEPHONY_LOGE("g_iconv result is %{public}u", err);
482     }
483     int utf8Length = maxLength - static_cast<int>(remainedLength);
484     if (utf8Length < 0 || utf8Length >= maxLength) {
485         return 0;
486     }
487     dest[utf8Length] = 0x00;
488     return utf8Length;
489 }
490 
ShiftjisToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength) const491 int TextCoder::ShiftjisToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength) const
492 {
493     if (srcLength == -1 && src) {
494         // null terminated string
495         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
496     }
497     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
498         TELEPHONY_LOGE("text is null");
499         return 0;
500     }
501 
502     gsize textLen = static_cast<gsize>(srcLength);
503     gsize remainedLength = static_cast<gsize>(maxLength);
504     uint32_t err = 0;
505     GIConv cd = g_iconv_open("UTF8", "SHIFT-JIS");
506     if (cd != nullptr) {
507         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
508             reinterpret_cast<gchar **>(&dest), reinterpret_cast<gsize *>(&remainedLength));
509     }
510     g_iconv_close(cd);
511     TELEPHONY_LOGI("g_iconv result is %{public}u", err);
512     int utf8Length = maxLength - static_cast<int>(remainedLength);
513     if (utf8Length < 0 || utf8Length >= maxLength) {
514         return 0;
515     }
516     dest[utf8Length] = 0x00;
517     return utf8Length;
518 }
519 
Ucs2ToGsm7bit(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,MSG_LANGUAGE_ID_T & langId)520 int TextCoder::Ucs2ToGsm7bit(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, MSG_LANGUAGE_ID_T &langId)
521 {
522     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
523         TELEPHONY_LOGE("text is null");
524         return -1;
525     }
526     int outTextLen = 0;
527     int remainLen = 0;
528     uint16_t inText = 0;
529     uint8_t currType = GetLangType(src, srcLength);
530     std::map<uint16_t, uint8_t>::iterator itChar;
531     for (int index = 0; index < (srcLength - 1); index += UCS2_LEN_MIN) {
532         inText = src[index];
533         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
534         itChar = gsm7bitDefMap_.find(inText); // check gsm7bit default char
535         if (itChar != gsm7bitDefMap_.end()) {
536             dest[outTextLen++] = static_cast<uint8_t>(itChar->second);
537         } else {
538             switch (currType) {
539                 case MSG_GSM7EXT_CHAR:
540                     remainLen = maxLength - outTextLen;
541                     outTextLen += FindGsm7bitExt(&dest[outTextLen], remainLen, inText);
542                     break;
543                 case MSG_TURKISH_CHAR:
544                     langId = MSG_ID_TURKISH_LANG;
545                     remainLen = maxLength - outTextLen;
546                     outTextLen += FindTurkish(&dest[outTextLen], remainLen, inText);
547                     break;
548                 case MSG_SPANISH_CHAR:
549                     langId = MSG_ID_SPANISH_LANG;
550                     remainLen = maxLength - outTextLen;
551                     outTextLen += FindSpanish(&dest[outTextLen], remainLen, inText);
552                     break;
553                 case MSG_PORTUGUESE_CHAR:
554                     langId = MSG_ID_PORTUGUESE_LANG;
555                     remainLen = maxLength - outTextLen;
556                     outTextLen += FindPortu(&dest[outTextLen], remainLen, inText);
557                     break;
558                 default:
559                     dest[outTextLen] = FindReplaceChar(inText);
560                     break;
561             }
562             outTextLen++;
563         }
564         // prevent buffer overflow
565         if (maxLength <= outTextLen) {
566             TELEPHONY_LOGE("buffer overflow");
567             break;
568         }
569     }
570     return outTextLen;
571 }
572 
Get7BitCodingExtMap(SmsCodingNationalType codingNationalType) const573 std::map<uint16_t, uint8_t> TextCoder::Get7BitCodingExtMap(SmsCodingNationalType codingNationalType) const
574 {
575     std::map<uint16_t, uint8_t> extMap = gsm7bitExtMap_;
576     switch (codingNationalType) {
577         case SMS_CODING_NATIONAL_TYPE_DEFAULT:
578             extMap = gsm7bitExtMap_;
579             break;
580         case SMS_CODING_NATIONAL_TYPE_TURKISH:
581             extMap = turkishMap_;
582             break;
583         case SMS_CODING_NATIONAL_TYPE_SPANISH:
584             extMap = spanishMap_;
585             break;
586         case SMS_CODING_NATIONAL_TYPE_PORTUGUESE:
587             extMap = portuMap_;
588             break;
589         default:
590             extMap = gsm7bitExtMap_;
591             break;
592     }
593     return extMap;
594 }
595 
Ucs2ToGsm7bitAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,bool & unknown,SmsCodingNationalType codingNationalType)596 int TextCoder::Ucs2ToGsm7bitAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength,
597     bool &unknown, SmsCodingNationalType codingNationalType)
598 {
599     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
600         TELEPHONY_LOGE("text is null");
601         return -1;
602     }
603 
604     std::map<uint16_t, uint8_t> extMap = Get7BitCodingExtMap(codingNationalType);
605     int outTextLen = 0;
606     std::map<uint16_t, uint8_t>::iterator itChar;
607     std::map<uint16_t, uint8_t>::iterator itExt;
608     uint16_t inText;
609     for (int i = 0; i < srcLength - 1; i += UCS2_LEN_MIN) {
610         inText = src[i];
611         inText = ((inText << 0x08) & 0xFF00) | src[i + 1];
612         itChar = gsm7bitDefMap_.find(inText); // check gsm7bit default char
613         if (itChar != gsm7bitDefMap_.end()) {
614             dest[outTextLen++] = static_cast<uint8_t>(itChar->second);
615         } else {
616             itExt = extMap.find(inText);
617             if (itExt == extMap.end()) {
618                 TELEPHONY_LOGI("Abnormal character is included. inText : [%{public}04x]", inText);
619                 unknown = true;
620                 return 0;
621             }
622             if (maxLength <= outTextLen + 1) {
623                 TELEPHONY_LOGE("buffer overflow.");
624                 break;
625             }
626             dest[outTextLen++] = 0x1B;
627             dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
628         }
629         // prevent buffer overflow
630         if (maxLength <= outTextLen) {
631             TELEPHONY_LOGE("buffer overflow");
632             break;
633         }
634     }
635     return outTextLen;
636 }
637 
Ucs2ToAscii(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,bool & unknown)638 int TextCoder::Ucs2ToAscii(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, bool &unknown)
639 {
640     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
641         TELEPHONY_LOGE("text is null");
642         return -1;
643     }
644 
645     int outTextLen = 0;
646     std::map<uint16_t, uint8_t>::iterator itChar;
647     std::map<uint16_t, uint8_t>::iterator itExt;
648     uint16_t inText;
649     for (int index = 0; index < srcLength - 1; index += UCS2_LEN_MIN) {
650         inText = src[index];
651         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
652         // check default char
653         if (inText > 0x007f) {
654             TELEPHONY_LOGI("abnormal character is included [%{public}04x]", inText);
655             unknown = true;
656             return 0;
657         }
658         dest[outTextLen++] = static_cast<uint8_t>(inText);
659         // prevent buffer overflow
660         if (maxLength <= outTextLen) {
661             TELEPHONY_LOGE("buffer overflow");
662             break;
663         }
664     }
665     return outTextLen;
666 }
667 
GetLangType(const uint8_t * src,int srcLength)668 uint8_t TextCoder::GetLangType(const uint8_t *src, int srcLength)
669 {
670     if (srcLength <= 0 || src == nullptr) {
671         TELEPHONY_LOGE("text is null");
672         return MSG_DEFAULT_CHAR;
673     }
674 
675     std::map<uint16_t, uint8_t>::iterator itExt;
676     uint8_t currType = MSG_DEFAULT_CHAR;
677     uint8_t newType = MSG_DEFAULT_CHAR;
678     uint16_t inText;
679     for (int index = 0; index < (srcLength - 1); index += UCS2_LEN_MIN) {
680         inText = src[index];
681         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
682         itExt = extCharMap_.find(inText);
683         if (itExt == extCharMap_.end()) {
684             continue;
685         }
686         newType = static_cast<uint8_t>(itExt->second);
687         if (newType >= currType) {
688             bool isTurkisk = (inText == 0x00e7 && currType <= MSG_TURKISH_CHAR);
689             currType = isTurkisk ? MSG_TURKISH_CHAR : newType;
690         }
691     }
692     TELEPHONY_LOGI("charType : [%{public}hhu]", currType);
693     return currType;
694 }
695 
FindGsm7bitExt(uint8_t * dest,int maxLength,const uint16_t inText)696 int TextCoder::FindGsm7bitExt(uint8_t *dest, int maxLength, const uint16_t inText)
697 {
698     int outTextLen = 0;
699     if (dest == nullptr || maxLength <= 0) {
700         TELEPHONY_LOGE("Invalid parameter.");
701         return outTextLen;
702     }
703 
704     auto itExt = gsm7bitExtMap_.find(inText);
705     if (itExt == gsm7bitExtMap_.end()) {
706         dest[outTextLen++] = FindReplaceChar(inText);
707         return outTextLen;
708     }
709     // prevent buffer overflow
710     if (maxLength <= outTextLen + 1) {
711         TELEPHONY_LOGE("FindGsm7bitExt buffer overflow");
712         return outTextLen;
713     }
714     dest[outTextLen++] = 0x1B;
715     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
716     return outTextLen;
717 }
718 
FindTurkish(uint8_t * dest,int maxLength,const uint16_t inText)719 int TextCoder::FindTurkish(uint8_t *dest, int maxLength, const uint16_t inText)
720 {
721     int outTextLen = 0;
722     if (dest == nullptr || maxLength <= 0) {
723         TELEPHONY_LOGE("Invalid parameter.");
724         return outTextLen;
725     }
726 
727     auto itExt = turkishMap_.find(inText);
728     if (itExt == turkishMap_.end()) {
729         dest[outTextLen++] = FindReplaceChar(inText);
730         return outTextLen;
731     }
732     // prevent buffer overflow
733     if (maxLength <= outTextLen + 1) {
734         TELEPHONY_LOGE("FindTurkish buffer overflow");
735         return outTextLen;
736     }
737     dest[outTextLen++] = 0x1B;
738     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
739     return outTextLen;
740 }
741 
FindSpanish(uint8_t * dest,int maxLength,const uint16_t inText)742 int TextCoder::FindSpanish(uint8_t *dest, int maxLength, const uint16_t inText)
743 {
744     int outTextLen = 0;
745     if (dest == nullptr || maxLength <= 0) {
746         TELEPHONY_LOGE("Invalid parameter.");
747         return outTextLen;
748     }
749 
750     auto itExt = spanishMap_.find(inText);
751     if (itExt == spanishMap_.end()) {
752         dest[outTextLen++] = FindReplaceChar(inText);
753         return outTextLen;
754     }
755     // prevent buffer overflow
756     if (maxLength <= outTextLen + 1) {
757         TELEPHONY_LOGE("FindSpanish buffer overflow");
758         return outTextLen;
759     }
760     dest[outTextLen++] = 0x1B;
761     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
762     return outTextLen;
763 }
764 
FindPortu(uint8_t * dest,int maxLength,const uint16_t inText)765 int TextCoder::FindPortu(uint8_t *dest, int maxLength, const uint16_t inText)
766 {
767     int outTextLen = 0;
768     if (dest == nullptr || maxLength <= 0) {
769         TELEPHONY_LOGE("Invalid parameter.");
770         return outTextLen;
771     }
772 
773     auto itExt = portuMap_.find(inText);
774     if (itExt == portuMap_.end()) {
775         dest[outTextLen++] = FindReplaceChar(inText);
776         return outTextLen;
777     }
778     // prevent buffer overflow
779     if (maxLength <= outTextLen + 1) {
780         TELEPHONY_LOGE("FindPortu buffer overflow");
781         return outTextLen;
782     }
783     dest[outTextLen++] = 0x1B;
784     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
785     return outTextLen;
786 }
787 
FindReplaceChar(const uint16_t inText)788 uint8_t TextCoder::FindReplaceChar(const uint16_t inText)
789 {
790     uint8_t result = 0;
791     auto itReplace = replaceCharMap_.find(inText);
792     if (itReplace != replaceCharMap_.end()) {
793         result = static_cast<uint8_t>(itReplace->second);
794     } else {
795         result = 0x3F;
796     }
797     return result;
798 }
799 
Gsm7bitToUcs2(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,const MsgLangInfo & langInfo)800 int TextCoder::Gsm7bitToUcs2(
801     uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, const MsgLangInfo &langInfo)
802 {
803     if (srcLength == 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
804         TELEPHONY_LOGE("text is null");
805         return -1;
806     }
807 
808     int outTextLen = 0;
809     uint8_t lowerByte = 0;
810     uint8_t upperByte = 0;
811     uint16_t result = 0;
812     for (int i = 0; i < srcLength && maxLength > UCS2_LEN_MIN; i++) {
813         if (src[i] >= 0x80) {
814             TELEPHONY_LOGE("a_pTextString[%{public}d]=%{public}x, The alpha isn't the gsm 7bit code", i, src[i]);
815             return -1;
816         }
817         if (langInfo.bLockingShift) {
818             TELEPHONY_LOGI("National Language Locking Shift [%{public}d]", langInfo.lockingLang);
819             if (langInfo.lockingLang == MSG_ID_TURKISH_LANG) {
820                 i += EscapeTurkishLockingToUcs2(&src[i], (srcLength - i), langInfo, result);
821                 lowerByte = static_cast<uint8_t>(result & 0x00FF);
822                 upperByte = static_cast<uint8_t>(result >> 0x08);
823             } else if (langInfo.lockingLang == MSG_ID_PORTUGUESE_LANG) {
824                 i += EscapePortuLockingToUcs2(&src[i], (srcLength - i), langInfo, result);
825                 lowerByte = static_cast<uint8_t>(result & 0x00FF);
826                 upperByte = static_cast<uint8_t>(result >> 0x08);
827             }
828         } else {
829             i += EscapeGsm7bitToUcs2(&src[i], (srcLength - i), langInfo, result);
830             lowerByte = static_cast<uint8_t>(result & 0x00FF);
831             upperByte = static_cast<uint8_t>(result >> 0x08);
832         }
833         dest[outTextLen++] = upperByte;
834         dest[outTextLen++] = lowerByte;
835         maxLength -= 0x02;
836     }
837     dest[outTextLen] = '\0';
838 
839     return outTextLen;
840 }
841 
EscapeTurkishLockingToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)842 int TextCoder::EscapeTurkishLockingToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
843 {
844     int index = 0;
845     if (src == nullptr || srcLen <= 0) {
846         return index;
847     }
848     // Turkish National Language Locking Shift Table
849     const WCHAR turkishLockingToUcs2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x20AC, 0x00E9, 0x00F9, 0x00EC, 0x00F2,
850         0x00C7, 0x000A, 0x011E, 0x011F, 0x000D, 0x00C5, 0x00E5, 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0,
851         0x03A8, 0x03A3, 0x0398, 0x039E, 0x001B, 0x015E, 0x015F, 0x00DF, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4,
852         0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032,
853         0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0130,
854         0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E,
855         0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6,
856         0x00D1, 0x00DC, 0x00A7, 0x00E7, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
857         0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
858         0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0 };
859     // Check Escape
860     if (turkishLockingToUcs2[src[index]] == 0x001B) {
861         index++;
862         if (index >= srcLen) {
863             return index;
864         }
865         result = EscapeToUcs2(src[index], langInfo);
866     } else {
867         // TURKISH
868         result = turkishLockingToUcs2[src[index]];
869     }
870     return index;
871 }
872 
EscapePortuLockingToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)873 int TextCoder::EscapePortuLockingToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
874 {
875     int index = 0;
876     if (src == nullptr || srcLen <= 0) {
877         return index;
878     }
879     // Portuguese National Language Locking Shift Table
880     const WCHAR portuLockingToUcs2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00EA, 0x00E9, 0x00FA, 0x00ED, 0x00F3, 0x00E7,
881         0x000A, 0x00D4, 0x00F4, 0x000D, 0x00C1, 0x00E1, 0x0394, 0x005F, 0x0020, 0x00C7, 0x00C0, 0x0020, 0x005E, 0x005C,
882         0x20AC, 0x00D3, 0x007C, 0x001B, 0x00C2, 0x00E2, 0x00CA, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025,
883         0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033,
884         0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x00CD, 0x0041,
885         0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
886         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C3, 0x00D5, 0x00DA,
887         0x00DC, 0x00A7, 0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
888         0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
889         0x007A, 0x00E3, 0x00F5, 0x0020, 0x00FC, 0x00E0 };
890     if (portuLockingToUcs2[src[index]] == 0x001B) {
891         index++;
892         if (index >= srcLen) {
893             return index;
894         }
895         result = EscapeToUcs2(src[index], langInfo);
896     } else {
897         // PORTUGUESE
898         result = portuLockingToUcs2[src[index]];
899     }
900     return index;
901 }
902 
EscapeGsm7bitToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)903 int TextCoder::EscapeGsm7bitToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
904 {
905     int index = 0;
906     if (src == nullptr || srcLen <= 0) {
907         return index;
908     }
909     if (GSM7_BIT_TO_UC_S2[src[index]] == 0x001B) {
910         index++;
911         if (index >= srcLen) {
912             return index;
913         }
914         result = EscapeToUcs2(src[index], langInfo);
915     } else {
916         result = GSM7_BIT_TO_UC_S2[src[index]];
917     }
918     return index;
919 }
920 
EscapeToUcs2(const uint8_t srcText,const MsgLangInfo & langInfo)921 uint16_t TextCoder::EscapeToUcs2(const uint8_t srcText, const MsgLangInfo &langInfo)
922 {
923     uint16_t result = 0;
924     if (langInfo.bSingleShift) {
925         TELEPHONY_LOGI("National Language Single Shift [%{public}d]", langInfo.singleLang);
926         switch (langInfo.singleLang) {
927             case MSG_ID_TURKISH_LANG:
928                 GetTurkishSingleToUcs2(srcText, result);
929                 break;
930             case MSG_ID_SPANISH_LANG:
931                 GetSpanishSingleToUcs2(srcText, result);
932                 break;
933             case MSG_ID_PORTUGUESE_LANG:
934                 GetPortuSingleToUcs2(srcText, result);
935                 break;
936             default:
937                 GetGsm7BitExtToUcs2(srcText, result);
938                 break;
939         }
940     } else {
941         GetGsm7BitExtToUcs2(srcText, result);
942     }
943     return result;
944 }
945 
GetUCS2Value(uint32_t charset)946 WCHAR TextCoder::GetUCS2Value(uint32_t charset)
947 {
948     if (charset < 0 || charset >= GSM7_DEFLIST_LEN) {
949         return 0;
950     }
951     return GSM7_BIT_TO_UC_S2[charset];
952 }
953 
GetTurkishSingleToUcs2(const uint8_t & srcText,uint16_t & result)954 void TextCoder::GetTurkishSingleToUcs2(const uint8_t &srcText, uint16_t &result)
955 {
956     // Turkish National Language Single Shift Table
957     const WCHAR turkishSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
958         0x0020, 0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020,
959         0x0020, 0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
960         0x0020, 0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020,
961         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C,
962         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x011E, 0x0020, 0x0130, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
963         0x0020, 0x0020, 0x0020, 0x0020, 0x015E, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
964         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00E7, 0x0020, 0x20AC, 0x0020, 0x011F, 0x0020, 0x0131, 0x0020,
965         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x015F, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
966         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
967     result = turkishSingleToUcs2[srcText];
968 }
969 
GetSpanishSingleToUcs2(const uint8_t & srcText,uint16_t & result)970 void TextCoder::GetSpanishSingleToUcs2(const uint8_t &srcText, uint16_t &result)
971 {
972     // Spanish National Language Single Shift Table
973     const WCHAR spanishSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
974         0x00E7, 0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020,
975         0x0020, 0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
976         0x0020, 0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020,
977         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C,
978         0x00C1, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
979         0x00D3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00DA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
980         0x0020, 0x0020, 0x0020, 0x0020, 0x00E1, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x00ED, 0x0020,
981         0x0020, 0x0020, 0x0020, 0x0020, 0x00F3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00FA, 0x0020, 0x0020, 0x0020,
982         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
983     result = spanishSingleToUcs2[srcText];
984 }
985 
GetGsm7BitExtToUcs2(const uint8_t & srcText,uint16_t & result)986 void TextCoder::GetGsm7BitExtToUcs2(const uint8_t &srcText, uint16_t &result)
987 {
988     // GSM 7 bit Default Alphabet Extension Table
989     const WCHAR gsm7BitExtToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
990         0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020, 0x0020,
991         0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
992         0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020, 0x0020,
993         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C, 0x0020,
994         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
995         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
996         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
997         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
998         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
999     result = gsm7BitExtToUcs2[srcText];
1000 }
1001 
GetPortuSingleToUcs2(const uint8_t & srcText,uint16_t & result)1002 void TextCoder::GetPortuSingleToUcs2(const uint8_t &srcText, uint16_t &result)
1003 {
1004     // Portuguese National Language Single Shift Table
1005     const WCHAR portuSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00EA, 0x0020, 0x0020, 0x0020, 0x00E7,
1006         0x000C, 0x00D4, 0x00F4, 0x0020, 0x00C1, 0x00E1, 0x0020, 0x0020, 0x03A6, 0x0393, 0x005E, 0x03A9, 0x03A0, 0x03A8,
1007         0x03A3, 0x0398, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x00CA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
1008         0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020, 0x0020,
1009         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C, 0x00C0,
1010         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00D3,
1011         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00DA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00C3, 0x00D5, 0x0020,
1012         0x0020, 0x0020, 0x0020, 0x00C2, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x00ED, 0x0020, 0x0020,
1013         0x0020, 0x0020, 0x0020, 0x00F3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00FA, 0x0020, 0x0020, 0x0020, 0x0020,
1014         0x0020, 0x00E3, 0x00F5, 0x0020, 0x0020, 0x00E2 };
1015     result = portuSingleToUcs2[srcText];
1016 }
1017 
1018 } // namespace Telephony
1019 } // namespace OHOS
1020