1 /*
2 * Copyright (c) 2025 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 <map>
17 #include "loglibrary_ani_util.h"
18 #include "hiview_service_agent.h"
19 #include "ipc_skeleton.h"
20 #include "tokenid_kit.h"
21
22 using namespace OHOS::HiviewDFX;
23 namespace {
24 DEFINE_LOG_LABEL(0xD002D10, "LogLibraryAniUtil");
25 static constexpr int32_t SUCCESS = 0;
26 }
27
ParseStringValue(ani_env * env,ani_string aniStrRef)28 std::string LogLibraryAniUtil::ParseStringValue(ani_env *env, ani_string aniStrRef)
29 {
30 ani_size strSize = 0;
31 if (ANI_OK != env->String_GetUTF8Size(aniStrRef, &strSize)) {
32 HILOG_ERROR(LOG_CORE, "String_GetUTF8Size Failed");
33 return "";
34 }
35 std::vector<char> buffer(strSize + 1);
36 char* utf8Buffer = buffer.data();
37 ani_size bytesWritten = 0;
38 if (ANI_OK != env->String_GetUTF8(aniStrRef, utf8Buffer, strSize + 1, &bytesWritten)) {
39 HILOG_ERROR(LOG_CORE, "String_GetUTF8 Failed");
40 return "";
41 }
42 utf8Buffer[bytesWritten] = '\0';
43 std::string content = std::string(utf8Buffer);
44 return content;
45 }
46
CreateLogEntryArray(ani_env * env,const std::vector<HiviewFileInfo> & fileInfos,ani_array_ref & logEntryArray)47 bool LogLibraryAniUtil::CreateLogEntryArray(ani_env *env,
48 const std::vector<HiviewFileInfo>& fileInfos, ani_array_ref &logEntryArray)
49 {
50 ani_size index = 0;
51 for (const auto& value: fileInfos) {
52 std::string name = value.name;
53 ani_string name_string{};
54 env->String_NewUTF8(name.c_str(), name.size(), &name_string);
55 ani_object logEntryObj = LogLibraryAniUtil::CreateLogEntryObject(env);
56 if (ANI_OK != env->Object_SetPropertyByName_Ref(logEntryObj, "name", name_string)) {
57 HILOG_ERROR(LOG_CORE, "Set LogEntry name Fail: %{public}s", CLASS_NAME_LOGENTRY);
58 return false;
59 }
60 if (ANI_OK != env->Object_SetPropertyByName_Double(logEntryObj, "mtime", value.mtime)) {
61 HILOG_ERROR(LOG_CORE, "Set LogEntry mtime Fail: %{public}s", CLASS_NAME_LOGENTRY);
62 return false;
63 }
64 if (ANI_OK != env->Object_SetPropertyByName_Double(logEntryObj, "size", value.size)) {
65 HILOG_ERROR(LOG_CORE, "Set LogEntry size Fail: %{public}s", CLASS_NAME_LOGENTRY);
66 return false;
67 }
68 if (ANI_OK != env->Array_Set_Ref(logEntryArray, index, static_cast<ani_ref>(logEntryObj))) {
69 HILOG_ERROR(LOG_CORE, "Set logEntryObj to array Fail: %{public}s", CLASS_NAME_LOGENTRY);
70 return false;
71 }
72 index++;
73 }
74 return true;
75 }
76
CreateLogEntryObject(ani_env * env)77 ani_object LogLibraryAniUtil::CreateLogEntryObject(ani_env *env)
78 {
79 ani_class cls {};
80 ani_object logEntryObj {};
81 if (ANI_OK != env->FindClass(CLASS_NAME_LOGENTRY, &cls)) {
82 HILOG_ERROR(LOG_CORE, "FindClass %{public}s Failed", CLASS_NAME_LOGENTRY);
83 return logEntryObj;
84 }
85
86 ani_method logEntryConstructor {};
87 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &logEntryConstructor)) {
88 HILOG_ERROR(LOG_CORE, "get %{public}s ctor Failed", CLASS_NAME_LOGENTRY);
89 return logEntryObj;
90 }
91
92 if (ANI_OK != env->Object_New(cls, logEntryConstructor, &logEntryObj)) {
93 HILOG_ERROR(LOG_CORE, "Create Object Failed: %{public}s", CLASS_NAME_LOGENTRY);
94 return logEntryObj;
95 }
96 return logEntryObj;
97 }
98
ListResult(ani_env * env,const std::vector<HiviewFileInfo> & fileInfos)99 ani_ref LogLibraryAniUtil::ListResult(ani_env *env, const std::vector<HiviewFileInfo>& fileInfos)
100 {
101 ani_class cls {};
102 ani_array_ref logEntryArray {};
103 if (ANI_OK != env->FindClass(CLASS_NAME_LOGENTRY, &cls)) {
104 HILOG_ERROR(LOG_CORE, "FindClass %{public}s Failed", CLASS_NAME_LOGENTRY);
105 return logEntryArray;
106 }
107
108 ani_ref undefinedRef = LogLibraryAniUtil::GetAniUndefined(env);
109 if (ANI_OK != env->Array_New_Ref(cls, fileInfos.size(), undefinedRef, &logEntryArray)) {
110 HILOG_ERROR(LOG_CORE, "Array_New_Ref Failed");
111 return logEntryArray;
112 }
113
114 if (fileInfos.empty()) {
115 return logEntryArray;
116 }
117
118 if (!CreateLogEntryArray(env, fileInfos, logEntryArray)) {
119 HILOG_ERROR(LOG_CORE, "CreateLogEntryArray Failed");
120 return logEntryArray;
121 }
122 return logEntryArray;
123 }
124
IsSystemAppCall()125 bool LogLibraryAniUtil::IsSystemAppCall()
126 {
127 uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
128 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
129 }
130
ThrowAniError(ani_env * env,int32_t code,const std::string & message)131 void LogLibraryAniUtil::ThrowAniError(ani_env *env, int32_t code, const std::string &message)
132 {
133 ani_class cls {};
134 if (ANI_OK != env->FindClass(CLASS_NAME_BUSINESSERROR, &cls)) {
135 HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_BUSINESSERROR);
136 return;
137 }
138 ani_method ctor {};
139 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
140 HILOG_ERROR(LOG_CORE, "find method BusinessError constructor failed");
141 return;
142 }
143 ani_object error {};
144 if (ANI_OK != env->Object_New(cls, ctor, &error)) {
145 HILOG_ERROR(LOG_CORE, "new object %{public}s failed", CLASS_NAME_BUSINESSERROR);
146 return;
147 }
148 if (ANI_OK != env->Object_SetPropertyByName_Double(error, "code", static_cast<ani_double>(code))) {
149 HILOG_ERROR(LOG_CORE, "set property BusinessError.code failed");
150 return;
151 }
152 ani_string messageRef {};
153 if (ANI_OK != env->String_NewUTF8(message.c_str(), message.size(), &messageRef)) {
154 HILOG_ERROR(LOG_CORE, "new message string failed");
155 return;
156 }
157 if (ANI_OK != env->Object_SetPropertyByName_Ref(error, "message", static_cast<ani_ref>(messageRef))) {
158 HILOG_ERROR(LOG_CORE, "set property BusinessError.message failed");
159 return;
160 }
161 if (ANI_OK != env->ThrowError(static_cast<ani_error>(error))) {
162 HILOG_ERROR(LOG_CORE, "throwError ani_error object failed");
163 }
164 }
165
GetErrorDetailByRet(const int32_t retCode)166 std::pair<int32_t, std::string> LogLibraryAniUtil::GetErrorDetailByRet(const int32_t retCode)
167 {
168 HIVIEW_LOGI("origin result code is %{public}d.", retCode);
169 const std::map<int32_t, std::pair<int32_t, std::string>> errMap = {
170 {SUCCESS, {SUCCESS, "Success."}},
171 {HiviewNapiErrCode::ERR_PERMISSION_CHECK, {HiviewNapiErrCode::ERR_PERMISSION_CHECK,
172 "Permission denied. The app does not have the necessary permissions."}},
173 {HiviewNapiErrCode::ERR_NON_SYS_APP_PERMISSION, {HiviewNapiErrCode::ERR_NON_SYS_APP_PERMISSION,
174 "Permission denied, non-system app called system api."}},
175 {HiviewNapiErrCode::ERR_PARAM_CHECK,
176 {HiviewNapiErrCode::ERR_PARAM_CHECK, "Parameter error. The content of dest is invalid."}},
177 {HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE,
178 {HiviewNapiErrCode::ERR_PARAM_CHECK, "Parameter error. The value of logType is invalid."}},
179 {HiviewNapiErrCode::ERR_INNER_READ_ONLY,
180 {HiviewNapiErrCode::ERR_PARAM_CHECK, "Parameter error. The specified logType is read-only."}},
181 {HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST,
182 {HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST, "Source file does not exists."}}
183 };
184 return errMap.find(retCode) == errMap.end() ?
185 std::make_pair(HiviewNapiErrCode::ERR_DEFAULT, "Environment is abnormal.") : errMap.at(retCode);
186 }
187
CopyOrMoveFile(ani_env * env,ani_string logType,ani_string logName,ani_string dest,bool isMove)188 ani_object LogLibraryAniUtil::CopyOrMoveFile(ani_env *env,
189 ani_string logType, ani_string logName, ani_string dest, bool isMove)
190 {
191 isMove ? HIVIEW_LOGI("call move") : HIVIEW_LOGI("call copy");
192 std::string logTypeTemp = LogLibraryAniUtil::ParseStringValue(env, logType);
193 std::string logNameTemp = LogLibraryAniUtil::ParseStringValue(env, logName);
194 std::string destTemp = LogLibraryAniUtil::ParseStringValue(env, dest);
195 HIVIEW_LOGI("type:%{public}s, name:%{public}s, dir: %{public}s",
196 logTypeTemp.c_str(), StringUtil::HideSnInfo(logNameTemp).c_str(), destTemp.c_str());
197
198 if (!LogLibraryAniUtil::CheckDirPath(destTemp)) {
199 HIVIEW_LOGE("dest param is invalid: %{public}s", destTemp.c_str());
200 return LogLibraryAniUtil::CopyOrMoveResult(env,
201 LogLibraryAniUtil::GetErrorDetailByRet(HiviewNapiErrCode::ERR_PARAM_CHECK));
202 }
203
204 if (isMove) {
205 int32_t result = HiviewServiceAgent::GetInstance().Move(logTypeTemp, logNameTemp, destTemp);
206 return LogLibraryAniUtil::CopyOrMoveResult(env, LogLibraryAniUtil::GetErrorDetailByRet(result));
207 } else {
208 int32_t result = HiviewServiceAgent::GetInstance().Copy(logTypeTemp, logNameTemp, destTemp);
209 return LogLibraryAniUtil::CopyOrMoveResult(env, LogLibraryAniUtil::GetErrorDetailByRet(result));
210 }
211 }
212
CheckDirPath(const std::string & path)213 bool LogLibraryAniUtil::CheckDirPath(const std::string& path)
214 {
215 return path.empty() || path.find("..") == std::string::npos;
216 }
217
CopyOrMoveResult(ani_env * env,std::pair<int32_t,std::string> result)218 ani_object LogLibraryAniUtil::CopyOrMoveResult(ani_env *env, std::pair<int32_t, std::string> result)
219 {
220 ani_object results_obj {};
221 ani_class cls {};
222 if (ANI_OK != env->FindClass(CLASS_NAME_RESULTS, &cls)) {
223 HILOG_ERROR(LOG_CORE, "failed to find class %{public}s", CLASS_NAME_RESULTS);
224 return results_obj;
225 }
226
227 ani_method ctor {};
228 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
229 HILOG_ERROR(LOG_CORE, "get method %{public}s <ctor> failed", CLASS_NAME_RESULTS);
230 return results_obj;
231 }
232
233 if (ANI_OK != env->Object_New(cls, ctor, &results_obj)) {
234 HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_RESULTS);
235 return results_obj;
236 }
237
238 ani_method codeSetter {};
239 if (ANI_OK != env->Class_FindMethod(cls, "<set>code", nullptr, &codeSetter)) {
240 HILOG_ERROR(LOG_CORE, "get method codeSetter %{public}s failed", CLASS_NAME_RESULTS);
241 return results_obj;
242 }
243
244 if (ANI_OK != env->Object_CallMethod_Void(results_obj, codeSetter, static_cast<ani_double>(result.first))) {
245 HILOG_ERROR(LOG_CORE, "call method codeSetter %{public}s failed", CLASS_NAME_RESULTS);
246 return results_obj;
247 }
248
249 ani_method messageSetter {};
250 if (ANI_OK != env->Class_FindMethod(cls, "<set>message", nullptr, &messageSetter)) {
251 HILOG_ERROR(LOG_CORE, "find method messageSetter %{public}s failed", CLASS_NAME_RESULTS);
252 return results_obj;
253 }
254
255 std::string message = result.second;
256 ani_string message_string {};
257 env->String_NewUTF8(message.c_str(), message.size(), &message_string);
258
259 if (ANI_OK != env->Object_CallMethod_Void(results_obj, messageSetter, message_string)) {
260 HILOG_ERROR(LOG_CORE, "call method messageSetter Fail %{public}s", CLASS_NAME_RESULTS);
261 return results_obj;
262 }
263
264 return results_obj;
265 }
266
GetAniUndefined(ani_env * env)267 ani_ref LogLibraryAniUtil::GetAniUndefined(ani_env *env)
268 {
269 ani_ref result {};
270 if (ANI_OK != env->GetUndefined(&result)) {
271 HILOG_ERROR(LOG_CORE, "GetUndefined Fail");
272 return result;
273 }
274 return result;
275 }
276