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