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 #define LOG_TAG "Udmf"
16 #include "udmf.h"
17 #include "udmf_err_code.h"
18 #include "data_provider_impl.h"
19 #include "udmf_client.h"
20 #include "securec.h"
21 #include "udmf_capi_common.h"
22 #include "int_wrapper.h"
23 #include "string_wrapper.h"
24 #include "unified_meta.h"
25 #include "udmf_meta.h"
26 #include "logger.h"
27 #include "plain_text.h"
28 #include "link.h"
29 #include "html.h"
30 #include "system_defined_appitem.h"
31 #include "application_defined_record.h"
32 #include "system_defined_pixelmap.h"
33 #include "file.h"
34 #include "audio.h"
35 #include "folder.h"
36 #include "image.h"
37 #include "video.h"
38 
39 using namespace OHOS::UDMF;
40 
41 static constexpr uint64_t MAX_RECORDS_COUNT = 4 * 1024 * 1024;
42 static constexpr uint64_t MAX_KEY_STRING_LEN = 1 * 1024 * 1024;
43 static const std::map<std::string, UDType> FILE_TYPES = {
44     { UDMF_META_GENERAL_FILE, UDType::FILE },
45     { UDMF_META_AUDIO, UDType::AUDIO },
46     { UDMF_META_FOLDER, UDType::FOLDER },
47     { UDMF_META_IMAGE, UDType::IMAGE },
48     { UDMF_META_VIDEO, UDType::VIDEO }
49 };
50 
DestroyStringArray(char ** & bufArray,unsigned int & count)51 static void DestroyStringArray(char**& bufArray, unsigned int& count)
52 {
53     if (bufArray == nullptr) {
54         return;
55     }
56     for (unsigned int i = 0; i < count; i++) {
57         if (bufArray[i] != nullptr) {
58             delete[] bufArray[i];
59             bufArray[i] = nullptr;
60         }
61     }
62     delete[] bufArray;
63     bufArray = nullptr;
64     count = 0;
65 }
66 
DestroyUnifiedRecordArray(OH_UdmfRecord ** & records,unsigned int & count)67 static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& count)
68 {
69     if (records == nullptr) {
70         return;
71     }
72     for (unsigned int i = 0; i < count; i++) {
73         if (records[i] != nullptr) {
74             delete records[i];
75             records[i] = nullptr;
76         }
77     }
78     delete[] records;
79     records = nullptr;
80     count = 0;
81 }
82 
StrVectorToTypesArray(const std::vector<std::string> & strVector)83 static char** StrVectorToTypesArray(const std::vector<std::string>& strVector)
84 {
85     unsigned int vectorSize = strVector.size();
86     if (vectorSize > MAX_RECORDS_COUNT) {
87         return nullptr;
88     }
89     char** typesArray = new (std::nothrow) char* [vectorSize] {nullptr};
90     for (unsigned int i = 0; i < vectorSize; ++i) {
91         unsigned int strLen = strVector[i].length() + 1;
92         if (strLen > MAX_KEY_STRING_LEN) {
93             LOG_INFO(UDMF_CAPI, "string exceeds maximum length, length is %{public}d", strLen);
94             DestroyStringArray(typesArray, vectorSize);
95             return nullptr;
96         }
97         typesArray[i] = new (std::nothrow) char[strLen];
98         if (typesArray[i] == nullptr ||
99             (strcpy_s(typesArray[i], strLen, strVector[i].c_str())) != EOK) {
100             LOG_ERROR(UDMF_CAPI, "string copy failed");
101             DestroyStringArray(typesArray, vectorSize);
102             return nullptr;
103         }
104     }
105     return typesArray;
106 }
107 
CreateUnifiedDataRecordsArray(OH_UdmfData * unifiedData,std::vector<std::shared_ptr<UnifiedRecord>> & records)108 static OH_UdmfRecord** CreateUnifiedDataRecordsArray(OH_UdmfData* unifiedData,
109                                                      std::vector<std::shared_ptr<UnifiedRecord>>& records)
110 {
111     unsigned int size = static_cast<unsigned int>(records.size());
112     if (unifiedData == nullptr || size == 0 || size > MAX_RECORDS_COUNT) {
113         return nullptr;
114     }
115     OH_UdmfRecord** result = new (std::nothrow) OH_UdmfRecord* [size] { nullptr };
116     if (result == nullptr) {
117         return nullptr;
118     }
119     for (unsigned int i = 0; i < size; i++) {
120         result[i] = new (std::nothrow) OH_UdmfRecord;
121         if (result[i] == nullptr) {
122             DestroyUnifiedRecordArray(result, size);
123             return nullptr;
124         }
125         result[i]->record_ = records[i];
126     }
127     unifiedData->records = result;
128     unifiedData->recordsCount = size;
129     return unifiedData->records;
130 }
131 
IsUnifiedDataValid(OH_UdmfData * data)132 static bool IsUnifiedDataValid(OH_UdmfData* data)
133 {
134     return data != nullptr && data->unifiedData_ != nullptr &&
135            data->cid == NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID;
136 }
137 
IsUnifiedRecordValid(OH_UdmfRecord * record)138 static bool IsUnifiedRecordValid(OH_UdmfRecord* record)
139 {
140     return record != nullptr && record->record_ != nullptr &&
141            record->cid == NdkStructId::UDMF_UNIFIED_RECORD_STRUCT_ID;
142 }
143 
IsUnifiedPropertiesValid(OH_UdmfProperty * properties)144 static bool IsUnifiedPropertiesValid(OH_UdmfProperty* properties)
145 {
146     return properties != nullptr && properties->properties_ != nullptr &&
147            properties->cid == NdkStructId::UDMF_UNIFIED_DATA_PROPERTIES_ID;
148 }
149 
AddFileUriTypeIfContains(std::vector<std::string> & types)150 static void AddFileUriTypeIfContains(std::vector<std::string>& types)
151 {
152     for (auto type : types) {
153         if (FILE_TYPES.find(type) != FILE_TYPES.end()) {
154             types.push_back(UDMF_META_GENERAL_FILE_URI);
155             break;
156         }
157     }
158     return;
159 }
160 
OH_UdmfData_Create()161 OH_UdmfData* OH_UdmfData_Create()
162 {
163     OH_UdmfData* data = new (std::nothrow) OH_UdmfData;
164     if (data == nullptr) {
165         return nullptr;
166     }
167     data->unifiedData_ = std::make_shared<UnifiedData>();
168     return data;
169 }
170 
OH_UdmfData_Destroy(OH_UdmfData * data)171 void OH_UdmfData_Destroy(OH_UdmfData* data)
172 {
173     if (data == nullptr) {
174         return;
175     }
176     DestroyStringArray(data->typesArray, data->typesCount);
177     DestroyUnifiedRecordArray(data->records, data->recordsCount);
178     delete data;
179 }
180 
OH_UdmfData_AddRecord(OH_UdmfData * unifiedData,OH_UdmfRecord * record)181 int OH_UdmfData_AddRecord(OH_UdmfData* unifiedData, OH_UdmfRecord* record)
182 {
183     if (!IsUnifiedDataValid(unifiedData) || !IsUnifiedRecordValid(record)) {
184         return UDMF_E_INVALID_PARAM;
185     }
186     unifiedData->unifiedData_->AddRecord(record->record_);
187     return UDMF_E_OK;
188 }
189 
OH_UdmfData_HasType(OH_UdmfData * unifiedData,const char * type)190 bool OH_UdmfData_HasType(OH_UdmfData* unifiedData, const char* type)
191 {
192     return IsUnifiedDataValid(unifiedData) && type != nullptr && unifiedData->unifiedData_->HasTypeInEntries(type);
193 }
194 
OH_UdmfData_GetTypes(OH_UdmfData * unifiedData,unsigned int * count)195 char** OH_UdmfData_GetTypes(OH_UdmfData* unifiedData, unsigned int* count)
196 {
197     if (!IsUnifiedDataValid(unifiedData) || count == nullptr) {
198         return nullptr;
199     }
200     std::lock_guard<std::mutex> lock(unifiedData->mutex);
201     if (unifiedData->typesArray != nullptr) {
202         LOG_DEBUG(UDMF_CAPI, "return cache value");
203         *count = unifiedData->typesCount;
204         return unifiedData->typesArray;
205     }
206     std::vector<std::string> typeLabels = unifiedData->unifiedData_->GetEntriesTypes();
207     AddFileUriTypeIfContains(typeLabels);
208     unifiedData->typesArray = StrVectorToTypesArray(typeLabels);
209     unifiedData->typesArray == nullptr ? unifiedData->typesCount = 0 : unifiedData->typesCount = typeLabels.size();
210     *count = unifiedData->typesCount;
211     return unifiedData->typesArray;
212 }
213 
OH_UdmfRecord_GetTypes(OH_UdmfRecord * record,unsigned int * count)214 char** OH_UdmfRecord_GetTypes(OH_UdmfRecord* record, unsigned int* count)
215 {
216     if (!IsUnifiedRecordValid(record) || count == nullptr) {
217         return nullptr;
218     }
219     std::lock_guard<std::mutex> lock(record->mutex);
220     if (record->typesArray != nullptr) {
221         LOG_DEBUG(UDMF_CAPI, "return cache value");
222         *count = record->typesCount;
223         return record->typesArray;
224     }
225     auto types = record->record_->GetUtdIds();
226     std::vector<std::string> typeLabels {types.begin(), types.end()};
227     AddFileUriTypeIfContains(typeLabels);
228     record->typesArray = StrVectorToTypesArray(typeLabels);
229     record->typesArray == nullptr ? record->typesCount = 0 : record->typesCount = typeLabels.size();
230     *count = record->typesCount;
231     return record->typesArray;
232 }
233 
OH_UdmfData_GetRecords(OH_UdmfData * unifiedData,unsigned int * count)234 OH_UdmfRecord** OH_UdmfData_GetRecords(OH_UdmfData* unifiedData, unsigned int* count)
235 {
236     if (!IsUnifiedDataValid(unifiedData) || count == nullptr) {
237         return nullptr;
238     }
239     std::lock_guard<std::mutex> lock(unifiedData->mutex);
240     if (unifiedData->records != nullptr) {
241         LOG_DEBUG(UDMF_CAPI, "return cache value");
242         *count = unifiedData->recordsCount;
243         return unifiedData->records;
244     }
245     std::vector<std::shared_ptr<UnifiedRecord>> records = unifiedData->unifiedData_->GetRecords();
246     CreateUnifiedDataRecordsArray(unifiedData, records);
247     *count = unifiedData->recordsCount;
248     return unifiedData->records;
249 }
250 
GetFirstPlainText(OH_UdmfRecord ** records,unsigned int recordCount,OH_UdsPlainText * plainText)251 static int GetFirstPlainText(OH_UdmfRecord **records, unsigned int recordCount, OH_UdsPlainText* plainText)
252 {
253     int ret = UDMF_ERR;
254     if (records == nullptr || recordCount == 0) {
255         return ret;
256     }
257     for (unsigned int i = 0; i < recordCount; i++) {
258         const char *type = OH_UdsPlainText_GetType(plainText);
259         if (type == nullptr || !records[i]->record_->HasType(type)) {
260             continue;
261         }
262         ret = OH_UdmfRecord_GetPlainText(records[i], plainText);
263         if (ret == UDMF_E_OK) {
264             return ret;
265         }
266     }
267     return ret;
268 }
269 
GetFirstHtml(OH_UdmfRecord ** records,unsigned int recordCount,OH_UdsHtml * html)270 static int GetFirstHtml(OH_UdmfRecord **records, unsigned int recordCount, OH_UdsHtml* html)
271 {
272     int ret = UDMF_ERR;
273     if (records == nullptr || recordCount == 0) {
274         return ret;
275     }
276     for (unsigned int i = 0; i < recordCount; i++) {
277         const char *type = OH_UdsHtml_GetType(html);
278         if (type == nullptr || !records[i]->record_->HasType(type)) {
279             continue;
280         }
281         ret = OH_UdmfRecord_GetHtml(records[i], html);
282         if (ret == UDMF_E_OK) {
283             return ret;
284         }
285     }
286     return ret;
287 }
288 
OH_UdmfData_GetPrimaryPlainText(OH_UdmfData * data,OH_UdsPlainText * plainText)289 int OH_UdmfData_GetPrimaryPlainText(OH_UdmfData* data, OH_UdsPlainText* plainText)
290 {
291     if (!IsUnifiedDataValid(data) || IsInvalidUdsObjectPtr(plainText, UDS_PLAIN_TEXT_STRUCT_ID)) {
292         return UDMF_E_INVALID_PARAM;
293     }
294     std::lock_guard<std::mutex> lock(data->mutex);
295     if (data->records == nullptr) {
296         LOG_DEBUG(UDMF_CAPI, "no cache value");
297         std::vector<std::shared_ptr<UnifiedRecord>> records = data->unifiedData_->GetRecords();
298         CreateUnifiedDataRecordsArray(data, records);
299     }
300 
301     return GetFirstPlainText(data->records, data->recordsCount, plainText);
302 }
303 
OH_UdmfData_GetPrimaryHtml(OH_UdmfData * data,OH_UdsHtml * html)304 int OH_UdmfData_GetPrimaryHtml(OH_UdmfData* data, OH_UdsHtml* html)
305 {
306     if (!IsUnifiedDataValid(data) || IsInvalidUdsObjectPtr(html, UDS_HTML_STRUCT_ID)) {
307         return UDMF_E_INVALID_PARAM;
308     }
309     std::lock_guard<std::mutex> lock(data->mutex);
310     if (data->records == nullptr) {
311         LOG_DEBUG(UDMF_CAPI, "no cache value");
312         std::vector<std::shared_ptr<UnifiedRecord>> records = data->unifiedData_->GetRecords();
313         CreateUnifiedDataRecordsArray(data, records);
314     }
315 
316     return GetFirstHtml(data->records, data->recordsCount, html);
317 }
318 
OH_UdmfData_GetRecordCount(OH_UdmfData * data)319 int OH_UdmfData_GetRecordCount(OH_UdmfData *data)
320 {
321     if (!IsUnifiedDataValid(data)) {
322         return 0;
323     }
324     std::lock_guard<std::mutex> lock(data->mutex);
325     if (data->records == nullptr) {
326         LOG_DEBUG(UDMF_CAPI, "no cache value");
327         std::vector<std::shared_ptr<UnifiedRecord>> records = data->unifiedData_->GetRecords();
328         CreateUnifiedDataRecordsArray(data, records);
329     }
330     return static_cast<int>(data->recordsCount);
331 }
332 
OH_UdmfData_GetRecord(OH_UdmfData * data,unsigned int index)333 OH_UdmfRecord* OH_UdmfData_GetRecord(OH_UdmfData* data, unsigned int index)
334 {
335     if (!IsUnifiedDataValid(data) || index < 0) {
336         return nullptr;
337     }
338     std::lock_guard<std::mutex> lock(data->mutex);
339     if (data->records == nullptr) {
340         LOG_DEBUG(UDMF_CAPI, "no cache value");
341         std::vector<std::shared_ptr<UnifiedRecord>> records = data->unifiedData_->GetRecords();
342         CreateUnifiedDataRecordsArray(data, records);
343     }
344     if (index >= data->recordsCount || data->records == nullptr) {
345         return nullptr;
346     }
347     return data->records[index];
348 }
349 
OH_UdmfData_IsLocal(OH_UdmfData * data)350 bool OH_UdmfData_IsLocal(OH_UdmfData* data)
351 {
352     if (!IsUnifiedDataValid(data) || data->unifiedData_->GetProperties() == nullptr) {
353         return true;
354     }
355     bool isRemote = data->unifiedData_->GetProperties()->isRemote;
356     return !isRemote;
357 }
358 
OH_Udmf_GetUnifiedData(const char * key,Udmf_Intention intention,OH_UdmfData * data)359 int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfData* data)
360 {
361     if (!IsUnifiedDataValid(data) || key == nullptr) {
362         return UDMF_E_INVALID_PARAM;
363     }
364     Intention queryOptIntent;
365     switch (intention) {
366         case UDMF_INTENTION_DRAG:
367             queryOptIntent = Intention::UD_INTENTION_DRAG;
368             break;
369         default:
370             return UDMF_E_INVALID_PARAM;
371     }
372     QueryOption query = {.key = std::string(key), .intention = queryOptIntent};
373     if (UdmfClient::GetInstance().GetData(query, *(data->unifiedData_)) != E_OK) {
374         LOG_ERROR(UDMF_CAPI, "get data error");
375         return UDMF_ERR;
376     }
377     return UDMF_E_OK;
378 }
379 
OH_Udmf_SetUnifiedData(Udmf_Intention intention,OH_UdmfData * unifiedData,char * key,unsigned int keyLen)380 int OH_Udmf_SetUnifiedData(Udmf_Intention intention, OH_UdmfData* unifiedData, char* key, unsigned int keyLen)
381 {
382     if (!IsUnifiedDataValid(unifiedData) || key == nullptr || keyLen < UDMF_KEY_BUFFER_LEN) {
383         return UDMF_E_INVALID_PARAM;
384     }
385     enum Intention customOptIntent;
386     switch (intention) {
387         case UDMF_INTENTION_DRAG:
388             customOptIntent = Intention::UD_INTENTION_DRAG;
389             break;
390         default:
391             return UDMF_E_INVALID_PARAM;
392     }
393     CustomOption option = {.intention = customOptIntent};
394     std::string keyStr;
395     if ((UdmfClient::GetInstance().SetData(option, *(unifiedData->unifiedData_), keyStr)) != E_OK) {
396         LOG_ERROR(UDMF_CAPI, "set data error");
397         return UDMF_ERR;
398     }
399     if (strcpy_s(key, keyLen, keyStr.c_str()) != EOK) {
400         LOG_INFO(UDMF_CAPI, "string copy failed");
401         return UDMF_ERR;
402     }
403     return UDMF_E_OK;
404 }
405 
OH_UdmfRecord_Create()406 OH_UdmfRecord* OH_UdmfRecord_Create()
407 {
408     OH_UdmfRecord* record = new (std::nothrow) OH_UdmfRecord;
409     if (record == nullptr) {
410         return nullptr;
411     }
412     record->record_ = std::make_shared<UnifiedRecord>();
413     return record;
414 }
415 
OH_UdmfRecord_Destroy(OH_UdmfRecord * record)416 void OH_UdmfRecord_Destroy(OH_UdmfRecord* record)
417 {
418     if (record == nullptr) {
419         return;
420     }
421     if (record->recordData != nullptr) {
422         delete[] record->recordData;
423         record->recordData = nullptr;
424     }
425     delete record;
426 }
427 
OH_UdmfRecord_AddGeneralEntry(OH_UdmfRecord * record,const char * typeId,const unsigned char * entry,unsigned int count)428 int OH_UdmfRecord_AddGeneralEntry(OH_UdmfRecord* record, const char* typeId,
429                                   const unsigned char* entry, unsigned int count)
430 {
431     if (!IsUnifiedRecordValid(record) || typeId == nullptr || entry == nullptr || count == 0 ||
432         count > MAX_GENERAL_ENTRY_SIZE || strlen(typeId) > MAX_KEY_STRING_LEN) {
433         return UDMF_E_INVALID_PARAM;
434     }
435     std::vector<uint8_t> recordValue(entry, entry + count);
436     if (record->record_->GetType() == UD_BUTT) {
437         record->record_ = std::make_shared<ApplicationDefinedRecord>(APPLICATION_DEFINED_RECORD, recordValue);
438         record->record_->SetUtdId(typeId);
439     } else {
440         record->record_->AddEntry(typeId, std::move(recordValue));
441     }
442     record->recordDataLen = count;
443     return UDMF_E_OK;
444 }
445 
GetValueFromUdsArrayBuffer(OH_UdmfRecord * record,const char * typeId,ValueType value)446 static int GetValueFromUdsArrayBuffer(OH_UdmfRecord *record, const char *typeId, ValueType value)
447 {
448     if (!std::holds_alternative<std::shared_ptr<Object>>(value)) {
449         LOG_ERROR(UDMF_CAPI, "valueType is not object sptr!");
450         return UDMF_ERR;
451     }
452     OH_UdsArrayBuffer *buffer = OH_UdsArrayBuffer_Create();
453     buffer->obj = std::get<std::shared_ptr<Object>>(value);
454 
455     int ret = OH_UdsArrayBuffer_GetData(buffer, &record->recordData, &record->recordDataLen);
456     if (ret != UDMF_E_OK) {
457         LOG_ERROR(UDMF_CAPI, "get data from buffer failed. ret: %{public}d", ret);
458         OH_UdsArrayBuffer_Destroy(buffer);
459         return ret;
460     }
461     record->lastType = const_cast<char*>(typeId);
462     return UDMF_E_OK;
463 }
464 
GetValueFromUint8Array(OH_UdmfRecord * record,const char * typeId,ValueType value)465 static int GetValueFromUint8Array(OH_UdmfRecord *record, const char *typeId, ValueType value)
466 {
467     auto recordValue = std::get_if<std::vector<uint8_t>>(&value);
468     if (recordValue == nullptr) {
469         return UDMF_ERR;
470     }
471     record->recordDataLen = recordValue->size();
472     if (record->recordDataLen > MAX_GENERAL_ENTRY_SIZE) {
473         LOG_INFO(UDMF_CAPI, "data size exceeds maximum size");
474         return UDMF_ERR;
475     }
476     record->recordData = new (std::nothrow) unsigned char[record->recordDataLen];
477     if (record->recordData == nullptr) {
478         return UDMF_ERR;
479     }
480     auto err = memcpy_s(record->recordData, record->recordDataLen, recordValue->data(), record->recordDataLen);
481     if (err != EOK) {
482         LOG_ERROR(UDMF_CAPI, "memcpy error! type:%{public}s", typeId);
483         return UDMF_ERR;
484     }
485     record->lastType = const_cast<char*>(typeId);
486     return UDMF_E_OK;
487 }
488 
OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord * record,const char * typeId,unsigned char ** entry,unsigned int * count)489 int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, unsigned char** entry, unsigned int* count)
490 {
491     if (!IsUnifiedRecordValid(record) || typeId == nullptr || entry == nullptr || count == nullptr) {
492         return UDMF_E_INVALID_PARAM;
493     }
494 
495     std::lock_guard<std::mutex> lock(record->mutex);
496     if (!record->record_->HasType(typeId)) {
497         LOG_ERROR(UDMF_CAPI, "no type:%{public}s", typeId);
498         return UDMF_E_INVALID_PARAM;
499     }
500     if (record->lastType == typeId && record->recordData != nullptr) {
501         LOG_DEBUG(UDMF_CAPI, "return cache value");
502         *entry = record->recordData;
503         *count = record->recordDataLen;
504         return UDMF_E_OK;
505     }
506 
507     auto value = record->record_->GetEntry(typeId);
508 
509     int result = UDMF_ERR;
510     if (std::holds_alternative<std::shared_ptr<Object>>(value)) {
511         result = GetValueFromUdsArrayBuffer(record, typeId, value);
512     } else if (std::holds_alternative<std::vector<uint8_t>>(value)) {
513         result = GetValueFromUint8Array(record, typeId, value);
514     } else {
515         LOG_ERROR(UDMF_CAPI, "Not contains right data type.");
516     }
517     if (result != UDMF_E_OK) {
518         LOG_ERROR(UDMF_CAPI, "Get value from valueType failed. typeId: %{public}s, result: %{public}d", typeId, result);
519         return result;
520     }
521     *count = record->recordDataLen;
522     *entry = record->recordData;
523     return UDMF_E_OK;
524 }
525 
526 template<typename T>
AddUds(OH_UdmfRecord * record,UdsObject * udsObject,UDType type)527 void AddUds(OH_UdmfRecord* record, UdsObject* udsObject, UDType type)
528 {
529     if (record->record_->GetType() == UD_BUTT) {
530         record->record_ = std::make_shared<T>(type, udsObject->obj);
531     } else {
532         record->record_->AddEntry(UtdUtils::GetUtdIdFromUtdEnum(type), udsObject->obj);
533     }
534 }
535 
OH_UdmfRecord_AddPlainText(OH_UdmfRecord * record,OH_UdsPlainText * plainText)536 int OH_UdmfRecord_AddPlainText(OH_UdmfRecord* record, OH_UdsPlainText* plainText)
537 {
538     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(plainText, UDS_PLAIN_TEXT_STRUCT_ID)) {
539         return UDMF_E_INVALID_PARAM;
540     }
541     AddUds<PlainText>(record, plainText, PLAIN_TEXT);
542     return UDMF_E_OK;
543 }
544 
OH_UdmfRecord_AddHyperlink(OH_UdmfRecord * record,OH_UdsHyperlink * hyperlink)545 int OH_UdmfRecord_AddHyperlink(OH_UdmfRecord* record, OH_UdsHyperlink* hyperlink)
546 {
547     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(hyperlink, UDS_HYPERLINK_STRUCT_ID)) {
548         return UDMF_E_INVALID_PARAM;
549     }
550     AddUds<Link>(record, hyperlink, HYPERLINK);
551     return UDMF_E_OK;
552 }
553 
OH_UdmfRecord_AddHtml(OH_UdmfRecord * record,OH_UdsHtml * html)554 int OH_UdmfRecord_AddHtml(OH_UdmfRecord* record, OH_UdsHtml* html)
555 {
556     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(html, UDS_HTML_STRUCT_ID)) {
557         return UDMF_E_INVALID_PARAM;
558     }
559     AddUds<Html>(record, html, HTML);
560     return UDMF_E_OK;
561 }
562 
OH_UdmfRecord_AddAppItem(OH_UdmfRecord * record,OH_UdsAppItem * appItem)563 int OH_UdmfRecord_AddAppItem(OH_UdmfRecord* record, OH_UdsAppItem* appItem)
564 {
565     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(appItem, UDS_APP_ITEM_STRUCT_ID)) {
566         return UDMF_E_INVALID_PARAM;
567     }
568     AddUds<SystemDefinedAppItem>(record, appItem, SYSTEM_DEFINED_APP_ITEM);
569     return UDMF_E_OK;
570 }
571 
OH_UdmfRecord_AddFileUri(OH_UdmfRecord * record,OH_UdsFileUri * fileUri)572 int OH_UdmfRecord_AddFileUri(OH_UdmfRecord* record, OH_UdsFileUri* fileUri)
573 {
574     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(fileUri, UDS_FILE_URI_STRUCT_ID)) {
575         return UDMF_E_INVALID_PARAM;
576     }
577     std::string* fileType = std::get_if<std::string>(&(fileUri->obj->value_[FILE_TYPE]));
578     if (fileType == nullptr) {
579         return UDMF_ERR;
580     }
581     int32_t utdId = UtdUtils::GetUtdEnumFromUtdId(*fileType);
582     switch (utdId) {
583         case UDType::FILE:
584             AddUds<File>(record, fileUri, UDType::FILE);
585             break;
586         case UDType::AUDIO:
587             AddUds<Audio>(record, fileUri, UDType::AUDIO);
588             break;
589         case UDType::FOLDER:
590             AddUds<Folder>(record, fileUri, UDType::FOLDER);
591             break;
592         case UDType::IMAGE:
593             AddUds<Image>(record, fileUri, UDType::IMAGE);
594             break;
595         case UDType::VIDEO:
596             AddUds<Video>(record, fileUri, UDType::VIDEO);
597             break;
598         default:
599             AddUds<UnifiedRecord>(record, fileUri, UDType::FILE_URI);
600     }
601     return UDMF_E_OK;
602 }
603 
OH_UdmfRecord_AddPixelMap(OH_UdmfRecord * record,OH_UdsPixelMap * pixelMap)604 int OH_UdmfRecord_AddPixelMap(OH_UdmfRecord* record, OH_UdsPixelMap* pixelMap)
605 {
606     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(pixelMap, UDS_PIXEL_MAP_STRUCT_ID)) {
607         return UDMF_E_INVALID_PARAM;
608     }
609     AddUds<SystemDefinedPixelMap>(record, pixelMap, UDType::SYSTEM_DEFINED_PIXEL_MAP);
610     return UDMF_E_OK;
611 }
612 
GetUds(OH_UdmfRecord * record,UdsObject * udsObject,UDType type)613 int GetUds(OH_UdmfRecord* record, UdsObject* udsObject, UDType type)
614 {
615     record->record_->InitObject();
616     auto value = record->record_->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(type));
617     if (!std::holds_alternative<std::shared_ptr<Object>>(value)) {
618         return UDMF_ERR;
619     }
620     udsObject->obj = std::get<std::shared_ptr<Object>>(value);
621     return UDMF_E_OK;
622 }
623 
OH_UdmfRecord_AddArrayBuffer(OH_UdmfRecord * record,const char * type,OH_UdsArrayBuffer * buffer)624 int OH_UdmfRecord_AddArrayBuffer(OH_UdmfRecord* record, const char* type, OH_UdsArrayBuffer* buffer)
625 {
626     if (!IsUnifiedRecordValid(record) || type == nullptr || strlen(type) > MAX_KEY_STRING_LEN ||
627         IsInvalidUdsObjectPtr(buffer, UDS_ARRAY_BUFFER_STRUCT_ID)) {
628         return UDMF_E_INVALID_PARAM;
629     }
630     unsigned char *entry;
631     unsigned int size;
632     int ret = OH_UdsArrayBuffer_GetData(buffer, &entry, &size);
633     if (ret != UDMF_E_OK) {
634         return UDMF_E_INVALID_PARAM;
635     }
636     buffer->obj->value_[UNIFORM_DATA_TYPE] = type;
637     return OH_UdmfRecord_AddGeneralEntry(record, type, entry, size);
638 }
639 
OH_UdmfRecord_AddContentForm(OH_UdmfRecord * record,OH_UdsContentForm * contentForm)640 int OH_UdmfRecord_AddContentForm(OH_UdmfRecord* record, OH_UdsContentForm* contentForm)
641 {
642     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(contentForm, UDS_CONTENT_FORM_STRUCT_ID)) {
643         return UDMF_E_INVALID_PARAM;
644     }
645     AddUds<UnifiedRecord>(record, contentForm, UDType::CONTENT_FORM);
646     return UDMF_E_OK;
647 }
648 
OH_UdmfRecord_GetPlainText(OH_UdmfRecord * record,OH_UdsPlainText * plainText)649 int OH_UdmfRecord_GetPlainText(OH_UdmfRecord* record, OH_UdsPlainText* plainText)
650 {
651     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(plainText, UDS_PLAIN_TEXT_STRUCT_ID)) {
652         return UDMF_E_INVALID_PARAM;
653     }
654     return GetUds(record, plainText, PLAIN_TEXT);
655 }
656 
OH_UdmfRecord_GetHyperlink(OH_UdmfRecord * record,OH_UdsHyperlink * hyperlink)657 int OH_UdmfRecord_GetHyperlink(OH_UdmfRecord* record, OH_UdsHyperlink* hyperlink)
658 {
659     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(hyperlink, UDS_HYPERLINK_STRUCT_ID)) {
660         return UDMF_E_INVALID_PARAM;
661     }
662     return GetUds(record, hyperlink, HYPERLINK);
663 }
664 
OH_UdmfRecord_GetHtml(OH_UdmfRecord * record,OH_UdsHtml * html)665 int OH_UdmfRecord_GetHtml(OH_UdmfRecord* record, OH_UdsHtml* html)
666 {
667     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(html, UDS_HTML_STRUCT_ID)) {
668         return UDMF_E_INVALID_PARAM;
669     }
670     return GetUds(record, html, HTML);
671 }
672 
OH_UdmfRecord_GetAppItem(OH_UdmfRecord * record,OH_UdsAppItem * appItem)673 int OH_UdmfRecord_GetAppItem(OH_UdmfRecord* record, OH_UdsAppItem* appItem)
674 {
675     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(appItem, UDS_APP_ITEM_STRUCT_ID)) {
676         return UDMF_E_INVALID_PARAM;
677     }
678     return GetUds(record, appItem, SYSTEM_DEFINED_APP_ITEM);
679 }
680 
OH_UdmfRecord_GetFileUri(OH_UdmfRecord * record,OH_UdsFileUri * fileUri)681 int OH_UdmfRecord_GetFileUri(OH_UdmfRecord* record, OH_UdsFileUri* fileUri)
682 {
683     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(fileUri, UDS_FILE_URI_STRUCT_ID)) {
684         return UDMF_E_INVALID_PARAM;
685     }
686     if (GetUds(record, fileUri, UDType::FILE_URI) == UDMF_E_OK) {
687         return UDMF_E_OK;
688     }
689     for (auto fileType : FILE_TYPES) {
690         int ret = GetUds(record, fileUri, fileType.second);
691         if (ret == UDMF_E_OK) {
692             fileUri->obj->value_[UNIFORM_DATA_TYPE] = UDMF_META_GENERAL_FILE_URI;
693             fileUri->obj->value_[FILE_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(fileType.second);
694             return UDMF_E_OK;
695         }
696     }
697     LOG_ERROR(UDMF_CAPI, "could't find file uri");
698     return UDMF_E_INVALID_PARAM;
699 }
700 
OH_UdmfRecord_GetPixelMap(OH_UdmfRecord * record,OH_UdsPixelMap * pixelMap)701 int OH_UdmfRecord_GetPixelMap(OH_UdmfRecord* record, OH_UdsPixelMap* pixelMap)
702 {
703     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(pixelMap, UDS_PIXEL_MAP_STRUCT_ID)) {
704         return UDMF_E_INVALID_PARAM;
705     }
706     return GetUds(record, pixelMap, UDType::SYSTEM_DEFINED_PIXEL_MAP);
707 }
708 
OH_UdmfRecord_GetArrayBuffer(OH_UdmfRecord * record,const char * type,OH_UdsArrayBuffer * buffer)709 int OH_UdmfRecord_GetArrayBuffer(OH_UdmfRecord* record, const char* type, OH_UdsArrayBuffer* buffer)
710 {
711     unsigned int size = 0;
712     unsigned char *entry;
713     int ret = OH_UdmfRecord_GetGeneralEntry(record, type, &entry, &size);
714     if (ret != UDMF_E_OK) {
715         LOG_ERROR(UDMF_CAPI, "OH_UdmfRecord_GetGeneralEntry ret: %{public}d.", ret);
716         return ret;
717     }
718     return OH_UdsArrayBuffer_SetData(buffer, entry, size);
719 }
720 
OH_UdmfRecord_GetContentForm(OH_UdmfRecord * record,OH_UdsContentForm * contentForm)721 int OH_UdmfRecord_GetContentForm(OH_UdmfRecord* record, OH_UdsContentForm* contentForm)
722 {
723     if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(contentForm, UDS_CONTENT_FORM_STRUCT_ID)) {
724         return UDMF_E_INVALID_PARAM;
725     }
726     return GetUds(record, contentForm, UDType::CONTENT_FORM);
727 }
728 
OH_UdmfProperty_Create(OH_UdmfData * data)729 OH_UdmfProperty* OH_UdmfProperty_Create(OH_UdmfData* data)
730 {
731     if (!IsUnifiedDataValid(data)) {
732         return nullptr;
733     }
734     OH_UdmfProperty* properties = new (std::nothrow) OH_UdmfProperty;
735     if (properties == nullptr) {
736         return nullptr;
737     }
738     properties->properties_ = data->unifiedData_->GetProperties();
739     return properties;
740 }
741 
OH_UdmfProperty_Destroy(OH_UdmfProperty * properties)742 void OH_UdmfProperty_Destroy(OH_UdmfProperty* properties)
743 {
744     if (properties != nullptr) {
745         delete properties;
746     }
747 }
748 
OH_UdmfProperty_GetTag(OH_UdmfProperty * properties)749 const char* OH_UdmfProperty_GetTag(OH_UdmfProperty* properties)
750 {
751     if (!IsUnifiedPropertiesValid(properties)) {
752         return nullptr;
753     }
754     return properties->properties_->tag.c_str();
755 }
756 
OH_UdmfProperty_GetTimestamp(OH_UdmfProperty * properties)757 int64_t OH_UdmfProperty_GetTimestamp(OH_UdmfProperty* properties)
758 {
759     if (!IsUnifiedPropertiesValid(properties)) {
760         return -1;
761     }
762     return properties->properties_->timestamp;
763 }
764 
OH_UdmfProperty_GetShareOption(OH_UdmfProperty * properties)765 Udmf_ShareOption OH_UdmfProperty_GetShareOption(OH_UdmfProperty* properties)
766 {
767     if (!IsUnifiedPropertiesValid(properties)) {
768         return Udmf_ShareOption::SHARE_OPTIONS_INVALID;
769     }
770     switch (properties->properties_->shareOptions) {
771         case ShareOptions::IN_APP:
772             return Udmf_ShareOption::SHARE_OPTIONS_IN_APP;
773         case ShareOptions::CROSS_APP:
774         case ShareOptions::CROSS_DEVICE:
775             return Udmf_ShareOption::SHARE_OPTIONS_CROSS_APP;
776         default:
777             return Udmf_ShareOption::SHARE_OPTIONS_INVALID;
778     }
779 }
780 
OH_UdmfProperty_GetExtrasIntParam(OH_UdmfProperty * properties,const char * key,const int defaultValue)781 int OH_UdmfProperty_GetExtrasIntParam(OH_UdmfProperty* properties, const char* key, const int defaultValue)
782 {
783     return (IsUnifiedPropertiesValid(properties) && key != nullptr) ?
784            properties->properties_->extras.GetIntParam(key, defaultValue) : defaultValue;
785 }
786 
OH_UdmfProperty_GetExtrasStringParam(OH_UdmfProperty * properties,const char * key)787 const char* OH_UdmfProperty_GetExtrasStringParam(OH_UdmfProperty* properties, const char* key)
788 {
789     if (!IsUnifiedPropertiesValid(properties) || key == nullptr) {
790         return nullptr;
791     }
792     properties->extraStr = properties->properties_->extras.GetStringParam(key);
793     return properties->extraStr.c_str();
794 }
795 
OH_UdmfProperty_SetTag(OH_UdmfProperty * properties,const char * tag)796 int OH_UdmfProperty_SetTag(OH_UdmfProperty* properties, const char* tag)
797 {
798     if (!IsUnifiedPropertiesValid(properties) || tag == nullptr) {
799         return UDMF_E_INVALID_PARAM;
800     }
801     properties->properties_->tag = tag;
802     return UDMF_E_OK;
803 }
804 
OH_UdmfProperty_SetShareOption(OH_UdmfProperty * properties,Udmf_ShareOption option)805 int OH_UdmfProperty_SetShareOption(OH_UdmfProperty* properties, Udmf_ShareOption option)
806 {
807     if (!IsUnifiedPropertiesValid(properties)) {
808         return UDMF_E_INVALID_PARAM;
809     }
810     std::lock_guard<std::mutex> lock(properties->mutex);
811     switch (option) {
812         case Udmf_ShareOption::SHARE_OPTIONS_IN_APP:
813             properties->properties_->shareOptions = ShareOptions::IN_APP;
814             break;
815         case Udmf_ShareOption::SHARE_OPTIONS_CROSS_APP:
816             properties->properties_->shareOptions = ShareOptions::CROSS_APP;
817             break;
818         default:
819             return UDMF_E_INVALID_PARAM;
820     }
821     return UDMF_E_OK;
822 }
823 
OH_UdmfProperty_SetExtrasIntParam(OH_UdmfProperty * properties,const char * key,int param)824 int OH_UdmfProperty_SetExtrasIntParam(OH_UdmfProperty* properties, const char* key, int param)
825 {
826     if (!IsUnifiedPropertiesValid(properties) || key == nullptr) {
827         return UDMF_E_INVALID_PARAM;
828     }
829     std::lock_guard<std::mutex> lock(properties->mutex);
830     properties->properties_->extras.SetParam(key, OHOS::AAFwk::Integer::Box(param));
831     return UDMF_E_OK;
832 }
833 
OH_UdmfProperty_SetExtrasStringParam(OH_UdmfProperty * properties,const char * key,const char * param)834 int OH_UdmfProperty_SetExtrasStringParam(OH_UdmfProperty* properties, const char* key, const char* param)
835 {
836     if (!IsUnifiedPropertiesValid(properties) || key == nullptr || param == nullptr) {
837         return UDMF_E_INVALID_PARAM;
838     }
839     std::lock_guard<std::mutex> lock(properties->mutex);
840     properties->properties_->extras.SetParam(key, OHOS::AAFwk::String::Box(param));
841     return UDMF_E_OK;
842 }
843 
OH_UdmfRecordProvider_Create()844 OH_UdmfRecordProvider* OH_UdmfRecordProvider_Create()
845 {
846     OH_UdmfRecordProvider* provider = new (std::nothrow) OH_UdmfRecordProvider();
847     if (provider == nullptr) {
848         LOG_ERROR(UDMF_CAPI, "allocate OH_UdmfRecordProvider memory fail");
849     }
850     return provider;
851 }
852 
OH_UdmfRecordProvider_Destroy(OH_UdmfRecordProvider * provider)853 int OH_UdmfRecordProvider_Destroy(OH_UdmfRecordProvider* provider)
854 {
855     if (provider == nullptr) {
856         return UDMF_E_INVALID_PARAM;
857     }
858     if (provider->context != nullptr && provider->finalize != nullptr) {
859         (provider->finalize)(provider->context);
860         LOG_INFO(UDMF_CAPI, "free context finished");
861     }
862     delete provider;
863     return UDMF_E_OK;
864 }
865 
OH_UdmfRecordProvider_SetData(OH_UdmfRecordProvider * provider,void * context,const OH_UdmfRecordProvider_GetData callback,const UdmfData_Finalize finalize)866 int OH_UdmfRecordProvider_SetData(OH_UdmfRecordProvider* provider, void* context,
867     const OH_UdmfRecordProvider_GetData callback, const UdmfData_Finalize finalize)
868 {
869     if (provider == nullptr || callback == nullptr) {
870         return UDMF_E_INVALID_PARAM;
871     }
872     provider->callback = callback;
873     if (context != nullptr && finalize == nullptr) {
874         LOG_ERROR(UDMF_CAPI, "finalize function is null when context not null");
875         return UDMF_E_INVALID_PARAM;
876     }
877     provider->context = context;
878     provider->finalize = finalize;
879     return UDMF_E_OK;
880 }
881 
OH_UdmfRecord_SetProvider(OH_UdmfRecord * record,const char * const * types,unsigned int count,OH_UdmfRecordProvider * provider)882 int OH_UdmfRecord_SetProvider(OH_UdmfRecord* record, const char* const* types, unsigned int count,
883     OH_UdmfRecordProvider* provider)
884 {
885     if (!IsUnifiedRecordValid(record) || types == nullptr || count == 0 || provider == nullptr) {
886         return UDMF_E_INVALID_PARAM;
887     }
888     std::shared_ptr<DataProviderImpl> providerBox = std::make_shared<DataProviderImpl>();
889     providerBox->SetInnerProvider(provider);
890     std::vector<std::string> udTypes;
891     std::set<std::string> udTypeSet;
892     for (unsigned int i = 0; i < count; ++i) {
893         if (types[i] == nullptr) {
894             LOG_ERROR(UDMF_CAPI, "The type with index %{public}d is empty", i);
895             continue;
896         }
897         if (udTypeSet.count(types[i]) == 0) {
898             udTypeSet.emplace(types[i]);
899             udTypes.emplace_back(types[i]);
900         }
901     }
902     record->record_->SetEntryGetter(udTypes, providerBox);
903     return UDMF_E_OK;
904 }
905