• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "copy_uri_handler.h"
21 #include "parcel_util.h"
22 #include "paste_uri_handler.h"
23 #include "pasteboard_error.h"
24 #include "pasteboard_hilog.h"
25 #include "pixel_map_parcel.h"
26 
27 using namespace OHOS::Media;
28 
29 namespace OHOS {
30 namespace MiscServices {
31 namespace {
32 constexpr int MAX_TEXT_LEN = 20 * 1024 * 1024;
33 }
34 
SetMimeType(std::string mimeType)35 PasteDataRecord::Builder &PasteDataRecord::Builder::SetMimeType(std::string mimeType)
36 {
37     record_->mimeType_ = std::move(mimeType);
38     return *this;
39 }
40 enum TAG_PASTEBOARD_RECORD : uint16_t {
41     TAG_MIMETYPE = TAG_BUFF + 1,
42     TAG_HTMLTEXT,
43     TAG_WANT,
44     TAG_PLAINTEXT,
45     TAG_URI,
46     TAG_PIXELMAP,
47     TAG_CUSTOM_DATA,
48     TAG_CONVERT_URI,
49     TAG_URI_PERMISSION,
50 };
51 
52 enum TAG_CUSTOMDATA : uint16_t {
53     TAG_ITEM_DATA = TAG_BUFF + 1,
54 };
55 
SetHtmlText(std::shared_ptr<std::string> htmlText)56 PasteDataRecord::Builder &PasteDataRecord::Builder::SetHtmlText(std::shared_ptr<std::string> htmlText)
57 {
58     record_->htmlText_ = std::move(htmlText);
59     return *this;
60 }
SetWant(std::shared_ptr<OHOS::AAFwk::Want> want)61 PasteDataRecord::Builder &PasteDataRecord::Builder::SetWant(std::shared_ptr<OHOS::AAFwk::Want> want)
62 {
63     record_->want_ = std::move(want);
64     return *this;
65 }
SetPlainText(std::shared_ptr<std::string> plainText)66 PasteDataRecord::Builder &PasteDataRecord::Builder::SetPlainText(std::shared_ptr<std::string> plainText)
67 {
68     record_->plainText_ = std::move(plainText);
69     return *this;
70 }
SetUri(std::shared_ptr<OHOS::Uri> uri)71 PasteDataRecord::Builder &PasteDataRecord::Builder::SetUri(std::shared_ptr<OHOS::Uri> uri)
72 {
73     record_->uri_ = std::move(uri);
74     return *this;
75 }
SetPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap)76 PasteDataRecord::Builder &PasteDataRecord::Builder::SetPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap)
77 {
78     record_->pixelMap_ = std::move(pixelMap);
79     return *this;
80 }
81 
SetCustomData(std::shared_ptr<MineCustomData> customData)82 PasteDataRecord::Builder &PasteDataRecord::Builder::SetCustomData(std::shared_ptr<MineCustomData> customData)
83 {
84     record_->customData_ = std::move(customData);
85     return *this;
86 }
87 
Build()88 std::shared_ptr<PasteDataRecord> PasteDataRecord::Builder::Build()
89 {
90     return record_;
91 }
Builder(const std::string & mimeType)92 PasteDataRecord::Builder::Builder(const std::string &mimeType)
93 {
94     record_ = std::make_shared<PasteDataRecord>();
95     if (record_ != nullptr) {
96         record_->mimeType_ = mimeType;
97         record_->htmlText_ = nullptr;
98         record_->want_ = nullptr;
99         record_->plainText_ = nullptr;
100         record_->uri_ = nullptr;
101         record_->convertUri_ = "";
102         record_->pixelMap_ = nullptr;
103         record_->customData_ = nullptr;
104     }
105 }
106 
NewHtmlRecord(const std::string & htmlText)107 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewHtmlRecord(const std::string &htmlText)
108 {
109     if (htmlText.length() >= MAX_TEXT_LEN) {
110         return nullptr;
111     }
112     return Builder(MIMETYPE_TEXT_HTML).SetHtmlText(std::make_shared<std::string>(htmlText)).Build();
113 }
114 
NewWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)115 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)
116 {
117     return Builder(MIMETYPE_TEXT_WANT).SetWant(std::move(want)).Build();
118 }
119 
NewPlaintTextRecord(const std::string & text)120 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewPlaintTextRecord(const std::string &text)
121 {
122     if (text.length() >= MAX_TEXT_LEN) {
123         return nullptr;
124     }
125     return Builder(MIMETYPE_TEXT_PLAIN).SetPlainText(std::make_shared<std::string>(text)).Build();
126 }
127 
NewPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)128 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)
129 {
130     return Builder(MIMETYPE_PIXELMAP).SetPixelMap(std::move(pixelMap)).Build();
131 }
132 
NewUriRecord(const OHOS::Uri & uri)133 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewUriRecord(const OHOS::Uri &uri)
134 {
135     return Builder(MIMETYPE_TEXT_URI).SetUri(std::make_shared<OHOS::Uri>(uri)).Build();
136 }
137 
NewKvRecord(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)138 std::shared_ptr<PasteDataRecord> PasteDataRecord::NewKvRecord(
139     const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
140 {
141     std::shared_ptr<MineCustomData> customData = std::make_shared<MineCustomData>();
142     customData->AddItemData(mimeType, arrayBuffer);
143     return Builder(mimeType).SetCustomData(std::move(customData)).Build();
144 }
145 
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)146 PasteDataRecord::PasteDataRecord(std::string mimeType, std::shared_ptr<std::string> htmlText,
147     std::shared_ptr<OHOS::AAFwk::Want> want, std::shared_ptr<std::string> plainText, std::shared_ptr<OHOS::Uri> uri)
148     : mimeType_{ std::move(mimeType) }, htmlText_{ std::move(htmlText) }, want_{ std::move(want) },
149       plainText_{ std::move(plainText) }, uri_{ std::move(uri) }
150 {
151 }
152 
PasteDataRecord()153 PasteDataRecord::PasteDataRecord()
154 {
155     fd_ = std::make_shared<FileDescriptor>();
156     InitDecodeMap();
157 }
158 
PasteDataRecord(const PasteDataRecord & record)159 PasteDataRecord::PasteDataRecord(const PasteDataRecord &record) : mimeType_(record.mimeType_),
160     htmlText_(record.htmlText_), want_(record.want_), plainText_(record.plainText_), uri_(record.uri_),
161     convertUri_(record.convertUri_), pixelMap_(record.pixelMap_), customData_(record.customData_),
162     hasGrantUriPermission_(record.hasGrantUriPermission_), fd_(record.fd_)
163 {
164     InitDecodeMap();
165 }
166 
InitDecodeMap()167 void PasteDataRecord::InitDecodeMap()
168 {
169     decodeMap = {
170         {TAG_MIMETYPE, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
171             ret = ret && ReadValue(buffer, mimeType_, head);
172             }
173         },
174         {TAG_HTMLTEXT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
175             ret = ret && ReadValue(buffer, htmlText_, head);
176             }
177         },
178         {TAG_WANT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
179             RawMem rawMem{};
180             ret = ret && ReadValue(buffer, rawMem, head);
181             want_ = ParcelUtil::Raw2Parcelable<AAFwk::Want>(rawMem);
182             }
183         },
184         {TAG_PLAINTEXT, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
185             ret = ret && ReadValue(buffer, plainText_, head);
186             }
187         },
188         {TAG_URI, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
189             RawMem rawMem{};
190             ret = ret && ReadValue(buffer, rawMem, head);
191             uri_ = ParcelUtil::Raw2Parcelable<OHOS::Uri>(rawMem);
192             }
193         },
194         {TAG_CONVERT_URI, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
195             ret = ret && ReadValue(buffer, convertUri_, head);
196             }
197         },
198         {TAG_PIXELMAP, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
199             std::vector<std::uint8_t> value;
200             ret = ret && ReadValue(buffer, value, head);
201             pixelMap_ = Vector2PixelMap(value);
202             }
203         },
204         {TAG_CUSTOM_DATA, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
205             ret = ret && ReadValue(buffer, customData_, head);
206             }
207         },
208         {TAG_URI_PERMISSION, [&](bool &ret, const std::vector<std::uint8_t> &buffer, TLVHead &head) -> void {
209             ret = ret && ReadValue(buffer, hasGrantUriPermission_, head);
210             }
211         },
212     };
213 }
214 
GetHtmlText() const215 std::shared_ptr<std::string> PasteDataRecord::GetHtmlText() const
216 {
217     return this->htmlText_;
218 }
219 
GetMimeType() const220 std::string PasteDataRecord::GetMimeType() const
221 {
222     return this->mimeType_;
223 }
224 
GetPlainText() const225 std::shared_ptr<std::string> PasteDataRecord::GetPlainText() const
226 {
227     return this->plainText_;
228 }
229 
GetPixelMap() const230 std::shared_ptr<PixelMap> PasteDataRecord::GetPixelMap() const
231 {
232     return this->pixelMap_;
233 }
234 
GetUri() const235 std::shared_ptr<OHOS::Uri> PasteDataRecord::GetUri() const
236 {
237     if (convertUri_.empty()) {
238         return uri_;
239     }
240     return std::make_shared<OHOS::Uri>(convertUri_);
241 }
242 
SetUri(std::shared_ptr<OHOS::Uri> uri)243 void PasteDataRecord::SetUri(std::shared_ptr<OHOS::Uri> uri)
244 {
245     uri_ = std::move(uri);
246 }
247 
GetOrginUri() const248 std::shared_ptr<OHOS::Uri> PasteDataRecord::GetOrginUri() const
249 {
250     return uri_;
251 }
252 
GetWant() const253 std::shared_ptr<OHOS::AAFwk::Want> PasteDataRecord::GetWant() const
254 {
255     return this->want_;
256 }
257 
GetCustomData() const258 std::shared_ptr<MineCustomData> PasteDataRecord::GetCustomData() const
259 {
260     return this->customData_;
261 }
262 
GetItemData()263 std::map<std::string, std::vector<uint8_t>> MineCustomData::GetItemData()
264 {
265     return this->itemData_;
266 }
267 
AddItemData(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)268 void MineCustomData::AddItemData(const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
269 {
270     itemData_.insert(std::make_pair(mimeType, arrayBuffer));
271     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "itemData_.size = %{public}zu", itemData_.size());
272 }
273 
ConvertToText() const274 std::string PasteDataRecord::ConvertToText() const
275 {
276     if (this->htmlText_) {
277         return *this->htmlText_;
278     } else if (this->plainText_) {
279         return *this->plainText_;
280     } else if (this->uri_) {
281         return this->uri_->ToString();
282     } else {
283         return "";
284     }
285 }
286 
Encode(std::vector<std::uint8_t> & buffer)287 bool MineCustomData::Encode(std::vector<std::uint8_t> &buffer)
288 {
289     return TLVObject::Write(buffer, TAG_ITEM_DATA, itemData_);
290 }
291 
Decode(const std::vector<std::uint8_t> & buffer)292 bool MineCustomData::Decode(const std::vector<std::uint8_t> &buffer)
293 {
294     for (; IsEnough();) {
295         TLVHead head{};
296         bool ret = ReadHead(buffer, head);
297         switch (head.tag) {
298             case TAG_ITEM_DATA:
299                 ret = ret && ReadValue(buffer, itemData_, head);
300                 break;
301             default:
302                 ret = ret && Skip(head.len, buffer.size());
303                 break;
304         }
305         if (!ret) {
306             return false;
307         }
308     }
309     return true;
310 }
311 
Count()312 size_t MineCustomData::Count()
313 {
314     return TLVObject::Count(itemData_);
315 }
316 
Encode(std::vector<std::uint8_t> & buffer)317 bool PasteDataRecord::Encode(std::vector<std::uint8_t> &buffer)
318 {
319     bool ret = Write(buffer, TAG_MIMETYPE, mimeType_);
320     ret = Write(buffer, TAG_HTMLTEXT, htmlText_) && ret;
321     ret = Write(buffer, TAG_WANT, ParcelUtil::Parcelable2Raw(want_.get())) && ret;
322     ret = Write(buffer, TAG_PLAINTEXT, plainText_) && ret;
323     ret = Write(buffer, TAG_URI, ParcelUtil::Parcelable2Raw(uri_.get())) && ret;
324     ret = Write(buffer, TAG_CONVERT_URI, convertUri_) && ret;
325     auto pixelVector = PixelMap2Vector(pixelMap_);
326     ret = Write(buffer, TAG_PIXELMAP, pixelVector) && ret;
327     ret = Write(buffer, TAG_CUSTOM_DATA, customData_) && ret;
328     ret = Write(buffer, TAG_URI_PERMISSION, hasGrantUriPermission_) && ret;
329     return ret;
330 }
331 
Decode(const std::vector<std::uint8_t> & buffer)332 bool PasteDataRecord::Decode(const std::vector<std::uint8_t> &buffer)
333 {
334     for (; IsEnough();) {
335         TLVHead head{};
336         bool ret = ReadHead(buffer, head);
337         auto it = decodeMap.find(head.tag);
338         if (it == decodeMap.end()) {
339             ret = ret && Skip(head.len, buffer.size());
340         } else {
341             auto func = it->second;
342             func(ret, buffer, head);
343         }
344         if (!ret) {
345             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u",
346                 head.tag, head.len);
347             return false;
348         }
349     }
350     return true;
351 }
Count()352 size_t PasteDataRecord::Count()
353 {
354     size_t expectedSize = 0;
355     expectedSize += TLVObject::Count(mimeType_);
356     expectedSize += TLVObject::Count(htmlText_);
357     expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(want_.get()));
358     expectedSize += TLVObject::Count(plainText_);
359     expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(uri_.get()));
360     expectedSize += TLVObject::Count(convertUri_);
361     auto pixelVector = PixelMap2Vector(pixelMap_);
362     expectedSize += TLVObject::Count(pixelVector);
363     expectedSize += TLVObject::Count(customData_);
364     expectedSize += TLVObject::Count(hasGrantUriPermission_);
365     return expectedSize;
366 }
367 
Vector2PixelMap(std::vector<std::uint8_t> & value)368 std::shared_ptr<PixelMap> PasteDataRecord::Vector2PixelMap(std::vector<std::uint8_t> &value)
369 {
370     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Vector2PixelMap, size is %{public}zu", value.size());
371     if (value.size() == 0) {
372         return nullptr;
373     }
374     return std::shared_ptr<PixelMap> (PixelMap::DecodeTlv(value));
375 }
376 
PixelMap2Vector(std::shared_ptr<PixelMap> & pixelMap)377 std::vector<std::uint8_t> PasteDataRecord::PixelMap2Vector(std::shared_ptr<PixelMap> &pixelMap)
378 {
379     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "PixelMap2Vector");
380     if (pixelMap == nullptr) {
381         return {};
382     }
383     std::vector<std::uint8_t> value;
384     if (!pixelMap->EncodeTlv(value)) {
385         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "pixelMap encode failed");
386         return {};
387     }
388     return value;
389 }
390 
WriteFd(MessageParcel & parcel,UriHandler & uriHandler,bool isClient)391 bool PasteDataRecord::WriteFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient)
392 {
393     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "isClient: %{public}d", isClient);
394     if (fd_->GetFd() >= 0) {
395         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "write fd_, fd_ is %{public}d", fd_->GetFd());
396         return parcel.WriteFileDescriptor(fd_->GetFd());
397     }
398     std::string tempUri = GetPassUri();
399     if (tempUri.empty()) {
400         return false;
401     }
402     int32_t fd = uriHandler.ToFd(tempUri, isClient);
403     bool ret = parcel.WriteFileDescriptor(fd);
404     uriHandler.ReleaseFd(fd);
405 
406     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "ret is %{public}d", ret);
407     return ret;
408 }
ReadFd(MessageParcel & parcel,UriHandler & uriHandler)409 bool PasteDataRecord::ReadFd(MessageParcel &parcel, UriHandler &uriHandler)
410 {
411     int32_t fd = parcel.ReadFileDescriptor();
412     if (fd >= 0) {
413         convertUri_ = uriHandler.ToUri(fd);
414         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "convertUri_:%{public}s", convertUri_.c_str());
415     }
416     if (!uriHandler.IsPaste()) {
417         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Set fd, fd is %{public}d", fd);
418         fd_->SetFd(fd);
419     }
420     return true;
421 }
NeedFd(const UriHandler & uriHandler)422 bool PasteDataRecord::NeedFd(const UriHandler &uriHandler)
423 {
424     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start");
425     std::string tempUri = GetPassUri();
426     if (tempUri.empty()) {
427         return false;
428     }
429     if (!uriHandler.IsFile(tempUri) && fd_->GetFd() < 0) {
430         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "invalid file uri, fd:%{public}d", fd_->GetFd());
431         return false;
432     }
433     return true;
434 }
GetPassUri()435 std::string PasteDataRecord::GetPassUri()
436 {
437     std::string tempUri;
438     if (uri_ != nullptr) {
439         tempUri = uri_->ToString();
440     }
441     if (!convertUri_.empty()) {
442         tempUri = convertUri_;
443     }
444     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "tempUri:%{public}s", tempUri.c_str());
445     return tempUri;
446 }
ReplaceShareUri(int32_t userId)447 void PasteDataRecord::ReplaceShareUri(int32_t userId)
448 {
449     if (convertUri_.empty()) {
450         return;
451     }
452 
453     // convert uri format: /mnt/hmdfs/100/account/merge_view/services/psteboard_service/.share/xxx.txt
454     constexpr const char *SHARE_PATH_PREFIX = "/mnt/hmdfs/";
455     auto frontPos = convertUri_.find(SHARE_PATH_PREFIX);
456     auto rearPos = convertUri_.find("/account/");
457     if (frontPos == 0 && rearPos != std::string::npos) {
458         convertUri_ = SHARE_PATH_PREFIX + std::to_string(userId) + convertUri_.substr(rearPos);
459         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "replace uri:%{public}s", convertUri_.c_str());
460     }
461 }
SetConvertUri(const std::string & value)462 void PasteDataRecord::SetConvertUri(const std::string &value)
463 {
464     convertUri_ = value;
465 }
GetConvertUri() const466 std::string PasteDataRecord::GetConvertUri() const
467 {
468     return convertUri_;
469 }
SetGrantUriPermission(bool hasPermission)470 void PasteDataRecord::SetGrantUriPermission(bool hasPermission)
471 {
472     hasGrantUriPermission_ = hasPermission;
473 }
HasGrantUriPermission()474 bool PasteDataRecord::HasGrantUriPermission()
475 {
476     return hasGrantUriPermission_;
477 }
~FileDescriptor()478 FileDescriptor::~FileDescriptor()
479 {
480     if (fd_ >= 0) {
481         close(fd_);
482         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "close fd_: %{public}d", fd_);
483     }
484 }
SetFd(int32_t fd)485 void FileDescriptor::SetFd(int32_t fd)
486 {
487     fd_ = fd;
488 }
GetFd() const489 int32_t FileDescriptor::GetFd() const
490 {
491     return fd_;
492 }
493 } // namespace MiscServices
494 } // namespace OHOS