Page MenuHomePhorge

No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/rich_media/parser/card.ex b/lib/pleroma/web/rich_media/parser/card.ex
index b29db730b..abae06ab9 100644
--- a/lib/pleroma/web/rich_media/parser/card.ex
+++ b/lib/pleroma/web/rich_media/parser/card.ex
@@ -1,136 +1,145 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Parser.Card do
alias Pleroma.Web.RichMedia.Parser.Card
alias Pleroma.Web.RichMedia.Parser.Embed
@types ["link", "photo", "video", "rich"]
# https://docs.joinmastodon.org/entities/card/
defstruct url: nil,
title: nil,
description: "",
type: "link",
author_name: "",
author_url: "",
provider_name: "",
provider_url: "",
html: "",
width: 0,
height: 0,
image: nil,
embed_url: "",
blurhash: nil
def parse(%Embed{url: url, oembed: %{"type" => type, "title" => title} = oembed} = embed)
when type in @types and is_binary(url) do
uri = URI.parse(url)
%Card{
url: url,
title: title,
description: get_description(embed),
type: oembed["type"],
author_name: oembed["author_name"],
author_url: oembed["author_url"],
provider_name: oembed["provider_name"] || uri.host,
provider_url: oembed["provider_url"] || "#{uri.scheme}://#{uri.host}",
html: sanitize_html(oembed["html"]),
width: oembed["width"],
height: oembed["height"],
- image: get_image(oembed) |> proxy(),
- embed_url: oembed["url"] |> proxy()
+ image: get_image(oembed) |> fix_uri(url) |> proxy(),
+ embed_url: oembed["url"] |> fix_uri(url) |> proxy()
}
|> validate()
end
def parse(%Embed{url: url} = embed) when is_binary(url) do
uri = URI.parse(url)
%Card{
url: url,
title: get_title(embed),
description: get_description(embed),
type: "link",
provider_name: uri.host,
provider_url: "#{uri.scheme}://#{uri.host}",
- image: get_image(embed) |> proxy()
+ image: get_image(embed) |> fix_uri(url) |> proxy()
}
|> validate()
end
def parse(card), do: {:error, {:invalid_metadata, card}}
defp get_title(embed) do
case embed do
%{meta: %{"twitter:title" => title}} when is_binary(title) and title != "" -> title
%{meta: %{"og:title" => title}} when is_binary(title) and title != "" -> title
%{title: title} when is_binary(title) and title != "" -> title
_ -> nil
end
end
defp get_description(%{meta: meta}) do
case meta do
%{"twitter:description" => desc} when is_binary(desc) and desc != "" -> desc
%{"og:description" => desc} when is_binary(desc) and desc != "" -> desc
%{"description" => desc} when is_binary(desc) and desc != "" -> desc
_ -> ""
end
end
defp get_image(%{meta: meta}) do
case meta do
%{"twitter:image" => image} when is_binary(image) and image != "" -> image
%{"og:image" => image} when is_binary(image) and image != "" -> image
_ -> ""
end
end
defp get_image(%{"thumbnail_url" => image}) when is_binary(image) and image != "", do: image
defp get_image(%{"type" => "photo", "url" => image}), do: image
defp get_image(_), do: ""
defp sanitize_html(html) do
with {:ok, html} <- FastSanitize.Sanitizer.scrub(html, Pleroma.HTML.Scrubber.OEmbed),
{:ok, [{"iframe", _, _}]} <- Floki.parse_fragment(html) do
html
else
_ -> ""
end
end
def to_map(%Card{} = card) do
card
|> Map.from_struct()
|> stringify_keys()
end
def to_map(%{} = card), do: stringify_keys(card)
defp stringify_keys(%{} = map), do: Map.new(map, fn {k, v} -> {Atom.to_string(k), v} end)
+ def fix_uri("http://" <> _ = uri, _base_uri), do: uri
+ def fix_uri("https://" <> _ = uri, _base_uri), do: uri
+ def fix_uri("/" <> _ = uri, base_uri), do: URI.merge(base_uri, uri) |> URI.to_string()
+
+ def fix_uri(uri, base_uri) when is_binary(uri),
+ do: URI.merge(base_uri, "/#{uri}") |> URI.to_string()
+
+ def fix_uri(_uri, _base_uri), do: nil
+
defp proxy(url) when is_binary(url), do: Pleroma.Web.MediaProxy.url(url)
defp proxy(_), do: nil
def validate(%Card{type: type, html: html} = card)
when type in ["video", "rich"] and (is_binary(html) == false or html == "") do
{:error, {:invalid_metadata, card}}
end
def validate(%Card{type: type, title: title} = card)
when type in @types and is_binary(title) and title != "" do
{:ok, card}
end
def validate(%Embed{} = embed) do
case Card.parse(embed) do
{:ok, %Card{} = card} -> validate(card)
card -> {:error, {:invalid_metadata, card}}
end
end
def validate(card), do: {:error, {:invalid_metadata, card}}
end
diff --git a/test/pleroma/web/rich_media/parser/card_test.exs b/test/pleroma/web/rich_media/parser/card_test.exs
index e09dfa6db..d85491f2e 100644
--- a/test/pleroma/web/rich_media/parser/card_test.exs
+++ b/test/pleroma/web/rich_media/parser/card_test.exs
@@ -1,48 +1,107 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Parser.CardTest do
use ExUnit.Case, async: true
alias Pleroma.Web.RichMedia.Parser.Card
alias Pleroma.Web.RichMedia.Parser.Embed
alias Pleroma.Web.RichMedia.Parsers.TwitterCard
describe "parse/1" do
test "converts an %Embed{} into a %Card{}" do
url =
"https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html"
embed =
File.read!("test/fixtures/nypd-facial-recognition-children-teenagers.html")
|> Floki.parse_document!()
|> TwitterCard.parse(%Embed{url: url})
expected = %Card{
description:
"With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
image:
"https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
title: "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
type: "link",
provider_name: "www.nytimes.com",
provider_url: "https://www.nytimes.com",
url: url
}
assert Card.parse(embed) == {:ok, expected}
end
+
+ test "converts URL paths into absolute URLs" do
+ embed = %Embed{
+ url: "https://spam.com/luigi",
+ title: "Watch Luigi not doing anything",
+ meta: %{
+ "og:image" => "/uploads/weegee.jpeg"
+ }
+ }
+
+ {:ok, card} = Card.parse(embed)
+ assert card.image == "https://spam.com/uploads/weegee.jpeg"
+ end
end
describe "validate/1" do
test "returns {:ok, card} with a valid %Card{}" do
card = %Card{
title: "Moms can't believe this one trick",
url: "http://spam.com",
type: "link"
}
assert {:ok, ^card} = Card.validate(card)
end
+
+ test "errors for video embeds without html" do
+ embed = %Embed{
+ url: "https://spam.com/xyz",
+ oembed: %{
+ "type" => "video",
+ "title" => "Yeeting soda cans"
+ }
+ }
+
+ assert {:error, {:invalid_metadata, _}} = Card.validate(embed)
+ end
+ end
+
+ describe "fix_uri/2" do
+ setup do: %{base_uri: "https://benis.xyz/hello/fam"}
+
+ test "two full URLs", %{base_uri: base_uri} do
+ uri = "https://benis.xyz/images/pic.jpeg"
+ assert Card.fix_uri(uri, base_uri) == uri
+ end
+
+ test "URI with leading slash", %{base_uri: base_uri} do
+ uri = "/images/pic.jpeg"
+ expected = "https://benis.xyz/images/pic.jpeg"
+ assert Card.fix_uri(uri, base_uri) == expected
+ end
+
+ test "URI without leading slash", %{base_uri: base_uri} do
+ uri = "images/pic.jpeg"
+ expected = "https://benis.xyz/images/pic.jpeg"
+ assert Card.fix_uri(uri, base_uri) == expected
+ end
+
+ test "nil URI", %{base_uri: base_uri} do
+ assert Card.fix_uri(nil, base_uri) == nil
+ end
+
+ # https://github.com/elixir-lang/elixir/issues/10771
+ test "Elixir #10771", _ do
+ uri =
+ "https://images.macrumors.com/t/4riJyi1XC906qyJ41nAfOgpvo1I=/1600x/https://images.macrumors.com/article-new/2020/09/spatialaudiofeature.jpg"
+
+ base_uri = "https://www.macrumors.com/guide/apps-support-apples-spatial-audio-feature/"
+ assert Card.fix_uri(uri, base_uri) == uri
+ end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 19, 8:24 AM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769187
Default Alt Text
(8 KB)

Event Timeline