PluginProbe
ActivityPub / 5.7.0
ActivityPub v5.7.0
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/handler/class-announce.php +37 -75 9.2.05.7.0 View file →
@@ -6,16 +6,14 @@
6 6 */
7 7
8 8 namespace Activitypub\Handler;
9 9
10 -use Activitypub\Collection\Actors;
10 +use Activitypub\Http;
11 +use Activitypub\Comment;
11 12 use Activitypub\Collection\Interactions;
12 -use Activitypub\Comment;
13 -use Activitypub\Http;
14 13
15 -use function Activitypub\is_activity;
14 +use function Activitypub\object_to_uri;
16 15 use function Activitypub\is_activity_public;
17 -use function Activitypub\object_to_uri;
18 16
19 17 /**
20 18 * Handle Create requests.
21 19 */
@@ -23,9 +21,14 @@
23 21 /**
24 22 * Initialize the class, registering WordPress hooks.
25 23 */
26 24 public static function init() {
27 - \add_action( 'activitypub_inbox_announce', array( self::class, 'handle_announce' ), 10, 3 );
25 + \add_action(
26 + 'activitypub_inbox_announce',
27 + array( self::class, 'handle_announce' ),
28 + 10,
29 + 3
30 + );
28 31 }
29 32
30 33 /**
31 34 * Handles "Announce" requests.
@@ -30,12 +33,12 @@
30 33 /**
31 34 * Handles "Announce" requests.
32 35 *
33 36 * @param array $announcement The activity-object.
34 - * @param int|int[] $user_ids The id(s) of the local blog-user(s).
37 + * @param int $user_id The id of the local blog-user.
35 38 * @param \Activitypub\Activity\Activity $activity The activity object.
36 39 */
37 - public static function handle_announce( $announcement, $user_ids, $activity = null ) {
40 + public static function handle_announce( $announcement, $user_id, $activity = null ) {
38 41 // Check if Activity is public or not.
39 42 if ( ! is_activity_public( $announcement ) ) {
40 43 // @todo maybe send email
41 44 return;
@@ -40,60 +43,26 @@
40 43 // @todo maybe send email
41 44 return;
42 45 }
43 46
44 - // Ignore announces from the blog actor.
45 - if ( Actors::BLOG_USER_ID === Actors::get_id_by_resource( $announcement['actor'] ) ) {
46 - return;
47 - }
48 -
49 47 // Check if reposts are allowed.
50 48 if ( ! Comment::is_comment_type_enabled( 'repost' ) ) {
51 49 return;
52 50 }
53 51
54 - self::maybe_save_announce( $announcement, $user_ids );
52 + self::maybe_save_announce( $announcement, $user_id );
55 53
56 - $object_url = object_to_uri( $announcement['object'] );
57 -
58 - // Force no redirects for this object's request only, so the requested host stays the authoritative origin.
59 - $no_redirects = static function ( $args, $url ) use ( $object_url ) {
60 - if ( $url === $object_url ) {
61 - $args['redirection'] = 0;
62 - }
63 - return $args;
64 - };
65 -
66 - /*
67 - * Fetch the activity from its own id rather than the inline copy the Announce
68 - * carries: that copy is the announcer's, who is not necessarily the activity's
69 - * author. Redirects are forbidden (above) and the cache is bypassed so the
70 - * requested host is the authoritative origin — otherwise a redirect, or a
71 - * response cached from an earlier redirect-following fetch, could resolve to
72 - * attacker content while the host check below still saw the trusted host.
73 - */
74 - \add_filter( 'http_request_args', $no_redirects, 10, 2 );
75 - $object = Http::get_remote_object( $object_url, false );
76 - \remove_filter( 'http_request_args', $no_redirects, 10 );
77 -
78 - if ( ! $object || \is_wp_error( $object ) || ! \is_array( $object ) ) {
79 - return;
54 + if ( is_string( $announcement['object'] ) ) {
55 + $object = Http::get_remote_object( $announcement['object'] );
56 + } else {
57 + $object = $announcement['object'];
80 58 }
81 59
82 - if ( ! is_activity( $object ) ) {
60 + if ( ! $object || is_wp_error( $object ) ) {
83 61 return;
84 62 }
85 63
86 - $origin_host = \strtolower( (string) \wp_parse_url( (string) $object_url, \PHP_URL_HOST ) );
87 - $actor_host = \strtolower( (string) \wp_parse_url( (string) object_to_uri( $object['actor'] ?? '' ), \PHP_URL_HOST ) );
88 -
89 - /*
90 - * Only an actor's own server may vouch for an activity attributed to it, so the
91 - * host it was fetched from must equal its actor's host — the same key-host ==
92 - * actor-host binding verify_key_id() enforces for signed requests, generalised
93 - * to every relayed activity type.
94 - */
95 - if ( '' === $origin_host || '' === $actor_host || $origin_host !== $actor_host ) {
64 + if ( ! isset( $object['type'] ) ) {
96 65 return;
97 66 }
98 67
99 68 $type = \strtolower( $object['type'] );
@@ -101,63 +70,56 @@
101 70 /**
102 71 * Fires after an Announce has been received.
103 72 *
104 73 * @param array $object The object.
105 - * @param int[] $user_ids The ids of the local blog-users.
74 + * @param int $user_id The id of the local blog-user.
106 75 * @param string $type The type of the activity.
107 76 * @param \Activitypub\Activity\Activity|null $activity The activity object.
108 77 */
109 - \do_action( 'activitypub_inbox', $object, (array) $user_ids, $type, $activity );
78 + \do_action( 'activitypub_inbox', $object, $user_id, $type, $activity );
110 79
111 80 /**
112 81 * Fires after an Announce of a specific type has been received.
113 82 *
114 83 * @param array $object The object.
115 - * @param int[] $user_ids The ids of the local blog-users.
84 + * @param int $user_id The id of the local blog-user.
116 85 * @param \Activitypub\Activity\Activity|null $activity The activity object.
117 86 */
118 - \do_action( "activitypub_inbox_{$type}", $object, (array) $user_ids, $activity );
87 + \do_action( "activitypub_inbox_{$type}", $object, $user_id, $activity );
119 88 }
120 89
121 90 /**
122 91 * Try to save the Announce.
123 92 *
124 - * @param array $activity The activity-object.
125 - * @param int|int[] $user_ids The id of the local blog-user.
93 + * @param array $activity The activity-object.
94 + * @param int $user_id The id of the local blog-user.
126 95 */
127 - public static function maybe_save_announce( $activity, $user_ids ) {
128 - $url = object_to_uri( $activity );
96 + public static function maybe_save_announce( $activity, $user_id ) {
97 + $url = object_to_uri( $activity['object'] );
129 98
130 99 if ( empty( $url ) ) {
131 100 return;
132 101 }
133 102
134 - // Match any status, so a repost that was marked as spam or trashed still counts as seen.
135 - $exists = Comment::object_id_to_comment( \esc_url_raw( $url ), array( 'status' => 'any' ) );
103 + $exists = Comment::object_id_to_comment( esc_url_raw( $url ) );
136 104 if ( $exists ) {
137 105 return;
138 106 }
139 107
140 - // If the object is a Create activity, extract the actual object from it.
141 - if ( isset( $activity['object']['type'] ) && 'Create' === $activity['object']['type'] ) {
142 - $activity['object'] = object_to_uri( $activity['object']['object'] );
143 - }
108 + $state = Interactions::add_reaction( $activity );
109 + $reaction = null;
144 110
145 - $success = false;
146 - $result = Interactions::add_reaction( $activity );
147 -
148 - if ( $result && ! \is_wp_error( $result ) ) {
149 - $success = true;
150 - $result = \get_comment( $result );
111 + if ( $state && ! is_wp_error( $state ) ) {
112 + $reaction = get_comment( $state );
151 113 }
152 114
153 115 /**
154 - * Fires after an ActivityPub Announce activity has been handled.
116 + * Fires after an Announce has been saved.
155 117 *
156 - * @param array $activity The ActivityPub activity data.
157 - * @param int[] $user_ids The local user IDs.
158 - * @param bool $success True on success, false otherwise.
159 - * @param array|string|int|\WP_Error|false $result The WP_Comment object of the created announce/repost comment, or null if creation failed.
118 + * @param array $activity The activity-object.
119 + * @param int $user_id The id of the local blog-user.
120 + * @param mixed $state The state of the reaction.
121 + * @param mixed $reaction The reaction.
160 122 */
161 - \do_action( 'activitypub_handled_announce', $activity, (array) $user_ids, $success, $result );
123 + do_action( 'activitypub_handled_announce', $activity, $user_id, $state, $reaction );
162 124 }
163 125 }