PluginProbe
ActivityPub / 7.7.0
ActivityPub v7.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 +9 -54 9.3.07.7.0 View file →
@@ -13,9 +13,8 @@
13 13 use Activitypub\Http;
14 14
15 15 use function Activitypub\is_activity;
16 16 use function Activitypub\is_activity_public;
17 -use function Activitypub\is_same_host;
18 17 use function Activitypub\object_to_uri;
19 18
20 19 /**
21 20 * Handle Create requests.
@@ -53,31 +52,15 @@
53 52 }
54 53
55 54 self::maybe_save_announce( $announcement, $user_ids );
56 55
57 - $object_url = object_to_uri( $announcement['object'] );
56 + if ( is_string( $announcement['object'] ) ) {
57 + $object = Http::get_remote_object( $announcement['object'] );
58 + } else {
59 + $object = $announcement['object'];
60 + }
58 61
59 - // Force no redirects for this object's request only, so the requested host stays the authoritative origin.
60 - $no_redirects = static function ( $args, $url ) use ( $object_url ) {
61 - if ( $url === $object_url ) {
62 - $args['redirection'] = 0;
63 - }
64 - return $args;
65 - };
66 -
67 - /*
68 - * Fetch the activity from its own id rather than the inline copy the Announce
69 - * carries: that copy is the announcer's, who is not necessarily the activity's
70 - * author. Redirects are forbidden (above) and the cache is bypassed so the
71 - * requested host is the authoritative origin — otherwise a redirect, or a
72 - * response cached from an earlier redirect-following fetch, could resolve to
73 - * attacker content while the host check below still saw the trusted host.
74 - */
75 - \add_filter( 'http_request_args', $no_redirects, 10, 2 );
76 - $object = Http::get_remote_object( $object_url, false );
77 - \remove_filter( 'http_request_args', $no_redirects, 10 );
78 -
79 - if ( ! $object || \is_wp_error( $object ) || ! \is_array( $object ) ) {
62 + if ( ! $object || is_wp_error( $object ) ) {
80 63 return;
81 64 }
82 65
83 66 if ( ! is_activity( $object ) ) {
@@ -83,35 +66,8 @@
83 66 if ( ! is_activity( $object ) ) {
84 67 return;
85 68 }
86 69
87 - /*
88 - * Only an actor's own server may vouch for an activity attributed to it, so the
89 - * host it was fetched from must equal its actor's host — the same key-host ==
90 - * actor-host binding verify_key_id() enforces for signed requests, generalised
91 - * to every relayed activity type.
92 - */
93 - if ( ! is_same_host( $object_url, $object['actor'] ?? '' ) ) {
94 - return;
95 - }
96 -
97 - /*
98 - * The requested URL is not always the host that answered: get_remote_object() re-fetches a
99 - * document from the id it declares when the two disagree, and returns the re-fetched copy.
100 - * Bind the actor to that id as well, which an authentic activity shares a host with.
101 - *
102 - * Only when the document declares one. The id is derived exactly as get_remote_object()
103 - * derives it, so the two cannot disagree about what counts as declared: whatever it treats
104 - * as id-less it returns as served, without re-fetching, and the origin check above is
105 - * already authoritative for those. Binding them here would drop relayed activities that
106 - * legitimately omit an id.
107 - */
108 - $declared_id = isset( $object['id'] ) && \is_string( $object['id'] ) ? $object['id'] : '';
109 -
110 - if ( '' !== $declared_id && ! is_same_host( $declared_id, $object['actor'] ?? '' ) ) {
111 - return;
112 - }
113 -
114 70 $type = \strtolower( $object['type'] );
115 71
116 72 /**
117 73 * Fires after an Announce has been received.
@@ -145,10 +101,9 @@
145 101 if ( empty( $url ) ) {
146 102 return;
147 103 }
148 104
149 - // Match any status, so a repost that was marked as spam or trashed still counts as seen.
150 - $exists = Comment::object_id_to_comment( \esc_url_raw( $url ), array( 'status' => 'any' ) );
105 + $exists = Comment::object_id_to_comment( esc_url_raw( $url ) );
151 106 if ( $exists ) {
152 107 return;
153 108 }
154 109
@@ -159,11 +114,11 @@
159 114
160 115 $success = false;
161 116 $result = Interactions::add_reaction( $activity );
162 117
163 - if ( $result && ! \is_wp_error( $result ) ) {
118 + if ( $result && ! is_wp_error( $result ) ) {
164 119 $success = true;
165 - $result = \get_comment( $result );
120 + $result = get_comment( $result );
166 121 }
167 122
168 123 /**
169 124 * Fires after an ActivityPub Announce activity has been handled.