diff --git a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp index cdbdfe061da..a3dc5b48ddd 100644 --- a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp +++ b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp @@ -13,13 +13,14 @@ #include inline namespace { -extern char const* s_xhtml_unified_dtd; +extern StringView s_xhtml_unified_dtd; } namespace Web { -ErrorOr resolve_xml_resource(XML::SystemID const&, Optional const& public_id) +ErrorOr>> resolve_xml_resource(XML::SystemID const&, Optional const& public_id) { + static Optional> s_parsed_xhtml_unified_dtd; if (!public_id.has_value()) return Error::from_string_literal("Refusing to load disallowed external entity"); @@ -36,7 +37,15 @@ ErrorOr resolve_xml_resource(XML::SystemID const&, Optional -)xmlxmlxml"; +)xmlxmlxml"sv; } diff --git a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.h b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.h index f176a359bc2..05a24e3f3e3 100644 --- a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.h +++ b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.h @@ -21,7 +21,7 @@ enum class XMLScriptingSupport { Enabled, }; -ErrorOr resolve_xml_resource(XML::SystemID const&, Optional const&); +ErrorOr>> resolve_xml_resource(XML::SystemID const&, Optional const&); class XMLDocumentBuilder final : public XML::Listener { public: diff --git a/Userland/Libraries/LibXML/Parser/Parser.cpp b/Userland/Libraries/LibXML/Parser/Parser.cpp index cb8b8c4116c..cd1ea593898 100644 --- a/Userland/Libraries/LibXML/Parser/Parser.cpp +++ b/Userland/Libraries/LibXML/Parser/Parser.cpp @@ -573,15 +573,21 @@ ErrorOr Parser::parse_doctype_decl() if (m_options.resolve_external_resource) { auto resource_result = m_options.resolve_external_resource(doctype.external_id->system_id, doctype.external_id->public_id); if (!resource_result.is_error()) { - StringView resolved_source = resource_result.value(); - TemporaryChange source { m_source, resolved_source }; - TemporaryChange lexer { m_lexer, LineTrackingLexer(m_source) }; - auto declarations = TRY(parse_external_subset()); - if (!m_lexer.is_eof()) { - return parse_error( - m_lexer.current_position(), - ByteString::formatted("Failed to resolve external subset '{}': garbage after declarations", doctype.external_id->system_id.system_literal)); - } + auto declarations = TRY(resource_result.release_value().visit( + [&](ByteString resolved_source) -> ErrorOr, ParseError> { + TemporaryChange source { m_source, resolved_source.view() }; + TemporaryChange lexer { m_lexer, LineTrackingLexer(m_source) }; + auto declarations = TRY(parse_external_subset()); + if (!m_lexer.is_eof()) { + return parse_error( + m_lexer.current_position(), + ByteString::formatted("Failed to resolve external subset '{}': garbage after declarations", doctype.external_id->system_id.system_literal)); + } + return declarations; + }, + [&](Vector declarations) -> ErrorOr, ParseError> { + return declarations; + })); doctype.markup_declarations.extend(move(declarations)); } } @@ -1755,7 +1761,10 @@ ErrorOr Parser::resolve_reference(EntityReference const& if (result.is_error()) return parse_error(m_lexer.position_for(0), ByteString::formatted("Failed to resolve external entity '{}': {}", reference.name, result.error())); - resolved = result.release_value(); + if (!result.value().has()) + return parse_error(m_lexer.position_for(0), ByteString::formatted("Failed to resolve external entity '{}': Resource is of the wrong type", reference.name)); + + resolved = result.release_value().get(); return {}; })); break; diff --git a/Userland/Libraries/LibXML/Parser/Parser.h b/Userland/Libraries/LibXML/Parser/Parser.h index b12bc031559..bc60c9046a2 100644 --- a/Userland/Libraries/LibXML/Parser/Parser.h +++ b/Userland/Libraries/LibXML/Parser/Parser.h @@ -49,7 +49,7 @@ public: bool preserve_cdata { true }; bool preserve_comments { false }; bool treat_errors_as_fatal { true }; - Function(SystemID const&, Optional const&)> resolve_external_resource {}; + Function>>(SystemID const&, Optional const&)> resolve_external_resource {}; }; Parser(StringView source, Options options) @@ -70,6 +70,8 @@ public: Vector const& parse_error_causes() const { return m_parse_errors; } + ErrorOr, ParseError> parse_external_subset(); + private: struct EntityReference { Name name; @@ -138,7 +140,6 @@ private: ErrorOr parse_system_id_literal(); ErrorOr parse_cdata_section(); ErrorOr parse_attribute_value_inner(StringView disallow); - ErrorOr, ParseError> parse_external_subset(); ErrorOr parse_text_declaration(); ErrorOr expect(StringView); diff --git a/Userland/Utilities/xml.cpp b/Userland/Utilities/xml.cpp index 319c0bcfe2e..a3b6acb3d67 100644 --- a/Userland/Utilities/xml.cpp +++ b/Userland/Utilities/xml.cpp @@ -362,7 +362,7 @@ static auto parse(StringView contents) contents, { .preserve_comments = true, - .resolve_external_resource = [&](XML::SystemID const& system_id, Optional const&) -> ErrorOr { + .resolve_external_resource = [&](XML::SystemID const& system_id, Optional const&) -> ErrorOr>> { auto base = URL::create_with_file_scheme(s_path); auto url = URL::Parser::basic_parse(system_id.system_literal, base); if (!url.is_valid())