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