1 /*
2 * Copyright (c) 2022 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 "utils/psue_manager.h"
17
18 #include <algorithm>
19 #include <cctype>
20 #include <cstdlib>
21 #include <iostream>
22 #include <string>
23 #include <unzip.h>
24 #include <vector>
25 #include "hilog_wrapper.h"
26 #include "map"
27 #include "utils/errors.h"
28 #ifdef __WINNT__
29 #include <windows.h>
30 #undef ERROR
31 #endif
32
33 namespace OHOS {
34 namespace Global {
35 namespace Resource {
36 using namespace std;
37
38 namespace {
39 const float DEFAULT_EXTEND_RATIO = 0.3f;
40
41 struct ExtendRatioTable {
42 int32_t count;
43 float ratio;
44 };
45
46 const ExtendRatioTable EXTEND_RATIO_RABLE[] = {
47 {10, 2.0f},
48 {20, 1.0f},
49 {30, 0.8f},
50 {50, 0.6f},
51 {70, 0.4f},
52 };
53 const std::wstring PSUE_CONFIG_CHARS = {L"ReÇÉÄßÑ¿ÃóèìжДﺥ"};
54
55 const map<wchar_t, wchar_t> REPLACE_TABLE {
56 {L'a', L'à'},
57 {L'A', L'À'},
58 {L'c', L'ć'},
59 {L'C', L'Ć'},
60 {L'i', L'ì'},
61 {L'I', L'Ì'},
62 {L'o', L'ó'},
63 {L'O', L'Ó'},
64 {L'u', L'ü'},
65 {L'U', L'Ü'},
66 {L'y', L'ÿ'},
67 {L'Y', L'Ÿ'},
68 {L'z', L'ž'},
69 {L'Z', L'Ž'},
70 };
71 }
72
PsueManager()73 PsueManager::PsueManager()
74 {
75 }
76
~PsueManager()77 PsueManager::~PsueManager()
78 {
79 }
80
81 /**
82 PsuedoTranslation level default value is 3
83 1. Enclosed in brackets
84 2. Letter replacement
85 3. Lengthen string
86 */
87 int g_fakeLocaleLevel = 3;
88
89 int g_levelForReplace = 2;
90 int g_levelForAppend = 3;
91 int g_levelForAddBracket = 1;
92
Convert(const std::string & src,std::string & dest)93 std::string PsueManager::Convert(const std::string &src, std::string &dest)
94 {
95 if (isDigit(src)) {
96 return "";
97 }
98 std::wstring ws;
99 std::string wsStr = ToWstring(ws, src);
100 if (wsStr != "") {
101 return wsStr;
102 }
103 if (g_fakeLocaleLevel >= g_levelForReplace) {
104 // char replace
105 ToAccent(ws);
106 }
107 if (g_fakeLocaleLevel == g_levelForAppend) {
108 // enhance length
109 unsigned int len = src.length();
110 unsigned int extendCount = len * GetExtendRatio(len);
111 unsigned int loop = extendCount / PSUE_CONFIG_CHARS.length();
112 unsigned int left = extendCount % PSUE_CONFIG_CHARS.length();
113 for (unsigned int i = 0; i < loop ; i++) {
114 ws += PSUE_CONFIG_CHARS;
115 }
116 if (left > 0) {
117 ws += PSUE_CONFIG_CHARS.substr(0, left);
118 }
119 }
120 std::string tsStr = ToString(dest, ws);
121 if (tsStr != "") {
122 return tsStr;
123 }
124 if (g_fakeLocaleLevel >= g_levelForAddBracket) {
125 // add brackets
126 dest = '[' + dest + ']';
127 }
128 return "";
129 }
130
isDigit(const std::string src)131 bool PsueManager::isDigit(const std::string src)
132 {
133 for (unsigned int i = 0 ; i < src.size() ; i++) {
134 if (!isdigit(src[i])) {
135 return false;
136 }
137 }
138 return true;
139 }
140
GetExtendRatio(int32_t len) const141 float PsueManager::GetExtendRatio(int32_t len) const
142 {
143 for (size_t i = 0; i < sizeof(EXTEND_RATIO_RABLE) / sizeof(EXTEND_RATIO_RABLE[0]) ; i++) {
144 if (len <= EXTEND_RATIO_RABLE[i].count) {
145 return EXTEND_RATIO_RABLE[i].ratio;
146 }
147 }
148 return DEFAULT_EXTEND_RATIO;
149 }
150
151 // letter replace
ToAccent(wstring & ws) const152 void PsueManager::ToAccent(wstring &ws) const
153 {
154 for (std::wstring::size_type i = 0 ; i < ws.length(); i++) {
155 if (ws[i] == L'%') {
156 i++;
157 } else if (ws[i] == L'{') {
158 while ((i + 1 < ws.length()) && (ws[++i] != L'}')) {}
159 } else {
160 auto iter = REPLACE_TABLE.find(ws[i]);
161 if (iter != REPLACE_TABLE.end()) {
162 ws[i] = iter->second;
163 }
164 }
165 }
166 }
167
ToWstring(std::wstring & dest,const std::string & src)168 std::string PsueManager::ToWstring(std::wstring &dest, const std::string &src)
169 {
170 char* result = setlocale(LC_CTYPE, "");
171 if (result == nullptr) {
172 return "set locale fail";
173 }
174 size_t destSize = mbstowcs(NULL, src.c_str(), 0);
175 if (destSize == size_t(-1)) {
176 return "get widechar size fail";
177 }
178 vector<wchar_t> buf(destSize + 1);
179 if (mbstowcs(&buf[0], src.c_str(), src.size()) == static_cast<size_t>(-1)) {
180 return "convert to widechar fail";
181 }
182
183 dest.assign(buf.begin(), buf.end() - 1);
184 return "";
185 }
186
ToString(std::string & dest,const std::wstring & src)187 std::string PsueManager::ToString(std::string &dest, const std::wstring &src)
188 {
189 size_t destSize = wcstombs(NULL, src.c_str(), 0);
190 if (destSize == size_t(-1)) {
191 return "get multibyte size fail";
192 }
193 vector<char> buf(destSize + 1);
194 if (wcstombs(&buf[0], src.c_str(), buf.size()) == static_cast<size_t>(-1)) {
195 return "convert to multibyte fail";
196 }
197
198 dest.assign(buf.begin(), buf.end() - 1);
199 return "";
200 }
201
SetFakeLocaleLevel(const int level)202 void PsueManager::SetFakeLocaleLevel(const int level)
203 {
204 if (level <= g_levelForAppend && level >= g_levelForAddBracket) {
205 g_fakeLocaleLevel = level;
206 }
207 }
208
IsAsciiString(const std::string & src)209 bool PsueManager::IsAsciiString(const std::string &src)
210 {
211 bool isAscii = true;
212 for (size_t i = 0; i < src.length(); i++) {
213 if (src[i] < 0 || src[i] > 127) { // 127 is the max value of ascii
214 isAscii = false;
215 break;
216 }
217 }
218 return isAscii;
219 }
220
BidirectionConvert(std::string & src)221 std::string PsueManager::BidirectionConvert(std::string &src)
222 {
223 if (!IsAsciiString(src)) {
224 return src;
225 }
226 std::string result;
227 size_t start = 0;
228 size_t end = 0;
229 while (start < src.length()) {
230 while (start < src.length() && isspace(src[start])) {
231 start++;
232 }
233 if (start > end) {
234 result += src.substr(end, start - end);
235 }
236 end = start;
237 while (end < src.length() && !isspace(src[end])) {
238 end++;
239 }
240 if (start < src.length()) {
241 result += directionHead;
242 result += src.substr(start, end - start);
243 result += directionTail;
244 }
245 start = end;
246 }
247 return result;
248 }
249 } // namespace Resource
250 } // namespace Global
251 } // namespace OHOS