diff options
| author | dcc <dcc@logografos.com> | 2024-05-15 00:57:23 -0700 |
|---|---|---|
| committer | dcc <dcc@logografos.com> | 2024-05-15 00:57:23 -0700 |
| commit | b31a934a804aed3f35442ceafe2080b0955e7317 (patch) | |
| tree | 947b13a0388ecea81e05dd980baa10f7546860b9 /lib/pleroma/web/activity_pub/mrf | |
| parent | ea33a0d3427f8b30b82a6ddbc0ff7429cfaf8d91 (diff) | |
| download | anni-master.tar.gz anni-master.tar.bz2 anni-master.zip | |
Diffstat (limited to 'lib/pleroma/web/activity_pub/mrf')
32 files changed, 512 insertions, 38 deletions
diff --git a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex index 88f6ca0..88f6ca0 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex index 97d75ec..df4ba81 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex @@ -56,8 +56,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do nick_score + name_score + actor_type_score end - defp determine_if_followbot(_), do: 0.0 - defp bot_allowed?(%{"object" => target}, bot_actor) do %User{} = user = normalize_by_ap_id(target) diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex index 3ec9c52..3ec9c52 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex index ad09368..ad09368 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex new file mode 100644 index 0000000..f884962 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex @@ -0,0 +1,281 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do + require Pleroma.Constants + + alias Pleroma.Object.Updater + alias Pleroma.Web.ActivityPub.MRF.Utils + + @moduledoc "Reject or force-unlisted emojis with certain URLs or names" + + @behaviour Pleroma.Web.ActivityPub.MRF.Policy + + defp config_remove_url do + Pleroma.Config.get([:mrf_emoji, :remove_url], []) + end + + defp config_remove_shortcode do + Pleroma.Config.get([:mrf_emoji, :remove_shortcode], []) + end + + defp config_unlist_url do + Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_url], []) + end + + defp config_unlist_shortcode do + Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_shortcode], []) + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def history_awareness, do: :manual + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = message) + when type in ["Create", "Update"] and objtype in Pleroma.Constants.status_object_types() do + with {:ok, object} <- + Updater.do_with_history(object, fn object -> + {:ok, process_remove(object, :url, config_remove_url())} + end), + {:ok, object} <- + Updater.do_with_history(object, fn object -> + {:ok, process_remove(object, :shortcode, config_remove_shortcode())} + end), + activity <- Map.put(message, "object", object), + activity <- maybe_delist(activity) do + {:ok, activity} + end + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def filter(%{"type" => type} = object) when type in Pleroma.Constants.actor_types() do + with object <- process_remove(object, :url, config_remove_url()), + object <- process_remove(object, :shortcode, config_remove_shortcode()) do + {:ok, object} + end + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def filter(%{"type" => "EmojiReact"} = object) do + with {:ok, _} <- + matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do + {:ok, object} + else + _ -> + {:reject, "[EmojiPolicy] Rejected for having disallowed emoji"} + end + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def filter(message) do + {:ok, message} + end + + defp match_string?(string, pattern) when is_binary(pattern) do + string == pattern + end + + defp match_string?(string, %Regex{} = pattern) do + String.match?(string, pattern) + end + + defp match_any?(string, patterns) do + Enum.any?(patterns, &match_string?(string, &1)) + end + + defp url_from_tag(%{"icon" => %{"url" => url}}), do: url + defp url_from_tag(_), do: nil + + defp url_from_emoji({_name, url}), do: url + + defp shortcode_from_tag(%{"name" => name}) when is_binary(name), do: String.trim(name, ":") + defp shortcode_from_tag(_), do: nil + + defp shortcode_from_emoji({name, _url}), do: name + + defp process_remove(object, :url, patterns) do + process_remove_impl(object, &url_from_tag/1, &url_from_emoji/1, patterns) + end + + defp process_remove(object, :shortcode, patterns) do + process_remove_impl(object, &shortcode_from_tag/1, &shortcode_from_emoji/1, patterns) + end + + defp process_remove_impl(object, extract_from_tag, extract_from_emoji, patterns) do + object = + if object["tag"] do + Map.put( + object, + "tag", + Enum.filter( + object["tag"], + fn + %{"type" => "Emoji"} = tag -> + str = extract_from_tag.(tag) + + if is_binary(str) do + not match_any?(str, patterns) + else + true + end + + _ -> + true + end + ) + ) + else + object + end + + object = + if object["emoji"] do + Map.put( + object, + "emoji", + object["emoji"] + |> Enum.reduce(%{}, fn {name, url} = emoji, acc -> + if not match_any?(extract_from_emoji.(emoji), patterns) do + Map.put(acc, name, url) + else + acc + end + end) + ) + else + object + end + + object + end + + defp matched_emoji_checker(urls, shortcodes) do + fn object -> + if any_emoji_match?(object, &url_from_tag/1, &url_from_emoji/1, urls) or + any_emoji_match?( + object, + &shortcode_from_tag/1, + &shortcode_from_emoji/1, + shortcodes + ) do + {:matched, nil} + else + {:ok, %{}} + end + end + end + + defp maybe_delist(%{"object" => object, "to" => to, "type" => "Create"} = activity) do + check = matched_emoji_checker(config_unlist_url(), config_unlist_shortcode()) + + should_delist? = fn object -> + with {:ok, _} <- Pleroma.Object.Updater.do_with_history(object, check) do + false + else + _ -> true + end + end + + if Pleroma.Constants.as_public() in to and should_delist?.(object) do + to = List.delete(to, Pleroma.Constants.as_public()) + cc = [Pleroma.Constants.as_public() | activity["cc"] || []] + + activity + |> Map.put("to", to) + |> Map.put("cc", cc) + else + activity + end + end + + defp maybe_delist(activity), do: activity + + defp any_emoji_match?(object, extract_from_tag, extract_from_emoji, patterns) do + Kernel.||( + Enum.any?( + object["tag"] || [], + fn + %{"type" => "Emoji"} = tag -> + str = extract_from_tag.(tag) + + if is_binary(str) do + match_any?(str, patterns) + else + false + end + + _ -> + false + end + ), + (object["emoji"] || []) + |> Enum.any?(fn emoji -> match_any?(extract_from_emoji.(emoji), patterns) end) + ) + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def describe do + mrf_emoji = + Pleroma.Config.get(:mrf_emoji, []) + |> Enum.map(fn {key, value} -> + {key, Enum.map(value, &Utils.describe_regex_or_string/1)} + end) + |> Enum.into(%{}) + + {:ok, %{mrf_emoji: mrf_emoji}} + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def config_description do + %{ + key: :mrf_emoji, + related_policy: "Pleroma.Web.ActivityPub.MRF.EmojiPolicy", + label: "MRF Emoji", + description: + "Reject or force-unlisted emojis whose URLs or names match a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).", + children: [ + %{ + key: :remove_url, + type: {:list, :string}, + description: """ + A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles. + + Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`. + """, + suggestions: ["https://example.org/foo.png", ~r/example.org\/foo/iu] + }, + %{ + key: :remove_shortcode, + type: {:list, :string}, + description: """ + A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles. + + Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`. + """, + suggestions: ["foo", ~r/foo/iu] + }, + %{ + key: :federated_timeline_removal_url, + type: {:list, :string}, + description: """ + A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses. + + Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`. + """, + suggestions: ["https://example.org/foo.png", ~r/example.org\/foo/iu] + }, + %{ + key: :federated_timeline_removal_shortcode, + type: {:list, :string}, + description: """ + A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses. + + Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`. + """, + suggestions: ["foo", ~r/foo/iu] + } + ] + } + end +end diff --git a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex index a148cc1..a148cc1 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex +++ b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex diff --git a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex index 5b6adbb..5a4a976 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do try_follow(follower, message) else nil -> - Logger.warn( + Logger.warning( "#{__MODULE__} skipped because of missing `:mrf_follow_bot, :follower_nickname` configuration, the :follower_nickname account does not exist, or the account is not correctly configured as a bot." ) diff --git a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex index 8cec8ea..8cec8ea 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/force_mention.ex b/lib/pleroma/web/activity_pub/mrf/force_mention.ex new file mode 100644 index 0000000..3853489 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/force_mention.ex @@ -0,0 +1,59 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do + require Pleroma.Constants + + alias Pleroma.Config + alias Pleroma.Object + alias Pleroma.User + + @behaviour Pleroma.Web.ActivityPub.MRF.Policy + + defp get_author(url) do + with %Object{data: %{"actor" => actor}} <- Object.normalize(url, fetch: false), + %User{ap_id: ap_id, nickname: nickname} <- User.get_cached_by_ap_id(actor) do + %{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"} + else + _ -> nil + end + end + + defp prepend_author(tags, _, false), do: tags + + defp prepend_author(tags, nil, _), do: tags + + defp prepend_author(tags, url, _) do + actor = get_author(url) + + if not is_nil(actor) do + [actor | tags] + else + tags + end + end + + @impl true + def filter(%{"type" => "Create", "object" => %{"tag" => tag} = object} = activity) do + tag = + tag + |> prepend_author( + object["inReplyTo"], + Config.get([:mrf_force_mention, :mention_parent, true]) + ) + |> prepend_author( + object["quoteUrl"], + Config.get([:mrf_force_mention, :mention_quoted, true]) + ) + |> Enum.uniq() + + {:ok, put_in(activity["object"]["tag"], tag)} + end + + @impl true + def filter(object), do: {:ok, object} + + @impl true + def describe, do: {:ok, %{}} +end diff --git a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex index 7022456..5532093 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex +++ b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do @@ -95,11 +95,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do |> Enum.reject(&is_nil/1) |> sort_replied_user(replied_to_user) - explicitly_mentioned_uris = extract_mention_uris_from_content(content) + explicitly_mentioned_uris = + extract_mention_uris_from_content(content) + |> MapSet.new() added_mentions = - Enum.reduce(mention_users, "", fn %User{ap_id: uri} = user, acc -> - unless uri in explicitly_mentioned_uris do + Enum.reduce(mention_users, "", fn %User{ap_id: ap_id, uri: uri} = user, acc -> + if MapSet.disjoint?(MapSet.new([ap_id, uri]), explicitly_mentioned_uris) do acc <> Formatter.mention_from_user(user, %{mentions_format: :compact}) <> " " else acc diff --git a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex index b73fd97..fdb9a9d 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do alias Pleroma.Object @moduledoc """ - Reject, TWKN-remove or Set-Sensitive messsages with specific hashtags (without the leading #) + Reject, TWKN-remove or Set-Sensitive messages with specific hashtags (without the leading #) Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists. """ @@ -84,7 +84,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do if hashtags != [] do with {:ok, message} <- check_reject(message, hashtags), {:ok, message} <- - (if "type" == "Create" do + (if type == "Create" do check_ftl_removal(message, hashtags) else {:ok, message} diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex index 80e235d..80e235d 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex new file mode 100644 index 0000000..b7a01c2 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex @@ -0,0 +1,77 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do + @moduledoc "Force a quote line into the message content." + @behaviour Pleroma.Web.ActivityPub.MRF.Policy + + defp build_inline_quote(template, url) do + quote_line = String.replace(template, "{url}", "<a href=\"#{url}\">#{url}</a>") + + "<span class=\"quote-inline\"><br/><br/>#{quote_line}</span>" + end + + defp has_inline_quote?(content, quote_url) do + cond do + # Does the quote URL exist in the content? + content =~ quote_url -> true + # Does the content already have a .quote-inline span? + content =~ "<span class=\"quote-inline\">" -> true + # No inline quote found + true -> false + end + end + + defp filter_object(%{"quoteUrl" => quote_url} = object) do + content = object["content"] || "" + + if has_inline_quote?(content, quote_url) do + object + else + template = Pleroma.Config.get([:mrf_inline_quote, :template]) + + content = + if String.ends_with?(content, "</p>"), + do: + String.trim_trailing(content, "</p>") <> + build_inline_quote(template, quote_url) <> "</p>", + else: content <> build_inline_quote(template, quote_url) + + Map.put(object, "content", content) + end + end + + @impl true + def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do + {:ok, Map.put(activity, "object", filter_object(object))} + end + + @impl true + def filter(object), do: {:ok, object} + + @impl true + def describe, do: {:ok, %{}} + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def history_awareness, do: :auto + + @impl true + def config_description do + %{ + key: :mrf_inline_quote, + related_policy: "Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy", + label: "MRF Inline Quote Policy", + description: "Force quote url to appear in post content.", + children: [ + %{ + key: :template, + type: :string, + description: + "The template to append to the post. `{url}` will be replaced with the actual link to the quoted post.", + suggestions: ["<bdi>RT:</bdi> {url}"] + } + ] + } + end +end diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex index 687ec6c..729da4e 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex @@ -5,18 +5,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do require Pleroma.Constants + alias Pleroma.Web.ActivityPub.MRF.Utils + @moduledoc "Reject or Word-Replace messages with a keyword or regex" @behaviour Pleroma.Web.ActivityPub.MRF.Policy - defp string_matches?(string, _) when not is_binary(string) do - false - end defp string_matches?(string, pattern) when is_binary(pattern) do String.contains?(string, pattern) end - defp string_matches?(string, pattern) do + defp string_matches?(string, %Regex{} = pattern) do String.match?(string, pattern) end @@ -128,7 +127,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do @impl true def describe do - # This horror is needed to convert regex sigils to strings mrf_keyword = Pleroma.Config.get(:mrf_keyword, []) |> Enum.map(fn {key, value} -> @@ -136,21 +134,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do Enum.map(value, fn {pattern, replacement} -> %{ - "pattern" => - if not is_binary(pattern) do - inspect(pattern) - else - pattern - end, + "pattern" => Utils.describe_regex_or_string(pattern), "replacement" => replacement } pattern -> - if not is_binary(pattern) do - inspect(pattern) - else - pattern - end + Utils.describe_regex_or_string(pattern) end)} end) |> Enum.into(%{}) diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex index c95d35b..c95d35b 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex index 8aa4f34..8aa4f34 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex index 855cda3..12bf4dd 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex @@ -10,9 +10,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do @impl true def filter(%{"actor" => actor} = object) do - with true <- is_local?(actor), - true <- is_eligible_type?(object), - true <- is_note?(object), + with true <- local?(actor), + true <- eligible_type?(object), + true <- note?(object), false <- has_attachment?(object), true <- only_mentions?(object) do {:reject, "[NoEmptyPolicy]"} @@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do def filter(object), do: {:ok, object} - defp is_local?(actor) do + defp local?(actor) do if actor |> String.starts_with?("#{Endpoint.url()}") do true else @@ -59,11 +59,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do defp only_mentions?(_), do: false - defp is_note?(%{"object" => %{"type" => "Note"}}), do: true - defp is_note?(_), do: false + defp note?(%{"object" => %{"type" => "Note"}}), do: true + defp note?(_), do: false - defp is_eligible_type?(%{"type" => type}) when type in ["Create", "Update"], do: true - defp is_eligible_type?(_), do: false + defp eligible_type?(%{"type" => type}) when type in ["Create", "Update"], do: true + defp eligible_type?(_), do: false @impl true def describe, do: {:ok, %{}} diff --git a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex index 8840c4f..8840c4f 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex index f81e9e5..f81e9e5 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex index 2dfc9a9..2dfc9a9 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex +++ b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex diff --git a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex index df1a6dc..df1a6dc 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex b/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex index b2477fe..b2477fe 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex +++ b/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex diff --git a/lib/pleroma/web/activity_pub/mrf/policy.ex b/lib/pleroma/web/activity_pub/mrf/policy.ex index 0234de4..1f34883 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/policy.ex @@ -3,8 +3,8 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.MRF.Policy do - @callback filter(Map.t()) :: {:ok | :reject, Map.t()} - @callback describe() :: {:ok | :error, Map.t()} + @callback filter(map()) :: {:ok | :reject, map()} + @callback describe() :: {:ok | :error, map()} @callback config_description() :: %{ optional(:children) => [map()], key: atom(), diff --git a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex new file mode 100644 index 0000000..ac353f0 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex @@ -0,0 +1,49 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do + @moduledoc "Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions)" + @behaviour Pleroma.Web.ActivityPub.MRF.Policy + + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes + + require Pleroma.Constants + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do + {:ok, Map.put(activity, "object", filter_object(object))} + end + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def filter(object), do: {:ok, object} + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def describe, do: {:ok, %{}} + + @impl Pleroma.Web.ActivityPub.MRF.Policy + def history_awareness, do: :auto + + defp filter_object(%{"quoteUrl" => quote_url} = object) do + tags = object["tag"] || [] + + if Enum.any?(tags, fn tag -> + CommonFixes.object_link_tag?(tag) and tag["href"] == quote_url + end) do + object + else + object + |> Map.put( + "tag", + tags ++ + [ + %{ + "type" => "Link", + "mediaType" => Pleroma.Constants.activity_json_canonical_mime_type(), + "href" => quote_url + } + ] + ) + end + end +end diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex index 9d4a7a4..9d4a7a4 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex +++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex index 829ddea..829ddea 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex index f66c379..fa6b595 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex @@ -34,14 +34,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do |> Path.basename() |> Path.extname() - file_path = Path.join(emoji_dir_path, shortcode <> (extension || ".png")) + extension = if extension == "", do: ".png", else: extension + + shortcode = Path.basename(shortcode) + file_path = Path.join(emoji_dir_path, shortcode <> extension) case File.write(file_path, response.body) do :ok -> shortcode e -> - Logger.warn("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}") + Logger.warning("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}") nil end else @@ -53,7 +56,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do end else e -> - Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}") + Logger.warning("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}") nil end end @@ -76,6 +79,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do new_emojis = foreign_emojis |> Enum.reject(fn {shortcode, _url} -> shortcode in installed_emoji end) + |> Enum.reject(fn {shortcode, _url} -> String.contains?(shortcode, ["/", "\\"]) end) |> Enum.filter(fn {shortcode, _url} -> reject_emoji? = [:mrf_steal_emoji, :rejected_shortcodes] diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex index fdb9e51..fdb9e51 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex index 73760ca..73760ca 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex index e14047d..e14047d 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/utils.ex b/lib/pleroma/web/activity_pub/mrf/utils.ex new file mode 100644 index 0000000..f2dc9ee --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/utils.ex @@ -0,0 +1,15 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.Utils do + @spec describe_regex_or_string(String.t() | Regex.t()) :: String.t() + def describe_regex_or_string(pattern) do + # This horror is needed to convert regex sigils to strings + if not is_binary(pattern) do + inspect(pattern) + else + pattern + end + end +end diff --git a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex index d9deff3..d9deff3 100755..100644 --- a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex |
