• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 
16 #include "web_clipboard_controller.h"
17 
18 #include <regex>
19 
20 namespace {
21 const std::string IMG_TAG_PATTERN = "<img.*?data-ohos=.*?>";
22 const std::string IMG_TAG_SRC_PATTERN = "src=\"([^\"]*)\"";
23 const std::string IMG_TAG_SRC_HEAD = "src=\"";
24 const std::string IMG_LOCAL_URI = "file:///";
25 const std::string IMG_LOCAL_PATH = "://";
26 constexpr uint32_t FOUR_BYTES = 4;
27 constexpr uint32_t EIGHT_BIT = 8;
28 
29 struct Cmp {
operator ()__anon995640570111::Cmp30     bool operator()(const uint32_t& lhs, const uint32_t& rhs) const
31     {
32         return lhs > rhs;
33     }
34 };
35 } // namespace
36 
37 namespace OHOS {
38 namespace NWeb {
39 
40 // static
GetInstance()41 WebClipboardController& WebClipboardController::GetInstance()
42 {
43     static WebClipboardController instance;
44     return instance;
45 }
46 
SplitHtml(std::shared_ptr<std::string> html)47 std::shared_ptr<MiscServices::PasteData> WebClipboardController::SplitHtml(std::shared_ptr<std::string> html) noexcept
48 {
49     std::vector<std::pair<std::string, uint32_t>> matchVec = SplitHtmlWithImgLabel(html);
50     std::map<std::string, std::vector<uint8_t>> imgSrcMap = SplitHtmlWithImgSrcLabel(matchVec);
51     std::shared_ptr<MiscServices::PasteData> pasteData = BuildPasteData(html, imgSrcMap);
52     return pasteData;
53 }
54 
RebuildHtml(std::shared_ptr<MiscServices::PasteData> pasteData)55 std::shared_ptr<std::string> WebClipboardController::RebuildHtml(
56     std::shared_ptr<MiscServices::PasteData> pasteData) noexcept
57 {
58     std::vector<std::shared_ptr<MiscServices::PasteDataRecord>> pasteDataRecords = pasteData->AllRecords();
59     std::shared_ptr<std::string> htmlData;
60     std::map<uint32_t, std::pair<std::string, std::string>, Cmp> replaceUris;
61 
62     for (auto& item : pasteDataRecords) {
63         std::shared_ptr<std::string> html = item->GetHtmlText();
64         if (html) {
65             htmlData = html;
66         }
67         std::shared_ptr<OHOS::Uri> uri = item->GetUri();
68         std::shared_ptr<MiscServices::MineCustomData> customData = item->GetCustomData();
69         if (!uri || !customData) {
70             continue;
71         }
72         std::map<std::string, std::vector<uint8_t>> customItemData = customData->GetItemData();
73         for (auto& itemData : customItemData) {
74             for (uint32_t i = 0; i < itemData.second.size(); i += FOUR_BYTES) {
75                 uint32_t offset = static_cast<uint32_t>(itemData.second[i]) |
76                                   static_cast<uint32_t>(itemData.second[i + 1] << 8) |
77                                   static_cast<uint32_t>(itemData.second[i + 2] << 16) |
78                                   static_cast<uint32_t>(itemData.second[i + 3] << 24);
79                 replaceUris[offset] = std::make_pair(uri->ToString(), itemData.first);
80             }
81         }
82     }
83 
84     RemoveAllRecord(pasteData);
85     for (auto& replaceUri : replaceUris) {
86         htmlData->replace(replaceUri.first, replaceUri.second.second.size(), replaceUri.second.first);
87     }
88     pasteData->AddHtmlRecord(*htmlData);
89     return htmlData;
90 }
91 
SplitHtmlWithImgLabel(const std::shared_ptr<std::string> html)92 std::vector<std::pair<std::string, uint32_t>> WebClipboardController::SplitHtmlWithImgLabel(
93     const std::shared_ptr<std::string> html) noexcept
94 {
95     std::smatch results;
96     std::string pattern(IMG_TAG_PATTERN);
97     std::regex r(pattern);
98     std::string::const_iterator iterStart = html->begin();
99     std::string::const_iterator iterEnd = html->end();
100     std::vector<std::pair<std::string, uint32_t>> matchVec;
101 
102     while (std::regex_search(iterStart, iterEnd, results, r)) {
103         std::string tmp = results[0];
104         iterStart = results[0].second;
105         uint32_t offset = static_cast<uint32_t>(results[0].first - html->begin());
106 
107         matchVec.emplace_back(std::make_pair(tmp, offset));
108     }
109 
110     return matchVec;
111 }
112 
SplitHtmlWithImgSrcLabel(const std::vector<std::pair<std::string,uint32_t>> & matchVec)113 std::map<std::string, std::vector<uint8_t>> WebClipboardController::SplitHtmlWithImgSrcLabel(
114     const std::vector<std::pair<std::string, uint32_t>>& matchVec) noexcept
115 {
116     std::map<std::string, std::vector<uint8_t>> res;
117     std::smatch match;
118     std::regex re(IMG_TAG_SRC_PATTERN);
119     for (auto& node : matchVec) {
120         std::string::const_iterator iterStart = node.first.begin();
121         std::string::const_iterator iterEnd = node.first.end();
122 
123         while (std::regex_search(iterStart, iterEnd, match, re)) {
124             std::string tmp = match[0];
125             iterStart = match[0].second;
126             uint32_t offset = static_cast<uint32_t>(match[0].first - node.first.begin());
127             tmp = tmp.substr(IMG_TAG_SRC_HEAD.size());
128             tmp.pop_back();
129             if (!IsLocalURI(tmp)) {
130                 continue;
131             }
132             offset += IMG_TAG_SRC_HEAD.size() + node.second;
133             for (uint32_t i = 0; i < FOUR_BYTES; i++) {
134                 res[tmp].emplace_back((offset >> (EIGHT_BIT * i)) & 0xff);
135             }
136         }
137     }
138     return res;
139 }
140 
BuildPasteData(std::shared_ptr<std::string> html,const std::map<std::string,std::vector<uint8_t>> & imgSrcMap)141 std::shared_ptr<MiscServices::PasteData> WebClipboardController::BuildPasteData(
142     std::shared_ptr<std::string> html, const std::map<std::string, std::vector<uint8_t>>& imgSrcMap) noexcept
143 {
144     std::shared_ptr<MiscServices::PasteData> pasteData = std::make_shared<MiscServices::PasteData>();
145     pasteData->AddHtmlRecord(*html);
146     for (auto& item : imgSrcMap) {
147         MiscServices::PasteDataRecord::Builder builder(MiscServices::MIMETYPE_TEXT_URI);
148         auto uri = std::make_shared<OHOS::Uri>(item.first);
149         builder.SetUri(uri);
150         auto customData = std::make_shared<MiscServices::MineCustomData>();
151 
152         customData->AddItemData(item.first, item.second);
153         builder.SetCustomData(customData);
154         auto record = builder.Build();
155         pasteData->AddRecord(record);
156     }
157     return pasteData;
158 }
159 
RemoveAllRecord(std::shared_ptr<MiscServices::PasteData> pasteData)160 void WebClipboardController::RemoveAllRecord(std::shared_ptr<MiscServices::PasteData> pasteData) noexcept
161 {
162     std::size_t recordCount = pasteData->GetRecordCount();
163     for (uint32_t i = 0; i < recordCount; i++) {
164         pasteData->RemoveRecordAt(i);
165     }
166 }
167 
IsLocalURI(std::string & uri)168 bool WebClipboardController::IsLocalURI(std::string& uri) noexcept
169 {
170     return uri.substr(0, IMG_LOCAL_URI.size()) == IMG_LOCAL_URI || uri.find(IMG_LOCAL_PATH) == std::string::npos;
171 }
172 } // namespace NWeb
173 } // namespace OHOS
174