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