1 /*
2 * Copyright (c) 2020-2021 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 "global.h"
17
18 #include <fcntl.h>
19 #include <limits.h>
20 #include <securec.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include "global_utils.h"
27
28 /*
29 * locale format as below, use '-' or '_' to link, e.g. en_Latn_US
30 * and needn't have all 3 elements, so max length is 13 including '\0'
31 * | language | script | region |
32 * | ----------- | --------- | ---------------------- |
33 * | 2-3 letters | 4 letters | 2 letters or 3 numbers |
34 */
35
36 #define MAX_LOCALE_LENGTH 13
37 #define UI_LOCALE_ELEMENT_NUM 2
38 #define MAX_SCRIPT_LENGTH 5
39 static char g_locale[MAX_LOCALE_LENGTH] = {0};
40
GLOBAL_ConfigLanguage(const char * appLanguage)41 void GLOBAL_ConfigLanguage(const char *appLanguage)
42 {
43 if (appLanguage == NULL) {
44 return;
45 }
46 // appLanguage is same as g_locale, needn't strcpy_s
47 if (strcmp(appLanguage, g_locale) == 0) {
48 return;
49 }
50 if (strcpy_s(g_locale, MAX_LOCALE_LENGTH, appLanguage) != EOK) {
51 return;
52 }
53 }
54
GLOBAL_GetLanguage(char * language,uint8_t len)55 int32_t GLOBAL_GetLanguage(char *language, uint8_t len)
56 {
57 if (language == NULL || len == 0) {
58 return MC_FAILURE;
59 }
60 char *localeArray[LOCALE_ELEMENT_NUM] = {NULL};
61 char tempLocale[MAX_LOCALE_LENGTH] = {'\0'};
62 int32_t ret = strcpy_s(tempLocale, MAX_LOCALE_LENGTH, g_locale);
63 if (ret != EOK) {
64 return MC_FAILURE;
65 }
66 int32_t count = 0;
67 ret = GetGlobalUtilsImpl()->SplitLocale(tempLocale, localeArray, &count);
68 if (ret == MC_FAILURE || count != UI_LOCALE_ELEMENT_NUM) {
69 return MC_FAILURE;
70 }
71
72 // language must be the element 0;
73 return (strncpy_s(language, len, localeArray[0], MAX_LANGUAGE_LENGTH - 1) != EOK) ? MC_FAILURE : MC_SUCCESS;
74 }
75
GLOBAL_IsRTL(void)76 int32_t GLOBAL_IsRTL(void)
77 {
78 char *localeArray[LOCALE_ELEMENT_NUM] = { NULL };
79 char tempLocale[MAX_LOCALE_LENGTH] = { '\0' };
80 int32_t ret = strcpy_s(tempLocale, MAX_LOCALE_LENGTH, g_locale);
81 if (ret != EOK) {
82 return 0;
83 }
84 int32_t count = 0;
85 ret = GetGlobalUtilsImpl()->SplitLocale(tempLocale, localeArray, &count);
86 if (ret == MC_FAILURE || count != UI_LOCALE_ELEMENT_NUM) {
87 return 0;
88 }
89 char script[MAX_SCRIPT_LENGTH] = { 0 };
90 if (strncpy_s(script, MAX_SCRIPT_LENGTH, localeArray[1], MAX_SCRIPT_LENGTH - 1) != EOK) {
91 return 0;
92 }
93 // if script is set and script != arab or script != hebr, return false;
94 if ((strlen(script) == MAX_SCRIPT_LENGTH - 1) &&
95 (strcmp(script, "Arab") != 0) && (strcmp(script, "Hebr") != 0)) {
96 return 0;
97 }
98 char language[MAX_LANGUAGE_LENGTH] = { 0 };
99 if (strncpy_s(language, MAX_LANGUAGE_LENGTH, localeArray[0], MAX_LANGUAGE_LENGTH - 1) != EOK) {
100 return 0;
101 }
102 if ((strcmp(language, "fa") == 0) || (strcmp(language, "ar") == 0) || (strcmp(language, "ur") == 0) ||
103 (strcmp(language, "ug") == 0) || (strcmp(language, "he") == 0) || (strcmp(language, "iw") == 0)) {
104 return 1;
105 }
106 return 0;
107 }
108
GLOBAL_GetRegion(char * region,uint8_t len)109 int32_t GLOBAL_GetRegion(char *region, uint8_t len)
110 {
111 if (region == NULL || len == 0) {
112 return MC_FAILURE;
113 }
114 char *localeArray[LOCALE_ELEMENT_NUM] = {NULL};
115 char tempLocale[MAX_LOCALE_LENGTH] = {'\0'};
116 int32_t ret = strcpy_s(tempLocale, MAX_LOCALE_LENGTH, g_locale);
117 if (ret != EOK) {
118 return MC_FAILURE;
119 }
120 int32_t count = 0;
121 ret = GetGlobalUtilsImpl()->SplitLocale(tempLocale, localeArray, &count);
122 if (ret == MC_FAILURE || count != UI_LOCALE_ELEMENT_NUM) {
123 return MC_FAILURE;
124 }
125
126 // region must be the element 1
127 return (strncpy_s(region, len, localeArray[1], MAX_REGION_LENGTH - 1) != EOK) ? MC_FAILURE : MC_SUCCESS;
128 }
129
FreeIdItem(IdItem * idItem)130 static void FreeIdItem(IdItem *idItem)
131 {
132 if (idItem == NULL) {
133 return;
134 }
135 free(idItem->value);
136 free(idItem->name);
137 idItem->value = NULL;
138 idItem->name = NULL;
139 }
140
FreeValue(char ** value)141 static void FreeValue(char **value)
142 {
143 if (*value != NULL) {
144 free(*value);
145 *value = NULL;
146 }
147 }
148
GLOBAL_GetValueByIdInternal(uint32_t id,const char * path,const char * locale,char ** value)149 static int32_t GLOBAL_GetValueByIdInternal(uint32_t id, const char *path, const char *locale, char **value)
150 {
151 char realResourcePath[PATH_MAX] = {'\0'};
152 GlobalUtilsImpl *utilsImpl = GetGlobalUtilsImpl();
153 if (utilsImpl->CheckFilePath(path, realResourcePath, PATH_MAX) == MC_FAILURE) {
154 return MC_FAILURE;
155 }
156
157 uint32_t idHeaderOffset = utilsImpl->GetOffsetByLocale(realResourcePath, locale, MAX_LOCALE_LENGTH);
158 IdHeader idHeader = {0, NULL};
159 int32_t file = open(realResourcePath, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH);
160 if (file < 0) {
161 return MC_FAILURE;
162 }
163 int32_t ret = utilsImpl->GetIdHeaderByOffset(file, idHeaderOffset, &idHeader);
164 if (ret != MC_SUCCESS) {
165 close(file);
166 return ret;
167 }
168
169 int32_t result = MC_FAILURE;
170 IdItem idItem = {0, INVALID_RES_TYPE, 0, 0, NULL, 0, NULL};
171 for (uint32_t i = 0; i < idHeader.count; i++) {
172 if (idHeader.idParams[i].id == id) {
173 ret = utilsImpl->GetIdItem(file, idHeader.idParams[i].offset, &idItem);
174 if (ret != MC_SUCCESS) {
175 close(file);
176 free(idHeader.idParams);
177 return ret;
178 }
179 *value = (char *)malloc(idItem.valueLen);
180 if (*value == NULL || strcpy_s(*value, idItem.valueLen, idItem.value) != EOK) {
181 close(file);
182 free(idHeader.idParams);
183 FreeIdItem(&idItem);
184 FreeValue(value);
185 return MC_FAILURE;
186 }
187 result = MC_SUCCESS;
188 break;
189 }
190 }
191 close(file);
192 free(idHeader.idParams);
193 FreeIdItem(&idItem);
194 return result;
195 }
196
GLOBAL_GetValueById(uint32_t id,const char * path,char ** value)197 int32_t GLOBAL_GetValueById(uint32_t id, const char *path, char **value)
198 {
199 if (path == NULL || path[0] == '\0' || value == NULL) {
200 return MC_FAILURE;
201 }
202
203 char tempLocale[MAX_LOCALE_LENGTH] = {'\0'};
204 int32_t ret = strcpy_s(tempLocale, MAX_LOCALE_LENGTH, g_locale);
205 if (ret != EOK) {
206 return MC_FAILURE;
207 }
208
209 char *locales[] = {tempLocale, ""};
210 for (int i = 0; i < 2; i++) { // 2 current language and the default.
211 if (GLOBAL_GetValueByIdInternal(id, path, locales[i], value) == MC_SUCCESS) {
212 return MC_SUCCESS;
213 }
214 }
215 return MC_FAILURE;
216 }
217
GLOBAL_GetValueByNameInternal(const char * name,const char * path,const char * locale,char ** value)218 static int32_t GLOBAL_GetValueByNameInternal(const char *name, const char *path, const char *locale, char **value)
219 {
220 char realResourcePath[PATH_MAX] = {'\0'};
221 GlobalUtilsImpl *utilsImpl = GetGlobalUtilsImpl();
222 if (utilsImpl->CheckFilePath(path, realResourcePath, PATH_MAX) == MC_FAILURE) {
223 return MC_FAILURE;
224 }
225 uint32_t idHeaderOffset = utilsImpl->GetOffsetByLocale(realResourcePath, locale, MAX_LOCALE_LENGTH);
226 IdHeader idHeader = {0, NULL};
227 int32_t file = open(realResourcePath, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH);
228 if (file < 0) {
229 return MC_FAILURE;
230 }
231 int32_t ret = utilsImpl->GetIdHeaderByOffset(file, idHeaderOffset, &idHeader);
232 if (ret != MC_SUCCESS) {
233 close(file);
234 return ret;
235 }
236
237 int32_t result = MC_FAILURE;
238 IdItem idItem = {0, INVALID_RES_TYPE, 0, 0, NULL, 0, NULL};
239 for (uint32_t i = 0; i < idHeader.count; i++) {
240 ret = utilsImpl->GetIdItem(file, idHeader.idParams[i].offset, &idItem);
241 if (ret != MC_SUCCESS) {
242 close(file);
243 free(idHeader.idParams);
244 return ret;
245 }
246 if (strcmp(name, idItem.name) != 0) {
247 FreeIdItem(&idItem);
248 continue;
249 }
250 *value = (char *)malloc(idItem.valueLen);
251 if (*value == NULL || strcpy_s(*value, idItem.valueLen, idItem.value) != EOK) {
252 close(file);
253 free(idHeader.idParams);
254 FreeIdItem(&idItem);
255 FreeValue(value);
256 return MC_FAILURE;
257 }
258 result = MC_SUCCESS;
259 break;
260 }
261
262 close(file);
263 free(idHeader.idParams);
264 FreeIdItem(&idItem);
265 return result;
266 }
267
GLOBAL_GetValueByName(const char * name,const char * path,char ** value)268 int32_t GLOBAL_GetValueByName(const char *name, const char *path, char **value)
269 {
270 if (name == NULL || strlen(name) == 0 || path == NULL || strlen(path) == 0 || value == NULL) {
271 return MC_FAILURE;
272 }
273
274 char tempLocale[MAX_LOCALE_LENGTH] = {'\0'};
275 int32_t ret = strcpy_s(tempLocale, MAX_LOCALE_LENGTH, g_locale);
276 if (ret != EOK) {
277 return MC_FAILURE;
278 }
279
280 char *locales[] = {tempLocale, ""};
281 for (int i = 0; i < 2; i++) { // 2 current language and the default.
282 if (GLOBAL_GetValueByNameInternal(name, path, locales[i], value) == MC_SUCCESS) {
283 return MC_SUCCESS;
284 }
285 }
286 return MC_FAILURE;
287 }
288