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