• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "js_uri.h"
17 namespace OHOS::Uri {
18     std::bitset<MAX_BIT_SIZE> g_ruleAlpha;
19     std::bitset<MAX_BIT_SIZE> g_ruleScheme;
20     std::bitset<MAX_BIT_SIZE> g_ruleUrlc;
21     std::bitset<MAX_BIT_SIZE> g_rulePath;
22     std::bitset<MAX_BIT_SIZE> g_ruleUserInfo;
23     std::bitset<MAX_BIT_SIZE> g_ruleDigit;
24     std::bitset<MAX_BIT_SIZE> g_rulePort;
PreliminaryWork() const25     void Uri::PreliminaryWork() const
26     {
27         std::string digitAggregate = "0123456789";
28         for (size_t i = 0; i < digitAggregate.size(); ++i) {
29             g_ruleDigit.set(digitAggregate[i]);
30         }
31 
32         std::string alphasAggregate = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
33         for (size_t i = 0; i < alphasAggregate.size(); ++i) {
34             g_ruleAlpha.set(alphasAggregate[i]);
35         }
36 
37         std::string schemeAggregate = digitAggregate + alphasAggregate + "+-.| _-~!$&=,;'(){}*";
38         for (size_t i = 0; i < schemeAggregate.size(); ++i) {
39             g_ruleScheme.set(schemeAggregate[i]);
40         }
41 
42         std::string uricAggregate = schemeAggregate + ";/?:@&=$,[]_!~*'()%\"";
43         for (size_t i = 0; i < uricAggregate.size(); ++i) {
44             g_ruleUrlc.set(uricAggregate[i]);
45         }
46 
47         std::string pathAggregate = schemeAggregate + ";/:@&=$,_!~*'()%";
48         for (size_t i = 0; i < pathAggregate.size(); ++i) {
49             g_rulePath.set(pathAggregate[i]);
50         }
51 
52         std::string userInfoAggregate = schemeAggregate + ";:&=$,_!~*'()%";
53         for (size_t i = 0; i < userInfoAggregate.size(); ++i) {
54             g_ruleUserInfo.set(userInfoAggregate[i]);
55         }
56 
57         std::string portAggregate = digitAggregate + alphasAggregate + ".:@-;&=+$,-_!~*'()";
58         for (size_t i = 0; i < portAggregate.size(); ++i) {
59             g_rulePort.set(portAggregate[i]);
60         }
61     }
62 
Uri(const std::string input)63     Uri::Uri(const std::string input)
64     {
65         PreliminaryWork();
66         errStr_ = "";
67         if (input.empty()) {
68             errStr_ = "uri is empty";
69             return;
70         }
71         inputUri_ = input;
72         AnalysisUri();
73     }
74 
AssignSchemeSpecificPart()75     void Uri::AssignSchemeSpecificPart()
76     {
77         uriData_.SchemeSpecificPart.reserve(data_.length() + uriData_.query.length() + 1);
78         uriData_.SchemeSpecificPart.append(data_);
79         if (!uriData_.query.empty()) {
80             uriData_.SchemeSpecificPart.append("?");
81             uriData_.SchemeSpecificPart.append(uriData_.query);
82         }
83     }
84 
AnalysisUri()85     void Uri::AnalysisUri()
86     {
87         data_ = inputUri_;
88         size_t pos = data_.find('#'); // Fragment
89         if (pos != std::string::npos) {
90             AnalysisFragment(pos);
91             if (!errStr_.empty()) {
92                 return;
93             }
94         }
95         pos = data_.find('?'); // Query
96         if (pos != std::string::npos) {
97             AnalysisQuery(pos);
98             if (!errStr_.empty()) {
99                 return;
100             }
101         }
102         pos = data_.find(':'); // Scheme
103         if (pos != std::string::npos) {
104             AnalysisScheme(pos);
105             if (!errStr_.empty()) {
106                 return;
107             }
108         } else {
109             SpecialPath();
110             if (!errStr_.empty()) {
111                 return;
112             }
113             AssignSchemeSpecificPart();
114             return;
115         }
116         pos = data_.find("//"); // userInfo path host port ipv4 or ipv6
117         if (pos != std::string::npos && pos == 0) {
118             AssignSchemeSpecificPart();
119             data_ = data_.substr(2); // 2:Intercept the string from the second subscript
120             AnalysisHostAndPath();
121             if (!errStr_.empty()) {
122                 return;
123             }
124         } else if (data_[0] == '/') {
125             uriData_.path = data_;
126             AssignSchemeSpecificPart();
127             data_ = "";
128         } else {
129             AssignSchemeSpecificPart();
130             uriData_.query = "";
131             data_ = "";
132         }
133     }
134 
CheckCharacter(std::string data,std::bitset<MAX_BIT_SIZE> rule,bool flag) const135     bool Uri::CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule, bool flag) const
136     {
137         size_t dataLen = data.size();
138         for (size_t i = 0; i < dataLen; ++i) {
139             if (static_cast<int>(data[i]) >= 0 && static_cast<int>(data[i]) < 128) { // 128:ASCII Max Number
140                 bool isLegal = rule.test(data[i]);
141                 if (!isLegal) {
142                     return false;
143                 }
144             } else if (!flag) {
145                 return false;
146             }
147         }
148         return true;
149     }
150 
SpecialPath()151     void Uri::SpecialPath()
152     {
153         if (!CheckCharacter(data_, g_rulePath, true)) {
154             errStr_ = "SpecialPath does not conform to the rule";
155             return;
156         }
157         uriData_.path = data_;
158         data_ = "";
159     }
160 
AnalysisFragment(size_t pos)161     void Uri::AnalysisFragment(size_t pos)
162     {
163         if (pos == 0) {
164             errStr_ = "#It can't be the first";
165             return;
166         }
167         std::string fragment = data_.substr(pos + 1);
168         if (!CheckCharacter(fragment, g_ruleUrlc, true)) {
169             errStr_ = "Fragment does not conform to the rule";
170             return;
171         }
172         uriData_.fragment = fragment;
173         data_ = data_.substr(0, pos);
174     }
175 
AnalysisQuery(size_t pos)176     void Uri::AnalysisQuery(size_t pos)
177     {
178         std::string query = data_.substr(pos + 1);
179         if (!CheckCharacter(query, g_ruleUrlc, true)) {
180             errStr_ = "Query does not conform to the rule";
181             return;
182         }
183         uriData_.query = query;
184         data_ = data_.substr(0, pos);
185     }
186 
AnalysisScheme(size_t pos)187     void Uri::AnalysisScheme(size_t pos)
188     {
189         size_t slashPos = data_.find('/');
190         if (slashPos != std::string::npos && slashPos < pos) {
191             SpecialPath();
192             uriData_.SchemeSpecificPart.reserve(uriData_.path.length() + uriData_.query.length() + 1);
193             uriData_.SchemeSpecificPart.append(uriData_.path);
194             uriData_.SchemeSpecificPart.append("?");
195             uriData_.SchemeSpecificPart.append(uriData_.query);
196             data_ = "";
197         } else {
198             if ((static_cast<int>(data_[0]) >= 0 && static_cast<int>(data_[0]) < MAX_BIT_SIZE) &&
199                 !g_ruleAlpha.test(data_[0])) {
200                 errStr_ = "Scheme the first character must be a letter";
201                 return;
202             }
203             std::string scheme = data_.substr(0, pos);
204             if (!CheckCharacter(scheme, g_ruleScheme, false)) {
205                 errStr_ = "scheme does not conform to the rule";
206                 return;
207             }
208             uriData_.scheme = scheme;
209             data_ = data_.substr(pos + 1);
210         }
211     }
212 
AnalysisHost(bool isLawfulProt)213     void Uri::AnalysisHost(bool isLawfulProt)
214     {
215         // find ipv4 or ipv6 or host
216         if (data_[0] == '[') {
217             if (data_[data_.size() - 1] == ']') {
218                 // IPV6
219                 if (!isLawfulProt) {
220                     errStr_ = "Prot does not conform to the rule";
221                     return;
222                 }
223                 AnalysisIPV6();
224             } else {
225                 errStr_ = "IPv6 is missing a closing bracket";
226                 return;
227             }
228         } else {
229             if (data_.find('[') != std::string::npos || data_.find(']') != std::string::npos) {
230                 errStr_ = "host does not conform to the rule";
231                 return;
232             }
233             // ipv4
234             if (!isLawfulProt || !AnalysisIPV4()) {
235                 uriData_.port = -1;
236                 uriData_.host = "";
237                 uriData_.userInfo = "";
238             }
239         }
240     }
241 
AnalysisHostAndPath()242     void Uri::AnalysisHostAndPath()
243     {
244         if (data_.empty()) {
245             return;
246         }
247         // find path
248         size_t pos = data_.find('/');
249         if (pos != std::string::npos) {
250             AnalysisPath(pos);
251             if (!errStr_.empty()) {
252                 return;
253             }
254         }
255         uriData_.authority = data_;
256         // find UserInfo
257         pos = data_.find('@');
258         if (pos != std::string::npos) {
259             AnalysisUserInfo(pos);
260             if (!errStr_.empty()) {
261                 return;
262             }
263         }
264         bool isLawfulProt = true;
265         // find port
266         pos = data_.rfind(':');
267         if (pos != std::string::npos) {
268             size_t pos1 = data_.rfind(']');
269             if (pos1 == std::string::npos || pos > pos1) {
270                 isLawfulProt = AnalysisPort(pos);
271             }
272             if (!errStr_.empty()) {
273             return;
274             }
275         }
276         AnalysisHost(isLawfulProt);
277     }
278 
AnalysisPath(size_t pos)279     void Uri::AnalysisPath(size_t pos)
280     {
281         std::string path = data_.substr(pos);
282         if (!CheckCharacter(path, g_rulePath, true)) {
283             errStr_ = "path does not conform to the rule";
284             return;
285         }
286         uriData_.path = path;
287         data_ = data_.substr(0, pos);
288     }
289 
AnalysisUserInfo(size_t pos)290     void Uri::AnalysisUserInfo(size_t pos)
291     {
292         std::string userInfo = data_.substr(0, pos);
293         if (!CheckCharacter(userInfo, g_ruleUserInfo, true)) {
294             errStr_ = "userInfo does not conform to the rule";
295             return;
296         }
297         uriData_.userInfo = userInfo;
298         data_ = data_.substr(pos + 1);
299     }
300 
AnalysisPort(size_t pos)301     bool Uri::AnalysisPort(size_t pos)
302     {
303         std::string port = data_.substr(pos + 1);
304         if (!CheckCharacter(port, g_rulePort, true)) {
305             errStr_ = "port does not conform to the rule";
306             return false;
307         } else if (CheckCharacter(port, g_ruleDigit, false)) {
308             if (port.size() == 0 || port.size() > 10) { // 10:The maximum number of bits for int value
309                 return false;
310             }
311             double tempPort = std::strtod(port.c_str(), nullptr);
312             if (tempPort < 0 || tempPort > INT32_MAX) {
313                 return false;
314             }
315             uriData_.port = static_cast<int>(tempPort);
316             data_ = data_.substr(0, pos);
317             return true;
318         } else {
319             data_ = data_.substr(0, pos);
320             return false;
321         }
322         return false;
323     }
324 
AnalysisIPV4()325     bool Uri::AnalysisIPV4()
326     {
327         std::regex ipv4("((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)");
328         std::regex hostname("(([a-zA-Z0-9]([a-zA-Z0-9\\-~_|\\+{}!$&=,;:'()\\*\\s]*[a-zA-Z0-9])?\\.)+"
329                            "([a-zA-Z]([a-zA-Z0-9\\-~_|\\+{}!$&=,;:'()\\*\\s]*"
330                            "[a-zA-Z0-9\\-~_|\\+{}!$&=,;:'()\\*\\s])?))|"
331                            "([a-zA-Z0-9]([a-zA-Z0-9\\-~_|\\+{}!$&=,;:'()\\*\\s]*[a-zA-Z0-9])?)");
332         bool isIpv4 = std::regex_match(data_, ipv4);
333         bool isHosName = std::regex_match(data_, hostname);
334         if (!isIpv4 && !isHosName) {
335             return false;
336         } else {
337             uriData_.host = data_;
338             data_ = "";
339             return true;
340         }
341     }
342 
AnalysisIPV6()343     void Uri::AnalysisIPV6()
344     {
345         std::string str = data_.substr(1, data_.size() - 2); // 2:Intercept the string from the second subscript
346         std::regex ipv6("(::|(:((:[0-9A-Fa-f]{1,4}){1,7}))|(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|"
347                         "(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(([0-9A-Fa-f]{1,4}:){2}"
348                         "(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})"
349                         "|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){5}"
350                         "(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|"
351                         "(((:(:[0-9A-Fa-f]{1,4}){0,5}:)|(([0-9A-Fa-f]{1,4}:){1}(:[0-9A-Fa-f]{1,4}){0,4}:)"
352                         "|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:)|(([0-9A-Fa-f]{1,4}:){3}"
353                         "(:[0-9A-Fa-f]{1,4}){0,2}:)|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4})?:)|"
354                         "(([0-9A-Fa-f]{1,4}:){5}:)|(([0-9A-Fa-f]{1,4}:){6}))((25[0-5]|2[0-4]\\d|1\\d{2}|"
355                         "[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)))(%[a-zA-Z0-9._]+)?");
356         if (!std::regex_match(str, ipv6)) {
357             errStr_ = "ipv6 does not conform to the rule";
358             return;
359         }
360         uriData_.host = data_;
361         data_ = "";
362     }
363 
Equals(const Uri other) const364     bool Uri::Equals(const Uri other) const
365     {
366         if (uriData_.port != other.uriData_.port) {
367             return false;
368         }
369         if (uriData_.scheme != other.uriData_.scheme) {
370             return false;
371         }
372         if (uriData_.userInfo != other.uriData_.userInfo) {
373             return false;
374         }
375         if (uriData_.host != other.uriData_.host) {
376             return false;
377         }
378         if (uriData_.query != other.uriData_.query) {
379             return false;
380         }
381         if (uriData_.fragment != other.uriData_.fragment) {
382             return false;
383         }
384         if (uriData_.path != other.uriData_.path) {
385             return false;
386         }
387         if (uriData_.authority != other.uriData_.authority) {
388             return false;
389         }
390         if (uriData_.SchemeSpecificPart != other.uriData_.SchemeSpecificPart) {
391             return false;
392         }
393         return true;
394     }
395 
ToString() const396     std::string Uri::ToString() const
397     {
398         return inputUri_;
399     }
400 
IsAbsolute() const401     bool Uri::IsAbsolute() const
402     {
403         return !uriData_.scheme.empty();
404     }
405 
IsRelative() const406     bool Uri::IsRelative() const
407     {
408         return uriData_.scheme.empty();
409     }
410 
IsOpaque() const411     bool Uri::IsOpaque() const
412     {
413         return !IsHierarchical();
414     }
415 
IsHierarchical() const416     bool Uri::IsHierarchical() const
417     {
418         size_t index = inputUri_.find(':');
419         if (index == std::string::npos) {
420             return true;
421         }
422         if (inputUri_.length() == index + 1) {
423             return false;
424         }
425         return inputUri_[index + 1] == '/';
426     }
427 
AddQueryValue(const std::string key,const std::string value) const428     std::string Uri::AddQueryValue(const std::string key, const std::string value) const
429     {
430         return BuildUriString("query", key + "=" + value);
431     }
432 
AddSegment(const std::string pathSegment) const433     std::string Uri::AddSegment(const std::string pathSegment) const
434     {
435         return BuildUriString("segment", pathSegment);
436     }
437 
BuildUriString(const std::string str,const std::string param) const438     std::string Uri::BuildUriString(const std::string str, const std::string param) const
439     {
440         std::string result = "";
441         if (!uriData_.scheme.empty()) {
442             result += uriData_.scheme + ":";
443         }
444         if (!uriData_.authority.empty()) {
445             result += "//" + uriData_.authority;
446         }
447         if (!uriData_.path.empty()) {
448             result += uriData_.path ;
449         }
450         if (str == "segment") {
451             if (result.back() == '/') {
452                 result += param;
453             } else {
454                 result += "/" + param;
455             }
456         }
457         if (str != "clearquery") {
458             if (uriData_.query.empty()) {
459                 if (str == "query") {
460                     result +=  "?" + param;
461                 }
462             } else {
463                 result +=  "?" + uriData_.query;
464                 if (str == "query") {
465                     result +=  "&" + param;
466                 }
467             }
468         }
469         if (!uriData_.fragment.empty()) {
470             result +=  "#" + uriData_.fragment;
471         }
472         return result;
473     }
474 
GetLastSegment() const475     std::string Uri::GetLastSegment() const
476     {
477         std::string trimmedPath = uriData_.path;
478         if (trimmedPath.empty()) {
479             return trimmedPath;
480         }
481         if (trimmedPath.back() == '/') {
482             trimmedPath.pop_back();
483         }
484 
485         size_t pos = trimmedPath.rfind('/');
486         if (pos != std::string::npos) {
487             return trimmedPath.substr(pos + 1);
488         }
489 
490         return trimmedPath;
491     }
492 
IsFailed() const493     std::string Uri::IsFailed() const
494     {
495         return errStr_;
496     }
497 
Normalize() const498     std::string Uri::Normalize() const
499     {
500         std::vector<std::string> temp;
501         size_t pathLen = uriData_.path.size();
502         if (pathLen == 0) {
503             return this->inputUri_;
504         }
505         size_t pos = 0;
506         size_t left = 0;
507         while ((pos = uriData_.path.find('/', left)) != std::string::npos) {
508             temp.push_back(uriData_.path.substr(left, pos - left));
509             left = pos + 1;
510         }
511         if (left != pathLen) {
512             temp.push_back(uriData_.path.substr(left));
513         }
514         size_t tempLen = temp.size();
515         std::vector<std::string> normalizeTemp;
516         for (size_t i = 0; i < tempLen; ++i) {
517             if (!temp[i].empty() && !(temp[i] == ".") && !(temp[i] == "..")) {
518                 normalizeTemp.push_back(temp[i]);
519             }
520             if (temp[i] == "..") {
521                 if (!normalizeTemp.empty() && normalizeTemp.back() != "..") {
522                     normalizeTemp.pop_back();
523                 } else {
524                     normalizeTemp.push_back(temp[i]);
525                 }
526             }
527         }
528         std::string normalizePath = "";
529         tempLen = normalizeTemp.size();
530         if (tempLen == 0) {
531             normalizePath = "/";
532         } else {
533             for (size_t i = 0; i < tempLen; ++i) {
534                 normalizePath += "/" + normalizeTemp[i];
535             }
536         }
537         return Split(normalizePath);
538     }
539 
540 
Split(const std::string & path) const541     std::string Uri::Split(const std::string &path) const
542     {
543         std::string normalizeUri = "";
544         if (!uriData_.scheme.empty()) {
545             normalizeUri += uriData_.scheme + ":";
546         }
547         if (uriData_.path.empty()) {
548             normalizeUri += uriData_.SchemeSpecificPart;
549         } else {
550             if (!uriData_.host.empty()) {
551                 normalizeUri += "//";
552                 if (!uriData_.userInfo.empty()) {
553                     normalizeUri += uriData_.userInfo + "@";
554                 }
555                 normalizeUri += uriData_.host;
556                 if (uriData_.port != -1) {
557                     normalizeUri += ":" + std::to_string(uriData_.port);
558                 }
559             } else if (!uriData_.authority.empty()) {
560                 normalizeUri += "//" + uriData_.authority;
561             }
562             normalizeUri += path;
563         }
564         if (!uriData_.query.empty()) {
565             normalizeUri += "?" + uriData_.query;
566         }
567         if (!uriData_.fragment.empty()) {
568             normalizeUri += "#" + uriData_.fragment;
569         }
570         return normalizeUri;
571     }
572 
UpdateToString() const573     std::string Uri::UpdateToString() const
574     {
575         std::string uriStr = "";
576         bool addQuery = false;
577         if (!uriData_.scheme.empty()) {
578             uriStr += uriData_.scheme + ":";
579         }
580         if (uriData_.path.empty()) {
581             uriStr += uriData_.SchemeSpecificPart;
582             addQuery = true;
583         } else {
584             if (!uriData_.host.empty()) {
585                 uriStr += "//";
586                 if (!uriData_.userInfo.empty()) {
587                     uriStr += uriData_.userInfo + "@";
588                 }
589                 uriStr += uriData_.host;
590                 if (uriData_.port != -1) {
591                     uriStr += ":" + std::to_string(uriData_.port);
592                 }
593             } else if (!uriData_.authority.empty()) {
594                 uriStr += "//" + uriData_.authority;
595             }
596             if (!uriData_.path.empty()) {
597                 uriData_.path[0] == '/' ? (uriStr += uriData_.path) : (uriStr += "/" + uriData_.path);
598             }
599         }
600         if (!uriData_.query.empty() && !addQuery) {
601             uriStr += "?" + uriData_.query;
602         }
603         if (!uriData_.fragment.empty()) {
604             uriStr += "#" + uriData_.fragment;
605         }
606         return uriStr;
607     }
608 
GetScheme() const609     std::string Uri::GetScheme() const
610     {
611         return uriData_.scheme;
612     }
613 
SetScheme(const std::string_view Scheme)614     void Uri::SetScheme(const std::string_view Scheme)
615     {
616         if ((static_cast<int>(Scheme[0]) >= 0 && static_cast<int>(Scheme[0]) < MAX_BIT_SIZE) &&
617             !g_ruleAlpha.test(Scheme[0])) {
618             errStr_ = "Scheme the first character must be a letter";
619             return;
620         }
621 
622         std::string temp = "";
623         size_t pos = Scheme.find(':');
624         if (pos != std::string_view::npos) {
625             temp = std::string(Scheme.substr(0, pos));
626         } else {
627             temp = std::string(Scheme);
628         }
629 
630         if (!CheckCharacter(temp, g_ruleScheme, false)) {
631             errStr_ = "scheme does not conform to the rule";
632             return;
633         }
634         uriData_.scheme = temp;
635         inputUri_ = UpdateToString();
636     }
637 
UpdateAuthority()638     void Uri::UpdateAuthority()
639     {
640         std::string temp = uriData_.userInfo;
641         if (!uriData_.userInfo.empty()) {
642             temp.append("@");
643         }
644         temp += uriData_.host;
645         if (uriData_.port != -1) {
646             temp += ":" + std::to_string(uriData_.port);
647         }
648         uriData_.authority = temp;
649     }
650 
UpdateSsp()651     void Uri::UpdateSsp()
652     {
653         std::string temp = "";
654         if (!uriData_.authority.empty()) {
655             temp += "//" +  uriData_.authority;
656         }
657         if (!uriData_.path.empty()) {
658             uriData_.path[0] == '/' ? (temp += uriData_.path) : (temp += "/" + uriData_.path);
659         }
660 
661         if (!uriData_.query.empty()) {
662             temp += "?" + uriData_.query;
663         }
664         uriData_.SchemeSpecificPart = temp;
665     }
666 
SetUserInfo(const std::string userInfo)667     void Uri::SetUserInfo(const std::string userInfo)
668     {
669         if (uriData_.host.empty() || (!CheckCharacter(userInfo, g_ruleUserInfo, true))) {
670             errStr_ = "userInfo does not conform to the rule";
671             return;
672         }
673         uriData_.userInfo = userInfo;
674         UpdateAuthority();
675         UpdateSsp();
676         inputUri_ = UpdateToString();
677     }
678 
SetPath(const std::string pathStr)679     void Uri::SetPath(const std::string pathStr)
680     {
681         if (!CheckCharacter(pathStr, g_rulePath, true)) {
682             errStr_ = "pathStr does not conform to the rule";
683             return;
684         }
685         uriData_.path = pathStr;
686         UpdateSsp();
687         inputUri_ = UpdateToString();
688     }
689 
SetQuery(const std::string queryStr)690     void Uri::SetQuery(const std::string queryStr)
691     {
692         if (!CheckCharacter(queryStr, g_ruleUrlc, true)) {
693             errStr_ = "QueryStr does not conform to the rule";
694             return;
695         }
696         uriData_.query = queryStr;
697         UpdateSsp();
698         inputUri_ = UpdateToString();
699     }
700 
SetFragment(const std::string fragmentStr)701     void Uri::SetFragment(const std::string fragmentStr)
702     {
703         if (!CheckCharacter(fragmentStr, g_ruleUrlc, true)) {
704             errStr_ = "Fragment does not conform to the rule";
705             return;
706         }
707         uriData_.fragment = fragmentStr;
708         inputUri_ = UpdateToString();
709     }
710 
SetAuthority(const std::string authorityStr)711     void Uri::SetAuthority(const std::string authorityStr)
712     {
713         uriData_.port = -1;
714         uriData_.host = "";
715         uriData_.userInfo = "";
716         uriData_.authority = authorityStr;
717         data_ = authorityStr;
718         // find UserInfo
719         size_t pos = data_.find('@');
720         if (pos != std::string::npos) {
721             std::string userStr = data_.substr(0, pos);
722             data_ = data_.substr(pos + 1);
723             if (!CheckCharacter(userStr, g_ruleUserInfo, true)) {
724                 errStr_ = "userInfo does not conform to the rule";
725                 return;
726             }
727             uriData_.userInfo = userStr;
728         }
729 
730         bool isLawfulProt = true;
731         // find port
732         pos = data_.rfind(':');
733         if (pos != std::string::npos) {
734             size_t pos1 = data_.rfind(']');
735             if (pos1 == std::string::npos || pos > pos1) {
736                 isLawfulProt = AnalysisPort(pos);
737             }
738             if (!errStr_.empty()) {
739             return;
740             }
741         }
742         AnalysisHost(isLawfulProt);
743         UpdateSsp();
744         inputUri_ = UpdateToString();
745     }
746 
SetSsp(const std::string sspStr)747     void Uri::SetSsp(const std::string sspStr)
748     {
749         uriData_.authority = "";
750         uriData_.port = -1;
751         uriData_.host = "";
752         uriData_.userInfo = "";
753         uriData_.query = "";
754         uriData_.path = "";
755         uriData_.SchemeSpecificPart = "";
756         data_ = sspStr;
757         size_t pos = data_.find('?'); // Query
758         if (pos != std::string::npos) {
759             AnalysisQuery(pos);
760         }
761         pos = data_.find("//"); // userInfo path host port ipv4 or ipv6
762         if (pos != std::string::npos && pos == 0) {
763             AssignSchemeSpecificPart();
764             data_ = data_.substr(2); // 2:Intercept the string from the second subscript
765             AnalysisHostAndPath();
766         } else if (data_[0] == '/') {
767             uriData_.path = data_;
768             AssignSchemeSpecificPart();
769             data_ = "";
770         } else {
771             AssignSchemeSpecificPart();
772             uriData_.path = "";
773             uriData_.query = "";
774             data_ = "";
775         }
776         inputUri_ = UpdateToString();
777     }
778 
GetAuthority() const779     std::string Uri::GetAuthority() const
780     {
781         return uriData_.authority;
782     }
783 
GetSsp() const784     std::string Uri::GetSsp() const
785     {
786         return uriData_.SchemeSpecificPart;
787     }
788 
GetUserinfo() const789     std::string Uri::GetUserinfo() const
790     {
791         return uriData_.userInfo;
792     }
793 
GetHost() const794     std::string Uri::GetHost() const
795     {
796         return uriData_.host;
797     }
798 
GetPort() const799     std::string Uri::GetPort() const
800     {
801         return std::to_string(uriData_.port);
802     }
803 
GetPath() const804     std::string Uri::GetPath() const
805     {
806         return uriData_.path;
807     }
808 
GetQuery() const809     std::string Uri::GetQuery() const
810     {
811         return uriData_.query;
812     }
813 
GetFragment() const814     std::string Uri::GetFragment() const
815     {
816         return uriData_.fragment;
817     }
818 
ClearQuery() const819     std::string Uri::ClearQuery() const
820     {
821         return BuildUriString("clearquery", "");
822     }
823 } // namespace OHOS::Uri
824