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 #include "paste_data_entry.h"
17 
18 #include "common/constant.h"
19 #include "pasteboard_hilog.h"
20 #include "pixel_map.h"
21 #include "tlv_object.h"
22 namespace OHOS {
23 namespace MiscServices {
24 
25 enum TAG_CUSTOMDATA : uint16_t {
26     TAG_ITEM_DATA = TAG_BUFF + 1,
27 };
28 
29 enum TAG_ENTRY : uint16_t {
30     TAG_ENTRY_UTDID = TAG_BUFF + 1,
31     TAG_ENTRY_MIMETYPE,
32     TAG_ENTRY_VALUE,
33 };
34 
GetItemData()35 std::map<std::string, std::vector<uint8_t>> MineCustomData::GetItemData()
36 {
37     return this->itemData_;
38 }
39 
AddItemData(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)40 void MineCustomData::AddItemData(const std::string& mimeType, const std::vector<uint8_t>& arrayBuffer)
41 {
42     itemData_.emplace(mimeType, arrayBuffer);
43     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "itemData_.size = %{public}zu", itemData_.size());
44 }
45 
Encode(std::vector<std::uint8_t> & buffer)46 bool MineCustomData::Encode(std::vector<std::uint8_t>& buffer)
47 {
48     return Write(buffer, TAG_ITEM_DATA, itemData_);
49 }
50 
Decode(const std::vector<std::uint8_t> & buffer)51 bool MineCustomData::Decode(const std::vector<std::uint8_t>& buffer)
52 {
53     for (; IsEnough();) {
54         TLVHead head{};
55         bool ret = ReadHead(buffer, head);
56         switch (head.tag) {
57             case TAG_ITEM_DATA:
58                 ret = ret && ReadValue(buffer, itemData_, head);
59                 break;
60             default:
61                 ret = ret && Skip(head.len, buffer.size());
62                 break;
63         }
64         if (!ret) {
65             return false;
66         }
67     }
68     return true;
69 }
70 
Count()71 size_t MineCustomData::Count()
72 {
73     return TLVObject::Count(itemData_);
74 }
75 
PasteDataEntry(const PasteDataEntry & entry)76 PasteDataEntry::PasteDataEntry(const PasteDataEntry& entry)
77     : utdId_(entry.utdId_), mimeType_(entry.mimeType_), value_(entry.value_)
78 {
79 }
80 
operator =(const PasteDataEntry & entry)81 PasteDataEntry& PasteDataEntry::operator=(const PasteDataEntry& entry)
82 {
83     if (this == &entry) {
84         return *this;
85     }
86     this->utdId_ = entry.GetUtdId();
87     this->mimeType_ = entry.GetMimeType();
88     this->value_ = entry.GetValue();
89     return *this;
90 }
91 
PasteDataEntry(const std::string & utdId,const EntryValue & value)92 PasteDataEntry::PasteDataEntry(const std::string& utdId, const EntryValue& value) : utdId_(utdId), value_(value)
93 {
94     mimeType_ = CommonUtils::Convert2MimeType(utdId_);
95 }
96 
PasteDataEntry(const std::string & utdId,const std::string & mimeType,const EntryValue & value)97 PasteDataEntry::PasteDataEntry(const std::string& utdId, const std::string& mimeType, const EntryValue& value)
98     : utdId_(utdId), mimeType_(std::move(mimeType)), value_(std::move(value))
99 {
100 }
101 
SetUtdId(const std::string & utdId)102 void PasteDataEntry::SetUtdId(const std::string& utdId)
103 {
104     utdId_ = utdId;
105 }
106 
GetUtdId() const107 std::string PasteDataEntry::GetUtdId() const
108 {
109     return utdId_;
110 }
111 
SetMimeType(const std::string & mimeType)112 void PasteDataEntry::SetMimeType(const std::string& mimeType)
113 {
114     mimeType_ = mimeType;
115 }
116 
GetMimeType() const117 std::string PasteDataEntry::GetMimeType() const
118 {
119     return mimeType_;
120 }
121 
GetValue() const122 EntryValue PasteDataEntry::GetValue() const
123 {
124     return value_;
125 }
126 
SetValue(const EntryValue & value)127 void PasteDataEntry::SetValue(const EntryValue& value)
128 {
129     value_ = value;
130 }
131 
Encode(std::vector<std::uint8_t> & buffer)132 bool PasteDataEntry::Encode(std::vector<std::uint8_t>& buffer)
133 {
134     bool ret = Write(buffer, TAG_ENTRY_UTDID, utdId_);
135     ret = ret && Write(buffer, TAG_ENTRY_MIMETYPE, mimeType_);
136     ret = ret && Write(buffer, TAG_ENTRY_VALUE, value_);
137     return ret;
138 }
139 
Decode(const std::vector<std::uint8_t> & buffer)140 bool PasteDataEntry::Decode(const std::vector<std::uint8_t>& buffer)
141 {
142     for (; IsEnough();) {
143         TLVHead head{};
144         bool ret = ReadHead(buffer, head);
145         switch (head.tag) {
146             case TAG_ENTRY_UTDID:
147                 ret = ret && ReadValue(buffer, utdId_, head);
148                 break;
149             case TAG_ENTRY_MIMETYPE: {
150                 ret = ret && ReadValue(buffer, mimeType_, head);
151                 break;
152             }
153             case TAG_ENTRY_VALUE: {
154                 ret = ret && ReadValue(buffer, value_, head);
155                 break;
156             }
157             default:
158                 ret = ret && Skip(head.len, buffer.size());
159                 break;
160         }
161         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u, ret:%{public}d",
162             head.tag, head.len, ret);
163         if (!ret) {
164             return false;
165         }
166     }
167     return true;
168 }
169 
Marshalling(std::vector<std::uint8_t> & buffer)170 bool PasteDataEntry::Marshalling(std::vector<std::uint8_t>& buffer)
171 {
172     Init(buffer);
173     return Encode(buffer);
174 }
175 
Unmarshalling(const std::vector<std::uint8_t> & buffer)176 bool PasteDataEntry::Unmarshalling(const std::vector<std::uint8_t>& buffer)
177 {
178     total_ = buffer.size();
179     return Decode(buffer);
180 }
181 
Count()182 size_t PasteDataEntry::Count()
183 {
184     size_t expectedSize = 0;
185     expectedSize += TLVObject::Count(utdId_);
186     expectedSize += TLVObject::Count(mimeType_);
187     expectedSize += TLVObject::Count(value_);
188     return expectedSize;
189 }
190 
ConvertToPlianText() const191 std::shared_ptr<std::string> PasteDataEntry::ConvertToPlianText() const
192 {
193     std::string res;
194     auto utdId = GetUtdId();
195     auto entry = GetValue();
196     if (std::holds_alternative<std::string>(entry)) {
197         res = std::get<std::string>(entry);
198         return std::make_shared<std::string>(res);
199     }
200     if (!std::holds_alternative<std::shared_ptr<Object>>(entry)) {
201         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no plaintext");
202         return nullptr;
203     }
204     auto object = std::get<std::shared_ptr<Object>>(entry);
205     if (utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::PLAIN_TEXT)) {
206         object->GetValue(UDMF::CONTENT, res);
207     } else {
208         object->GetValue(UDMF::URL, res);
209     }
210     return std::make_shared<std::string>(res);
211 }
212 
ConvertToHtml() const213 std::shared_ptr<std::string> PasteDataEntry::ConvertToHtml() const
214 {
215     std::string res;
216     if (GetUtdId() != UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)) {
217         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, utdId:%{public}s", GetUtdId().c_str());
218         return nullptr;
219     }
220     auto entry = GetValue();
221     if (std::holds_alternative<std::string>(entry)) {
222         res = std::get<std::string>(entry);
223         return std::make_shared<std::string>(res);
224     }
225     if (!std::holds_alternative<std::shared_ptr<Object>>(entry)) {
226         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no html");
227         return nullptr;
228     }
229     auto object = std::get<std::shared_ptr<Object>>(entry);
230     object->GetValue(UDMF::HTML_CONTENT, res);
231     return std::make_shared<std::string>(res);
232 }
233 
ConvertToUri() const234 std::shared_ptr<Uri> PasteDataEntry::ConvertToUri() const
235 {
236     std::string res;
237     if (!CommonUtils::IsFileUri(GetUtdId())) {
238         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, utdId:%{public}s", GetUtdId().c_str());
239         return nullptr;
240     }
241     auto entry = GetValue();
242     if (std::holds_alternative<std::string>(entry)) {
243         res = std::get<std::string>(entry);
244         return std::make_shared<Uri>(Uri(res));
245     }
246     if (!std::holds_alternative<std::shared_ptr<Object>>(entry)) {
247         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no uri");
248         return nullptr;
249     }
250     auto object = std::get<std::shared_ptr<Object>>(entry);
251     object->GetValue(UDMF::FILE_URI_PARAM, res);
252     return std::make_shared<Uri>(Uri(res));
253 }
254 
ConvertToWant() const255 std::shared_ptr<AAFwk::Want> PasteDataEntry::ConvertToWant() const
256 {
257     if (GetUtdId() != UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::OPENHARMONY_WANT)) {
258         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, utdId:%{public}s", GetUtdId().c_str());
259         return nullptr;
260     }
261     auto entry = GetValue();
262     if (!std::holds_alternative<std::shared_ptr<AAFwk::Want>>(entry)) {
263         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no want");
264         return nullptr;
265     }
266     // no uds want
267     return std::get<std::shared_ptr<AAFwk::Want>>(entry);
268 }
269 
ConvertToPixelMap() const270 std::shared_ptr<Media::PixelMap> PasteDataEntry::ConvertToPixelMap() const
271 {
272     auto utdId = GetUtdId();
273     if (utdId != UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::SYSTEM_DEFINED_PIXEL_MAP)) {
274         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, utdId:%{public}s", utdId.c_str());
275         return nullptr;
276     }
277     auto entry = GetValue();
278     if (std::holds_alternative<std::shared_ptr<Media::PixelMap>>(entry)) {
279         return std::get<std::shared_ptr<Media::PixelMap>>(entry);
280     }
281     if (!std::holds_alternative<std::shared_ptr<Object>>(entry)) {
282         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no pixelmap");
283         return nullptr;
284     }
285     auto object = std::get<std::shared_ptr<Object>>(entry);
286     std::string objecType;
287     if (!object->GetValue(UDMF::UNIFORM_DATA_TYPE, objecType)) {
288         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, utdId:%{public}s", utdId.c_str());
289         return nullptr;
290     }
291     if (objecType != UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::SYSTEM_DEFINED_PIXEL_MAP)) {
292         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, objecType:%{public}s", objecType.c_str());
293         return nullptr;
294     }
295     auto val = object->value_[UDMF::PIXEL_MAP];
296     if (std::holds_alternative<std::shared_ptr<Media::PixelMap>>(val)) {
297         return std::get<std::shared_ptr<Media::PixelMap>>(val);
298     }
299     PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no pixelmap");
300     return nullptr;
301 }
302 
ConvertToCustomData() const303 std::shared_ptr<MineCustomData> PasteDataEntry::ConvertToCustomData() const
304 {
305     auto entry = GetValue();
306     MineCustomData customdata;
307     if (std::holds_alternative<std::vector<uint8_t>>(entry)) {
308         customdata.AddItemData(GetMimeType(), std::get<std::vector<uint8_t>>(entry));
309         return std::make_shared<MineCustomData>(customdata);
310     }
311     if (!std::holds_alternative<std::shared_ptr<Object>>(entry)) {
312         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "value error, no cust data, utdId:%{public}s", utdId_.c_str());
313         return nullptr;
314     }
315     auto object = std::get<std::shared_ptr<Object>>(entry);
316     std::string objecType;
317     if (!object->GetValue(UDMF::UNIFORM_DATA_TYPE, objecType)) {
318         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type error, utdId:%{public}s", utdId_.c_str());
319         return nullptr;
320     }
321     if (objecType != GetUtdId()) {
322         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "type diff error, utdId:%{public}s, objecType:%{public}s",
323             utdId_.c_str(), objecType.c_str());
324     }
325     std::vector<uint8_t> recordValue;
326     if (!object->GetValue(UDMF::ARRAY_BUFFER, recordValue)) {
327         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "get value error, utdId:%{public}s", utdId_.c_str());
328         return nullptr;
329     }
330     customdata.AddItemData(utdId_, recordValue);
331     return std::make_shared<MineCustomData>(customdata);
332 }
333 
HasContent(const std::string & utdId) const334 bool PasteDataEntry::HasContent(const std::string &utdId) const
335 {
336     auto mimeType = CommonUtils::Convert2MimeType(utdId);
337     if (mimeType == MIMETYPE_PIXELMAP) {
338         return ConvertToPixelMap() != nullptr;
339     } else if (mimeType == MIMETYPE_TEXT_HTML) {
340         auto html = ConvertToHtml();
341         return html != nullptr && !html->empty();
342     } else if (mimeType == MIMETYPE_TEXT_PLAIN) {
343         auto plianText = ConvertToPlianText();
344         return plianText != nullptr && !plianText->empty();
345     } else if (mimeType == MIMETYPE_TEXT_URI) {
346         auto uri = ConvertToUri();
347         return uri != nullptr && !uri->ToString().empty();
348     } else if (mimeType == MIMETYPE_TEXT_WANT) {
349         return ConvertToWant() != nullptr;
350     } else {
351         return ConvertToCustomData() != nullptr;
352     }
353 }
354 
Convert(UDType uDType)355 std::string CommonUtils::Convert(UDType uDType)
356 {
357     switch (uDType) {
358         case UDType::PLAIN_TEXT:
359         case UDType::HYPERLINK:
360             return MIMETYPE_TEXT_PLAIN;
361         case UDType::HTML:
362             return MIMETYPE_TEXT_HTML;
363         case UDType::FILE:
364         case UDType::IMAGE:
365         case UDType::VIDEO:
366         case UDType::AUDIO:
367         case UDType::FOLDER:
368         case UDType::FILE_URI:
369             return MIMETYPE_TEXT_URI;
370         case UDType::SYSTEM_DEFINED_PIXEL_MAP:
371             return MIMETYPE_PIXELMAP;
372         case UDType::OPENHARMONY_WANT:
373             return MIMETYPE_TEXT_WANT;
374         default:
375             return UDMF::UtdUtils::GetUtdIdFromUtdEnum(uDType);
376     }
377 }
378 
Convert2MimeType(const std::string & utdId)379 std::string CommonUtils::Convert2MimeType(const std::string& utdId)
380 {
381     if (utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::PLAIN_TEXT) ||
382         utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::HYPERLINK)) {
383         return MIMETYPE_TEXT_PLAIN;
384     }
385     if (utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)) {
386         return MIMETYPE_TEXT_HTML;
387     }
388     if (IsFileUri(utdId)) {
389         return MIMETYPE_TEXT_URI;
390     }
391     if (utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::SYSTEM_DEFINED_PIXEL_MAP)) {
392         return MIMETYPE_PIXELMAP;
393     }
394     if (utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::OPENHARMONY_WANT)) {
395         return MIMETYPE_TEXT_WANT;
396     }
397     return utdId;
398 }
399 
400 // other is appdefined-types
Convert2UtdId(int32_t uDType,const std::string & mimeType)401 std::string CommonUtils::Convert2UtdId(int32_t uDType, const std::string& mimeType)
402 {
403     if (mimeType == MIMETYPE_TEXT_PLAIN && uDType == UDMF::HYPERLINK) {
404         return UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::HYPERLINK);
405     }
406     if (mimeType == MIMETYPE_TEXT_PLAIN) {
407         return UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::PLAIN_TEXT);
408     }
409     if (mimeType == MIMETYPE_TEXT_URI) {
410         return UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::FILE_URI);
411     }
412     if (mimeType == MIMETYPE_TEXT_HTML) {
413         return UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML);
414     }
415     if (mimeType == MIMETYPE_TEXT_WANT) {
416         return UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::OPENHARMONY_WANT);
417     }
418     if (mimeType == MIMETYPE_PIXELMAP) {
419         return UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::SYSTEM_DEFINED_PIXEL_MAP);
420     }
421     return mimeType;
422 }
423 
Convert(int32_t uDType,const std::string & mimeType)424 UDMF::UDType CommonUtils::Convert(int32_t uDType, const std::string& mimeType)
425 {
426     if (uDType != UDMF::UD_BUTT) {
427         return static_cast<UDType>(uDType);
428     }
429     if (mimeType == MIMETYPE_TEXT_URI) {
430         return UDMF::FILE_URI;
431     }
432     if (mimeType == MIMETYPE_TEXT_PLAIN) {
433         return UDMF::PLAIN_TEXT;
434     }
435     if (mimeType == MIMETYPE_TEXT_HTML) {
436         return UDMF::HTML;
437     }
438     if (mimeType == MIMETYPE_TEXT_WANT) {
439         return UDMF::OPENHARMONY_WANT;
440     }
441     if (mimeType == MIMETYPE_PIXELMAP) {
442         return UDMF::SYSTEM_DEFINED_PIXEL_MAP;
443     }
444     auto type = UDMF::UtdUtils::GetUtdEnumFromUtdId(mimeType);
445     if (type != UDMF::UD_BUTT) {
446         return static_cast<UDType>(type);
447     }
448     return UDMF::APPLICATION_DEFINED_RECORD;
449 }
450 
IsFileUri(const std::string & utdId)451 bool CommonUtils::IsFileUri(const std::string &utdId)
452 {
453     return utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::FILE_URI) ||
454            utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::FILE) ||
455            utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::AUDIO) ||
456            utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::IMAGE) ||
457            utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::FOLDER) ||
458            utdId == UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDType::VIDEO);
459 }
460 } // namespace MiscServices
461 } // namespace OHOS