1 /*
2  * Copyright (C) 2021-2023 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 #include "paste_data_record.h"
16 
17 #include <sys/stat.h>
18 #include <unistd.h>
19 
20 #include "convert_utils.h"
21 #include "copy_uri_handler.h"
22 #include "parcel_util.h"
23 #include "paste_data_entry.h"
24 #include "paste_uri_handler.h"
25 #include "pasteboard_error.h"
26 #include "pasteboard_client.h"
27 #include "pasteboard_hilog.h"
28 #include "pixel_map_parcel.h"
29 
30 using namespace OHOS::Media;
31 
32 namespace OHOS {
33 namespace MiscServices {
34 namespace {
35 constexpr int MAX_TEXT_LEN = 20 * 1024 * 1024;
36 }
SetMimeType(std::string mimeType)37 PasteDataRecord::Builder &PasteDataRecord::Builder::SetMimeType(std::string mimeType)
38 {
39     record_->mimeType_ = std::move(mimeType);
40     return *this;
41 }
42 enum TAG_PASTEBOARD_RECORD : uint16_t {
43     TAG_MIMETYPE = TAG_BUFF + 1,
44     TAG_HTMLTEXT,
45     TAG_WANT,
46     TAG_PLAINTEXT,
47     TAG_URI,
48     TAG_PIXELMAP,
49     TAG_CUSTOM_DATA,
50     TAG_CONVERT_URI,
51     TAG_URI_PERMISSION,
52     TAG_UDC_UDTYPE,
53     TAG_UDC_DETAILS,
54     TAG_UDC_TEXTCONTENT,
55     TAG_UDC_SYSTEMCONTENTS,
56 	TAG_UDC_UDMFVALUE,
57     TAG_UDC_ENTYIES,
58     TAG_DATA_ID,
59     TAG_RECORD_ID,
60     TAG_DELAY_RECORD_FLAG,
61     TAG_FROM,
62 };
63 
64 enum TAG_CUSTOMDATA : uint16_t {
65     TAG_ITEM_DATA = TAG_BUFF + 1,
66 };
67 
SetHtmlText(std::shared_ptr<std::string> htmlText)68 PasteDataRecord::Builder &PasteDataRecord::Builder::SetHtmlText(std::shared_ptr<std::string> htmlText)
69 {
70     record_->htmlText_ = std::move(htmlText);
71     return *this;
72 }
73 
SetWant(std::shared_ptr<OHOS::AAFwk::Want> want)74 PasteDataRecord::Builder &PasteDataRecord::Builder::SetWant(std::shared_ptr<OHOS::AAFwk::Want> want)
75 {
76     record_->want_ = std::move(want);
77     return *this;
78 }
79 
SetPlainText(std::shared_ptr<std::string> plainText)80 PasteDataRecord::Builder &PasteDataRecord::Builder::SetPlainText(std::shared_ptr<std::string> plainText)
81 {
82     record_->plainText_ = std::move(plainText);
83     return *this;
84 }
85 
SetUri(std::shared_ptr<OHOS::Uri> uri)86 PasteDataRecord::Builder &PasteDataRecord::Builder::SetUri(std::shared_ptr<OHOS::Uri> uri)
87 {
88     record_->uri_ = std::move(uri);
89     return *this;
90 }
91 
SetPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap)92 PasteDataRecord::Builder &PasteDataRecord::Builder::SetPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap)
93 {
94     record_->pixelMap_ = std::move(pixelMap);
95     return *this;
96 }
97 
SetCustomData(std::shared_ptr<MineCustomData> customData)98 PasteDataRecord::Builder &PasteDataRecord::Builder::SetCustomData(std::shared_ptr<MineCustomData> customData)
99 {
100     record_->customData_ = std::move(customData);
101     return *this;
102 }
103 
Build()104 std::shared_ptr<PasteDataRecord> PasteDataRecord::Builder::Build()
105 {
106     return record_;
107 }
108 
Builder(const std::string & mimeType)109 PasteDataRecord::Builder::Builder(const std::string &mimeType)
110 {
111     record_ = std::make_shared<PasteDataRecord>();
112     if (record_ != nullptr) {
113         record_->mimeType_ = mimeType;
114         record_->htmlText_ = nullptr;
115         record_->want_ = nullptr;
116         record_->plainText_ = nullptr;
117         record_->uri_ = nullptr;
118         record_->convertUri_ = "";
119         record_->pixelMap_ = nullptr;
120         record_->customData_ = nullptr;
121     }
122 }
123 
AddUriEntry()124 void PasteDataRecord::AddUriEntry()
125 {
126     auto object = std::make_shared<Object>();
127     object->value_[UDMF::UNIFORM_DATA_TYPE] = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::FILE_URI);
128     if (uri_ != nullptr) {
129         object->value_[UDMF::FILE_URI_PARAM] = uri_->ToString();
130     }
131     auto utdId = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::FILE_URI);
132     AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, object));
133 }
134 
NewHtmlRecord(const std::string & htmlText)135 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewHtmlRecord(const std::string &htmlText)
136 {
137     if (htmlText.length() >= MAX_TEXT_LEN) {
138         return nullptr;
139     }
140     return Builder(MIMETYPE_TEXT_HTML).SetHtmlText(std::make_shared<std::string>(htmlText)).Build();
141 }
142 
NewWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)143 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)
144 {
145     return Builder(MIMETYPE_TEXT_WANT).SetWant(std::move(want)).Build();
146 }
147 
NewPlaintTextRecord(const std::string & text)148 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewPlaintTextRecord(const std::string &text)
149 {
150     if (text.length() >= MAX_TEXT_LEN) {
151         return nullptr;
152     }
153     return Builder(MIMETYPE_TEXT_PLAIN).SetPlainText(std::make_shared<std::string>(text)).Build();
154 }
155 
NewPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)156 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)
157 {
158     return Builder(MIMETYPE_PIXELMAP).SetPixelMap(std::move(pixelMap)).Build();
159 }
160 
NewUriRecord(const OHOS::Uri & uri)161 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewUriRecord(const OHOS::Uri &uri)
162 {
163     return Builder(MIMETYPE_TEXT_URI).SetUri(std::make_shared<OHOS::Uri>(uri)).Build();
164 }
165 
NewKvRecord(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)166 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewKvRecord(
167     const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
168 {
169     std::shared_ptr<MineCustomData> customData = std::make_shared<MineCustomData>();
170     customData->AddItemData(mimeType, arrayBuffer);
171     return Builder(mimeType).SetCustomData(std::move(customData)).Build();
172 }
173 
NewMultiTypeRecord(std::shared_ptr<std::map<std::string,std::shared_ptr<EntryValue>>> values,const std::string & recordMimeType)174 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewMultiTypeRecord(
175     std::shared_ptr<std::map<std::string, std::shared_ptr<EntryValue>>> values, const std::string &recordMimeType)
176 {
177     auto record = std::make_shared<PasteDataRecord>();
178     if (values == nullptr) {
179         return record;
180     }
181     if (!recordMimeType.empty()) {
182         auto recordDefaultIter = values->find(recordMimeType);
183         if (recordDefaultIter != values->end() && recordDefaultIter->second != nullptr) {
184             auto utdId = CommonUtils::Convert2UtdId(UDMF::UDType::UD_BUTT, recordMimeType);
185             record->AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, *(recordDefaultIter->second)));
186         }
187     }
188     for (auto [mimeType, value] : *values) {
189         if (mimeType == recordMimeType) {
190             continue;
191         }
192         auto utdId = CommonUtils::Convert2UtdId(UDMF::UDType::UD_BUTT, mimeType);
193         record->AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, *value));
194     }
195     return record;
196 }
197 
NewMultiTypeDelayRecord(std::vector<std::string> mimeTypes,const std::shared_ptr<UDMF::EntryGetter> entryGetter)198 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewMultiTypeDelayRecord(
199     std::vector<std::string> mimeTypes, const std::shared_ptr<UDMF::EntryGetter> entryGetter)
200 {
201     auto record = std::make_shared<PasteDataRecord>();
202     for (auto mimeType : mimeTypes) {
203         auto utdId = CommonUtils::Convert2UtdId(UDMF::UDType::UD_BUTT, mimeType);
204         auto entry = std::make_shared<PasteDataEntry>();
205         entry->SetMimeType(mimeType);
206         entry->SetUtdId(utdId);
207         record->AddEntry(utdId, entry);
208     }
209     if (entryGetter != nullptr) {
210         record->SetEntryGetter(entryGetter);
211         record->SetDelayRecordFlag(true);
212     }
213     return record;
214 }
215 
PasteDataRecord(std::string mimeType,std::shared_ptr<std::string> htmlText,std::shared_ptr<OHOS::AAFwk::Want> want,std::shared_ptr<std::string> plainText,std::shared_ptr<OHOS::Uri> uri)216 PasteDataRecord::PasteDataRecord(std::string mimeType, std::shared_ptr<std::string> htmlText,
217     std::shared_ptr<OHOS::AAFwk::Want> want, std::shared_ptr<std::string> plainText, std::shared_ptr<OHOS::Uri> uri)
218     : mimeType_{ std::move(mimeType) }, htmlText_{ std::move(htmlText) }, want_{ std::move(want) },
219       plainText_{ std::move(plainText) }, uri_{ std::move(uri) }
220 {
221 }
222 
PasteDataRecord()223 PasteDataRecord::PasteDataRecord()
224 {
225     fd_ = std::make_shared<FileDescriptor>();
226     InitDecodeMap();
227 }
228 
~PasteDataRecord()229 PasteDataRecord::~PasteDataRecord()
230 {
231     decodeMap.clear();
232 }
233 
PasteDataRecord(const PasteDataRecord & record)234 PasteDataRecord::PasteDataRecord(const PasteDataRecord& record)
235     : mimeType_(record.mimeType_), htmlText_(record.htmlText_), want_(record.want_), plainText_(record.plainText_),
236       uri_(record.uri_), convertUri_(record.convertUri_), pixelMap_(record.pixelMap_), customData_(record.customData_),
237       hasGrantUriPermission_(record.hasGrantUriPermission_), fd_(record.fd_), udType_(record.udType_),
238       details_(record.details_), textContent_(record.textContent_),
239       systemDefinedContents_(record.systemDefinedContents_), udmfValue_(record.udmfValue_), entries_(record.entries_),
240       dataId_(record.dataId_), recordId_(record.recordId_), isDelay_(record.isDelay_),
241       entryGetter_(record.entryGetter_), from_(record.from_)
242 {
243     this->isConvertUriFromRemote = record.isConvertUriFromRemote;
244     InitDecodeMap();
245 }
246 
InitDecodeMap()247 void PasteDataRecord::InitDecodeMap()
248 {
249     decodeMap = {
250         {TAG_MIMETYPE, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
251             ret = ret && ReadValue(buffer, mimeType_, head);}},
252         {TAG_HTMLTEXT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
253             ret = ret && ReadValue(buffer, htmlText_, head);}},
254         {TAG_WANT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
255             RawMem rawMem{};
256             ret = ret && ReadValue(buffer, rawMem, head);
257             want_ = ParcelUtil::Raw2Parcelable<AAFwk::Want>(rawMem);}},
258         {TAG_PLAINTEXT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
259             ret = ret && ReadValue(buffer, plainText_, head); }},
260         {TAG_URI, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
261             RawMem rawMem{};
262             ret = ret && ReadValue(buffer, rawMem, head);
263             uri_ = ParcelUtil::Raw2Parcelable<OHOS::Uri>(rawMem);}},
264         {TAG_CONVERT_URI, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
265             ret = ret && ReadValue(buffer, convertUri_, head);}},
266         {TAG_PIXELMAP, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
267             std::vector<std::uint8_t> value;
268             ret = ret && ReadValue(buffer, value, head);
269             pixelMap_ = Vector2PixelMap(value);}},
270         {TAG_CUSTOM_DATA, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
271             ret = ret && ReadValue(buffer, customData_, head);}},
272         {TAG_URI_PERMISSION, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
273             ret = ret && ReadValue(buffer, hasGrantUriPermission_, head);}},
274         {TAG_UDC_UDTYPE, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
275             ret = ret && ReadValue(buffer, udType_, head);}},
276         {TAG_UDC_DETAILS, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
277             ret = ret && ReadValue(buffer, details_, head);}},
278         {TAG_UDC_TEXTCONTENT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
279             ret = ret && ReadValue(buffer, textContent_, head);}},
280         {TAG_UDC_SYSTEMCONTENTS, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
281             ret = ret && ReadValue(buffer, systemDefinedContents_, head);}},
282         {TAG_UDC_UDMFVALUE, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
283             ret = ret && ReadValue(buffer, udmfValue_, head);}},
284         {TAG_UDC_ENTYIES, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
285             ret = ret && ReadValue(buffer, entries_, head);}},
286         {TAG_DATA_ID, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
287             ret = ret && ReadValue(buffer, dataId_, head);}},
288         {TAG_RECORD_ID, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
289             ret = ret && ReadValue(buffer, recordId_, head);}},
290         {TAG_DELAY_RECORD_FLAG, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
291             ret = ret && ReadValue(buffer, isDelay_, head);}},
292         {TAG_FROM, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
293             ret = ret && ReadValue(buffer, from_, head);}},
294     };
295 }
296 
GetHtmlText() const297 std::shared_ptr<std::string> PasteDataRecord::GetHtmlText() const
298 {
299     if (htmlText_ != nullptr && mimeType_ == MIMETYPE_TEXT_HTML) {
300         return htmlText_;
301     }
302     for (const auto &entry : entries_) {
303         if (entry && entry->GetMimeType() == MIMETYPE_TEXT_HTML) {
304             return entry->ConvertToHtml();
305         }
306     }
307     return htmlText_;
308 }
309 
GetMimeType() const310 std::string PasteDataRecord::GetMimeType() const
311 {
312     return this->mimeType_;
313 }
314 
GetPlainText() const315 std::shared_ptr<std::string> PasteDataRecord::GetPlainText() const
316 {
317     if (plainText_ != nullptr && mimeType_ == MIMETYPE_TEXT_PLAIN) {
318         return plainText_;
319     }
320     for (const auto &entry : entries_) {
321         if (entry && entry->GetMimeType() == MIMETYPE_TEXT_PLAIN) {
322             return entry->ConvertToPlianText();
323         }
324     }
325     return plainText_;
326 }
327 
GetPixelMap() const328 std::shared_ptr<PixelMap> PasteDataRecord::GetPixelMap() const
329 {
330     if (pixelMap_ != nullptr && mimeType_ == MIMETYPE_PIXELMAP) {
331         return pixelMap_;
332     }
333     for (const auto &entry : entries_) {
334         if (entry && entry->GetMimeType() == MIMETYPE_PIXELMAP) {
335             return entry->ConvertToPixelMap();
336         }
337     }
338     return pixelMap_;
339 }
340 
GetUri() const341 std::shared_ptr<OHOS::Uri> PasteDataRecord::GetUri() const
342 {
343     if (convertUri_.empty()) {
344         return GetOrginUri();
345     }
346     return std::make_shared<OHOS::Uri>(convertUri_);
347 }
348 
ClearPixelMap()349 void PasteDataRecord::ClearPixelMap()
350 {
351     this->pixelMap_ = nullptr;
352 }
353 
SetUri(std::shared_ptr<OHOS::Uri> uri)354 void PasteDataRecord::SetUri(std::shared_ptr<OHOS::Uri> uri)
355 {
356     uri_ = std::move(uri);
357     AddUriEntry();
358 }
359 
GetOrginUri() const360 std::shared_ptr<OHOS::Uri> PasteDataRecord::GetOrginUri() const
361 {
362     if (uri_ != nullptr && mimeType_ == MIMETYPE_TEXT_URI) {
363         return uri_;
364     }
365     for (const auto &entry : entries_) {
366         if (entry && entry->GetMimeType() == MIMETYPE_TEXT_URI) {
367             return entry->ConvertToUri();
368         }
369     }
370     return uri_;
371 }
372 
GetWant() const373 std::shared_ptr<OHOS::AAFwk::Want> PasteDataRecord::GetWant() const
374 {
375     if (want_ != nullptr && mimeType_ == MIMETYPE_TEXT_WANT) {
376         return want_;
377     }
378     for (const auto &entry : entries_) {
379         if (entry && entry->GetMimeType() == MIMETYPE_TEXT_WANT) {
380             return entry->ConvertToWant();
381         }
382     }
383     return want_;
384 }
385 
GetCustomData() const386 std::shared_ptr<MineCustomData> PasteDataRecord::GetCustomData() const
387 {
388     std::shared_ptr<MineCustomData> customData = std::make_shared<MineCustomData>();
389     if (customData_) {
390         const std::map<std::string, std::vector<uint8_t>> &itemData = customData_->GetItemData();
391         for (const auto &[key, value] : itemData) {
392             customData->AddItemData(key, value);
393         }
394     }
395     for (const auto &entry : entries_) {
396         if (entry && entry->GetMimeType() == entry->GetUtdId()) {
397             std::shared_ptr<MineCustomData> entryCustomData = entry->ConvertToCustomData();
398             if (entryCustomData == nullptr) {
399                 continue;
400             }
401             const std::map<std::string, std::vector<uint8_t>> &itemData = entryCustomData->GetItemData();
402             for (const auto &[key, value] : itemData) {
403                 customData->AddItemData(key, value);
404             }
405         }
406     }
407     return customData->GetItemData().empty() ? nullptr : customData;
408 }
409 
ConvertToText() const410 std::string PasteDataRecord::ConvertToText() const
411 {
412     if (this->htmlText_) {
413         return *this->htmlText_;
414     } else if (this->plainText_) {
415         return *this->plainText_;
416     } else if (this->uri_) {
417         return this->uri_->ToString();
418     } else {
419         return "";
420     }
421 }
422 
Encode(std::vector<std::uint8_t> & buffer)423 bool PasteDataRecord::Encode(std::vector<std::uint8_t> &buffer)
424 {
425     bool ret = Write(buffer, TAG_MIMETYPE, mimeType_);
426     ret = Write(buffer, TAG_HTMLTEXT, htmlText_) && ret;
427     ret = Write(buffer, TAG_WANT, ParcelUtil::Parcelable2Raw(want_.get())) && ret;
428     ret = Write(buffer, TAG_PLAINTEXT, plainText_) && ret;
429     ret = Write(buffer, TAG_URI, ParcelUtil::Parcelable2Raw(uri_.get())) && ret;
430     ret = Write(buffer, TAG_CONVERT_URI, convertUri_) && ret;
431     auto pixelVector = PixelMap2Vector(pixelMap_);
432     ret = Write(buffer, TAG_PIXELMAP, pixelVector) && ret;
433     ret = Write(buffer, TAG_CUSTOM_DATA, customData_) && ret;
434     ret = Write(buffer, TAG_URI_PERMISSION, hasGrantUriPermission_) && ret;
435     ret = Write(buffer, TAG_UDC_UDTYPE, udType_) && ret;
436     ret = Write(buffer, TAG_UDC_DETAILS, details_) && ret;
437     ret = Write(buffer, TAG_UDC_TEXTCONTENT, textContent_) && ret;
438     ret = Write(buffer, TAG_UDC_SYSTEMCONTENTS, systemDefinedContents_) && ret;
439     ret = Write(buffer, TAG_UDC_UDMFVALUE, udmfValue_) && ret;
440     ret = Write(buffer, TAG_UDC_ENTYIES, entries_) && ret;
441     ret = Write(buffer, TAG_DATA_ID, dataId_) && ret;
442     ret = Write(buffer, TAG_RECORD_ID, recordId_) && ret;
443     ret = Write(buffer, TAG_DELAY_RECORD_FLAG, isDelay_) && ret;
444     ret = Write(buffer, TAG_FROM, from_) && ret;
445     return ret;
446 }
447 
Decode(const std::vector<std::uint8_t> & buffer)448 bool PasteDataRecord::Decode(const std::vector<std::uint8_t> &buffer)
449 {
450     for (; IsEnough();) {
451         TLVHead head{};
452         bool ret = ReadHead(buffer, head);
453         auto it = decodeMap.find(head.tag);
454         if (it == decodeMap.end()) {
455             ret = ret && Skip(head.len, buffer.size());
456         } else {
457             auto func = it->second;
458             func(ret, buffer, head);
459         }
460         if (!ret) {
461             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u",
462                 head.tag, head.len);
463             return false;
464         }
465     }
466     return true;
467 }
Count()468 size_t PasteDataRecord::Count()
469 {
470     size_t expectedSize = 0;
471     expectedSize += TLVObject::Count(mimeType_);
472     expectedSize += TLVObject::Count(htmlText_);
473     expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(want_.get()));
474     expectedSize += TLVObject::Count(plainText_);
475     expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(uri_.get()));
476     expectedSize += TLVObject::Count(convertUri_);
477     auto pixelVector = PixelMap2Vector(pixelMap_);
478     expectedSize += TLVObject::Count(pixelVector);
479     expectedSize += TLVObject::Count(customData_);
480     expectedSize += TLVObject::Count(hasGrantUriPermission_);
481     expectedSize += TLVObject::Count(udType_);
482     expectedSize += TLVObject::Count(details_);
483     expectedSize += TLVObject::Count(textContent_);
484     expectedSize += TLVObject::Count(systemDefinedContents_);
485     expectedSize += TLVObject::Count(udmfValue_);
486     expectedSize += TLVObject::Count(entries_);
487     expectedSize += TLVObject::Count(dataId_);
488     expectedSize += TLVObject::Count(recordId_);
489     expectedSize += TLVObject::Count(isDelay_);
490     expectedSize += TLVObject::Count(from_);
491     return expectedSize;
492 }
493 
WriteFd(MessageParcel & parcel,UriHandler & uriHandler,bool isClient)494 bool PasteDataRecord::WriteFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient)
495 {
496     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "isClient: %{public}d", isClient);
497     if (fd_->GetFd() >= 0) {
498         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "write fd_, fd_ is %{public}d", fd_->GetFd());
499         return parcel.WriteFileDescriptor(fd_->GetFd());
500     }
501     std::string tempUri = GetPassUri();
502     if (tempUri.empty()) {
503         return false;
504     }
505     int32_t fd = uriHandler.ToFd(tempUri, isClient);
506     bool ret = parcel.WriteFileDescriptor(fd);
507     uriHandler.ReleaseFd(fd);
508 
509     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "ret is %{public}d", ret);
510     return ret;
511 }
512 
ReadFd(MessageParcel & parcel,UriHandler & uriHandler)513 bool PasteDataRecord::ReadFd(MessageParcel &parcel, UriHandler &uriHandler)
514 {
515     int32_t fd = parcel.ReadFileDescriptor();
516     if (fd >= 0) {
517         convertUri_ = uriHandler.ToUri(fd);
518     }
519     if (!uriHandler.IsPaste()) {
520         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Set fd, fd is %{public}d", fd);
521         fd_->SetFd(fd);
522     }
523     return true;
524 }
NeedFd(const UriHandler & uriHandler)525 bool PasteDataRecord::NeedFd(const UriHandler &uriHandler)
526 {
527     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start");
528     std::string tempUri = GetPassUri();
529     if (tempUri.empty()) {
530         return false;
531     }
532     if (!uriHandler.IsFile(tempUri) && fd_->GetFd() < 0) {
533         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "invalid file uri, fd:%{public}d", fd_->GetFd());
534         return false;
535     }
536     return true;
537 }
GetPassUri()538 std::string PasteDataRecord::GetPassUri()
539 {
540     std::string tempUri;
541     if (uri_ != nullptr) {
542         tempUri = uri_->ToString();
543     }
544     if (!convertUri_.empty()) {
545         tempUri = convertUri_;
546     }
547     return tempUri;
548 }
549 
ReplaceShareUri(int32_t userId)550 void PasteDataRecord::ReplaceShareUri(int32_t userId)
551 {
552     if (convertUri_.empty()) {
553         return;
554     }
555 
556     // convert uri format: /mnt/hmdfs/100/account/merge_view/services/psteboard_service/.share/xxx.txt
557     constexpr const char *SHARE_PATH_PREFIX = "/mnt/hmdfs/";
558     auto frontPos = convertUri_.find(SHARE_PATH_PREFIX);
559     auto rearPos = convertUri_.find("/account/");
560     if (frontPos == 0 && rearPos != std::string::npos) {
561         convertUri_ = SHARE_PATH_PREFIX + std::to_string(userId) + convertUri_.substr(rearPos);
562     }
563 }
SetConvertUri(const std::string & value)564 void PasteDataRecord::SetConvertUri(const std::string &value)
565 {
566     convertUri_ = value;
567 }
GetConvertUri() const568 std::string PasteDataRecord::GetConvertUri() const
569 {
570     return convertUri_;
571 }
SetGrantUriPermission(bool hasPermission)572 void PasteDataRecord::SetGrantUriPermission(bool hasPermission)
573 {
574     hasGrantUriPermission_ = hasPermission;
575 }
HasGrantUriPermission()576 bool PasteDataRecord::HasGrantUriPermission()
577 {
578     return hasGrantUriPermission_;
579 }
580 
SetTextContent(const std::string & content)581 void PasteDataRecord::SetTextContent(const std::string& content)
582 {
583     this->textContent_ = content;
584 }
585 
GetTextContent() const586 std::string PasteDataRecord::GetTextContent() const
587 {
588     return this->textContent_;
589 }
590 
SetDetails(const Details & details)591 void PasteDataRecord::SetDetails(const Details& details)
592 {
593     this->details_ = std::make_shared<Details>(details);
594 }
595 
GetDetails() const596 std::shared_ptr<Details> PasteDataRecord::GetDetails() const
597 {
598     return this->details_;
599 }
600 
SetSystemDefinedContent(const Details & contents)601 void PasteDataRecord::SetSystemDefinedContent(const Details& contents)
602 {
603     this->systemDefinedContents_ = std::make_shared<Details>(contents);
604 }
605 
GetSystemDefinedContent() const606 std::shared_ptr<Details> PasteDataRecord::GetSystemDefinedContent() const
607 {
608     return this->systemDefinedContents_;
609 }
GetUDType() const610 int32_t PasteDataRecord::GetUDType() const
611 {
612     return this->udType_;
613 }
614 
SetUDType(int32_t type)615 void PasteDataRecord::SetUDType(int32_t type)
616 {
617     this->udType_ = type;
618 }
619 
GetValidMimeTypes(const std::vector<std::string> & mimeTypes) const620 std::vector<std::string> PasteDataRecord::GetValidMimeTypes(const std::vector<std::string>& mimeTypes) const
621 {
622     std::vector<std::string> res;
623     auto allTypes = GetMimeTypes();
624     for (auto const& type : mimeTypes) {
625         if (allTypes.find(type) != allTypes.end()) {
626             res.emplace_back(type);
627         }
628     }
629     return res;
630 }
631 
GetValidTypes(const std::vector<std::string> & types) const632 std::vector<std::string> PasteDataRecord::GetValidTypes(const std::vector<std::string>& types) const
633 {
634     std::vector<std::string> res;
635     auto allTypes = GetUdtTypes();
636     for (auto const& type : types) {
637         if (allTypes.find(type) != allTypes.end()) {
638             res.emplace_back(type);
639         }
640     }
641     return res;
642 }
643 
HasEmptyEntry() const644 bool PasteDataRecord::HasEmptyEntry() const
645 {
646     if (udmfValue_ && !std::holds_alternative<std::monostate>(*udmfValue_)) {
647         return false;
648     }
649     for (auto const &entry : GetEntries()) {
650         if (std::holds_alternative<std::monostate>(entry->GetValue())) {
651             return true;
652         }
653     }
654     return false;
655 }
656 
SetUDMFValue(const std::shared_ptr<EntryValue> & udmfValue)657 void PasteDataRecord::SetUDMFValue(const std::shared_ptr<EntryValue>& udmfValue)
658 {
659     this->udmfValue_ = udmfValue;
660 }
661 
GetUDMFValue()662 std::shared_ptr<EntryValue> PasteDataRecord::GetUDMFValue()
663 {
664     if (udmfValue_) {
665         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "udmfValue_ is not null");
666         return this->udmfValue_;
667     }
668     if (mimeType_.empty()) {
669         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "mimetype is null");
670         return nullptr;
671     }
672     auto object = std::make_shared<Object>();
673     if (mimeType_ == MIMETYPE_TEXT_PLAIN) {
674         object->value_[UDMF::UNIFORM_DATA_TYPE] = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::PLAIN_TEXT);
675         if (plainText_ != nullptr) {
676             object->value_[UDMF::CONTENT] = *plainText_;
677         }
678     } else if (mimeType_ == MIMETYPE_TEXT_HTML) {
679         object->value_[UDMF::UNIFORM_DATA_TYPE] = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::HTML);
680         if (htmlText_ != nullptr) {
681             object->value_[UDMF::HTML_CONTENT] = *htmlText_;
682         }
683     } else if (mimeType_ == MIMETYPE_PIXELMAP) {
684         object->value_[UDMF::UNIFORM_DATA_TYPE] = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::SYSTEM_DEFINED_PIXEL_MAP);
685         if (pixelMap_ != nullptr) {
686             object->value_[UDMF::PIXEL_MAP] = pixelMap_;
687         }
688     } else if (mimeType_ == MIMETYPE_TEXT_URI) {
689         object->value_[UDMF::UNIFORM_DATA_TYPE] = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::FILE_URI);
690         auto uri = GetUri();
691         if (uri != nullptr) {
692             object->value_[UDMF::FILE_URI_PARAM] = uri->ToString();
693         }
694     } else if (mimeType_ == MIMETYPE_TEXT_WANT) {
695         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "mimeType is want, udmf not surpport");
696     } else if (customData_ != nullptr) {
697         auto itemData = customData_->GetItemData();
698         if (itemData.size() == 0) {
699             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "no customData");
700             return udmfValue_;
701         }
702         if (itemData.size() != 1) {
703             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT,
704                 "not surrport u8 map, mimeType:%{public}s, customData.size:%{public}zu", mimeType_.c_str(),
705                 itemData.size());
706         }
707         udmfValue_ = std::make_shared<EntryValue>(itemData.begin()->second);
708         return udmfValue_;
709     }
710     udmfValue_ = std::make_shared<EntryValue>(object);
711     return udmfValue_;
712 }
713 
GetUdtTypes() const714 std::set<std::string> PasteDataRecord::GetUdtTypes() const
715 {
716     std::set<std::string> types;
717     types.emplace(CommonUtils::Convert2UtdId(udType_, mimeType_));
718     for (auto const& entry: entries_) {
719         types.emplace(entry->GetUtdId());
720     }
721     return types;
722 }
723 
GetMimeTypes() const724 std::set<std::string> PasteDataRecord::GetMimeTypes() const
725 {
726     std::set<std::string> types;
727     types.emplace(mimeType_);
728     for (auto const& entry: entries_) {
729         types.emplace(entry->GetMimeType());
730     }
731     return types;
732 }
733 
AddEntryByMimeType(const std::string & mimeType,std::shared_ptr<PasteDataEntry> value)734 void PasteDataRecord::AddEntryByMimeType(const std::string& mimeType, std::shared_ptr<PasteDataEntry> value)
735 {
736     if (value == nullptr) {
737         return;
738     }
739     auto utdId = CommonUtils::Convert2UtdId(UDMF::UDType::UD_BUTT, mimeType);
740     value->SetUtdId(utdId);
741     AddEntry(utdId, value);
742 }
743 
AddEntry(const std::string & utdType,std::shared_ptr<PasteDataEntry> value)744 void PasteDataRecord::AddEntry(const std::string& utdType, std::shared_ptr<PasteDataEntry> value)
745 {
746     if (!value) {
747         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "entry is null");
748         return;
749     }
750     if (utdType != value->GetUtdId()) {
751         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type is diff. utdtype:%{public}s, UtdId:%{public}s",
752             utdType.c_str(), value->GetUtdId().c_str());
753         return;
754     }
755     // first entry save to record, or record type same
756     if (mimeType_.empty() || utdType == CommonUtils::Convert2UtdId(udType_, mimeType_)) {
757         mimeType_ = value->GetMimeType();
758         auto udType = UDMF::UtdUtils::GetUtdEnumFromUtdId(utdType);
759         udType_ = udType == UDMF::UDType::UD_BUTT ? UDMF::UDType::APPLICATION_DEFINED_RECORD : udType;
760         udmfValue_ = std::make_shared<EntryValue>(value->GetValue());
761         if (mimeType_ == MIMETYPE_PIXELMAP) {
762             pixelMap_ = value->ConvertToPixelMap();
763         } else if (mimeType_ == MIMETYPE_TEXT_HTML) {
764             htmlText_ = value->ConvertToHtml();
765         } else if (mimeType_ == MIMETYPE_TEXT_PLAIN) {
766             plainText_ = value->ConvertToPlianText();
767         } else if (mimeType_ == MIMETYPE_TEXT_URI) {
768             uri_ = value->ConvertToUri();
769         } else if (mimeType_ == MIMETYPE_TEXT_WANT) {
770             want_ = value->ConvertToWant();
771         } else {
772             customData_ = value->ConvertToCustomData();
773         }
774         return;
775     }
776     // not firest entry
777     bool has = false;
778     for (auto& entry : entries_) {
779         if (entry->GetUtdId() == utdType) {
780             entry = value;
781             has = true;
782             break;
783         }
784     }
785     if (!has) {
786         entries_.emplace_back(value);
787     }
788 }
789 
GetEntryByMimeType(const std::string & mimeType)790 std::shared_ptr<PasteDataEntry> PasteDataRecord::GetEntryByMimeType(const std::string& mimeType)
791 {
792     if (!udmfValue_) {
793         udmfValue_ = GetUDMFValue();
794     }
795     auto utdId = CommonUtils::Convert2UtdId(UDMF::UDType::UD_BUTT, mimeType);
796     return GetEntry(utdId);
797 }
798 
GetEntry(const std::string & utdType)799 std::shared_ptr<PasteDataEntry> PasteDataRecord::GetEntry(const std::string& utdType)
800 {
801     if (!udmfValue_) {
802         udmfValue_ = GetUDMFValue();
803     }
804     if (CommonUtils::Convert2UtdId(udType_, mimeType_) == utdType) {
805         if (udmfValue_ == nullptr) {
806             return nullptr;
807         }
808         auto entry = std::make_shared<PasteDataEntry>(utdType, *udmfValue_);
809         if (isDelay_ && !entry->HasContent(utdType)) {
810             PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Begin GetRecordValueByType1");
811             PasteboardClient::GetInstance()->GetRecordValueByType(dataId_, recordId_, *entry);
812         }
813         if (CommonUtils::IsFileUri(utdType) && GetUri() != nullptr) {
814             return std::make_shared<PasteDataEntry>(utdType, GetUri()->ToString());
815         } else if (mimeType_ == MIMETYPE_TEXT_WANT) {
816             return std::make_shared<PasteDataEntry>(utdType, want_);
817         }
818         return entry;
819     }
820     for (auto const &entry : entries_) {
821         if (entry->GetUtdId() == utdType ||
822             (CommonUtils::IsFileUri(utdType) && CommonUtils::IsFileUri(entry->GetUtdId()))) {
823             if (isDelay_ && !entry->HasContent(utdType)) {
824                 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Begin GetRecordValueByType2");
825                 PasteboardClient::GetInstance()->GetRecordValueByType(dataId_, recordId_, *entry);
826             }
827             if (CommonUtils::IsFileUri(utdType) && GetUri() != nullptr) {
828                 return std::make_shared<PasteDataEntry>(utdType, GetUri()->ToString());
829             }
830             return entry;
831         }
832     }
833     return nullptr;
834 }
835 
GetEntries() const836 std::vector<std::shared_ptr<PasteDataEntry>> PasteDataRecord::GetEntries() const
837 {
838     std::vector<std::shared_ptr<PasteDataEntry>> entries = entries_;
839     if (udmfValue_) {
840         entries.insert(entries.begin(),
841             std::make_shared<PasteDataEntry>(CommonUtils::Convert2UtdId(udType_, mimeType_), *udmfValue_));
842     }
843     return entries;
844 }
845 
SetDataId(uint32_t dataId)846 void PasteDataRecord::SetDataId(uint32_t dataId)
847 {
848     dataId_ = dataId;
849 }
850 
GetDataId() const851 uint32_t PasteDataRecord::GetDataId() const
852 {
853     return dataId_;
854 }
855 
SetRecordId(uint32_t recordId)856 void PasteDataRecord::SetRecordId(uint32_t recordId)
857 {
858     recordId_ = recordId;
859 }
860 
GetRecordId() const861 uint32_t PasteDataRecord::GetRecordId() const
862 {
863     return recordId_;
864 }
865 
SetDelayRecordFlag(bool isDelay)866 void PasteDataRecord::SetDelayRecordFlag(bool isDelay)
867 {
868     isDelay_ = isDelay;
869 }
870 
IsDelayRecord() const871 bool PasteDataRecord::IsDelayRecord() const
872 {
873     return isDelay_;
874 }
875 
SetEntryGetter(const std::shared_ptr<UDMF::EntryGetter> entryGetter)876 void PasteDataRecord::SetEntryGetter(const std::shared_ptr<UDMF::EntryGetter> entryGetter)
877 {
878     entryGetter_ = std::move(entryGetter);
879 }
880 
SetFrom(uint32_t from)881 void PasteDataRecord::SetFrom(uint32_t from)
882 {
883     from_ = from;
884 }
885 
GetFrom() const886 uint32_t PasteDataRecord::GetFrom() const
887 {
888     return from_;
889 }
890 
GetEntryGetter()891 std::shared_ptr<UDMF::EntryGetter> PasteDataRecord::GetEntryGetter()
892 {
893     return entryGetter_;
894 }
895 
~FileDescriptor()896 FileDescriptor::~FileDescriptor()
897 {
898     if (fd_ >= 0) {
899         close(fd_);
900         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "close fd_: %{public}d", fd_);
901     }
902 }
SetFd(int32_t fd)903 void FileDescriptor::SetFd(int32_t fd)
904 {
905     fd_ = fd;
906 }
GetFd() const907 int32_t FileDescriptor::GetFd() const
908 {
909     return fd_;
910 }
911 } // namespace MiscServices
912 } // namespace OHOS