diff --git a/README.md b/README.md index 9de8b8f..969f562 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # ActivityPub # -**Contributors:** [pfefferle](https://profiles.wordpress.org/pfefferle/), [mediaformat](https://profiles.wordpress.org/mediaformat/), [akirk](https://profiles.wordpress.org/akirk/) -**Donate link:** https://notiz.blog/donate/ +**Contributors:** [pfefferle](https://profiles.wordpress.org/pfefferle/), [mediaformat](https://profiles.wordpress.org/mediaformat/), [akirk](https://profiles.wordpress.org/akirk/), [automattic](https://profiles.wordpress.org/automattic/) **Tags:** OStatus, fediverse, activitypub, activitystream **Requires at least:** 4.7 **Tested up to:** 6.1 -**Stable tag:** 0.16.2 +**Stable tag:** 0.17.0 **Requires PHP:** 5.6 **License:** MIT **License URI:** http://opensource.org/licenses/MIT @@ -88,6 +87,25 @@ Where 'blog' is the path to the subdirectory at which your blog resides. Project maintained on GitHub at [pfefferle/wordpress-activitypub](https://github.com/pfefferle/wordpress-activitypub). +### 0.17.0 ### + +* Fix type-selector +* Allow more HTML elements in Activity-Objects + +### 0.16.5 ### + +* Return empty content/excerpt on password protected posts/pages + +### 0.16.4 ### + +* Remove scripts later in the queue, to also handle scripts added by blocks +* Add published date to author profiles + +### 0.16.3 ### + +* "cc", "to", ... fields can either be an array or a string +* Remove "style" and "script" HTML elements from content + ### 0.16.2 ### * Fix fatal error in outbox diff --git a/activitypub.php b/activitypub.php index fe50550..f8633e8 100644 --- a/activitypub.php +++ b/activitypub.php @@ -3,9 +3,9 @@ * Plugin Name: ActivityPub * Plugin URI: https://github.com/pfefferle/wordpress-activitypub/ * Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format. - * Version: 0.16.2 - * Author: Matthias Pfefferle - * Author URI: https://notiz.blog/ + * Version: 0.17.0 + * Author: Matthias Pfefferle & Automattic + * Author URI: https://automattic.com/ * License: MIT * License URI: http://opensource.org/licenses/MIT * Requires PHP: 5.6 diff --git a/docker-compose-test.yml b/docker-compose-test.yml index a293823..4c69e44 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -1,6 +1,7 @@ version: '2' services: test-db: + platform: linux/x86_64 image: mysql:5.7 environment: MYSQL_DATABASE: activitypub-test diff --git a/includes/class-shortcodes.php b/includes/class-shortcodes.php index b6fc4ad..7289808 100644 --- a/includes/class-shortcodes.php +++ b/includes/class-shortcodes.php @@ -82,7 +82,7 @@ class Shortcodes { public static function excerpt( $atts, $content, $tag ) { $post = get_post(); - if ( ! $post ) { + if ( ! $post || \post_password_required( $post ) ) { return ''; } @@ -106,13 +106,11 @@ class Shortcodes { // An empty string will make wp_trim_excerpt do stuff we do not want. if ( '' !== $content ) { - $excerpt = \strip_shortcodes( $content ); /** This filter is documented in wp-includes/post-template.php */ $excerpt = \apply_filters( 'the_content', $excerpt ); $excerpt = \str_replace( ']]>', ']]>', $excerpt ); - } } @@ -187,7 +185,7 @@ class Shortcodes { public static function content( $atts, $content, $tag ) { $post = get_post(); - if ( ! $post ) { + if ( ! $post || \post_password_required( $post ) ) { return ''; } @@ -207,6 +205,11 @@ class Shortcodes { $content = wp_filter_content_tags( $content ); } + // replace script and style elements + $content = \preg_replace( '@<(script|style)[^>]*?>.*?\\1>@si', '', $content ); + + $content = \trim( \preg_replace( '/[\n\r\t]/', '', $content ) ); + return $content; } diff --git a/includes/model/class-post.php b/includes/model/class-post.php index 5546c88..d83384e 100644 --- a/includes/model/class-post.php +++ b/includes/model/class-post.php @@ -61,7 +61,7 @@ class Post { * * @var string */ - private $object_type = 'Note'; + private $object_type; /** * The Allowed Tags, used in the content. @@ -85,6 +85,23 @@ class Post { 'div' => array( 'class' => array(), ), + 'ul' => array(), + 'ol' => array(), + 'li' => array(), + 'strong' => array( + 'class' => array(), + ), + 'b' => array( + 'class' => array(), + ), + 'i' => array( + 'class' => array(), + ), + 'em' => array( + 'class' => array(), + ), + 'blockquote' => array(), + 'cite' => array(), ); /** @@ -385,12 +402,11 @@ class Post { wp_reset_postdata(); $content = \wpautop( \wp_kses( $content, $this->allowed_tags ) ); - - $filtered_content = \apply_filters( 'activitypub_the_content', $content, $post ); - $decoded_content = \html_entity_decode( $filtered_content, \ENT_QUOTES, 'UTF-8' ); - $content = \trim( \preg_replace( '/[\n\r\t]/', '', $content ) ); + $content = \apply_filters( 'activitypub_the_content', $content, $post ); + $content = \html_entity_decode( $content, \ENT_QUOTES, 'UTF-8' ); + $this->content = $content; return $content; @@ -403,15 +419,15 @@ class Post { */ public function get_post_content_template() { if ( 'excerpt' === \get_option( 'activitypub_post_content_type', 'content' ) ) { - return "[ap_excerpt]\n\n[ap_permalink]"; + return "[ap_excerpt]\n\n[ap_permalink type=\"html\"]"; } if ( 'title' === \get_option( 'activitypub_post_content_type', 'content' ) ) { - return "[ap_title]\n\n[ap_permalink]"; + return "[ap_title]\n\n[ap_permalink type=\"html\"]"; } if ( 'content' === \get_option( 'activitypub_post_content_type', 'content' ) ) { - return "[ap_content]\n\n[ap_hashtags]\n\n[ap_permalink]"; + return "[ap_content]\n\n[ap_hashtags]\n\n[ap_permalink type=\"html\"]"; } // Upgrade from old template codes to shortcodes. diff --git a/includes/rest/class-inbox.php b/includes/rest/class-inbox.php index 0067936..2ad5ea2 100644 --- a/includes/rest/class-inbox.php +++ b/includes/rest/class-inbox.php @@ -492,11 +492,21 @@ class Inbox { foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) { if ( array_key_exists( $i, $data ) ) { - $recipient_items = array_merge( $recipient_items, $data[ $i ] ); + if ( is_array( $data[ $i ] ) ) { + $recipient = $data[ $i ]; + } else { + $recipient = array( $data[ $i ] ); + } + $recipient_items = array_merge( $recipient_items, $recipient ); } if ( array_key_exists( $i, $data['object'] ) ) { - $recipient_items = array_merge( $recipient_items, $data[ $i ] ); + if ( is_array( $data['object'][ $i ] ) ) { + $recipient = $data['object'][ $i ]; + } else { + $recipient = array( $data['object'][ $i ] ); + } + $recipient_items = array_merge( $recipient_items, $recipient ); } } diff --git a/package.json b/package.json index b06ccaf..741ae18 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "activitypub", + "name": "wordpress-activitypub", "description": "The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.", "repository": { "type": "git", diff --git a/readme.txt b/readme.txt index ad6ad3d..63e1f6a 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,9 @@ === ActivityPub === -Contributors: pfefferle, mediaformat, akirk -Donate link: https://notiz.blog/donate/ +Contributors: pfefferle, mediaformat, akirk, automattic Tags: OStatus, fediverse, activitypub, activitystream Requires at least: 4.7 Tested up to: 6.1 -Stable tag: 0.16.2 +Stable tag: 0.17.0 Requires PHP: 5.6 License: MIT License URI: http://opensource.org/licenses/MIT @@ -88,6 +87,25 @@ Where 'blog' is the path to the subdirectory at which your blog resides. Project maintained on GitHub at [pfefferle/wordpress-activitypub](https://github.com/pfefferle/wordpress-activitypub). += 0.17.0 = + +* Fix type-selector +* Allow more HTML elements in Activity-Objects + += 0.16.5 = + +* Return empty content/excerpt on password protected posts/pages + += 0.16.4 = + +* Remove scripts later in the queue, to also handle scripts added by blocks +* Add published date to author profiles + += 0.16.3 = + +* "cc", "to", ... fields can either be an array or a string +* Remove "style" and "script" HTML elements from content + = 0.16.2 = * Fix fatal error in outbox diff --git a/templates/author-json.php b/templates/author-json.php index 8c5951c..1003989 100644 --- a/templates/author-json.php +++ b/templates/author-json.php @@ -19,6 +19,8 @@ $json->icon = array( 'url' => \get_avatar_url( $author_id, array( 'size' => 120 ) ), ); +$json->published = \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( \get_the_author_meta( 'registered', $author_id ) ) ); + if ( \has_header_image() ) { $json->image = array( 'type' => 'Image', diff --git a/tests/test-class-activitypub-rest-inbox.php b/tests/test-class-activitypub-rest-inbox.php new file mode 100644 index 0000000..58f16f3 --- /dev/null +++ b/tests/test-class-activitypub-rest-inbox.php @@ -0,0 +1,75 @@ +assertEquals( $check, Activitypub\Rest\Inbox::is_activity_public( $data ) ); + } + + public function the_data_provider() { + return array( + array( + array( + 'cc' => array( + 'https://example.org/@test', + 'https://example.com/@test2', + ), + 'to' => 'https://www.w3.org/ns/activitystreams#Public', + 'object' => array(), + ), + true, + ), + array( + array( + 'cc' => array( + 'https://example.org/@test', + 'https://example.com/@test2', + ), + 'to' => array( + 'https://www.w3.org/ns/activitystreams#Public', + ), + 'object' => array(), + ), + true, + ), + array( + array( + 'cc' => array( + 'https://example.org/@test', + 'https://example.com/@test2', + ), + 'object' => array(), + ), + false, + ), + array( + array( + 'cc' => array( + 'https://example.org/@test', + 'https://example.com/@test2', + ), + 'object' => array( + 'to' => 'https://www.w3.org/ns/activitystreams#Public', + ), + ), + true, + ), + array( + array( + 'cc' => array( + 'https://example.org/@test', + 'https://example.com/@test2', + ), + 'object' => array( + 'to' => array( + 'https://www.w3.org/ns/activitystreams#Public', + ), + ), + ), + true, + ), + ); + } +} diff --git a/tests/test-class-activitypub-shortcodes.php b/tests/test-class-activitypub-shortcodes.php new file mode 100644 index 0000000..5ba69d9 --- /dev/null +++ b/tests/test-class-activitypub-shortcodes.php @@ -0,0 +1,59 @@ +ID = $post_id; + $post->post_author = 1; + $post->post_date = current_time( 'mysql' ); + $post->post_date_gmt = current_time( 'mysql', 1 ); + $post->post_title = 'Some title or other'; + $post->post_content = 'hallo'; + $post->post_status = 'publish'; + $post->comment_status = 'closed'; + $post->ping_status = 'closed'; + $post->post_name = 'fake-page-' . rand( 1, 99999 ); // append random number to avoid clash + $post->post_type = 'page'; + $post->filter = 'raw'; // important! + + $content = '[ap_content]'; + + // Fill in the shortcodes. + setup_postdata( $post ); + $content = do_shortcode( $content ); + wp_reset_postdata(); + + $this->assertEquals( '
hallo
', $content ); + } + + public function test_password_protected_content() { + global $post; + + $post_id = -98; // negative ID, to avoid clash with a valid post + $post = new stdClass(); + $post->ID = $post_id; + $post->post_author = 1; + $post->post_date = current_time( 'mysql' ); + $post->post_date_gmt = current_time( 'mysql', 1 ); + $post->post_title = 'Some title or other'; + $post->post_content = 'hallo'; + $post->post_status = 'publish'; + $post->comment_status = 'closed'; + $post->ping_status = 'closed'; + $post->post_name = 'fake-page-' . rand( 1, 99999 ); // append random number to avoid clash + $post->post_type = 'page'; + $post->post_password = 'abc'; + $post->filter = 'raw'; // important! + + $content = '[ap_content]'; + + // Fill in the shortcodes. + setup_postdata( $post ); + $content = do_shortcode( $content ); + wp_reset_postdata(); + + $this->assertEquals( '', $content ); + } +}