1 /*
2  * Copyright (c) 2024 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 #define LOG_TAG "Utd"
17 #include "utd.h"
18 
19 #include "securec.h"
20 #include "logger.h"
21 #include "utd_client.h"
22 #include "udmf_capi_common.h"
23 #include "udmf_err_code.h"
24 
25 using namespace OHOS::UDMF;
26 
27 static constexpr const int32_t MAX_UTD_SIZE = 50;
28 
29 typedef Status (UtdClient::*GetUtdByConditionPtr)(const std::string&, std::string&, std::string);
30 
DestroyArrayPtr(const char ** & arrayPtr,unsigned int & count)31 static void DestroyArrayPtr(const char** &arrayPtr, unsigned int& count)
32 {
33     if (arrayPtr == nullptr) {
34         LOG_ERROR(UDMF_CAPI, "Cannot delete arrayPtr because it's a nullptr.");
35         return;
36     }
37     for (unsigned int i = 0; i < count; i++) {
38         if (arrayPtr[i] != nullptr) {
39             delete[] arrayPtr[i];
40             arrayPtr[i] = nullptr;
41         }
42     }
43     delete[] arrayPtr;
44     arrayPtr = nullptr;
45     count = 0;
46     LOG_INFO(UDMF_CAPI, "delete arrayPtr finish.");
47 }
48 
CreateStrArrByVector(const std::vector<std::string> & paramVector,unsigned int * count)49 static const char** CreateStrArrByVector(const std::vector<std::string>& paramVector, unsigned int* count)
50 {
51     unsigned int size = paramVector.size();
52     if (size == 0 || size > MAX_UTD_SIZE) {
53         LOG_ERROR(UDMF_CAPI, "Cannot create array, because size is illegal or exceeds the max value of UTD.");
54         *count = 0;
55         return nullptr;
56     }
57     auto charPtr = new (std::nothrow) char* [size];
58     if (charPtr == nullptr) {
59         *count = 0;
60         return nullptr;
61     }
62     for (unsigned int i = 0; i < size; i++) {
63         charPtr[i] = new (std::nothrow) char[paramVector[i].size() + 1];
64         if (charPtr[i] == nullptr ||
65             strcpy_s(charPtr[i], paramVector[i].size() + 1, paramVector[i].c_str()) != UDMF_E_OK) {
66             LOG_ERROR(UDMF_CAPI, "obtain the memory error, or str copy error!");
67             const char** arrayPtr = const_cast<const char**>(charPtr);
68             DestroyArrayPtr(arrayPtr, size);
69             *count = 0;
70             return nullptr;
71         }
72     }
73     *count = size;
74     return const_cast<const char**>(charPtr);
75 }
76 
GetTypeDescriptorByUtdClient(const char * typeId)77 static std::shared_ptr<TypeDescriptor> GetTypeDescriptorByUtdClient(const char* typeId)
78 {
79     std::shared_ptr<TypeDescriptor> typeDescriptor;
80     UtdClient::GetInstance().GetTypeDescriptor(typeId, typeDescriptor);
81     return typeDescriptor;
82 }
83 
IsUtdInvalid(OH_Utd * pThis)84 static bool IsUtdInvalid(OH_Utd* pThis)
85 {
86     return pThis == nullptr || pThis->cid != NdkStructId::UTD_STRUCT_ID;
87 }
88 
GetTypesByCondition(const char * condition,unsigned int * count,GetUtdByConditionPtr funcPtr)89 static const char** GetTypesByCondition(const char* condition, unsigned int* count, GetUtdByConditionPtr funcPtr)
90 {
91     if (condition == nullptr || count == nullptr || funcPtr == nullptr) {
92         return nullptr;
93     }
94     std::string typeIdStr;
95     Status result = (UtdClient::GetInstance().*funcPtr)(condition, typeIdStr, DEFAULT_TYPE_ID);
96     if (result != Status::E_OK || typeIdStr.empty()) {
97         LOG_ERROR(UDMF_CAPI, "Failed to obtain typeId by invoking the native function.");
98         return nullptr;
99     }
100     auto typeId = new (std::nothrow) char[typeIdStr.size() + 1];
101     if (typeId == nullptr) {
102         LOG_ERROR(UDMF_CAPI, "obtain typeId's memory error!");
103         return nullptr;
104     }
105     if (strcpy_s(typeId, typeIdStr.size() + 1, typeIdStr.c_str()) != UDMF_E_OK) {
106         LOG_ERROR(UDMF_CAPI, "str copy error!");
107         delete[] typeId;
108         return nullptr;
109     }
110     *count = 1;
111     auto typeIds = new char* [*count];
112     typeIds[0] = typeId;
113     return const_cast<const char**>(typeIds);
114 }
115 
OH_Utd_Create(const char * typeId)116 OH_Utd* OH_Utd_Create(const char* typeId)
117 {
118     if (typeId == nullptr) {
119         return nullptr;
120     }
121     auto pThis = new (std::nothrow) OH_Utd();
122     if (pThis == nullptr) {
123         LOG_ERROR(UDMF_CAPI, "Failed to apply for memory.");
124         return nullptr;
125     }
126     auto typeDescriptor = GetTypeDescriptorByUtdClient(typeId);
127     if (typeDescriptor == nullptr) {
128         LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function.");
129         delete pThis;
130         return nullptr;
131     }
132     pThis->typeId = typeDescriptor->GetTypeId();
133     pThis->description = typeDescriptor->GetDescription();
134     pThis->referenceURL = typeDescriptor->GetReferenceURL();
135     pThis->iconFile = typeDescriptor->GetIconFile();
136     pThis->belongingToTypes =
137         CreateStrArrByVector(typeDescriptor->GetBelongingToTypes(), &(pThis->belongingToTypesCount));
138     pThis->filenameExtensions =
139         CreateStrArrByVector(typeDescriptor->GetFilenameExtensions(), &(pThis->filenameExtensionsCount));
140     pThis->mimeTypes = CreateStrArrByVector(typeDescriptor->GetMimeTypes(), &(pThis->mimeTypeCount));
141     return pThis;
142 }
143 
OH_Utd_Destroy(OH_Utd * pThis)144 void OH_Utd_Destroy(OH_Utd* pThis)
145 {
146     if (IsUtdInvalid(pThis)) {
147         LOG_ERROR(UDMF_CAPI, "Failed to Destroy UTD, because pThis maybe nullptr or non-UTD struct ptr.");
148         return;
149     }
150     DestroyArrayPtr(pThis->belongingToTypes, pThis->belongingToTypesCount);
151     DestroyArrayPtr(pThis->filenameExtensions, pThis->filenameExtensionsCount);
152     DestroyArrayPtr(pThis->mimeTypes, pThis->mimeTypeCount);
153     delete pThis;
154     LOG_INFO(UDMF_CAPI, "OH_Utd ptr already be delete");
155 }
156 
OH_Utd_GetTypeId(OH_Utd * pThis)157 const char* OH_Utd_GetTypeId(OH_Utd* pThis)
158 {
159     return IsUtdInvalid(pThis) ? nullptr : pThis->typeId.c_str();
160 }
161 
OH_Utd_GetDescription(OH_Utd * pThis)162 const char* OH_Utd_GetDescription(OH_Utd* pThis)
163 {
164     return IsUtdInvalid(pThis) ? nullptr : pThis->description.c_str();
165 }
166 
OH_Utd_GetReferenceUrl(OH_Utd * pThis)167 const char* OH_Utd_GetReferenceUrl(OH_Utd* pThis)
168 {
169     return IsUtdInvalid(pThis) ? nullptr : pThis->referenceURL.c_str();
170 }
171 
OH_Utd_GetIconFile(OH_Utd * pThis)172 const char* OH_Utd_GetIconFile(OH_Utd* pThis)
173 {
174     return IsUtdInvalid(pThis) ? nullptr : pThis->iconFile.c_str();
175 }
176 
OH_Utd_GetBelongingToTypes(OH_Utd * pThis,unsigned int * count)177 const char** OH_Utd_GetBelongingToTypes(OH_Utd* pThis, unsigned int* count)
178 {
179     if (IsUtdInvalid(pThis) || count == nullptr) {
180         return nullptr;
181     }
182     *count = pThis->belongingToTypesCount;
183     return pThis->belongingToTypes;
184 }
185 
OH_Utd_GetFilenameExtensions(OH_Utd * pThis,unsigned int * count)186 const char** OH_Utd_GetFilenameExtensions(OH_Utd* pThis, unsigned int* count)
187 {
188     if (IsUtdInvalid(pThis) || count == nullptr) {
189         return nullptr;
190     }
191     *count = pThis->filenameExtensionsCount;
192     return pThis->filenameExtensions;
193 }
194 
OH_Utd_GetMimeTypes(OH_Utd * pThis,unsigned int * count)195 const char** OH_Utd_GetMimeTypes(OH_Utd* pThis, unsigned int* count)
196 {
197     if (IsUtdInvalid(pThis) || count == nullptr) {
198         return nullptr;
199     }
200     *count = pThis->mimeTypeCount;
201     return pThis->mimeTypes;
202 }
203 
OH_Utd_GetTypesByFilenameExtension(const char * extension,unsigned int * count)204 const char** OH_Utd_GetTypesByFilenameExtension(const char* extension, unsigned int* count)
205 {
206     return GetTypesByCondition(extension, count, &UtdClient::GetUniformDataTypeByFilenameExtension);
207 }
208 
OH_Utd_GetTypesByMimeType(const char * mimeType,unsigned int * count)209 const char** OH_Utd_GetTypesByMimeType(const char* mimeType, unsigned int* count)
210 {
211     return GetTypesByCondition(mimeType, count, &UtdClient::GetUniformDataTypeByMIMEType);
212 }
213 
OH_Utd_BelongsTo(const char * srcTypeId,const char * destTypeId)214 bool OH_Utd_BelongsTo(const char* srcTypeId, const char* destTypeId)
215 {
216     if (srcTypeId == nullptr || destTypeId == nullptr) {
217         LOG_ERROR(UDMF_CAPI, "The input parameter is nullptr");
218         return false;
219     }
220     auto typeDescriptor = GetTypeDescriptorByUtdClient(srcTypeId);
221     if (typeDescriptor == nullptr) {
222         LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function.");
223         return false;
224     }
225     bool checkResult{false};
226     if (typeDescriptor->BelongsTo(destTypeId, checkResult) != Status::E_OK) {
227         LOG_ERROR(UDMF_CAPI, "invoke the native function error.");
228     }
229     return checkResult;
230 }
231 
OH_Utd_IsLower(const char * srcTypeId,const char * destTypeId)232 bool OH_Utd_IsLower(const char* srcTypeId, const char* destTypeId)
233 {
234     if (srcTypeId == nullptr || destTypeId == nullptr) {
235         LOG_ERROR(UDMF_CAPI, "The input parameter is nullptr");
236         return false;
237     }
238     auto typeDescriptor = GetTypeDescriptorByUtdClient(srcTypeId);
239     if (typeDescriptor == nullptr) {
240         LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function.");
241         return false;
242     }
243     bool checkResult{false};
244     if (typeDescriptor->IsLowerLevelType(destTypeId, checkResult) != Status::E_OK) {
245         LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function.");
246     }
247     return checkResult;
248 }
249 
OH_Utd_IsHigher(const char * srcTypeId,const char * destTypeId)250 bool OH_Utd_IsHigher(const char* srcTypeId, const char* destTypeId)
251 {
252     if (srcTypeId == nullptr || destTypeId == nullptr) {
253         LOG_ERROR(UDMF_CAPI, "The input parameter is nullptr");
254         return false;
255     }
256     auto typeDescriptor = GetTypeDescriptorByUtdClient(srcTypeId);
257     if (typeDescriptor == nullptr) {
258         LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function.");
259         return false;
260     }
261     bool checkResult{false};
262     if (typeDescriptor->IsHigherLevelType(destTypeId, checkResult) != Status::E_OK) {
263         LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function.");
264     }
265     return checkResult;
266 }
267 
OH_Utd_Equals(OH_Utd * utd1,OH_Utd * utd2)268 bool OH_Utd_Equals(OH_Utd* utd1, OH_Utd* utd2)
269 {
270     if (IsUtdInvalid(utd1) || IsUtdInvalid(utd2)) {
271         LOG_ERROR(UDMF_CAPI, "The input parameter is invalid");
272         return false;
273     }
274     auto typeDescriptor1 = GetTypeDescriptorByUtdClient(utd1->typeId.c_str());
275     if (typeDescriptor1 == nullptr) {
276         LOG_ERROR(UDMF_CAPI, "utd1 failed to create by invoking the native function.");
277         return false;
278     }
279     auto typeDescriptor2 = GetTypeDescriptorByUtdClient(utd2->typeId.c_str());
280     if (typeDescriptor2 == nullptr) {
281         LOG_ERROR(UDMF_CAPI, "utd2 failed to create by invoking the native function.");
282         return false;
283     }
284     return typeDescriptor1->Equals(typeDescriptor2);
285 }
286 
OH_Utd_DestroyStringList(const char ** list,unsigned int count)287 void OH_Utd_DestroyStringList(const char** list, unsigned int count)
288 {
289     DestroyArrayPtr(list, count);
290 }
291