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