diff --git a/lib/pleroma/web/xml.ex b/lib/pleroma/web/xml.ex index ba8886548..e68341e20 100644 --- a/lib/pleroma/web/xml.ex +++ b/lib/pleroma/web/xml.ex @@ -26,13 +26,7 @@ def string_from_xpath(xpath, doc) do def parse_document(text) do try do - {doc, _rest} = - text - |> :binary.bin_to_list() - |> :xmerl_scan.string( - quiet: true, - allow_entities: false - ) + doc = SweetXml.parse(text, dtd: :none) {:ok, doc} rescue diff --git a/mix.exs b/mix.exs index 5ffbf0fe7..5aa1381d5 100644 --- a/mix.exs +++ b/mix.exs @@ -204,6 +204,7 @@ defp deps do {:mox, "~> 1.0", only: :test}, {:websockex, "~> 0.4.3", only: :test}, {:dialyxir, "~> 1.3", only: [:dev], runtime: false}, + {:elixir_xml_to_map, "~> 3.0", only: :test}, {:mint, "~> 1.5.1", override: true}, {:nimble_pool, "~> 1.0", override: true} ] ++ oauth_deps() diff --git a/mix.lock b/mix.lock index aab94708c..471e61750 100644 --- a/mix.lock +++ b/mix.lock @@ -33,7 +33,9 @@ "ecto_sql": {:hex, :ecto_sql, "3.10.1", "6ea6b3036a0b0ca94c2a02613fd9f742614b5cfe494c41af2e6571bb034dd94c", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f6a25bdbbd695f12c8171eaff0851fa4c8e72eec1e98c7364402dda9ce11c56b"}, "elasticsearch": {:git, "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", "6cd946f75f6ab9042521a009d1d32d29a90113ca", [ref: "main"]}, "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, + "elixir_xml_to_map": {:hex, :elixir_xml_to_map, "3.0.0", "67dcff30ecf72aed37ab08525133e4420717a749436e22bfece431e7dddeea7e", [:mix], [{:erlsom, "~> 1.4", [hex: :erlsom, repo: "hexpm", optional: false]}], "hexpm", "11222dd7f029f8db7a6662b41c992dbdb0e1c6e4fdea6a42056f9d27c847efbb"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, + "erlsom": {:hex, :erlsom, "1.5.1", "c8fe2babd33ff0846403f6522328b8ab676f896b793634cfe7ef181c05316c03", [:rebar3], [], "hexpm", "7965485494c5844dd127656ac40f141aadfa174839ec1be1074e7edf5b4239eb"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "ex_aws": {:hex, :ex_aws, "2.4.4", "d7886eaca7e10f7bd3d9e9d2d5414cb336737b3ab2fddd4fa30358b725293fe0", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a7d63e485ca2b16fb804f3f20097827aa69885eea6e69fa75c98f353c9c91dc7"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.4.0", "ce8decb6b523381812798396bc0e3aaa62282e1b40520125d1f4eff4abdff0f4", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "85dda6e27754d94582869d39cba3241d9ea60b6aa4167f9c88e309dc687e56bb"}, diff --git a/test/fixtures/xml_normal.xml b/test/fixtures/xml_normal.xml new file mode 100644 index 000000000..8dfa0af54 --- /dev/null +++ b/test/fixtures/xml_normal.xml @@ -0,0 +1,44 @@ + + + + + Match One + + + 1 + Team One + + + 2 + Team Two + + + + + Match Two + + + 2 + Team Two + + + 3 + Team Three + + + + + Match Three + + + 1 + Team One + + + 3 + Team Three + + + + + diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs index 6b5b7c46c..929ebbed0 100644 --- a/test/pleroma/web/web_finger/web_finger_controller_test.exs +++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do import ExUnit.CaptureLog import Pleroma.Factory import Tesla.Mock + import Pleroma.Test.Matchers.XML setup do mock(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -23,8 +24,8 @@ test "GET host-meta" do assert response.status == 200 - assert response.resp_body == - ~s() + assert_xml_equals(response.resp_body, + ~s()) end test "Webfinger JRD" do diff --git a/test/pleroma/web/xml_test.exs b/test/pleroma/web/xml_test.exs index 49306430b..0dc8d299e 100644 --- a/test/pleroma/web/xml_test.exs +++ b/test/pleroma/web/xml_test.exs @@ -3,6 +3,11 @@ defmodule Pleroma.Web.XMLTest do alias Pleroma.Web.XML + test "parses normal XML" do + data = File.read!("test/fixtures/xml_normal.xml") + assert {:ok, _} = XML.parse_document(data) + end + test "refuses to parse any entities from XML" do data = File.read!("test/fixtures/xml_billion_laughs.xml") assert(:error == XML.parse_document(data)) diff --git a/test/support/matchers/xml.ex b/test/support/matchers/xml.ex new file mode 100644 index 000000000..9f260ce82 --- /dev/null +++ b/test/support/matchers/xml.ex @@ -0,0 +1,18 @@ +defmodule Pleroma.Test.Matchers.XML do + import ExUnit.Assertions + + def assert_xml_equals(xml_a, xml_b) do + map_a = XmlToMap.naive_map(xml_a) + map_b = XmlToMap.naive_map(xml_b) + + if map_a != map_b do + flunk(~s|Expected XML + #{xml_a} + + to equal + + #{xml_b} + |) + end + end +end