diff options
author | Andreas Kling <kling@serenityos.org> | 2020-04-26 22:48:54 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-26 22:56:58 +0200 |
commit | 389eb1b693d592e05d54af8b37858f8cf37eeffa (patch) | |
tree | 92a407068fc2093880dbfb96be228777603e02c4 | |
parent | da04147cf674b709e84161e25ad5305d22c56c21 (diff) | |
download | serenity-389eb1b693d592e05d54af8b37858f8cf37eeffa.zip |
AK: Teach URL how to parse data: URLs :^)
-rw-r--r-- | AK/URL.cpp | 54 | ||||
-rw-r--r-- | AK/URL.h | 7 |
2 files changed, 58 insertions, 3 deletions
diff --git a/AK/URL.cpp b/AK/URL.cpp index 8c77031b88..7e690ff68b 100644 --- a/AK/URL.cpp +++ b/AK/URL.cpp @@ -54,6 +54,8 @@ bool URL::parse(const StringView& string) InPath, InQuery, InFragment, + InDataMimeType, + InDataPayload, }; Vector<char, 256> buffer; @@ -75,30 +77,39 @@ bool URL::parse(const StringView& string) while (index < string.length()) { switch (state) { - case State::InProtocol: + case State::InProtocol: { if (is_valid_protocol_character(peek())) { buffer.append(consume()); continue; } if (consume() != ':') return false; + + m_protocol = String::copy(buffer); + + if (m_protocol == "data") { + buffer.clear(); + state = State::InDataMimeType; + continue; + } + if (consume() != '/') return false; if (consume() != '/') return false; if (buffer.is_empty()) return false; - m_protocol = String::copy(buffer); if (m_protocol == "http") m_port = 80; else if (m_protocol == "https") m_port = 443; - buffer.clear(); if (m_protocol == "file") state = State::InPath; else state = State::InHostname; + buffer.clear(); continue; + } case State::InHostname: if (is_valid_hostname_character(peek())) { buffer.append(consume()); @@ -160,6 +171,41 @@ bool URL::parse(const StringView& string) case State::InFragment: buffer.append(consume()); continue; + case State::InDataMimeType: { + if (peek() != ';' && peek() != ',') { + buffer.append(consume()); + continue; + } + + m_data_mime_type = String::copy(buffer); + buffer.clear(); + + if (peek() == ';') { + consume(); + if (consume() != 'b') + return false; + if (consume() != 'a') + return false; + if (consume() != 's') + return false; + if (consume() != 'e') + return false; + if (consume() != '6') + return false; + if (consume() != '4') + return false; + m_data_payload_is_base64 = true; + } + + if (consume() != ',') + return false; + + state = State::InDataPayload; + break; + } + case State::InDataPayload: + buffer.append(consume()); + break; } } if (state == State::InHostname) { @@ -177,6 +223,8 @@ bool URL::parse(const StringView& string) m_query = String::copy(buffer); if (state == State::InFragment) m_fragment = String::copy(buffer); + if (state == State::InDataPayload) + m_data_payload = String::copy(buffer); if (m_query.is_null()) m_query = ""; if (m_fragment.is_null()) @@ -65,6 +65,10 @@ public: URL complete_url(const String&) const; + bool data_payload_is_base64() const { return m_data_payload_is_base64; } + const String& data_mime_type() const { return m_data_mime_type; } + const String& data_payload() const { return m_data_payload; } + static URL create_with_url_or_path(const String& url_or_path); static URL create_with_file_protocol(const String& path); @@ -74,11 +78,14 @@ private: bool m_valid { false }; u16 m_port { 80 }; + bool m_data_payload_is_base64 { false }; String m_protocol; String m_host; String m_path; String m_query; String m_fragment; + String m_data_mime_type; + String m_data_payload; }; } |