Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85829845
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 92ea0182a..6d1d20ae8 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
alias Pleroma.Activity
alias Pleroma.Delivery
+ alias Pleroma.Emoji
alias Pleroma.HTML
alias Pleroma.Object
alias Pleroma.Object.Fetcher
@@ -554,7 +555,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
"context" => client_object_context(object)
})
- with :ok <- check_character_limit(object) do
+ with :ok <- check_character_limit(object),
+ :ok <- check_emoji_names(object) do
{:ok, Map.put(activity, "object", object)}
end
end
@@ -567,7 +569,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> Map.drop(~w(source generator))
|> normalize_client_content()
- with :ok <- check_character_limit(object) do
+ with :ok <- check_character_limit(object),
+ :ok <- check_emoji_names(object) do
{:ok, Map.put(activity, "object", object)}
end
end
@@ -634,6 +637,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
defp client_object_context(_object), do: Utils.generate_context_id()
+ # Clients may use emoji of other instances (remote images), but the names
+ # must be shortcodes. Installed emoji may have any name.
+ defp check_emoji_names(object) do
+ tag_names = for %{"type" => "Emoji", "name" => name} <- List.wrap(object["tag"]), do: name
+ names = Map.keys(if(is_map(object["emoji"]), do: object["emoji"], else: %{})) ++ tag_names
+
+ if Enum.all?(names, &valid_emoji_name?/1),
+ do: :ok,
+ else: {:error, "Invalid emoji name"}
+ end
+
+ defp valid_emoji_name?(name) when is_binary(name) do
+ name = String.trim(name, ":")
+ Emoji.custom?(":#{name}:") or Emoji.exist?(name)
+ end
+
+ defp valid_emoji_name?(_name), do: false
+
defp check_character_limit(object) do
length =
[object["content"], object["summary"], object["name"]]
diff --git a/lib/pleroma/web/activity_pub/object_validators/local_object_validator.ex b/lib/pleroma/web/activity_pub/object_validators/local_object_validator.ex
index 05f011d27..9d801b679 100644
--- a/lib/pleroma/web/activity_pub/object_validators/local_object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/local_object_validator.ex
@@ -10,7 +10,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LocalObjectValidator do
"""
alias Pleroma.Config
- alias Pleroma.Emoji
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
@@ -24,8 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LocalObjectValidator do
with :ok <- validate_in_reply_to(object, user),
:ok <- validate_quote(object, user),
- :ok <- validate_attachments(object, user, []),
- :ok <- validate_emoji(object) do
+ :ok <- validate_attachments(object, user, []) do
validate_type(object)
end
end
@@ -35,9 +33,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LocalObjectValidator do
def validate_update(%{"actor" => actor} = object, %Object{data: orig_data}) do
known_hrefs = Enum.flat_map(List.wrap(orig_data["attachment"]), &hrefs/1)
- with :ok <- validate_attachments(object, User.get_cached_by_ap_id(actor), known_hrefs) do
- validate_emoji(object)
- end
+ validate_attachments(object, User.get_cached_by_ap_id(actor), known_hrefs)
end
defp validate_type(%{"type" => "Question"} = question),
@@ -116,22 +112,4 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LocalObjectValidator do
end
defp own_upload?(_attachment, _user), do: false
-
- # Remote images are fine (clients use emoji of other instances), but the
- # names must be shortcodes. Installed emoji may have any name.
- defp validate_emoji(object) do
- tag_names = for %{"type" => "Emoji", "name" => name} <- List.wrap(object["tag"]), do: name
- names = Map.keys(object["emoji"] || %{}) ++ tag_names
-
- if Enum.all?(names, &valid_emoji_name?/1),
- do: :ok,
- else: {:error, "Invalid emoji name"}
- end
-
- defp valid_emoji_name?(name) when is_binary(name) do
- name = String.trim(name, ":")
- Emoji.custom?(":#{name}:") or Emoji.exist?(name)
- end
-
- defp valid_emoji_name?(_name), do: false
end
diff --git a/test/pleroma/web/activity_pub/activity_pub_controller_c2s_test.exs b/test/pleroma/web/activity_pub/activity_pub_controller_c2s_test.exs
index e0b1c1c9e..5a9d1d02c 100644
--- a/test/pleroma/web/activity_pub/activity_pub_controller_c2s_test.exs
+++ b/test/pleroma/web/activity_pub/activity_pub_controller_c2s_test.exs
@@ -437,7 +437,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerC2STest do
test "rejects emoji with invalid names", %{conn: conn} do
tag = emoji_tag("<b>x</b> visit evil.example", "https://remote.example/x.png")
- post_outbox(conn, insert(:user), note(%{"tag" => [tag]}), 400)
+ user = insert(:user)
+ post_outbox(conn, user, note(%{"tag" => [tag]}), 400)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "hi"})
+ object = %{"id" => post.data["object"], "type" => "Note", "content" => "x", "tag" => [tag]}
+ post_outbox(conn, user, %{"type" => "Update", "to" => [@public], "object" => object}, 400)
end
end
diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs
index b39da6cd0..e595c03d5 100644
--- a/test/pleroma/web/common_api_test.exs
+++ b/test/pleroma/web/common_api_test.exs
@@ -2146,6 +2146,34 @@ defmodule Pleroma.Web.CommonAPITest do
end
end
+ test "a reply copies remote emoji with unusual names from the replied post's summary" do
+ for name <- ["blob+cat", "ねこ"] do
+ remote_emoji_uri = "https://remote.org/emoji.png"
+
+ note =
+ insert(:note,
+ data: %{
+ "summary" => ":#{name}:",
+ "emoji" => %{name => remote_emoji_uri},
+ "tag" => [
+ %{"type" => "Emoji", "name" => name, "icon" => %{"url" => remote_emoji_uri}}
+ ]
+ }
+ )
+
+ note_activity = insert(:note_activity, note: note)
+
+ assert {:ok, reply} =
+ CommonAPI.post(insert(:user), %{
+ status: "reply",
+ spoiler_text: ":#{name}:",
+ in_reply_to_id: note_activity.id
+ })
+
+ assert reply.object.data["emoji"][name] == remote_emoji_uri
+ end
+ end
+
test "editing a post that copied a remote title with remote emoji should keep that emoji" do
remote_emoji_uri = "https://remote.org/emoji.png"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Nov 1, 12:50 AM (17 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1802010
Default Alt Text
(6 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline