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