summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-26 22:48:54 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-26 22:56:58 +0200
commit389eb1b693d592e05d54af8b37858f8cf37eeffa (patch)
tree92a407068fc2093880dbfb96be228777603e02c4
parentda04147cf674b709e84161e25ad5305d22c56c21 (diff)
downloadserenity-389eb1b693d592e05d54af8b37858f8cf37eeffa.zip
AK: Teach URL how to parse data: URLs :^)
-rw-r--r--AK/URL.cpp54
-rw-r--r--AK/URL.h7
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())
diff --git a/AK/URL.h b/AK/URL.h
index be8bc05c93..4c47f0368e 100644
--- a/AK/URL.h
+++ b/AK/URL.h
@@ -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;
};
}