logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/
commit: 19f3e2050eb77d9231bb3ca4c8bd056981e96018
parent 2c20b3fc046a7bfaf9e75d3add2383998282e033
Author: Lain Soykaf <lain@lain.com>
Date:   Tue,  6 Jan 2026 15:12:49 +0400

Emoji: Handle more edge cases for local emoji with strange filenames.

Diffstat:

Mlib/pleroma/emoji.ex19++++++++++++++++++-
Mlib/pleroma/emoji/formatter.ex3+--
Mlib/pleroma/web/activity_pub/builder.ex3+--
Mlib/pleroma/web/mastodon_api/views/custom_emoji_view.ex3+--
Mlib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex3+--
Mtest/pleroma/web/activity_pub/transmogrifier/emoji_tag_building_test.exs30++++++++++++++++++++++++++++--
6 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/lib/pleroma/emoji.ex b/lib/pleroma/emoji.ex @@ -11,6 +11,8 @@ defmodule Pleroma.Emoji do alias Pleroma.Emoji.Combinations alias Pleroma.Emoji.Loader + alias Pleroma.Utils.URIEncoding + alias Pleroma.Web.Endpoint require Logger @@ -189,8 +191,23 @@ defmodule Pleroma.Emoji do def emoji_url(_), do: nil + @spec local_url(String.t() | nil) :: String.t() | nil + def local_url(nil), do: nil + + def local_url("http" <> _ = url) do + URIEncoding.encode_url(url) + end + + def local_url("/" <> _ = path) do + URIEncoding.encode_url(Endpoint.url() <> path, bypass_decode: true) + end + + def local_url(path) when is_binary(path) do + local_url("/" <> path) + end + def build_emoji_tag({name, url}) do - url = URI.encode(url) + url = URIEncoding.encode_url(url) %{ "icon" => %{"url" => "#{url}", "type" => "Image"}, diff --git a/lib/pleroma/emoji/formatter.ex b/lib/pleroma/emoji/formatter.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Emoji.Formatter do alias Pleroma.Emoji alias Pleroma.HTML - alias Pleroma.Web.Endpoint alias Pleroma.Web.MediaProxy def emojify(text) do @@ -44,7 +43,7 @@ defmodule Pleroma.Emoji.Formatter do Emoji.get_all() |> Enum.filter(fn {emoji, %Emoji{}} -> String.contains?(text, ":#{emoji}:") end) |> Enum.reduce(%{}, fn {name, %Emoji{file: file}}, acc -> - Map.put(acc, name, to_string(URI.merge(Endpoint.url(), file))) + Map.put(acc, name, Emoji.local_url(file)) end) end diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex @@ -17,7 +17,6 @@ defmodule Pleroma.Web.ActivityPub.Builder do alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.CommonAPI.ActivityDraft - alias Pleroma.Web.Endpoint require Pleroma.Constants @@ -105,7 +104,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do defp local_custom_emoji_react(data, emoji) do with %{file: path} = emojo <- Emoji.get(emoji) do - url = "#{Endpoint.url()}#{path}" + url = Emoji.local_url(path) add_emoji_content(data, emojo.code, url) else _ -> {:error, "Emoji does not exist"} diff --git a/lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex b/lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex @@ -6,14 +6,13 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiView do use Pleroma.Web, :view alias Pleroma.Emoji - alias Pleroma.Web.Endpoint def render("index.json", %{custom_emojis: custom_emojis}) do render_many(custom_emojis, __MODULE__, "show.json") end def render("show.json", %{custom_emoji: {shortcode, %Emoji{file: relative_url, tags: tags}}}) do - url = Endpoint.url() |> URI.merge(relative_url) |> to_string() + url = Emoji.local_url(relative_url) %{ "shortcode" => shortcode, diff --git a/lib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex b/lib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex @@ -7,7 +7,6 @@ defmodule Pleroma.Web.PleromaAPI.BookmarkFolderView do alias Pleroma.BookmarkFolder alias Pleroma.Emoji - alias Pleroma.Web.Endpoint def render("show.json", %{folder: %BookmarkFolder{} = folder}) do %{ @@ -33,7 +32,7 @@ defmodule Pleroma.Web.PleromaAPI.BookmarkFolderView do emoji = Emoji.get(emoji) if emoji != nil do - Endpoint.url() |> URI.merge(emoji.file) |> to_string() + Emoji.local_url(emoji.file) else nil end diff --git a/test/pleroma/web/activity_pub/transmogrifier/emoji_tag_building_test.exs b/test/pleroma/web/activity_pub/transmogrifier/emoji_tag_building_test.exs @@ -1,8 +1,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiTagBuildingTest do use Pleroma.DataCase, async: true - alias Pleroma.Web.ActivityPub.Transmogrifier - test "it encodes the id to be a valid url" do name = "hanapog" url = "https://misskey.local.live/emojis/hana pog.png" @@ -11,4 +9,32 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiTagBuildingTest do assert tag["id"] == "https://misskey.local.live/emojis/hana%20pog.png" end + + test "it does not double-encode already encoded urls" do + name = "hanapog" + url = "https://misskey.local.live/emojis/hana%20pog.png" + + tag = Pleroma.Emoji.build_emoji_tag({name, url}) + + assert tag["id"] == url + end + + test "it encodes disallowed path characters" do + name = "hanapog" + url = "https://example.com/emojis/hana[pog].png" + + tag = Pleroma.Emoji.build_emoji_tag({name, url}) + + assert tag["id"] == "https://example.com/emojis/hana%5Bpog%5D.png" + end + + test "local_url does not decode percent in filenames" do + url = Pleroma.Emoji.local_url("/emoji/hana%20pog.png") + + assert url == Pleroma.Web.Endpoint.url() <> "/emoji/hana%2520pog.png" + + tag = Pleroma.Emoji.build_emoji_tag({"hanapog", url}) + + assert tag["id"] == url + end end