summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Strizhakov <alex.strizhakov@gmail.com>2021-03-18 13:49:03 +0300
committerAlexander Strizhakov <alex.strizhakov@gmail.com>2021-03-19 18:53:55 +0300
commitd7e51206a251b9da0180a4df3c879531ac302e1a (patch)
tree735e353eb08e1bfbec80165721791a9d7f192e10
parenta9bc652ab9f4880566a823d3d67fe0247f7954f4 (diff)
respect content-type header in finger request
-rw-r--r--lib/pleroma/web/web_finger.ex98
-rw-r--r--lib/pleroma/web/xml.ex2
-rw-r--r--test/fixtures/tesla_mock/xn--q9jyb4c_host_meta4
-rw-r--r--test/pleroma/web/web_finger_test.exs67
-rw-r--r--test/support/http_request_mock.ex47
5 files changed, 145 insertions, 73 deletions
diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex
index 15002b29f..21b10e654 100644
--- a/lib/pleroma/web/web_finger.ex
+++ b/lib/pleroma/web/web_finger.ex
@@ -94,52 +94,56 @@ defmodule Pleroma.Web.WebFinger do
|> XmlBuilder.to_doc()
end
- defp webfinger_from_xml(doc) do
- subject = XML.string_from_xpath("//Subject", doc)
-
- subscribe_address =
- ~s{//Link[@rel="http://ostatus.org/schema/1.0/subscribe"]/@template}
- |> XML.string_from_xpath(doc)
-
- ap_id =
- ~s{//Link[@rel="self" and @type="application/activity+json"]/@href}
- |> XML.string_from_xpath(doc)
-
- data = %{
- "subject" => subject,
- "subscribe_address" => subscribe_address,
- "ap_id" => ap_id
- }
+ defp webfinger_from_xml(body) do
+ with {:ok, doc} <- XML.parse_document(body) do
+ subject = XML.string_from_xpath("//Subject", doc)
+
+ subscribe_address =
+ ~s{//Link[@rel="http://ostatus.org/schema/1.0/subscribe"]/@template}
+ |> XML.string_from_xpath(doc)
+
+ ap_id =
+ ~s{//Link[@rel="self" and @type="application/activity+json"]/@href}
+ |> XML.string_from_xpath(doc)
+
+ data = %{
+ "subject" => subject,
+ "subscribe_address" => subscribe_address,
+ "ap_id" => ap_id
+ }
- {:ok, data}
+ {:ok, data}
+ end
end
- defp webfinger_from_json(doc) do
- data =
- Enum.reduce(doc["links"], %{"subject" => doc["subject"]}, fn link, data ->
- case {link["type"], link["rel"]} do
- {"application/activity+json", "self"} ->
- Map.put(data, "ap_id", link["href"])
+ defp webfinger_from_json(body) do
+ with {:ok, doc} <- Jason.decode(body) do
+ data =
+ Enum.reduce(doc["links"], %{"subject" => doc["subject"]}, fn link, data ->
+ case {link["type"], link["rel"]} do
+ {"application/activity+json", "self"} ->
+ Map.put(data, "ap_id", link["href"])
- {"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"", "self"} ->
- Map.put(data, "ap_id", link["href"])
+ {"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"", "self"} ->
+ Map.put(data, "ap_id", link["href"])
- {nil, "http://ostatus.org/schema/1.0/subscribe"} ->
- Map.put(data, "subscribe_address", link["template"])
+ {nil, "http://ostatus.org/schema/1.0/subscribe"} ->
+ Map.put(data, "subscribe_address", link["template"])
- _ ->
- Logger.debug("Unhandled type: #{inspect(link["type"])}")
- data
- end
- end)
+ _ ->
+ Logger.debug("Unhandled type: #{inspect(link["type"])}")
+ data
+ end
+ end)
- {:ok, data}
+ {:ok, data}
+ end
end
def get_template_from_xml(body) do
xpath = "//Link[@rel='lrdd']/@template"
- with doc when doc != :error <- XML.parse_document(body),
+ with {:ok, doc} <- XML.parse_document(body),
template when template != nil <- XML.string_from_xpath(xpath, doc) do
{:ok, template}
end
@@ -192,15 +196,23 @@ defmodule Pleroma.Web.WebFinger do
address,
[{"accept", "application/xrd+xml,application/jrd+json"}]
),
- {:ok, %{status: status, body: body}} when status in 200..299 <- response do
- doc = XML.parse_document(body)
-
- if doc != :error do
- webfinger_from_xml(doc)
- else
- with {:ok, doc} <- Jason.decode(body) do
- webfinger_from_json(doc)
- end
+ {:ok, %{status: status, body: body, headers: headers}} when status in 200..299 <-
+ response do
+ case List.keyfind(headers, "content-type", 0) do
+ {_, content_type} ->
+ case Plug.Conn.Utils.media_type(content_type) do
+ {:ok, "application", subtype, _} when subtype in ~w(xrd+xml xml) ->
+ webfinger_from_xml(body)
+
+ {:ok, "application", subtype, _} when subtype in ~w(jrd+json json) ->
+ webfinger_from_json(body)
+
+ _ ->
+ {:error, {:content_type, content_type}}
+ end
+
+ _ ->
+ {:error, {:content_type, nil}}
end
else
e ->
diff --git a/lib/pleroma/web/xml.ex b/lib/pleroma/web/xml.ex
index 2b34611ac..0ab6e9d32 100644
--- a/lib/pleroma/web/xml.ex
+++ b/lib/pleroma/web/xml.ex
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.XML do
|> :binary.bin_to_list()
|> :xmerl_scan.string(quiet: true)
- doc
+ {:ok, doc}
rescue
_e ->
Logger.debug("Couldn't parse XML: #{inspect(text)}")
diff --git a/test/fixtures/tesla_mock/xn--q9jyb4c_host_meta b/test/fixtures/tesla_mock/xn--q9jyb4c_host_meta
deleted file mode 100644
index 45d260e55..000000000
--- a/test/fixtures/tesla_mock/xn--q9jyb4c_host_meta
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
- <Link rel="lrdd" template="https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
-</XRD>
diff --git a/test/pleroma/web/web_finger_test.exs b/test/pleroma/web/web_finger_test.exs
index 84477d5a1..2d7b4a40b 100644
--- a/test/pleroma/web/web_finger_test.exs
+++ b/test/pleroma/web/web_finger_test.exs
@@ -45,6 +45,26 @@ defmodule Pleroma.Web.WebFingerTest do
assert {:error, _} = WebFinger.finger("pleroma.social")
end
+ test "returns error when there is no content-type header" do
+ Tesla.Mock.mock(fn
+ %{url: "http://social.heldscal.la/.well-known/host-meta"} ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/social.heldscal.la_host_meta")
+ }}
+
+ %{
+ url:
+ "https://social.heldscal.la/.well-known/webfinger?resource=acct:invalid_content@social.heldscal.la"
+ } ->
+ {:ok, %Tesla.Env{status: 200, body: ""}}
+ end)
+
+ user = "invalid_content@social.heldscal.la"
+ assert {:error, {:content_type, nil}} = WebFinger.finger(user)
+ end
+
test "returns error when fails parse xml or json" do
user = "invalid_content@social.heldscal.la"
assert {:error, %Jason.DecodeError{}} = WebFinger.finger(user)
@@ -113,5 +133,52 @@ defmodule Pleroma.Web.WebFingerTest do
ap_id = "https://" <> to_string(:idna.encode("zetsubou.みんな")) <> "/users/lain"
{:ok, _data} = WebFinger.finger(ap_id)
end
+
+ test "respects json content-type" do
+ Tesla.Mock.mock(fn
+ %{
+ url:
+ "https://mastodon.social/.well-known/webfinger?resource=acct:emelie@mastodon.social"
+ } ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/webfinger_emelie.json"),
+ headers: [{"content-type", "application/jrd+json"}]
+ }}
+
+ %{url: "http://mastodon.social/.well-known/host-meta"} ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/mastodon.social_host_meta")
+ }}
+ end)
+
+ {:ok, _data} = WebFinger.finger("emelie@mastodon.social")
+ end
+
+ test "respects xml content-type" do
+ Tesla.Mock.mock(fn
+ %{
+ url: "https://pawoo.net/.well-known/webfinger?resource=acct:pekorino@pawoo.net"
+ } ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/https___pawoo.net_users_pekorino.xml"),
+ headers: [{"content-type", "application/xrd+xml"}]
+ }}
+
+ %{url: "http://pawoo.net/.well-known/host-meta"} ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/pawoo.net_host_meta")
+ }}
+ end)
+
+ {:ok, _data} = WebFinger.finger("pekorino@pawoo.net")
+ end
end
end
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index 1328d6225..1e98020f0 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -122,7 +122,7 @@ defmodule HttpRequestMock do
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/tesla_mock/mike@osada.macgirvin.com.json"),
- headers: activitypub_object_headers()
+ headers: [{"content-type", "application/jrd+json"}]
}}
end
@@ -187,7 +187,8 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- body: File.read!("test/fixtures/tesla_mock/lain_squeet.me_webfinger.xml")
+ body: File.read!("test/fixtures/tesla_mock/lain_squeet.me_webfinger.xml"),
+ headers: [{"content-type", "application/xrd+xml"}]
}}
end
@@ -526,22 +527,6 @@ defmodule HttpRequestMock do
}}
end
- def get("http://zetsubou.xn--q9jyb4c/.well-known/host-meta", _, _, _) do
- {:ok,
- %Tesla.Env{
- status: 200,
- body: File.read!("test/fixtures/tesla_mock/xn--q9jyb4c_host_meta")
- }}
- end
-
- def get("https://zetsubou.xn--q9jyb4c/.well-known/host-meta", _, _, _) do
- {:ok,
- %Tesla.Env{
- status: 200,
- body: File.read!("test/fixtures/tesla_mock/xn--q9jyb4c_host_meta")
- }}
- end
-
def get("http://pleroma.soykaf.com/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
@@ -786,7 +771,8 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- body: File.read!("test/fixtures/tesla_mock/shp@social.heldscal.la.xml")
+ body: File.read!("test/fixtures/tesla_mock/shp@social.heldscal.la.xml"),
+ headers: [{"content-type", "application/xrd+xml"}]
}}
end
@@ -796,7 +782,7 @@ defmodule HttpRequestMock do
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
) do
- {:ok, %Tesla.Env{status: 200, body: ""}}
+ {:ok, %Tesla.Env{status: 200, body: "", headers: [{"content-type", "application/jrd+json"}]}}
end
def get("http://framatube.org/.well-known/host-meta", _, _, _) do
@@ -816,7 +802,7 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- headers: [{"content-type", "application/json"}],
+ headers: [{"content-type", "application/jrd+json"}],
body: File.read!("test/fixtures/tesla_mock/framasoft@framatube.org.json")
}}
end
@@ -876,7 +862,7 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- headers: [{"content-type", "application/json"}],
+ headers: [{"content-type", "application/jrd+json"}],
body: File.read!("test/fixtures/tesla_mock/kaniini@gerzilla.de.json")
}}
end
@@ -1074,7 +1060,8 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- body: File.read!("test/fixtures/lain.xml")
+ body: File.read!("test/fixtures/lain.xml"),
+ headers: [{"content-type", "application/xrd+xml"}]
}}
end
@@ -1087,7 +1074,16 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- body: File.read!("test/fixtures/lain.xml")
+ body: File.read!("test/fixtures/lain.xml"),
+ headers: [{"content-type", "application/xrd+xml"}]
+ }}
+ end
+
+ def get("http://zetsubou.xn--q9jyb4c/.well-known/host-meta", _, _, _) do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/host-meta-zetsubou.xn--q9jyb4c.xml")
}}
end
@@ -1153,7 +1149,8 @@ defmodule HttpRequestMock do
{:ok,
%Tesla.Env{
status: 200,
- body: File.read!("test/fixtures/tesla_mock/kpherox@mstdn.jp.xml")
+ body: File.read!("test/fixtures/tesla_mock/kpherox@mstdn.jp.xml"),
+ headers: [{"content-type", "application/xrd+xml"}]
}}
end