• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "text_coder.h"
17 
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