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