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 #define LOG_TAG "URIUtils"
16
17 #include "uri_utils.h"
18
19 #include <string>
20
21 #include "log_print.h"
22 #include "string_ex.h"
23 #include "uri.h"
24 #include "utils/anonymous.h"
25
26 namespace OHOS::DataShare {
GetInfoFromURI(const std::string & uri,UriInfo & uriInfo)27 bool URIUtils::GetInfoFromURI(const std::string &uri, UriInfo &uriInfo)
28 {
29 Uri uriTemp(uri);
30 std::vector<std::string> splitUri;
31 SplitStr(uriTemp.GetPath(), "/", splitUri);
32 if (splitUri.size() < PARAM_SIZE) {
33 return false;
34 }
35
36 if (splitUri[BUNDLE_NAME].empty() || splitUri[MODULE_NAME].empty() ||
37 splitUri[STORE_NAME].empty() || splitUri[TABLE_NAME].empty()) {
38 ZLOGE("Uri has empty field! bundleName: %{public}s uri: %{public}s", splitUri[BUNDLE_NAME].c_str(),
39 DistributedData::Anonymous::Change(uri).c_str());
40 return false;
41 }
42
43 uriInfo.bundleName = splitUri[BUNDLE_NAME];
44 uriInfo.moduleName = splitUri[MODULE_NAME];
45 uriInfo.storeName = splitUri[STORE_NAME];
46 uriInfo.tableName = splitUri[TABLE_NAME];
47 return true;
48 }
49
IsDataProxyURI(const std::string & uri)50 bool URIUtils::IsDataProxyURI(const std::string &uri)
51 {
52 return uri.compare(0, DATA_PROXY_SCHEMA_LEN, URIUtils::DATA_PROXY_SCHEMA) == 0;
53 }
54
GetBundleNameFromProxyURI(const std::string & uri,std::string & bundleName)55 bool URIUtils::GetBundleNameFromProxyURI(const std::string &uri, std::string &bundleName)
56 {
57 Uri uriTemp(uri);
58 if (!uriTemp.GetAuthority().empty()) {
59 bundleName = uriTemp.GetAuthority();
60 }
61 return true;
62 }
63
GetAppIndexFromProxyURI(const std::string & uri,int32_t & appIndex)64 bool URIUtils::GetAppIndexFromProxyURI(const std::string &uri, int32_t &appIndex)
65 {
66 auto queryParams = URIUtils::GetQueryParams(uri);
67 if (!queryParams[APP_INDEX].empty()) {
68 auto [success, data] = URIUtils::Strtoul(queryParams[APP_INDEX]);
69 if (!success) {
70 appIndex = -1;
71 ZLOGE("appIndex is invalid! appIndex: %{public}s", queryParams[APP_INDEX].c_str());
72 return false;
73 }
74 appIndex = static_cast<int32_t>(data);
75 }
76 return true;
77 }
78
GetUserFromProxyURI(const std::string & uri)79 std::pair<bool, int32_t> URIUtils::GetUserFromProxyURI(const std::string &uri)
80 {
81 auto queryParams = URIUtils::GetQueryParams(uri);
82 if (queryParams[USER_PARAM].empty()) {
83 // -1 is placeholder for visit provider's user
84 return std::make_pair(true, -1);
85 }
86 auto [success, data] = URIUtils::Strtoul(queryParams[USER_PARAM]);
87 if (!success) {
88 return std::make_pair(false, -1);
89 }
90 if (data < 0 || data > INT32_MAX) {
91 return std::make_pair(false, -1);
92 }
93 return std::make_pair(true, data);
94 }
95
FormatUri(std::string & uri)96 void URIUtils::FormatUri(std::string &uri)
97 {
98 auto pos = uri.find_last_of('?');
99 if (pos == std::string::npos) {
100 return;
101 }
102
103 uri.resize(pos);
104 }
105
FormatConstUri(const std::string & uri)106 std::string URIUtils::FormatConstUri(const std::string &uri)
107 {
108 auto pos = uri.find_last_of('?');
109 if (pos == std::string::npos) {
110 return uri;
111 }
112
113 return uri.substr(0, pos);
114 }
115
GetUriConfig(const std::string & uri)116 __attribute__((no_sanitize("cfi"))) UriConfig URIUtils::GetUriConfig(const std::string &uri)
117 {
118 UriConfig uriConfig;
119 Uri uriTemp(uri);
120 uriConfig.authority = uriTemp.GetAuthority();
121 uriConfig.path = uriTemp.GetPath();
122 uriTemp.GetPathSegments(uriConfig.pathSegments);
123 uriConfig.scheme = uriTemp.GetScheme();
124 std::string convertUri = DATA_PROXY_SCHEMA + uriConfig.authority + uriConfig.path;
125 size_t schemePos = convertUri.find(PARAM_URI_SEPARATOR);
126 if (schemePos != std::string::npos) {
127 convertUri.replace(schemePos, PARAM_URI_SEPARATOR_LEN, SCHEME_SEPARATOR);
128 }
129 uriConfig.formatUri = convertUri;
130 return uriConfig;
131 }
132
Anonymous(const std::string & uri)133 std::string URIUtils::Anonymous(const std::string &uri)
134 {
135 if (uri.length() <= END_LENGTH) {
136 return DEFAULT_ANONYMOUS;
137 }
138
139 return (DEFAULT_ANONYMOUS + uri.substr(uri.length() - END_LENGTH, END_LENGTH));
140 }
141
Strtoul(const std::string & str)142 std::pair<bool, uint32_t> URIUtils::Strtoul(const std::string &str)
143 {
144 unsigned long data = 0;
145 if (str.empty()) {
146 return std::make_pair(false, data);
147 }
148 char* end = nullptr;
149 errno = 0;
150 data = strtoul(str.c_str(), &end, 10);
151 if (errno == ERANGE || end == nullptr || end == str || *end != '\0') {
152 return std::make_pair(false, data);
153 }
154 return std::make_pair(true, data);
155 }
156
GetQueryParams(const std::string & uri)157 std::map<std::string, std::string> URIUtils::GetQueryParams(const std::string& uri)
158 {
159 size_t queryStartPos = uri.find('?');
160 if (queryStartPos == std::string::npos) {
161 return {};
162 }
163 std::map<std::string, std::string> params;
164 std::string queryParams = uri.substr(queryStartPos + 1);
165 size_t startPos = 0;
166 while (startPos < queryParams.size()) {
167 size_t delimiterIndex = queryParams.find('&', startPos);
168 if (delimiterIndex == std::string::npos) {
169 delimiterIndex = queryParams.size();
170 }
171 size_t equalIndex = queryParams.find('=', startPos);
172 if (equalIndex == std::string::npos || equalIndex > delimiterIndex) {
173 startPos = delimiterIndex + 1;
174 continue;
175 }
176 std::string key = queryParams.substr(startPos, equalIndex - startPos);
177 std::string value = queryParams.substr(equalIndex + 1, delimiterIndex - equalIndex - 1);
178 params[key] = value;
179 startPos = delimiterIndex + 1;
180 }
181 return params;
182 }
183 } // namespace OHOS::DataShare