From 3bb40669d5efea707a90171ad2430a81fd4f4726 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Mon, 26 Apr 2021 09:33:28 +0200 Subject: [Net] Implement String::parse_url for parsing URLs. Splits the URL into (scheme, host, port, path). Supports both literal IPv4 and IPv6. Strip credentials when present (e.g. http://user:pass@example.com/). Use that function in both HTTPRequest and WebSocketClient. --- core/string/ustring.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ core/string/ustring.h | 1 + 2 files changed, 66 insertions(+) (limited to 'core/string') diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index cf0040353d..108f90fd5d 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -240,6 +240,71 @@ String String::word_wrap(int p_chars_per_line) const { return ret; } +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. + String base = *this; + r_scheme = ""; + r_host = ""; + r_port = 0; + r_path = ""; + 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); + } + pos = base.find("/"); + // Path + if (pos != -1) { + r_path = base.substr(pos, base.length() - pos); + base = base.substr(0, pos); + } + // Host + pos = base.find("@"); + if (pos != -1) { + // Strip credentials + base = base.substr(pos + 1, base.length() - pos - 1); + } + if (base.begins_with("[")) { + // Literal IPv6 + pos = base.rfind("]"); + if (pos == -1) { + return ERR_INVALID_PARAMETER; + } + r_host = base.substr(1, pos - 1); + base = base.substr(pos + 1, base.length() - pos - 1); + } else { + // Anything else + if (base.get_slice_count(":") > 1) { + return ERR_INVALID_PARAMETER; + } + pos = base.rfind(":"); + if (pos == -1) { + r_host = base; + base = ""; + } else { + r_host = base.substr(0, pos); + base = base.substr(pos, base.length() - pos); + } + } + if (r_host.is_empty()) { + return ERR_INVALID_PARAMETER; + } + r_host = r_host.to_lower(); + // Port + if (base.begins_with(":")) { + base = base.substr(1, base.length() - 1); + if (!base.is_valid_integer()) { + return ERR_INVALID_PARAMETER; + } + r_port = base.to_int(); + if (r_port < 1 || r_port > 65535) { + return ERR_INVALID_PARAMETER; + } + } + return OK; +} + void String::copy_from(const char *p_cstr) { // copy Latin-1 encoded c-string directly if (!p_cstr) { diff --git a/core/string/ustring.h b/core/string/ustring.h index 1e362d7683..a56845deff 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -416,6 +416,7 @@ public: String c_unescape() const; String json_escape() const; String word_wrap(int p_chars_per_line) const; + Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const; String property_name_encode() const; -- cgit v1.2.3