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