PluginProbe
ActivityPub / 7.8.2
ActivityPub v7.8.2
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/class-query.php +16 -109 9.2.07.8.2 View file →
@@ -6,13 +6,11 @@
6 6 */
7 7
8 8 namespace Activitypub;
9 9
10 -use Activitypub\Activity\Extended_Object\Feature_Authorization;
11 10 use Activitypub\Activity\Extended_Object\Quote_Authorization;
12 11 use Activitypub\Collection\Actors;
13 12 use Activitypub\Collection\Outbox;
14 -use Activitypub\Handler\Feature_Request;
15 13 use Activitypub\Transformer\Factory;
16 14
17 15 /**
18 16 * Singleton class to handle and store the ActivityPub query.
@@ -140,17 +138,10 @@
140 138 */
141 139 private function prepare_activitypub_data() {
142 140 $queried_object = $this->get_queried_object();
143 141
144 - if ( \get_query_var( 'stamp' ) ) {
145 - if ( $queried_object instanceof \WP_Post ) {
146 - return $this->maybe_get_stamp();
147 - }
148 -
149 - // Note: the blog actor's `actor` query var is '0', which is falsy but valid.
150 - if ( $queried_object instanceof \WP_User || '' !== \get_query_var( 'actor' ) ) {
151 - return $this->maybe_get_actor_stamp();
152 - }
142 + if ( $queried_object instanceof \WP_Post && \get_query_var( 'stamp' ) ) {
143 + return $this->maybe_get_stamp();
153 144 }
154 145
155 146 // Check for Outbox Activity.
156 147 if (
@@ -228,9 +219,9 @@
228 219 * Filters the queried object.
229 220 *
230 221 * @param \WP_Term|\WP_Post_Type|\WP_Post|\WP_User|\WP_Comment|null $queried_object The queried object.
231 222 */
232 - return \apply_filters( 'activitypub_queried_object', $queried_object );
223 + return apply_filters( 'activitypub_queried_object', $queried_object );
233 224 }
234 225
235 226 /**
236 227 * Get the virtual object.
@@ -235,11 +226,12 @@
235 226 /**
236 227 * Get the virtual object.
237 228 *
238 229 * Virtual objects are objects that are not stored in the database, but are created on the fly.
239 - * The plugin currently supports one virtual object: The Blog-Actor.
230 + * The plugins currently supports two virtual objects: The Blog-Actor and the Application-Actor.
240 231 *
241 232 * @see \Activitypub\Model\Blog
233 + * @see \Activitypub\Model\Application
242 234 *
243 235 * @return object|null The virtual object.
244 236 */
245 237 protected function maybe_get_virtual_object() {
@@ -250,9 +242,9 @@
250 242 }
251 243
252 244 $author_id = url_to_authorid( $url );
253 245
254 - if ( ! \is_numeric( $author_id ) ) {
246 + if ( ! is_numeric( $author_id ) ) {
255 247 $author_id = $url;
256 248 }
257 249
258 250 $user = Actors::get_by_various( $author_id );
@@ -299,24 +291,19 @@
299 291 $this->is_activitypub_request = true;
300 292
301 293 // The other (more common) option to make an ActivityPub request is to send an Accept header.
302 294 } elseif ( isset( $_SERVER['HTTP_ACCEPT'] ) ) {
295 + $accept = \sanitize_text_field( \wp_unslash( $_SERVER['HTTP_ACCEPT'] ) );
296 +
303 297 /*
304 - * The Accept-header decision is delegated to is_json_only_accept() so the plugin and the
305 - * Surge cache drop-in classify byte-for-byte identically. Both must hand it the same raw
306 - * header, and they reach that raw form differently on purpose: this runs after
307 - * wp_magic_quotes() has addslashed $_SERVER, so it wp_unslash()es to recover the original
308 - * bytes; the drop-in runs before wp_magic_quotes() and passes its already-raw value
309 - * untouched. Do NOT sanitize it (the drop-in can't, its sanitizers aren't loaded yet) and
310 - * the helper must not stripslashes() either (that would corrupt the drop-in's genuine
311 - * bytes). It is only used to pick a content type, never stored or echoed.
312 - *
313 - * The request is ActivityPub only when *every* media type is JSON; a client that also
314 - * accepts HTML (e.g. a browser sending `text/html, application/activity+json`) gets the
315 - * normal HTML page.
298 + * $accept can be a single value, or a comma separated list of values.
299 + * We want to support both scenarios,
300 + * and return true when the header includes at least one of the following:
301 + * - application/activity+json
302 + * - application/ld+json
303 + * - application/json
316 304 */
317 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Classified only; wp_unslash() recovers the raw bytes the pre-plugin cache path sees, and it must not be sanitized.
318 - if ( is_json_only_accept( \wp_unslash( $_SERVER['HTTP_ACCEPT'] ) ) ) {
305 + if ( \preg_match( '/(application\/(ld\+json|activity\+json|json))/i', $accept ) ) {
319 306 \defined( 'ACTIVITYPUB_REQUEST' ) || \define( 'ACTIVITYPUB_REQUEST', true );
320 307 $this->is_activitypub_request = true;
321 308 }
322 309 }
@@ -350,12 +337,8 @@
350 337 if ( \get_option( 'activitypub_content_negotiation', '1' ) ) {
351 338 $return = true;
352 339 }
353 340
354 - if ( \is_author() && \get_user_option( 'activitypub_use_permalink_as_id', \get_queried_object_id() ) ) {
355 - $return = true;
356 - }
357 -
358 341 /**
359 342 * Filters whether content negotiation should be forced.
360 343 *
361 344 * @param bool $return Whether content negotiation should be forced.
@@ -413,20 +396,9 @@
413 396 if ( ! $meta ) {
414 397 return false;
415 398 }
416 399
417 - $post = $this->get_queried_object();
418 -
419 - /*
420 - * Only quote-authorization meta may be reflected as a stamp, and only for the queried
421 - * post. Checking the post id alone would still let an unauthenticated request read any
422 - * of that post's meta rows (e.g. _edit_lock or private custom fields) by guessing a
423 - * meta_id, so the meta key is verified too.
424 - */
425 - if ( '_activitypub_quoted_by' !== $meta->meta_key || (int) $meta->post_id !== $post->ID ) {
426 - return false;
427 - }
428 -
400 + $post = $this->get_queried_object();
429 401 $user_uri = get_user_id( $post->post_author );
430 402
431 403 if ( ! $user_uri ) {
432 404 return false;
@@ -447,73 +419,8 @@
447 419 $activitypub_object->set_interaction_target( get_post_id( $post->ID ) );
448 420
449 421 $this->activitypub_object = $activitypub_object;
450 422 $this->activitypub_object_id = $activitypub_object->get_id();
451 -
452 - return true;
453 - }
454 -
455 - /**
456 - * Maybe get a FeatureAuthorization object from an actor-scoped stamp.
457 - *
458 - * Resolves URLs of the form `?actor=USER_ID&stamp=STAMP_ID` against the
459 - * actor's stamp store, see {@see Feature_Request::get_stamp()}. Ownership
460 - * is enforced by resolving the stamp scoped to the queried actor, which
461 - * includes the blog actor (`actor=0`).
462 - *
463 - * @return bool True if a FeatureAuthorization was prepared, false otherwise.
464 - */
465 - private function maybe_get_actor_stamp() {
466 - $stamp_id = (int) \get_query_var( 'stamp' );
467 - $actor_var = \get_query_var( 'actor' );
468 -
469 - if ( ! $stamp_id ) {
470 - return false;
471 - }
472 -
473 - if ( '' === $actor_var ) {
474 - $queried = $this->get_queried_object();
475 - if ( ! $queried instanceof \WP_User ) {
476 - return false;
477 - }
478 -
479 - $actor_id = (int) $queried->ID;
480 - } else {
481 - // Values like '0e1' or '1.5' pass is_numeric() but cast to 0/1 and alias
482 - // an actor, so require a plain decimal integer before casting.
483 - if ( ! \ctype_digit( (string) $actor_var ) ) {
484 - return false;
485 - }
486 -
487 - $actor_id = (int) $actor_var;
488 - }
489 -
490 - $instrument = Feature_Request::get_stamp( $actor_id, $stamp_id );
491 - if ( null === $instrument ) {
492 - return false;
493 - }
494 -
495 - $actor = Actors::get_by_id( $actor_id );
496 - if ( \is_wp_error( $actor ) ) {
497 - return false;
498 - }
499 -
500 - $stamp_url = \add_query_arg(
501 - array(
502 - 'actor' => $actor_id,
503 - 'stamp' => $stamp_id,
504 - ),
505 - \home_url( '/' )
506 - );
507 -
508 - $authorization = new Feature_Authorization();
509 - $authorization->set_id( $stamp_url );
510 - $authorization->set_attributed_to( $actor->get_id() );
511 - $authorization->set_interacting_object( $instrument );
512 - $authorization->set_interaction_target( $actor->get_id() );
513 -
514 - $this->activitypub_object = $authorization;
515 - $this->activitypub_object_id = $authorization->get_id();
516 423
517 424 return true;
518 425 }
519 426 }