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