summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaoyu Qiu <timothyqiu32@gmail.com>2024-05-22 10:22:50 +0800
committerHaoyu Qiu <timothyqiu32@gmail.com>2024-09-27 19:42:30 +0800
commit6516ca6b11a6241d7908eb322343d44c10050d98 (patch)
tree4ab5d25c59eb44498f47b981714b88cdc5fe519c
parent506d6e427a4eecfc1e5e5ee1180019a876119701 (diff)
downloadredot-engine-6516ca6b11a6241d7908eb322343d44c10050d98.tar.gz
Parse fragment from URL
-rw-r--r--core/string/ustring.cpp25
-rw-r--r--core/string/ustring.h2
-rw-r--r--editor/debugger/editor_debugger_server.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp3
-rw-r--r--modules/websocket/editor/editor_debugger_server_websocket.cpp4
-rw-r--r--modules/websocket/emws_peer.cpp3
-rw-r--r--modules/websocket/wsl_peer.cpp3
-rw-r--r--scene/main/http_request.cpp3
-rw-r--r--tests/core/string/test_string.h40
9 files changed, 74 insertions, 13 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 391a203d5b..e6f7492a18 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -221,18 +221,35 @@ void CharString::copy_from(const char *p_cstr) {
/* String */
/*************************************************************************/
-Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const {
- // Splits the URL into scheme, host, port, path. Strip credentials when present.
+Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path, String &r_fragment) const {
+ // Splits the URL into scheme, host, port, path, fragment. Strip credentials when present.
String base = *this;
r_scheme = "";
r_host = "";
r_port = 0;
r_path = "";
+ r_fragment = "";
+
int pos = base.find("://");
// Scheme
if (pos != -1) {
- r_scheme = base.substr(0, pos + 3).to_lower();
- base = base.substr(pos + 3, base.length() - pos - 3);
+ bool is_scheme_valid = true;
+ for (int i = 0; i < pos; i++) {
+ if (!is_ascii_alphanumeric_char(base[i]) && base[i] != '+' && base[i] != '-' && base[i] != '.') {
+ is_scheme_valid = false;
+ break;
+ }
+ }
+ if (is_scheme_valid) {
+ r_scheme = base.substr(0, pos + 3).to_lower();
+ base = base.substr(pos + 3, base.length() - pos - 3);
+ }
+ }
+ pos = base.find("#");
+ // Fragment
+ if (pos != -1) {
+ r_fragment = base.substr(pos + 1);
+ base = base.substr(0, pos);
}
pos = base.find("/");
// Path
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 5d4b209c25..aa62c9cb18 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -452,7 +452,7 @@ public:
String c_escape_multiline() const;
String c_unescape() const;
String json_escape() const;
- Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const;
+ Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path, String &r_fragment) const;
String property_name_encode() const;
diff --git a/editor/debugger/editor_debugger_server.cpp b/editor/debugger/editor_debugger_server.cpp
index c0efc6a1fc..9ec6058132 100644
--- a/editor/debugger/editor_debugger_server.cpp
+++ b/editor/debugger/editor_debugger_server.cpp
@@ -77,8 +77,8 @@ Error EditorDebuggerServerTCP::start(const String &p_uri) {
// Optionally override
if (!p_uri.is_empty() && p_uri != "tcp://") {
- String scheme, path;
- Error err = p_uri.parse_url(scheme, bind_host, bind_port, path);
+ String scheme, path, fragment;
+ Error err = p_uri.parse_url(scheme, bind_host, bind_port, path, fragment);
ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER);
}
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index af4b3a1643..fec8d4b897 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -993,7 +993,8 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, int p_asset_id, String p
String url_host;
int url_port;
String url_path;
- Error err = trimmed_url.parse_url(url_scheme, url_host, url_port, url_path);
+ String url_fragment;
+ Error err = trimmed_url.parse_url(url_scheme, url_host, url_port, url_path, url_fragment);
if (err != OK) {
if (is_print_verbose_enabled()) {
ERR_PRINT(vformat("Asset Library: Invalid image URL '%s' for asset # %d.", trimmed_url, p_asset_id));
diff --git a/modules/websocket/editor/editor_debugger_server_websocket.cpp b/modules/websocket/editor/editor_debugger_server_websocket.cpp
index a28fc53440..344a0356c5 100644
--- a/modules/websocket/editor/editor_debugger_server_websocket.cpp
+++ b/modules/websocket/editor/editor_debugger_server_websocket.cpp
@@ -77,8 +77,8 @@ Error EditorDebuggerServerWebSocket::start(const String &p_uri) {
// Optionally override
if (!p_uri.is_empty() && p_uri != "ws://") {
- String scheme, path;
- Error err = p_uri.parse_url(scheme, bind_host, bind_port, path);
+ String scheme, path, fragment;
+ Error err = p_uri.parse_url(scheme, bind_host, bind_port, path, fragment);
ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER);
}
diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp
index 03a530909b..c5768c9f0b 100644
--- a/modules/websocket/emws_peer.cpp
+++ b/modules/websocket/emws_peer.cpp
@@ -68,8 +68,9 @@ Error EMWSPeer::connect_to_url(const String &p_url, Ref<TLSOptions> p_tls_option
String host;
String path;
String scheme;
+ String fragment;
int port = 0;
- Error err = p_url.parse_url(scheme, host, port, path);
+ Error err = p_url.parse_url(scheme, host, port, path, fragment);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
if (scheme.is_empty()) {
diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp
index 0a9a4053e3..0c0a046805 100644
--- a/modules/websocket/wsl_peer.cpp
+++ b/modules/websocket/wsl_peer.cpp
@@ -482,8 +482,9 @@ Error WSLPeer::connect_to_url(const String &p_url, Ref<TLSOptions> p_options) {
String host;
String path;
String scheme;
+ String fragment;
int port = 0;
- Error err = p_url.parse_url(scheme, host, port, path);
+ Error err = p_url.parse_url(scheme, host, port, path, fragment);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
if (scheme.is_empty()) {
scheme = "ws://";
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 3469b806a6..8526611093 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -49,7 +49,8 @@ Error HTTPRequest::_parse_url(const String &p_url) {
redirections = 0;
String scheme;
- Error err = p_url.parse_url(scheme, url, port, request_string);
+ String fragment;
+ Error err = p_url.parse_url(scheme, url, port, request_string, fragment);
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error parsing URL: '%s'.", p_url));
if (scheme == "https://") {
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 301771a3de..0131f4c02a 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -1988,6 +1988,46 @@ TEST_CASE("[String] Variant ptr indexed set") {
CHECK_EQ(s, String("azcd"));
}
+TEST_CASE("[String] parse_url") {
+ String scheme, host, path, fragment;
+ int port;
+
+ SUBCASE("Typical URL") {
+ Error err = String("https://docs.godotengine.org/en/stable/").parse_url(scheme, host, port, path, fragment);
+ REQUIRE(err == OK);
+ CHECK_EQ(scheme, "https://");
+ CHECK_EQ(host, "docs.godotengine.org");
+ CHECK_EQ(port, 0);
+ CHECK_EQ(path, "/en/stable/");
+ CHECK_EQ(fragment, "");
+ }
+
+ SUBCASE("All Elements") {
+ Error err = String("https://www.example.com:8080/path/to/file.html#fragment").parse_url(scheme, host, port, path, fragment);
+ REQUIRE(err == OK);
+ CHECK_EQ(scheme, "https://");
+ CHECK_EQ(host, "www.example.com");
+ CHECK_EQ(port, 8080);
+ CHECK_EQ(path, "/path/to/file.html");
+ CHECK_EQ(fragment, "fragment");
+ }
+
+ SUBCASE("Invalid Scheme") {
+ Error err = String("http_://example.com").parse_url(scheme, host, port, path, fragment);
+ REQUIRE(err == ERR_INVALID_PARAMETER); // Host being empty is an error.
+ }
+
+ SUBCASE("Scheme vs Fragment") {
+ Error err = String("google.com/#goto=http://redirect_url/").parse_url(scheme, host, port, path, fragment);
+ REQUIRE(err == OK);
+ CHECK_EQ(scheme, "");
+ CHECK_EQ(host, "google.com");
+ CHECK_EQ(port, 0);
+ CHECK_EQ(path, "/");
+ CHECK_EQ(fragment, "goto=http://redirect_url/");
+ }
+}
+
TEST_CASE("[Stress][String] Empty via ' == String()'") {
for (int i = 0; i < 100000; ++i) {
String str = "Hello World!";