1 /*
2 * Copyright (c) 2021 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 "data_uri_utils.h"
16
17 #include <memory>
18 #include <regex>
19 #include <vector>
20
21 #include "securec.h"
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace {
26 const string EMPTY = "";
27 const std::regex INTEGER_REGEX("^[-+]?([0-9]+)([.]([0-9]+))?$");
28 const int BUFFER_LEN = 64;
29 const char *SEPARATOR = "/";
30 }; // namespace
31
32 /**
33 * @brief Default constructor of DataUriUtils class
34 * @return None
35 */
DataUriUtils()36 DataUriUtils::DataUriUtils()
37 {}
38
39 /**
40 * @brief Default deconstructor of DataUriUtils class
41 * @return None
42 */
~DataUriUtils()43 DataUriUtils::~DataUriUtils()
44 {}
45
46 /**
47 * @brief Attaches the given ID to the end of the path component of the given URI.
48 * @param dataUri based on RFC 2396( Uniform Resource Identifier ).
49 * @param id
50 * @return Uri( scheme://authority/path1/path2/path3/updateIDNumber....)
51 */
AttachId(const Uri & dataUri,long long id)52 Uri DataUriUtils::AttachId(const Uri &dataUri, long long id)
53 {
54 // 1. get Path
55 string path = const_cast<Uri &>(dataUri).GetPath();
56 if (path.empty()) {
57 return dataUri;
58 }
59
60 string uriString = dataUri.ToString();
61
62 std::vector<string> pathVector;
63 const_cast<Uri &>(dataUri).GetPathSegments(pathVector);
64 if (pathVector.empty()) {
65 return dataUri;
66 }
67 string lastPath = pathVector[pathVector.size() - 1];
68
69 char longBuffer[BUFFER_LEN] = {0};
70
71 int ret = sprintf_s(longBuffer, sizeof(longBuffer), "%lld", id);
72 if (ret == -1) {
73 return dataUri;
74 }
75 // new path string (lastPath+SEPARATOR+number)
76 string newLastPath("");
77
78 newLastPath = lastPath + string(SEPARATOR) + string(longBuffer);
79
80 // find "/+lastPath"
81 string tempLastPath = string(SEPARATOR) + lastPath;
82 auto lastPathPos = uriString.rfind(tempLastPath);
83
84 uriString.replace(lastPathPos + 1, tempLastPath.size() - 1, newLastPath.c_str());
85 return Uri(uriString);
86 }
87
88 /**
89 * @brief Obtains the ID attached to the end of the path component of the given URI.
90 * @param dataUri based on RFC 2396( Uniform Resource Identifier ).
91 * @return long ID
92 */
GetId(const Uri & dataUri)93 long long DataUriUtils::GetId(const Uri &dataUri)
94 {
95 // 1. get Path
96 string path = const_cast<Uri &>(dataUri).GetPath();
97 if (path.empty()) {
98 return -1;
99 }
100 std::vector<string> pathVector;
101 const_cast<Uri &>(dataUri).GetPathSegments(pathVector);
102 if (pathVector.empty()) {
103 return -1;
104 }
105 string lastPath = pathVector[pathVector.size() - 1];
106 if (!IsNumber(lastPath)) {
107 return -1;
108 }
109 return std::atoll(lastPath.c_str());
110 }
111
112 /**
113 * @brief Deletes the ID from the end of the path component of the given URI.
114 * @param dataUri based on RFC 2396( Uniform Resource Identifier ).
115 * @return long ID
116 */
DeleteId(const Uri & dataUri)117 Uri DataUriUtils::DeleteId(const Uri &dataUri)
118 {
119 return UriUpateLastPath(dataUri, EMPTY);
120 }
121
122 /**
123 * @brief Updates the ID in the specified dataUri
124 * @param dataUri based on RFC 2396( Uniform Resource Identifier ).
125 * @param id indiates Update attached to the end of the path component of the given URI
126 * @return Uri return is the URI after path is updated
127 */
UpdateId(const Uri & dataUri,long long id)128 Uri DataUriUtils::UpdateId(const Uri &dataUri, long long id)
129 {
130 char longBuffer[BUFFER_LEN] = {0};
131 int ret = sprintf_s(longBuffer, sizeof(longBuffer), "%lld", id);
132 if (ret == -1) {
133 return dataUri;
134 }
135
136 string newLastPath("");
137 newLastPath = string(longBuffer);
138
139 return UriUpateLastPath(dataUri, newLastPath);
140 }
141
142 /**
143 * @brief Does the end path of the path component of the given URI have an ID attached to it?
144 * @param dataUri based on RFC 2396( Uniform Resource Identifier ).
145 * @return bool
146 */
IsAttachedId(const Uri & dataUri)147 bool DataUriUtils::IsAttachedId(const Uri &dataUri)
148 {
149 // 1. get Path
150 string path = const_cast<Uri &>(dataUri).GetPath();
151 if (path.empty()) {
152 return false;
153 }
154
155 std::vector<string> pathVector;
156 const_cast<Uri &>(dataUri).GetPathSegments(pathVector);
157 if (pathVector.empty()) {
158 return false;
159 }
160 string lastPath = pathVector[pathVector.size() - 1];
161
162 return IsNumber(lastPath);
163 }
164
165 /**
166 * @brief Determine whether the string content is a numeric string
167 * @param str indicates stirng.
168 * @return bool
169 */
IsNumber(const string & str)170 bool DataUriUtils::IsNumber(const string &str)
171 {
172 return std::regex_match(str, INTEGER_REGEX);
173 }
174
175 /**
176 * @brief Determine whether the string content is a numeric string
177 * @param dataUri indicates Uri object
178 scheme://authority/path/aaa?query/#fragment
179 * @return Uri return is the URI after path is updated
180 */
UriUpateLastPath(const Uri & dataUri,const string & updateLastPath)181 Uri DataUriUtils::UriUpateLastPath(const Uri &dataUri, const string &updateLastPath)
182 {
183 std::string strUpdateLastPath;
184
185 if (updateLastPath.size() > 0) {
186 strUpdateLastPath = SEPARATOR + updateLastPath;
187 }
188
189 // 1. get Path
190 string path = const_cast<Uri &>(dataUri).GetPath();
191 if (path.empty()) {
192 return dataUri;
193 }
194
195 std::vector<string> pathVector;
196 const_cast<Uri &>(dataUri).GetPathSegments(pathVector);
197 if (pathVector.empty()) {
198 return dataUri;
199 }
200 string lastPath = pathVector[pathVector.size() - 1];
201 if (!IsNumber(lastPath)) {
202 return dataUri;
203 }
204
205 string uriString = dataUri.ToString();
206 // find "/+lastPath"
207 int lastPathPos = (int)uriString.rfind(string(SEPARATOR) + lastPath);
208 if (lastPathPos == -1) {
209 return dataUri;
210 }
211
212 // replace "/lastpath"==>""
213 uriString.replace(lastPathPos, lastPath.size() + 1, strUpdateLastPath);
214
215 return Uri(uriString);
216 }
217 } // namespace AppExecFwk
218 } // namespace OHOS
219