DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
Uri.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "System/Uri.h"
3#include <string>
4#include <algorithm>
5#include <cctype>
6
7namespace DotNetDupe {
8 namespace System {
9 Uri::Uri(const String& uriString) : _uriString(uriString) {
11 ParseUri();
12 }
13
14 static void ParseSchemeAndAuthority(const std::string& rawUri, String& scheme, String& authority) {
16 size_t schemeEnd = rawUri.find(':');
17 if (schemeEnd == std::string::npos) return;
18 scheme = String(rawUri.substr(0, schemeEnd).c_str());
19
21 size_t authStart = schemeEnd + 1;
22 if (authStart + 1 < rawUri.length() && rawUri.substr(authStart, 2) == "//") {
23 authStart += 2;
24 size_t authEnd = rawUri.find_first_of("/?#", authStart);
25 authority = (authEnd == std::string::npos)
26 ? String(rawUri.substr(authStart).c_str())
27 : String(rawUri.substr(authStart, authEnd - authStart).c_str());
28 }
29 }
30
31 static void ParsePath(const std::string& rawUri, const String& scheme, String& path) {
33 size_t pathStart = rawUri.find("//");
34 if (pathStart != std::string::npos) {
35 pathStart = rawUri.find('/', pathStart + 2);
36 } else {
37 size_t colon = rawUri.find(':');
38 pathStart = (colon != std::string::npos)
39 ? (scheme.Equals("mailto") ? colon + 1 : rawUri.find('/', colon + 1))
40 : 0;
41 }
42
44 if (pathStart != std::string::npos) {
45 size_t pathEnd = rawUri.find_first_of("?#", pathStart);
46 path = (pathEnd == std::string::npos)
47 ? String(rawUri.substr(pathStart).c_str())
48 : String(rawUri.substr(pathStart, pathEnd - pathStart).c_str());
49 }
50 if (path.IsEmpty()) path = String("/");
51 }
52
53 static void ParseQueryAndFragment(const std::string& rawUri, String& query, String& fragment) {
55 size_t qStart = rawUri.find('?');
56 if (qStart != std::string::npos) {
57 size_t qEnd = rawUri.find('#', qStart);
58 query = (qEnd == std::string::npos)
59 ? String(rawUri.substr(qStart + 1).c_str())
60 : String(rawUri.substr(qStart + 1, qEnd - qStart - 1).c_str());
61 }
62
64 size_t fStart = rawUri.find('#');
65 if (fStart != std::string::npos) {
66 fragment = String(rawUri.substr(fStart + 1).c_str());
67 }
68 }
69
70 static void ParseAuthorityComponents(const String& authority, const String& scheme, String& userInfo, String& host, int& port) {
72 std::string authStr = (const char*)authority;
73 if (authStr.empty()) return;
74
76 size_t userEnd = authStr.find('@');
77 if (userEnd != std::string::npos) {
78 userInfo = String(authStr.substr(0, userEnd).c_str());
79 authStr = authStr.substr(userEnd + 1);
80 }
81
83 size_t portStart = authStr.find(':');
84 if (portStart != std::string::npos) {
85 host = String(authStr.substr(0, portStart).c_str());
86 port = std::stoi(authStr.substr(portStart + 1));
87 } else {
88 host = String(authStr.c_str());
89 port = (scheme.ToLower() == "https") ? 443 : 80;
90 }
91 }
92
93 void Uri::ParseUri() {
95 std::string rawUri = (const char*)_uriString;
96 ParseSchemeAndAuthority(rawUri, _scheme, _authority);
97 ParsePath(rawUri, _scheme, _path);
98 ParseQueryAndFragment(rawUri, _query, _fragment);
99 ParseAuthorityComponents(_authority, _scheme, _userInfo, _host, _port);
100 }
101
102 String Uri::GetScheme() const { return _scheme; }
103 String Uri::GetAbsoluteUri() const { return _uriString; }
104 String Uri::GetAuthority() const { return _authority; }
105 String Uri::GetHost() const { return _host; }
106 int Uri::GetPort() const { return _port; }
107 String Uri::GetAbsolutePath() const { return _path; }
108 String Uri::GetQuery() const { return _query; }
109 String Uri::GetFragment() const { return _fragment; }
110 String Uri::GetUserInfo() const { return _userInfo; }
111 String Uri::GetOriginalString() const { return _uriString; }
112
115 return _uriString;
116 }
117
118 bool Uri::IsDefaultPort() const {
120 if (_scheme.Equals("http") && _port == 80) return true;
121 if (_scheme.Equals("https") && _port == 443) return true;
122 return false;
123 }
124
125 bool Uri::IsFile() const {
127 return _scheme.Equals("file");
128 }
129
130 bool Uri::IsLoopback() const {
132 return _host.Equals("localhost") || _host.Equals("127.0.0.1") || _host.Equals("::1");
133 }
134
135 String Uri::EscapeDataString(const String& stringToEscape) {
137 std::string s = (const char*)stringToEscape;
138 std::string escaped;
139 for (char c : s) {
140 if (isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~') {
141 escaped += c;
142 } else {
143 char buf[4];
144 snprintf(buf, 4, "%%%02X", static_cast<unsigned char>(c));
145 escaped += buf;
146 }
147 }
148 return String(escaped.c_str());
149 }
150
151 static void UnescapePercentChar(const std::string& s, size_t& i, std::string& unescaped) {
153 int value;
154#if defined(_WIN32)
155 if (sscanf_s(s.substr(i + 1, 2).c_str(), "%x", &value) == 1) {
156#else
157 if (sscanf(s.substr(i + 1, 2).c_str(), "%x", &value) == 1) {
158#endif
159 unescaped += static_cast<char>(value);
160 i += 2;
161 } else {
162 unescaped += s[i];
163 }
164 }
165
166 String Uri::UnescapeDataString(const String& stringToUnescape) {
168 std::string s = (const char*)stringToUnescape;
169 std::string unescaped;
170 for (size_t i = 0; i < s.length(); ++i) {
171 if (s[i] == '%' && i + 2 < s.length()) {
172 UnescapePercentChar(s, i, unescaped);
173 } else {
174 unescaped += s[i];
175 }
176 }
177 return String(unescaped.c_str());
178 }
179 }
180}
Provides an object representation of a Uniform Resource Identifier (URI) and easy access to its parts...
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
Definition String.h:74
String ToLower() const
Definition String.cpp:672
String()
Initializes a new instance of the String class to an empty string.
Definition String.cpp:64
static bool Equals(const String &sStr1, const String &sStr2)
Definition String.cpp:334
String GetHost() const
Gets the host component of this instance.
Definition Uri.cpp:105
String GetFragment() const
Gets the escaped URI fragment.
Definition Uri.cpp:109
String GetOriginalString() const
Gets the original URI string passed to the constructor.
Definition Uri.cpp:111
bool IsFile() const
Determines whether the specified Uri is a file URI.
Definition Uri.cpp:125
int GetPort() const
Gets the port number of this URI.
Definition Uri.cpp:106
String GetUserInfo() const
Gets the user name, password, or other user-specific information associated with the specified URI.
Definition Uri.cpp:110
bool IsLoopback() const
Determines whether the specified Uri references the local host.
Definition Uri.cpp:130
String GetScheme() const
Gets the scheme name for this URI.
Definition Uri.cpp:102
Uri(const String &uriString)
Initializes a new instance of the Uri class with the specified URI string.
Definition Uri.cpp:9
static String UnescapeDataString(const String &stringToUnescape)
Converts a string to its unescaped representation according to RFC 3986.
Definition Uri.cpp:166
String GetQuery() const
Gets any query information included in the specified URI.
Definition Uri.cpp:108
bool IsDefaultPort() const
Determines whether the port value of the URI is the default for this scheme.
Definition Uri.cpp:118
String GetAbsoluteUri() const
Gets the absolute URI string representation.
Definition Uri.cpp:103
String GetAuthority() const
Gets the authority (host, optional port, and optional user information).
Definition Uri.cpp:104
String ToString() const
Gets the canonical string representation for the specified Uri instance.
Definition Uri.cpp:113
String GetAbsolutePath() const
Gets the absolute path of the URI.
Definition Uri.cpp:107
static String EscapeDataString(const String &stringToEscape)
Converts a string to its escaped representation according to RFC 3986.
Definition Uri.cpp:135
static void ParseAuthorityComponents(const String &authority, const String &scheme, String &userInfo, String &host, int &port)
Definition Uri.cpp:70
static void ParseQueryAndFragment(const std::string &rawUri, String &query, String &fragment)
Definition Uri.cpp:53
static void ParseSchemeAndAuthority(const std::string &rawUri, String &scheme, String &authority)
Definition Uri.cpp:14
static void ParsePath(const std::string &rawUri, const String &scheme, String &path)
Definition Uri.cpp:31
static void UnescapePercentChar(const std::string &s, size_t &i, std::string &unescaped)
Definition Uri.cpp:151