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