• 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 "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", maxLength);
412     TELEPHONY_LOGI("srcLength = %{public}d", srcLength);
413     int ucs2Length =
414         Gsm7bitToUcs2(reinterpret_cast<uint8_t *>(pUcs2Text), maxUcs2Length * sizeof(WCHAR), src, srcLength, langInfo);
415     if (ucs2Length > maxLength) {
416         TELEPHONY_LOGE("src over size");
417         return 0;
418     }
419     return Ucs2ToUtf8(dest, maxLength, reinterpret_cast<uint8_t *>(pUcs2Text), ucs2Length);
420 }
421 
Ucs2ToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)422 int TextCoder::Ucs2ToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
423 {
424     if (srcLength == -1 && src) {
425         TELEPHONY_LOGE("stcLength == -1 && src branch");
426         // null terminated string
427         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
428     }
429     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
430         TELEPHONY_LOGE("text is null");
431         return 0;
432     }
433 
434     gsize textLen = static_cast<gsize>(srcLength);
435     uint32_t err = 0;
436     gsize remainedLength = static_cast<gsize>(maxLength);
437     GIConv cd = g_iconv_open("UTF8", "UTF16BE");
438     if (cd != nullptr) {
439         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
440             reinterpret_cast<gchar **>(&dest), reinterpret_cast<gsize *>(&remainedLength));
441     }
442     g_iconv_close(cd);
443     if (err != 0) {
444         TELEPHONY_LOGE("g_iconv result is %{public}u", err);
445     }
446     int length = maxLength - static_cast<int>(remainedLength);
447     if (length < 0 || length >= maxLength) {
448         return 0;
449     }
450     return length;
451 }
452 
EuckrToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength)453 int TextCoder::EuckrToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength)
454 {
455     if (srcLength == -1 && src) {
456         // null terminated string
457         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
458     }
459     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
460         TELEPHONY_LOGE("text is null");
461         return 0;
462     }
463 
464     gsize remainedLength = static_cast<gsize>(maxLength);
465     gsize textLen = static_cast<gsize>(srcLength);
466     uint32_t err = 0;
467     GIConv cd = g_iconv_open("UTF8", "EUCKR");
468     if (cd != nullptr) {
469         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
470             reinterpret_cast<gchar **>(&dest), reinterpret_cast<gsize *>(&remainedLength));
471     }
472     g_iconv_close(cd);
473     if (err != 0) {
474         TELEPHONY_LOGE("g_iconv result is %{public}u", err);
475     }
476     int utf8Length = maxLength - static_cast<int>(remainedLength);
477     if (utf8Length < 0 || utf8Length >= maxLength) {
478         return 0;
479     }
480     dest[utf8Length] = 0x00;
481     return utf8Length;
482 }
483 
ShiftjisToUtf8(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength) const484 int TextCoder::ShiftjisToUtf8(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength) const
485 {
486     if (srcLength == -1 && src) {
487         // null terminated string
488         srcLength = strlen(reinterpret_cast<gchar *>(const_cast<uint8_t *>(src)));
489     }
490     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
491         TELEPHONY_LOGE("text is null");
492         return 0;
493     }
494 
495     gsize textLen = static_cast<gsize>(srcLength);
496     gsize remainedLength = static_cast<gsize>(maxLength);
497     uint32_t err = 0;
498     GIConv cd = g_iconv_open("UTF8", "SHIFT-JIS");
499     if (cd != nullptr) {
500         err = g_iconv(cd, reinterpret_cast<gchar **>(const_cast<uint8_t **>(&src)), reinterpret_cast<gsize *>(&textLen),
501             reinterpret_cast<gchar **>(&dest), reinterpret_cast<gsize *>(&remainedLength));
502     }
503     g_iconv_close(cd);
504     TELEPHONY_LOGI("g_iconv result is %{public}u", err);
505     int utf8Length = maxLength - static_cast<int>(remainedLength);
506     if (utf8Length < 0 || utf8Length >= maxLength) {
507         return 0;
508     }
509     dest[utf8Length] = 0x00;
510     return utf8Length;
511 }
512 
Ucs2ToGsm7bit(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,MSG_LANGUAGE_ID_T & langId)513 int TextCoder::Ucs2ToGsm7bit(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, MSG_LANGUAGE_ID_T &langId)
514 {
515     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
516         TELEPHONY_LOGE("text is null");
517         return -1;
518     }
519     int outTextLen = 0;
520     int remainLen = 0;
521     uint16_t inText = 0;
522     uint8_t currType = GetLangType(src, srcLength);
523     std::map<uint16_t, uint8_t>::iterator itChar;
524     for (int index = 0; index < (srcLength - 1); index += UCS2_LEN_MIN) {
525         inText = src[index];
526         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
527         itChar = gsm7bitDefMap_.find(inText); // check gsm7bit default char
528         if (itChar != gsm7bitDefMap_.end()) {
529             dest[outTextLen++] = static_cast<uint8_t>(itChar->second);
530         } else {
531             switch (currType) {
532                 case MSG_GSM7EXT_CHAR:
533                     remainLen = maxLength - outTextLen;
534                     outTextLen += FindGsm7bitExt(&dest[outTextLen], remainLen, inText);
535                     break;
536                 case MSG_TURKISH_CHAR:
537                     langId = MSG_ID_TURKISH_LANG;
538                     remainLen = maxLength - outTextLen;
539                     outTextLen += FindTurkish(&dest[outTextLen], remainLen, inText);
540                     break;
541                 case MSG_SPANISH_CHAR:
542                     langId = MSG_ID_SPANISH_LANG;
543                     remainLen = maxLength - outTextLen;
544                     outTextLen += FindSpanish(&dest[outTextLen], remainLen, inText);
545                     break;
546                 case MSG_PORTUGUESE_CHAR:
547                     langId = MSG_ID_PORTUGUESE_LANG;
548                     remainLen = maxLength - outTextLen;
549                     outTextLen += FindPortu(&dest[outTextLen], remainLen, inText);
550                     break;
551                 default:
552                     dest[outTextLen] = FindReplaceChar(inText);
553                     break;
554             }
555             outTextLen++;
556         }
557         // prevent buffer overflow
558         if (maxLength <= outTextLen) {
559             TELEPHONY_LOGE("buffer overflow");
560             break;
561         }
562     }
563     return outTextLen;
564 }
565 
Get7BitCodingExtMap(SmsCodingNationalType codingNationalType) const566 std::map<uint16_t, uint8_t> TextCoder::Get7BitCodingExtMap(SmsCodingNationalType codingNationalType) const
567 {
568     std::map<uint16_t, uint8_t> extMap = gsm7bitExtMap_;
569     switch (codingNationalType) {
570         case SMS_CODING_NATIONAL_TYPE_DEFAULT:
571             extMap = gsm7bitExtMap_;
572             break;
573         case SMS_CODING_NATIONAL_TYPE_TURKISH:
574             extMap = turkishMap_;
575             break;
576         case SMS_CODING_NATIONAL_TYPE_SPANISH:
577             extMap = spanishMap_;
578             break;
579         case SMS_CODING_NATIONAL_TYPE_PORTUGUESE:
580             extMap = portuMap_;
581             break;
582         default:
583             extMap = gsm7bitExtMap_;
584             break;
585     }
586     return extMap;
587 }
588 
Ucs2ToGsm7bitAuto(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,bool & unknown,SmsCodingNationalType codingNationalType)589 int TextCoder::Ucs2ToGsm7bitAuto(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength,
590     bool &unknown, SmsCodingNationalType codingNationalType)
591 {
592     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
593         TELEPHONY_LOGE("text is null");
594         return -1;
595     }
596 
597     std::map<uint16_t, uint8_t> extMap = Get7BitCodingExtMap(codingNationalType);
598     int outTextLen = 0;
599     std::map<uint16_t, uint8_t>::iterator itChar;
600     std::map<uint16_t, uint8_t>::iterator itExt;
601     uint16_t inText;
602     for (int i = 0; i < srcLength - 1; i += UCS2_LEN_MIN) {
603         inText = src[i];
604         inText = ((inText << 0x08) & 0xFF00) | src[i + 1];
605         itChar = gsm7bitDefMap_.find(inText); // check gsm7bit default char
606         if (itChar != gsm7bitDefMap_.end()) {
607             dest[outTextLen++] = static_cast<uint8_t>(itChar->second);
608         } else {
609             itExt = extMap.find(inText);
610             if (itExt == extMap.end()) {
611                 TELEPHONY_LOGI("Abnormal character is included. inText : [%{public}04x]", inText);
612                 unknown = true;
613                 return 0;
614             }
615             if (maxLength <= outTextLen + 1) {
616                 TELEPHONY_LOGE("buffer overflow.");
617                 break;
618             }
619             dest[outTextLen++] = 0x1B;
620             dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
621         }
622         // prevent buffer overflow
623         if (maxLength <= outTextLen) {
624             TELEPHONY_LOGE("buffer overflow");
625             break;
626         }
627     }
628     return outTextLen;
629 }
630 
Ucs2ToAscii(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,bool & unknown)631 int TextCoder::Ucs2ToAscii(uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, bool &unknown)
632 {
633     if (srcLength <= 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
634         TELEPHONY_LOGE("text is null");
635         return -1;
636     }
637 
638     int outTextLen = 0;
639     std::map<uint16_t, uint8_t>::iterator itChar;
640     std::map<uint16_t, uint8_t>::iterator itExt;
641     uint16_t inText;
642     for (int index = 0; index < srcLength - 1; index += UCS2_LEN_MIN) {
643         inText = src[index];
644         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
645         // check default char
646         if (inText > 0x007f) {
647             TELEPHONY_LOGI("abnormal character is included [%{public}04x]", inText);
648             unknown = true;
649             return 0;
650         }
651         dest[outTextLen++] = static_cast<uint8_t>(inText);
652         // prevent buffer overflow
653         if (maxLength <= outTextLen) {
654             TELEPHONY_LOGE("buffer overflow");
655             break;
656         }
657     }
658     return outTextLen;
659 }
660 
GetLangType(const uint8_t * src,int srcLength)661 uint8_t TextCoder::GetLangType(const uint8_t *src, int srcLength)
662 {
663     if (srcLength <= 0 || src == nullptr) {
664         TELEPHONY_LOGE("text is null");
665         return MSG_DEFAULT_CHAR;
666     }
667 
668     std::map<uint16_t, uint8_t>::iterator itExt;
669     uint8_t currType = MSG_DEFAULT_CHAR;
670     uint8_t newType = MSG_DEFAULT_CHAR;
671     uint16_t inText;
672     for (int index = 0; index < (srcLength - 1); index += UCS2_LEN_MIN) {
673         inText = src[index];
674         inText = ((inText << 0x08) & 0xFF00) | src[index + 1];
675         itExt = extCharMap_.find(inText);
676         if (itExt == extCharMap_.end()) {
677             continue;
678         }
679         newType = static_cast<uint8_t>(itExt->second);
680         if (newType >= currType) {
681             bool isTurkisk = (inText == 0x00e7 && currType <= MSG_TURKISH_CHAR);
682             currType = isTurkisk ? MSG_TURKISH_CHAR : newType;
683         }
684     }
685     TELEPHONY_LOGI("charType : [%{public}hhu]", currType);
686     return currType;
687 }
688 
FindGsm7bitExt(uint8_t * dest,int maxLength,const uint16_t inText)689 int TextCoder::FindGsm7bitExt(uint8_t *dest, int maxLength, const uint16_t inText)
690 {
691     int outTextLen = 0;
692     if (dest == nullptr || maxLength <= 0) {
693         TELEPHONY_LOGE("Invalid parameter.");
694         return outTextLen;
695     }
696 
697     auto itExt = gsm7bitExtMap_.find(inText);
698     if (itExt == gsm7bitExtMap_.end()) {
699         dest[outTextLen++] = FindReplaceChar(inText);
700         return outTextLen;
701     }
702     // prevent buffer overflow
703     if (maxLength <= outTextLen + 1) {
704         TELEPHONY_LOGE("FindGsm7bitExt buffer overflow");
705         return outTextLen;
706     }
707     dest[outTextLen++] = 0x1B;
708     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
709     return outTextLen;
710 }
711 
FindTurkish(uint8_t * dest,int maxLength,const uint16_t inText)712 int TextCoder::FindTurkish(uint8_t *dest, int maxLength, const uint16_t inText)
713 {
714     int outTextLen = 0;
715     if (dest == nullptr || maxLength <= 0) {
716         TELEPHONY_LOGE("Invalid parameter.");
717         return outTextLen;
718     }
719 
720     auto itExt = turkishMap_.find(inText);
721     if (itExt == turkishMap_.end()) {
722         dest[outTextLen++] = FindReplaceChar(inText);
723         return outTextLen;
724     }
725     // prevent buffer overflow
726     if (maxLength <= outTextLen + 1) {
727         TELEPHONY_LOGE("FindTurkish buffer overflow");
728         return outTextLen;
729     }
730     dest[outTextLen++] = 0x1B;
731     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
732     return outTextLen;
733 }
734 
FindSpanish(uint8_t * dest,int maxLength,const uint16_t inText)735 int TextCoder::FindSpanish(uint8_t *dest, int maxLength, const uint16_t inText)
736 {
737     int outTextLen = 0;
738     if (dest == nullptr || maxLength <= 0) {
739         TELEPHONY_LOGE("Invalid parameter.");
740         return outTextLen;
741     }
742 
743     auto itExt = spanishMap_.find(inText);
744     if (itExt == spanishMap_.end()) {
745         dest[outTextLen++] = FindReplaceChar(inText);
746         return outTextLen;
747     }
748     // prevent buffer overflow
749     if (maxLength <= outTextLen + 1) {
750         TELEPHONY_LOGE("FindSpanish buffer overflow");
751         return outTextLen;
752     }
753     dest[outTextLen++] = 0x1B;
754     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
755     return outTextLen;
756 }
757 
FindPortu(uint8_t * dest,int maxLength,const uint16_t inText)758 int TextCoder::FindPortu(uint8_t *dest, int maxLength, const uint16_t inText)
759 {
760     int outTextLen = 0;
761     if (dest == nullptr || maxLength <= 0) {
762         TELEPHONY_LOGE("Invalid parameter.");
763         return outTextLen;
764     }
765 
766     auto itExt = portuMap_.find(inText);
767     if (itExt == portuMap_.end()) {
768         dest[outTextLen++] = FindReplaceChar(inText);
769         return outTextLen;
770     }
771     // prevent buffer overflow
772     if (maxLength <= outTextLen + 1) {
773         TELEPHONY_LOGE("FindPortu buffer overflow");
774         return outTextLen;
775     }
776     dest[outTextLen++] = 0x1B;
777     dest[outTextLen++] = static_cast<uint8_t>(itExt->second);
778     return outTextLen;
779 }
780 
FindReplaceChar(const uint16_t inText)781 uint8_t TextCoder::FindReplaceChar(const uint16_t inText)
782 {
783     uint8_t result = 0;
784     auto itReplace = replaceCharMap_.find(inText);
785     if (itReplace != replaceCharMap_.end()) {
786         result = static_cast<uint8_t>(itReplace->second);
787     } else {
788         result = 0x3F;
789     }
790     return result;
791 }
792 
Gsm7bitToUcs2(uint8_t * dest,int maxLength,const uint8_t * src,int srcLength,const MsgLangInfo & langInfo)793 int TextCoder::Gsm7bitToUcs2(
794     uint8_t *dest, int maxLength, const uint8_t *src, int srcLength, const MsgLangInfo &langInfo)
795 {
796     if (srcLength == 0 || src == nullptr || dest == nullptr || maxLength <= 0) {
797         TELEPHONY_LOGE("text is null");
798         return -1;
799     }
800 
801     int outTextLen = 0;
802     uint8_t lowerByte = 0;
803     uint8_t upperByte = 0;
804     uint16_t result = 0;
805     for (int i = 0; i < srcLength && maxLength > UCS2_LEN_MIN; i++) {
806         if (src[i] >= 0x80) {
807             TELEPHONY_LOGE("a_pTextString[%{public}d]=%{public}x, The alpha isn't the gsm 7bit code", i, src[i]);
808             return -1;
809         }
810         if (langInfo.bLockingShift) {
811             TELEPHONY_LOGI("National Language Locking Shift [%{public}d]", langInfo.lockingLang);
812             if (langInfo.lockingLang == MSG_ID_TURKISH_LANG) {
813                 i += EscapeTurkishLockingToUcs2(&src[i], (srcLength - i), langInfo, result);
814                 lowerByte = static_cast<uint8_t>(result & 0x00FF);
815                 upperByte = static_cast<uint8_t>(result >> 0x08);
816             } else if (langInfo.lockingLang == MSG_ID_PORTUGUESE_LANG) {
817                 i += EscapePortuLockingToUcs2(&src[i], (srcLength - i), langInfo, result);
818                 lowerByte = static_cast<uint8_t>(result & 0x00FF);
819                 upperByte = static_cast<uint8_t>(result >> 0x08);
820             }
821         } else {
822             i += EscapeGsm7bitToUcs2(&src[i], (srcLength - i), langInfo, result);
823             lowerByte = static_cast<uint8_t>(result & 0x00FF);
824             upperByte = static_cast<uint8_t>(result >> 0x08);
825         }
826         dest[outTextLen++] = upperByte;
827         dest[outTextLen++] = lowerByte;
828         maxLength -= 0x02;
829     }
830     dest[outTextLen] = '\0';
831 
832     return outTextLen;
833 }
834 
EscapeTurkishLockingToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)835 int TextCoder::EscapeTurkishLockingToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
836 {
837     int index = 0;
838     if (src == nullptr || srcLen <= 0) {
839         return index;
840     }
841     // Turkish National Language Locking Shift Table
842     const WCHAR turkishLockingToUcs2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x20AC, 0x00E9, 0x00F9, 0x00EC, 0x00F2,
843         0x00C7, 0x000A, 0x011E, 0x011F, 0x000D, 0x00C5, 0x00E5, 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0,
844         0x03A8, 0x03A3, 0x0398, 0x039E, 0x001B, 0x015E, 0x015F, 0x00DF, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4,
845         0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032,
846         0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0130,
847         0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E,
848         0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6,
849         0x00D1, 0x00DC, 0x00A7, 0x00E7, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
850         0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
851         0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0 };
852     // Check Escape
853     if (turkishLockingToUcs2[src[index]] == 0x001B) {
854         index++;
855         if (index >= srcLen) {
856             return index;
857         }
858         result = EscapeToUcs2(src[index], langInfo);
859     } else {
860         // TURKISH
861         result = turkishLockingToUcs2[src[index]];
862     }
863     return index;
864 }
865 
EscapePortuLockingToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)866 int TextCoder::EscapePortuLockingToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
867 {
868     int index = 0;
869     if (src == nullptr || srcLen <= 0) {
870         return index;
871     }
872     // Portuguese National Language Locking Shift Table
873     const WCHAR portuLockingToUcs2[] = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00EA, 0x00E9, 0x00FA, 0x00ED, 0x00F3, 0x00E7,
874         0x000A, 0x00D4, 0x00F4, 0x000D, 0x00C1, 0x00E1, 0x0394, 0x005F, 0x0020, 0x00C7, 0x00C0, 0x0020, 0x005E, 0x005C,
875         0x20AC, 0x00D3, 0x007C, 0x001B, 0x00C2, 0x00E2, 0x00CA, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025,
876         0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033,
877         0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x00CD, 0x0041,
878         0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
879         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C3, 0x00D5, 0x00DA,
880         0x00DC, 0x00A7, 0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
881         0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
882         0x007A, 0x00E3, 0x00F5, 0x0020, 0x00FC, 0x00E0 };
883     if (portuLockingToUcs2[src[index]] == 0x001B) {
884         index++;
885         if (index >= srcLen) {
886             return index;
887         }
888         result = EscapeToUcs2(src[index], langInfo);
889     } else {
890         // PORTUGUESE
891         result = portuLockingToUcs2[src[index]];
892     }
893     return index;
894 }
895 
EscapeGsm7bitToUcs2(const uint8_t * src,int srcLen,const MsgLangInfo & langInfo,uint16_t & result)896 int TextCoder::EscapeGsm7bitToUcs2(const uint8_t *src, int srcLen, const MsgLangInfo &langInfo, uint16_t &result)
897 {
898     int index = 0;
899     if (src == nullptr || srcLen <= 0) {
900         return index;
901     }
902     if (GSM7_BIT_TO_UC_S2[src[index]] == 0x001B) {
903         index++;
904         if (index >= srcLen) {
905             return index;
906         }
907         result = EscapeToUcs2(src[index], langInfo);
908     } else {
909         result = GSM7_BIT_TO_UC_S2[src[index]];
910     }
911     return index;
912 }
913 
EscapeToUcs2(const uint8_t srcText,const MsgLangInfo & langInfo)914 uint16_t TextCoder::EscapeToUcs2(const uint8_t srcText, const MsgLangInfo &langInfo)
915 {
916     uint16_t result = 0;
917     if (langInfo.bSingleShift) {
918         TELEPHONY_LOGI("National Language Single Shift [%{public}d]", langInfo.singleLang);
919         switch (langInfo.singleLang) {
920             case MSG_ID_TURKISH_LANG:
921                 GetTurkishSingleToUcs2(srcText, result);
922                 break;
923             case MSG_ID_SPANISH_LANG:
924                 GetSpanishSingleToUcs2(srcText, result);
925                 break;
926             case MSG_ID_PORTUGUESE_LANG:
927                 GetPortuSingleToUcs2(srcText, result);
928                 break;
929             default:
930                 GetGsm7BitExtToUcs2(srcText, result);
931                 break;
932         }
933     } else {
934         GetGsm7BitExtToUcs2(srcText, result);
935     }
936     return result;
937 }
938 
GetTurkishSingleToUcs2(const uint8_t & srcText,uint16_t & result)939 void TextCoder::GetTurkishSingleToUcs2(const uint8_t &srcText, uint16_t &result)
940 {
941     // Turkish National Language Single Shift Table
942     const WCHAR turkishSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
943         0x0020, 0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020,
944         0x0020, 0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
945         0x0020, 0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020,
946         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C,
947         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x011E, 0x0020, 0x0130, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
948         0x0020, 0x0020, 0x0020, 0x0020, 0x015E, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
949         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00E7, 0x0020, 0x20AC, 0x0020, 0x011F, 0x0020, 0x0131, 0x0020,
950         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x015F, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
951         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
952     result = turkishSingleToUcs2[srcText];
953 }
954 
GetSpanishSingleToUcs2(const uint8_t & srcText,uint16_t & result)955 void TextCoder::GetSpanishSingleToUcs2(const uint8_t &srcText, uint16_t &result)
956 {
957     // Spanish National Language Single Shift Table
958     const WCHAR spanishSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
959         0x00E7, 0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020,
960         0x0020, 0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
961         0x0020, 0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020,
962         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C,
963         0x00C1, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
964         0x00D3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00DA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
965         0x0020, 0x0020, 0x0020, 0x0020, 0x00E1, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x00ED, 0x0020,
966         0x0020, 0x0020, 0x0020, 0x0020, 0x00F3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00FA, 0x0020, 0x0020, 0x0020,
967         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
968     result = spanishSingleToUcs2[srcText];
969 }
970 
GetGsm7BitExtToUcs2(const uint8_t & srcText,uint16_t & result)971 void TextCoder::GetGsm7BitExtToUcs2(const uint8_t &srcText, uint16_t &result)
972 {
973     // GSM 7 bit Default Alphabet Extension Table
974     const WCHAR gsm7BitExtToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
975         0x000C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005E, 0x0020, 0x0020, 0x0020,
976         0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
977         0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020, 0x0020,
978         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C, 0x0020,
979         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
980         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
981         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
982         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
983         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 };
984     result = gsm7BitExtToUcs2[srcText];
985 }
986 
GetPortuSingleToUcs2(const uint8_t & srcText,uint16_t & result)987 void TextCoder::GetPortuSingleToUcs2(const uint8_t &srcText, uint16_t &result)
988 {
989     // Portuguese National Language Single Shift Table
990     const WCHAR portuSingleToUcs2[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00EA, 0x0020, 0x0020, 0x0020, 0x00E7,
991         0x000C, 0x00D4, 0x00F4, 0x0020, 0x00C1, 0x00E1, 0x0020, 0x0020, 0x03A6, 0x0393, 0x005E, 0x03A9, 0x03A0, 0x03A8,
992         0x03A3, 0x0398, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x00CA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
993         0x0020, 0x0020, 0x007B, 0x007D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005C, 0x0020, 0x0020, 0x0020, 0x0020,
994         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x005B, 0x007E, 0x005D, 0x0020, 0x007C, 0x00C0,
995         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00CD, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00D3,
996         0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00DA, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00C3, 0x00D5, 0x0020,
997         0x0020, 0x0020, 0x0020, 0x00C2, 0x0020, 0x0020, 0x0020, 0x20AC, 0x0020, 0x0020, 0x0020, 0x00ED, 0x0020, 0x0020,
998         0x0020, 0x0020, 0x0020, 0x00F3, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x00FA, 0x0020, 0x0020, 0x0020, 0x0020,
999         0x0020, 0x00E3, 0x00F5, 0x0020, 0x0020, 0x00E2 };
1000     result = portuSingleToUcs2[srcText];
1001 }
1002 
1003 } // namespace Telephony
1004 } // namespace OHOS
1005