• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "uri_ext.h"
17 #include <iostream>
18 #include <vector>
19 #include <regex>
20 #include "hilog/log.h"
21 #include "string_ex.h"
22 
23 using std::string;
24 using std::regex;
25 using OHOS::HiviewDFX::HiLog;
26 
27 namespace OHOS {
28 namespace FileAccessFwk {
29 // 默认构造函数实现
Urie()30 Urie::Urie() : OHOS::Uri("")
31 {
32     cachedSsi_ = NOT_FOUND;
33     cachedFsi_ = NOT_FOUND;
34     port_ = NOT_CALCULATED;
35 }
36 
37 // 接受字符串参数的构造函数实现
Urie(const std::string & uriString)38 Urie::Urie(const std::string& uriString) : OHOS::Uri(uriString)
39 {
40     cachedSsi_ = NOT_FOUND;
41     cachedFsi_ = NOT_FOUND;
42     port_ = NOT_CALCULATED;
43 
44     if (uriString.empty()) {
45         return;
46     }
47 
48     uriString_ = uriString;
49     scheme_ = NOT_CACHED;
50     ssp_ = NOT_CACHED;
51     authority_ = NOT_CACHED;
52     host_ = NOT_CACHED;
53     userInfo_ = NOT_CACHED;
54     query_ = NOT_CACHED;
55     path_ = NOT_CACHED;
56     fragment_ = NOT_CACHED;
57 
58     if (!CheckScheme()) {
59         uriString_ = EMPTY;
60         std::cerr << "URI Scheme wrong" << std::endl;  // 简单的错误输出,可替换为合适的日志记录方式
61     }
62 }
63 
64 // 析构函数实现
~Urie()65 Urie::~Urie() {
66 }
67 
CheckScheme()68 bool Urie::CheckScheme()
69 {
70     scheme_ = ParseScheme();
71     if (scheme_.empty()) {
72         return true;
73     }
74     regex schemeRegex("[a-zA-Z][a-zA-Z|\\d|\\+|\\-|.]*$");
75     if (!regex_match(scheme_, schemeRegex)) {
76         return false;
77     }
78     return true;
79 }
80 
GetScheme()81 string Urie::GetScheme()
82 {
83     if (uriString_.empty()) {
84         return EMPTY;
85     }
86 
87     if (scheme_ == NOT_CACHED) {
88         scheme_ = ParseScheme();
89     }
90     return scheme_;
91 }
92 
ParseScheme()93 string Urie::ParseScheme()
94 {
95     size_t ssi = FindSchemeSeparator();
96     return (ssi == NOT_FOUND) ? EMPTY : uriString_.substr(0, ssi);
97 }
98 
GetSchemeSpecificPart()99 string Urie::GetSchemeSpecificPart()
100 {
101     if (uriString_.empty()) {
102         return EMPTY;
103     }
104 
105     return (ssp_ == NOT_CACHED) ? (ssp_ = ParseSsp()) : ssp_;
106 }
107 
ParseSsp()108 string Urie::ParseSsp()
109 {
110     size_t ssi = FindSchemeSeparator();
111     size_t fsi = FindFragmentSeparator();
112 
113     size_t start = (ssi == NOT_FOUND) ? 0 : (ssi + 1);
114     size_t end = (fsi == NOT_FOUND) ? uriString_.size() : fsi;
115 
116     // Return everything between ssi and fsi.
117     string ssp = EMPTY;
118     if (end > start) {
119         ssp = uriString_.substr(start, end - start);
120     }
121 
122     return ssp;
123 }
124 
GetAuthority()125 string Urie::GetAuthority()
126 {
127     if (uriString_.empty()) {
128         return EMPTY;
129     }
130 
131     if (authority_ == NOT_CACHED) {
132         authority_ = ParseAuthority();
133     }
134     return authority_;
135 }
136 
ParseAuthority()137 string Urie::ParseAuthority()
138 {
139     size_t ssi = FindSchemeSeparator();
140     if (ssi == NOT_FOUND) {
141         return EMPTY;
142     }
143 
144     size_t length = uriString_.length();
145     // If "//" follows the scheme separator, we have an authority.
146     if ((length > (ssi + POS_INC_MORE)) && (uriString_.at(ssi + POS_INC) == LEFT_SEPARATOR) &&
147         (uriString_.at(ssi + POS_INC_MORE) == LEFT_SEPARATOR)) {
148         // Look for the start of the path, query, or fragment, or the end of the string.
149         size_t start = ssi + POS_INC_AGAIN;
150         size_t end = start;
151 
152         while (end < length) {
153             char ch = uriString_.at(end);
154             if ((ch == LEFT_SEPARATOR) || (ch == RIGHT_SEPARATOR) || (ch == QUERY_FLAG) ||
155                 (ch == SCHEME_FRAGMENT)) {
156                 break;
157             }
158 
159             end++;
160         }
161 
162         return uriString_.substr(start, end - start);
163     } else {
164         return EMPTY;
165     }
166 }
167 
GetUserInfo()168 string Urie::GetUserInfo()
169 {
170     if (uriString_.empty()) {
171         return EMPTY;
172     }
173 
174     if (userInfo_ == NOT_CACHED) {
175         userInfo_ = ParseUserInfo();
176     }
177     return userInfo_;
178 }
179 
ParseUserInfo()180 string Urie::ParseUserInfo()
181 {
182     string authority = GetAuthority();
183     if (authority.empty()) {
184         return EMPTY;
185     }
186 
187     size_t end = authority.find_last_of(USER_HOST_SEPARATOR);
188     return (end == NOT_FOUND) ? EMPTY : authority.substr(0, end);
189 }
190 
GetHost()191 string Urie::GetHost()
192 {
193     if (uriString_.empty()) {
194         return EMPTY;
195     }
196 
197     if (host_ == NOT_CACHED) {
198         host_ = ParseHost();
199     }
200     return host_;
201 }
202 
ParseHost()203 string Urie::ParseHost()
204 {
205     string authority = GetAuthority();
206     if (authority.empty()) {
207         return EMPTY;
208     }
209 
210     // Parse out user info and then port.
211     size_t userInfoSeparator = authority.find_last_of(USER_HOST_SEPARATOR);
212     size_t start = (userInfoSeparator == NOT_FOUND) ? 0 : (userInfoSeparator + 1);
213     size_t portSeparator = authority.find_first_of(PORT_SEPARATOR, start);
214     size_t end = (portSeparator == NOT_FOUND) ? authority.size() : portSeparator;
215 
216     string host = EMPTY;
217     if (start < end) {
218         host = authority.substr(start, end - start);
219     }
220 
221     return host;
222 }
223 
GetPort()224 int Urie::GetPort()
225 {
226     if (uriString_.empty()) {
227         return PORT_NONE;
228     }
229 
230     if (port_ == NOT_CALCULATED) {
231         port_ = ParsePort();
232     }
233     return port_;
234 }
235 
ParsePort()236 int Urie::ParsePort()
237 {
238     string authority = GetAuthority();
239     if (authority.empty()) {
240         return PORT_NONE;
241     }
242 
243     // Make sure we look for the port separtor *after* the user info separator.
244     size_t userInfoSeparator = authority.find_last_of(USER_HOST_SEPARATOR);
245     size_t start = (userInfoSeparator == NOT_FOUND) ? 0 : (userInfoSeparator + 1);
246     size_t portSeparator = authority.find_first_of(PORT_SEPARATOR, start);
247     if (portSeparator == NOT_FOUND) {
248         return PORT_NONE;
249     }
250 
251     start = portSeparator + 1;
252     string portString = authority.substr(start);
253 
254     int value = PORT_NONE;
255     return StrToInt(portString, value) ? value : PORT_NONE;
256 }
257 
GetQuery()258 string Urie::GetQuery()
259 {
260     if (uriString_.empty()) {
261         return EMPTY;
262     }
263 
264     if (query_ == NOT_CACHED) {
265         query_ = ParseQuery();
266     }
267     return query_;
268 }
269 
ParseQuery()270 string Urie::ParseQuery()
271 {
272     size_t ssi = FindSchemeSeparator();
273     if (ssi == NOT_FOUND) {
274         ssi = 0;
275     }
276     size_t qsi = uriString_.find_first_of(QUERY_FLAG, ssi);
277     if (qsi == NOT_FOUND) {
278         return EMPTY;
279     }
280 
281     size_t start = qsi + 1;
282     size_t fsi = FindFragmentSeparator();
283     if (fsi == NOT_FOUND) {
284         return uriString_.substr(start);
285     }
286 
287     if (fsi < qsi) {
288         // Invalid.
289         return EMPTY;
290     }
291 
292     return uriString_.substr(start, fsi - start);
293 }
294 
GetPath()295 string Urie::GetPath()
296 {
297     if (uriString_.empty()) {
298         return EMPTY;
299     }
300 
301     if (path_ == NOT_CACHED) {
302         path_ = ParsePath();
303     }
304     return path_;
305 }
306 
GetPathSegments(std::vector<std::string> & segments)307 void Urie::GetPathSegments(std::vector<std::string>& segments)
308 {
309     if (uriString_.empty()) {
310         return;
311     }
312     if (path_ == NOT_CACHED) {
313         path_ = ParsePath();
314     }
315 
316     size_t previous = 0;
317     size_t current;
318     while ((current = path_.find(LEFT_SEPARATOR, previous)) != std::string::npos) {
319         if (previous < current) {
320             segments.emplace_back(path_.substr(previous, current - previous));
321         }
322         previous = current + POS_INC;
323     }
324     // Add in the final path segment.
325     if (previous < path_.length()) {
326         segments.emplace_back(path_.substr(previous));
327     }
328 }
329 
ParsePath()330 string Urie::ParsePath()
331 {
332     size_t ssi = FindSchemeSeparator();
333     // If the URI is absolute.
334     if (ssi != NOT_FOUND) {
335         // Is there anything after the ':'?
336         if ((ssi + 1) == uriString_.length()) {
337             // Opaque URI.
338             return EMPTY;
339         }
340 
341         // A '/' after the ':' means this is hierarchical.
342         if (uriString_.at(ssi + 1) != LEFT_SEPARATOR) {
343             // Opaque URI.
344             return EMPTY;
345         }
346     } else {
347         // All relative URIs are hierarchical.
348     }
349 
350     return ParsePath(ssi);
351 }
352 
ParsePath(size_t ssi)353 string Urie::ParsePath(size_t ssi)
354 {
355     size_t length = uriString_.length();
356 
357     // Find start of path.
358     size_t pathStart = (ssi == NOT_FOUND) ? 0 : (ssi + POS_INC);
359     if ((length > (pathStart + POS_INC)) && (uriString_.at(pathStart) == LEFT_SEPARATOR) &&
360         (uriString_.at(pathStart + POS_INC) == LEFT_SEPARATOR)) {
361         // Skip over authority to path.
362         pathStart += POS_INC_MORE;
363 
364         while (pathStart < length) {
365             char ch = uriString_.at(pathStart);
366             if ((ch == QUERY_FLAG) || (ch == SCHEME_FRAGMENT)) {
367                 return EMPTY;
368             }
369 
370             if ((ch == LEFT_SEPARATOR) || (ch == RIGHT_SEPARATOR)) {
371                 break;
372             }
373 
374             pathStart++;
375         }
376     }
377 
378     // Find end of path.
379     size_t pathEnd = pathStart;
380     while (pathEnd < length) {
381         char ch = uriString_.at(pathEnd);
382         if ((ch == QUERY_FLAG) || (ch == SCHEME_FRAGMENT)) {
383             break;
384         }
385 
386         pathEnd++;
387     }
388 
389     return uriString_.substr(pathStart, pathEnd - pathStart);
390 }
391 
GetFragment()392 string Urie::GetFragment()
393 {
394     if (uriString_.empty()) {
395         return EMPTY;
396     }
397 
398     if (fragment_ == NOT_CACHED) {
399         fragment_ = ParseFragment();
400     }
401     return fragment_;
402 }
403 
ParseFragment()404 string Urie::ParseFragment()
405 {
406     size_t fsi = FindFragmentSeparator();
407     return (fsi == NOT_FOUND) ? EMPTY : uriString_.substr(fsi + 1);
408 }
409 
FindSchemeSeparator()410 size_t Urie::FindSchemeSeparator()
411 {
412     if (cachedSsi_ == NOT_FOUND) {
413         cachedSsi_ = uriString_.find_first_of(SCHEME_SEPARATOR);
414     }
415     return cachedSsi_;
416 }
417 
FindFragmentSeparator()418 size_t Urie::FindFragmentSeparator()
419 {
420     if (cachedFsi_ == NOT_FOUND) {
421         cachedFsi_ = uriString_.find_first_of(SCHEME_FRAGMENT, FindSchemeSeparator());
422     }
423     return cachedFsi_;
424 }
425 
IsHierarchical()426 bool Urie::IsHierarchical()
427 {
428     if (uriString_.empty()) {
429         return false;
430     }
431 
432     size_t ssi = FindSchemeSeparator();
433     if (ssi == NOT_FOUND) {
434         // All relative URIs are hierarchical.
435         return true;
436     }
437 
438     if (uriString_.length() == (ssi + 1)) {
439         // No ssp.
440         return false;
441     }
442 
443     // If the ssp starts with a '/', this is hierarchical.
444     return (uriString_.at(ssi + 1) == LEFT_SEPARATOR);
445 }
446 
IsAbsolute()447 bool Urie::IsAbsolute()
448 {
449     if (uriString_.empty()) {
450         return false;
451     }
452 
453     return !IsRelative();
454 }
455 
IsRelative()456 bool Urie::IsRelative()
457 {
458     if (uriString_.empty()) {
459         return false;
460     }
461 
462     // Note: We return true if the index is 0
463     return FindSchemeSeparator() == NOT_FOUND;
464 }
465 
Equals(const Urie & other) const466 bool Urie::Equals(const Urie& other) const
467 {
468     return uriString_ == other.ToString();
469 }
470 
CompareTo(const Urie & other) const471 int Urie::CompareTo(const Urie& other) const
472 {
473     return uriString_.compare(other.ToString());
474 }
475 
ToString() const476 string Urie::ToString() const
477 {
478     return uriString_;
479 }
480 
operator ==(const Urie & other) const481 bool Urie::operator==(const Urie& other) const
482 {
483     return uriString_ == other.ToString();
484 }
485 
Marshalling(Parcel & parcel) const486 bool Urie::Marshalling(Parcel& parcel) const
487 {
488     if (IsAsciiString(uriString_)) {
489         return parcel.WriteString16(Str8ToStr16(uriString_));
490     }
491 
492     HILOG_IMPL(LOG_CORE, LOG_ERROR, 0xD001305,  "URIe", "uriString_ is not ascii string");
493     return false;
494 }
495 
Unmarshalling(Parcel & parcel)496 Urie* Urie::Unmarshalling(Parcel& parcel)
497 {
498     return new Urie(Str16ToStr8(parcel.ReadString16()));
499 }
500 }
501 }