From 71a6aab25a0ad3adc56345a3d91b546653c28088 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Fri, 9 May 2025 05:31:21 +0200 Subject: [PATCH 01/12] Fix broken rewrite rules (#524) --- includes/class-frontend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-frontend.php b/includes/class-frontend.php index 89a33efb..c35f3a01 100644 --- a/includes/class-frontend.php +++ b/includes/class-frontend.php @@ -99,7 +99,7 @@ private function register_hooks() { add_filter( 'friends_header_widget_title', array( $this, 'header_widget_title' ) ); add_filter( 'get_edit_post_link', array( $this, 'friend_post_edit_link' ) ); add_filter( 'template_include', array( $this, 'template_override' ) ); - add_filter( 'plugins_loaded', array( $this, 'add_rewrite_rule' ) ); + add_filter( 'wp_loaded', array( $this, 'add_rewrite_rule' ) ); add_filter( 'init', array( $this, 'register_friends_sidebar' ) ); add_action( 'init', array( $this, 'add_theme_supports' ) ); add_action( 'wp_ajax_friends_publish', array( $this, 'ajax_frontend_publish_post' ) ); From 174537c4a684d7077f2f927ceb5d4e4168aaa1a2 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Fri, 9 May 2025 05:32:38 +0200 Subject: [PATCH 02/12] Fix undefined user_id variable (#525) --- feed-parsers/class-feed-parser-activitypub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feed-parsers/class-feed-parser-activitypub.php b/feed-parsers/class-feed-parser-activitypub.php index 921a9a2e..7f727df1 100644 --- a/feed-parsers/class-feed-parser-activitypub.php +++ b/feed-parsers/class-feed-parser-activitypub.php @@ -415,7 +415,7 @@ public function friends_send_direct_message( $post_id, User $friend_user, $to, $ require_once __DIR__ . '/activitypub/class-activitypub-transformer-message.php'; - $user_id = $this->get_activitypub_actor_id( $user_id ); + $user_id = $this->get_activitypub_actor_id( get_current_user_id() ); $actor = $this->get_activitypub_actor( $user_id ); if ( ! $actor ) { return $post_id; From 1c6db3f06b3be3ade6ce236ccbf03ed367f92265 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Fri, 9 May 2025 05:35:09 +0200 Subject: [PATCH 03/12] Version bump + Changelog --- CHANGELOG.md | 7 +++++++ README.md | 9 ++++++++- friends.php | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 263a0dfb..78746ab5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 3.5.1 +- Fix undefined user_id variable ([#525]) +- Fix broken rewrite rules ([#524]) + ### 3.5.0 - Prevent friends page running wide in compact view ([#522]) - Prevent fatal for boosted post ([#521]) @@ -655,3 +659,6 @@ Hoping that this hardening will bring back the plugin to the WordPress.org direc [#520]: https://github.com/akirk/friends/pull/520 [#521]: https://github.com/akirk/friends/pull/521 [#522]: https://github.com/akirk/friends/pull/522 + +[#524]: https://github.com/akirk/friends/pull/524 +[#525]: https://github.com/akirk/friends/pull/525 diff --git a/README.md b/README.md index 1851bc4d..2d7de11d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ - Requires PHP: 7.2 - Tested up to: 6.8 - License: GPL-2.0-or-later -- Stable tag: 3.5.0 +- Stable tag: 3.5.1 Your own WordPress at the center of your online activity. Follow friends and other websites and establish friendship relationships between blogs. @@ -96,6 +96,10 @@ There is a cache of your friends post in form of a Custom Post Type friend_post ## Changelog +### 3.5.1 +- Fix undefined user_id variable ([#525]) +- Fix broken rewrite rules ([#524]) + ### 3.5.0 - Prevent friends page running wide in compact view ([#522]) - Prevent fatal for boosted post ([#521]) @@ -396,3 +400,6 @@ Hoping that this hardening will bring back the plugin to the WordPress.org direc [#520]: https://github.com/akirk/friends/pull/520 [#521]: https://github.com/akirk/friends/pull/521 [#522]: https://github.com/akirk/friends/pull/522 + +[#524]: https://github.com/akirk/friends/pull/524 +[#525]: https://github.com/akirk/friends/pull/525 diff --git a/friends.php b/friends.php index 80d5998d..7f0c0bbd 100644 --- a/friends.php +++ b/friends.php @@ -3,7 +3,7 @@ * Plugin name: Friends * Plugin author: Alex Kirk * Plugin URI: https://github.com/akirk/friends - * Version: 3.5.0 + * Version: 3.5.1 * Requires PHP: 5.6 * Description: A social network between WordPresses. Privacy focused, by itself a self-hosted RSS++ reader with notifications. @@ -25,7 +25,7 @@ define( 'FRIENDS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'FRIENDS_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); define( 'FRIENDS_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . '/' . basename( __FILE__ ) ); -define( 'FRIENDS_VERSION', '3.5.0' ); +define( 'FRIENDS_VERSION', '3.5.1' ); require_once __DIR__ . '/libs/Mf2/Parser.php'; From c03cf181e7e3a9300523b9e994668985224504c8 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Fri, 9 May 2025 05:41:11 +0200 Subject: [PATCH 04/12] Update release script --- .gitignore | 2 +- bin/release.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index bf0f98df..6f662acb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ node_modules readme.txt yarn.lock .phpunit.result.cache -new_release.md +new-changelog.md diff --git a/bin/release.sh b/bin/release.sh index 0d671627..83f962b9 100755 --- a/bin/release.sh +++ b/bin/release.sh @@ -57,10 +57,10 @@ if $(git tag | grep -Eq ^$FRIENDS_VERSION\$); then echo "This is the generated changelog:" cat new-changelog.md - echo -n "Do you want to continue? [y/N] " + echo -n "Do you want to continue? [Y/n] " read - if [ "$REPLY" != "y" ]; then + if [ "$REPLY" == "n" ]; then exit 1 fi fi From 2d5628d4072c9ba2035868cfbe7790f48ecd3830 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Wed, 21 May 2025 11:29:56 +0200 Subject: [PATCH 05/12] Always apply replace rules and fix html entity replacing (#530) --- includes/class-admin.php | 32 +++++++++++++++++--------------- includes/class-feed.php | 31 ++++++++++++++++++++++++------- templates/admin/edit-rules.php | 4 ++-- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/includes/class-admin.php b/includes/class-admin.php index afbb7f6f..9a8bfbb0 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -2157,22 +2157,24 @@ public function render_admin_add_friend() { $title = wp_strip_all_tags( $item->content ); } ?> -
  • date ); ?> (author: author ); ?>, type: post_format ); ?>): +
  • - content ) ) ); ?> words - -

    - content ), - array( - 'a' => array( 'href' => array() ), - 'img' => array( 'src' => array() ), - ) - ); - ?> -

    - +
    + + date ); ?> (author: author ); ?>, type: post_format ); ?>): + + content ) ) ); ?> words + +

    + + content ); + ?> + +

    + +

    +
  • get_feed_rules(); $action = $friend_user->get_feed_catch_all(); + $decided = false; foreach ( $rules as $rule ) { if ( $item instanceof \WP_Post ) { @@ -339,33 +340,49 @@ public function apply_feed_rules( $item, ?User_Feed $feed = null, ?User $friend_ } else { $field = $rule['field']; } - - if ( $item->$field && preg_match( '/' . str_replace( '/', '\\/', $rule['regex'] ) . '/ius', $item->$field ) ) { + $subject = false; + if ( $item->$field ) { + $subject = $item->$field; + } + $field_rule_field = $this->get_feed_rule_field( $rule['field'], $item ); + if ( isset( $item->_feed_rule_transform[ $field_rule_field ] ) ) { + $subject = $item->_feed_rule_transform[ $field_rule_field ]; + } + if ( $subject && preg_match( '/' . str_replace( '/', '\\/', $rule['regex'] ) . '/ius', $subject ) ) { if ( 'replace' === $rule['action'] ) { $item->_feed_rule_transform = array( - $this->get_feed_rule_field( $rule['field'], $item ) => preg_replace( '/' . $rule['regex'] . '/iu', $rule['replace'], $item->$field ), + $field_rule_field => preg_replace( '/' . str_replace( '/', '\\/', $rule['regex'] ) . '/ius', $rule['replace'], $subject ), ); continue; } + if ( $decided ) { + continue; + } $action = $rule['action']; - break; + $decided = true; } } + switch ( $action ) { case 'delete': $item->_feed_rule_delete = true; return $item; case 'trash': - $item->_feed_rule_transform = array( - 'post_status' => 'trash', + if ( empty( $item->_feed_rule_transform ) ) { + $item->_feed_rule_transform = array(); + } + $item->_feed_rule_transform = array_merge( + $item->_feed_rule_transform, + array( + 'post_status' => 'trash', + ) ); return $item; case 'accept': return $item; } - return $item; } diff --git a/templates/admin/edit-rules.php b/templates/admin/edit-rules.php index 83f1591a..dae5d449 100644 --- a/templates/admin/edit-rules.php +++ b/templates/admin/edit-rules.php @@ -23,7 +23,7 @@ - + - + () From 401629ca9f8a91b2bd5e7c4a91b3e91490a5ccc2 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Wed, 21 May 2025 11:30:07 +0200 Subject: [PATCH 06/12] Ajaxify Post Count display on the main friends page (#531) --- friends.js | 22 ++++++++ includes/class-access-control.php | 26 ++++++--- includes/class-admin.php | 18 +++++- includes/class-friends.php | 73 ++++++++++++++++++++++++- includes/class-frontend.php | 19 +++++++ templates/frontend/main-feed-header.php | 6 +- 6 files changed, 151 insertions(+), 13 deletions(-) diff --git a/friends.js b/friends.js index 233200a8..4eb640dd 100644 --- a/friends.js +++ b/friends.js @@ -201,6 +201,28 @@ refresh_feeds_now.apply( $( 'a.friends-refresh' ) ); } + $( function () { + const standard_count = $( '.chip.post-count-standard' ); + if ( standard_count.text().substr( 0, 3 ) === '...' ) { + wp.ajax.send( 'friends-get-post-counts', { + data: { + _ajax_nonce: standard_count.data( 'nonce' ) + }, + success( r ) { + for ( const i in r ) { + if ( ! r[ i ] ) { + $( '.chip.post-count-' + i ).remove(); + continue; + } + $( '.chip.post-count-' + i ).text( r[ i ] ); + } + }, + } ); + return false; + + } + }); + $document.on( 'click', 'a.friends-auth-link, button.comments.friends-auth-link', diff --git a/includes/class-access-control.php b/includes/class-access-control.php index 71eb716c..d3ef5826 100644 --- a/includes/class-access-control.php +++ b/includes/class-access-control.php @@ -312,22 +312,32 @@ public function notify_new_friend_request( $user_id, $new_role, $old_roles ) { * @return array */ public function strict_friend_checking_for_super_admin( $caps, $cap, $user_id ) { + static $user_roles = array(), $is_superadmin = array(); + if ( ! in_array( $cap, array( 'friend', 'acquaintance', 'pending_friend_request', 'friend_request', 'subscription' ) ) ) { return $caps; } - if ( ! is_multisite() || ! is_super_admin( $user_id ) ) { + + if ( isset( $is_superadmin[ $user_id ] ) ) { + if ( ! $is_superadmin[ $user_id ] ) { + return $caps; + } + } elseif ( ! is_multisite() || ! is_super_admin( $user_id ) ) { + $is_superadmin[ $user_id ] = false; return $caps; } + $is_superadmin[ $user_id ] = true; - $user = get_user_by( 'id', $user_id ); - if ( ! $user ) { - return $caps; + if ( ! isset( $user_roles[ $user_id ] ) ) { + $user_roles[ $user_id ] = get_user_meta( $user_id, 'wp_capabilities', true ); } - foreach ( $user->roles as $role ) { - // If they have the role we are checking for, we'll respond with unmapped caps. - if ( $cap === $role ) { - return $caps; + if ( is_array( $user_roles[ $user_id ] ) ) { + foreach ( $user_roles[ $user_id ] as $role ) { + // If they have the role we are checking for, we'll respond with unmapped caps. + if ( $cap === $role ) { + return $caps; + } } } diff --git a/includes/class-admin.php b/includes/class-admin.php index 9a8bfbb0..768c5ab9 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -492,6 +492,19 @@ public function send_friend_request( $rest_url, $user_login, $user_url, $display * @return string|bool The edit link or false. */ public static function admin_edit_user_link( $link, $user ) { + static $cache = array(); + if ( $user instanceof \WP_User ) { + $cache_key = $user->ID; + } else { + $cache_key = $user; + } + + if ( isset( $cache[ $cache_key ] ) ) { + if ( false === $cache[ $cache_key ] ) { + return $link; + } + return $cache[ $cache_key ]; + } if ( ! $user instanceof \WP_User ) { if ( is_string( $user ) ) { $user = User::get_by_username( $user ); @@ -501,13 +514,16 @@ public static function admin_edit_user_link( $link, $user ) { } if ( is_multisite() && is_super_admin( $user->ID ) ) { + $cache[ $cache_key ] = false; return $link; } if ( ! $user->has_cap( 'friends_plugin' ) ) { + $cache[ $cache_key ] = false; return $link; } - return self_admin_url( 'admin.php?page=edit-friend&user=' . $user->user_login ); + $cache[ $cache_key ] = self_admin_url( 'admin.php?page=edit-friend&user=' . $user->user_login ); + return $cache[ $cache_key ]; } public static function get_edit_friend_link( $user ) { diff --git a/includes/class-friends.php b/includes/class-friends.php index ff99f07e..b2309d88 100644 --- a/includes/class-friends.php +++ b/includes/class-friends.php @@ -889,14 +889,62 @@ public static function add_frontend_post_types( $post_types ) { return array_merge( array( Friends::CPT ), $post_types ); } + /** + * Gets the post count by post status. + * + * @param bool $force_fetching Whether to force fetching. + * + * @return object The post count. + */ + public function get_post_count_by_post_status( $force_fetching = false ) { + $cache_key = 'friends_post_count'; + + $post_types = apply_filters( 'friends_frontend_post_types', array() ); + + $counts = wp_cache_get( $cache_key, 'friends' ); + if ( false !== $counts ) { + return $counts; + } + + $counts = get_transient( $cache_key ); + if ( false !== $counts ) { + return $counts; + } elseif ( ! $force_fetching ) { + return (object) array( + 'trash' => '...', + ); + } + + $counts = new \stdClass(); + + foreach ( $post_types as $post_type ) { + $count = wp_count_posts( $post_type ); + foreach ( (array) $count as $post_status => $c ) { + if ( ! isset( $counts->$post_status ) ) { + $counts->$post_status = 0; + } + $counts->$post_status += $c; + } + } + + set_transient( $cache_key, $counts, HOUR_IN_SECONDS ); + wp_cache_set( $cache_key, $counts, 'friends', HOUR_IN_SECONDS ); + + return $counts; + } + /** * Gets the post count by post format. * + * @param bool $force_fetching Whether to force fetching. + * * @return array The post count by post format. */ - public function get_post_count_by_post_format() { + public function get_post_count_by_post_format( $force_fetching = false ) { $cache_key = 'post_count_by_post_format'; + $post_types = apply_filters( 'friends_frontend_post_types', array() ); + $counts = wp_cache_get( $cache_key, 'friends' ); if ( false !== $counts ) { return $counts; @@ -905,10 +953,25 @@ public function get_post_count_by_post_format() { $counts = get_transient( $cache_key ); if ( false !== $counts ) { return $counts; + } elseif ( ! $force_fetching ) { + $post_formats = get_post_format_slugs(); + uksort( + $post_formats, + function ( $a, $b ) { + // Sort standard to the top. + if ( 'standard' === $a ) { + return -1; + } elseif ( 'standard' === $b ) { + return 1; + } + return strnatcmp( $a, $b ); + } + ); + $counts = array_fill_keys( $post_formats, '...' ); + return $counts; } $counts = array(); - $post_types = apply_filters( 'friends_frontend_post_types', array() ); global $wpdb; @@ -1057,7 +1120,7 @@ public function get_main_header_data() { $data = array( 'description' => '', 'post_count_by_post_format' => $this->get_post_count_by_post_format(), - 'post_count_by_post_status' => \wp_count_posts( self::CPT ), + 'post_count_by_post_status' => $this->get_post_count_by_post_status(), ); return $data; @@ -1234,6 +1297,10 @@ public function get_post_format_plural_string( $format, $count ) { 'audio' => _nx_noop( '%s audio', '%s audios', 'Post format', 'friends' ), ); + if ( ! is_numeric( $count ) ) { + return sprintf( translate_nooped_plural( $plurals[ $format ], 0, 'friends' ), $count ); + } + return sprintf( translate_nooped_plural( $plurals[ $format ], $count, 'friends' ), number_format_i18n( $count ) ); } diff --git a/includes/class-frontend.php b/includes/class-frontend.php index c35f3a01..4bf1f098 100644 --- a/includes/class-frontend.php +++ b/includes/class-frontend.php @@ -107,6 +107,7 @@ private function register_hooks() { add_action( 'wp_ajax_friends-load-next-page', array( $this, 'ajax_load_next_page' ) ); add_action( 'wp_ajax_friends-autocomplete', array( $this, 'ajax_autocomplete' ) ); add_action( 'wp_ajax_friends-set-widget-open-state', array( $this, 'ajax_set_widget_open_state' ) ); + add_action( 'wp_ajax_friends-get-post-counts', array( $this, 'ajax_get_post_counts' ) ); add_action( 'friends_search_autocomplete', array( $this, 'autocomplete_user_search' ), 10, 2 ); add_action( 'wp_ajax_friends-star', array( $this, 'ajax_star_friend_user' ) ); add_action( 'wp_ajax_friends-load-comments', array( $this, 'ajax_load_comments' ) ); @@ -1093,6 +1094,24 @@ public function ajax_set_widget_open_state() { wp_send_json_success(); } + public function ajax_get_post_counts() { + check_ajax_referer( 'friends_post_counts' ); + $counts = array_fill_keys( get_post_format_slugs(), 0 ); + + foreach ( $this->friends->get_post_count_by_post_format( true ) as $post_format => $count ) { + $counts[ $post_format ] = $this->friends->get_post_format_plural_string( $post_format, $count ); + } + + $post_counts = $this->friends->get_post_count_by_post_status( true ); + if ( isset( $post_counts->trash ) && $post_counts->trash ) { + $counts['trash'] = sprintf( /* translators: %s is the number of hidden posts */_n( '%s hidden items', '%s hidden items', $post_counts->trash, 'friends' ), number_format_i18n( $post_counts->trash ) ); + } else { + $counts['trash'] = 0; + } + + wp_send_json_success( $counts ); + } + /** * Don't show the edit link for friend posts. * diff --git a/templates/frontend/main-feed-header.php b/templates/frontend/main-feed-header.php index b4e93085..5cb2f451 100644 --- a/templates/frontend/main-feed-header.php +++ b/templates/frontend/main-feed-header.php @@ -88,7 +88,7 @@ $count ) : ?> - get_post_format_plural_string( $post_format, $count ) ); ?> + get_post_format_plural_string( $post_format, $count ) ); ?> @@ -99,6 +99,10 @@ + + + + From de0ecacb62c52e6d7234ac2a0f9d1726af496210 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Wed, 21 May 2025 11:30:24 +0200 Subject: [PATCH 07/12] Fix missing nonce --- templates/frontend/author-header.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/frontend/author-header.php b/templates/frontend/author-header.php index eb6af7e4..1482ee30 100644 --- a/templates/frontend/author-header.php +++ b/templates/frontend/author-header.php @@ -113,7 +113,7 @@ 0 ) : ?> - + Date: Thu, 22 May 2025 09:55:14 +0200 Subject: [PATCH 08/12] Plugin Check Fixes (#532) --- README.md | 2 +- .../SimplePie/class-simplepie-misc.php | 4 ++-- friends.php | 4 ++-- includes/class-admin.php | 11 +++++++++-- includes/class-frontend.php | 2 +- includes/class-user-query.php | 2 +- templates/admin/dashboard-widget.php | 2 +- templates/admin/edit-feeds.php | 2 +- templates/admin/edit-friend.php | 2 +- templates/admin/import-export.php | 6 +++--- .../email/accepted-friend-request-text.php | 3 +++ templates/email/accepted-friend-request.php | 6 +++--- templates/email/footer-text.php | 3 +++ .../email/friend-message-received-text.php | 3 +++ templates/email/friend-message-received.php | 6 +++--- templates/email/keyword-match-post-text.php | 3 +++ templates/email/keyword-match-post.php | 19 +++++++++++++------ templates/email/lost-follower-text.php | 3 +++ templates/email/lost-follower.php | 6 +++--- templates/email/new-follower-text.php | 3 +++ templates/email/new-follower.php | 8 ++++---- templates/email/new-friend-post-text.php | 4 +++- templates/email/new-friend-post.php | 18 ++++++++++++------ templates/email/new-friend-request-text.php | 5 ++++- templates/email/new-friend-request.php | 6 +++--- .../unknown-friend-message-received-text.php | 13 ++++++++----- .../email/unknown-friend-message-received.php | 6 +++--- templates/embed/embed-content.php | 2 +- 28 files changed, 100 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 2d7de11d..cae440ca 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ - License: GPL-2.0-or-later - Stable tag: 3.5.1 -Your own WordPress at the center of your online activity. Follow friends and other websites and establish friendship relationships between blogs. +Follow others via RSS and ActivityPub and read their posts on your own WordPress. [![Active Installs](https://img.shields.io/wordpress/plugin/installs/friends?logo=wordpress&logoColor=%23fff&label=Active%20Installs&labelColor=%2323282dA&color=%2323282dA)](https://wordpress.org/plugins/friends/) [![Playground Demo Link](https://img.shields.io/wordpress/plugin/v/friends?logo=wordpress&logoColor=%23fff&label=Playground%20Demo&labelColor=%233858e9&color=%233858e9)](https://playground.wordpress.net/?networking=yes&blueprint-url=https://raw.githubusercontent.com/akirk/friends/refs/heads/main/assets/blueprints/blueprint.json) [![Configured Playground Demo Link](https://img.shields.io/wordpress/plugin/v/friends?logo=wordpress&logoColor=%23fff&label=Configured%20Playground%20Demo&labelColor=%23089809&color=%23089809)](https://playground.wordpress.net/?networking=yes&blueprint-url=https://raw.githubusercontent.com/akirk/friends/refs/heads/main/assets/blueprints/blueprint-prefilled.json) diff --git a/feed-parsers/SimplePie/class-simplepie-misc.php b/feed-parsers/SimplePie/class-simplepie-misc.php index 7d197cb6..2ade6ca2 100644 --- a/feed-parsers/SimplePie/class-simplepie-misc.php +++ b/feed-parsers/SimplePie/class-simplepie-misc.php @@ -24,7 +24,7 @@ class SimplePie_Misc extends \SimplePie_Misc { */ public static function change_encoding( $data, $input, $output ) { if ( 'UTF-8' === $input && 'UTF-8' === $output ) { - $clean_utf8_regex = <<<'END' + $clean_utf8_regex = ' ! # Thanks, https://stackoverflow.com/a/1401716/578588 ( # modified to clean for valid XML ASCII, see https://www.w3.org/TR/REC-xml/#NT-Char (?: [\x9\xD] # valid XML single-bytes @@ -38,7 +38,7 @@ public static function change_encoding( $data, $input, $output ) { | ( [\xC0-\xFF] ) # invalid byte in range 11000000 - 11111111 | (.) !x -END; +'; $data = preg_replace_callback( $clean_utf8_regex, function ( $captures ) { diff --git a/friends.php b/friends.php index 7f0c0bbd..bdccf275 100644 --- a/friends.php +++ b/friends.php @@ -4,9 +4,9 @@ * Plugin author: Alex Kirk * Plugin URI: https://github.com/akirk/friends * Version: 3.5.1 - * Requires PHP: 5.6 + * Requires PHP: 7.2 - * Description: A social network between WordPresses. Privacy focused, by itself a self-hosted RSS++ reader with notifications. + * Description: Follow others via RSS and ActivityPub and read their posts on your own WordPress. * * License: GPL2 * Text Domain: friends diff --git a/includes/class-admin.php b/includes/class-admin.php index 768c5ab9..103135ab 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -354,8 +354,15 @@ public function admin_refresh_friend_posts() { add_filter( 'friends_friend_private_feed_url', function ( $feed_url, $friend_user ) { - // translators: %1s is the name of the friend, %2$s is the feed URL. - printf( __( 'Refreshing %1$s at %2$s', 'friends' ) . '
    ', '
    ' . esc_html( $friend_user->user_login ) . '', '' . esc_html( $feed_url ) . '' ); + echo wp_kses( + // translators: %1s is the name of the friend, %2$s is the feed URL. + sprintf( __( 'Refreshing %1$s at %2$s', 'friends' ) . '
    ', '' . esc_html( $friend_user->user_login ) . '', '' . esc_html( $feed_url ) . '' ), + array( + 'a' => array( + 'href' => array(), + ), + ) + ); return $feed_url; }, 10, diff --git a/includes/class-frontend.php b/includes/class-frontend.php index 4bf1f098..0a0642c3 100644 --- a/includes/class-frontend.php +++ b/includes/class-frontend.php @@ -1406,7 +1406,7 @@ public function friend_posts_query( $query ) { exit; } } elseif ( ! Friends::is_main_user() ) { - wp_die( __( 'You are not allowed to view this page.', 'friends' ) ); + wp_die( esc_html__( 'You are not allowed to view this page.', 'friends' ) ); } return $query; diff --git a/includes/class-user-query.php b/includes/class-user-query.php index b66ba15a..09be0fb0 100644 --- a/includes/class-user-query.php +++ b/includes/class-user-query.php @@ -109,7 +109,7 @@ public static function all_associated_users() { } public function add_virtual_subscriptions( $args = array() ) { - if ( isset( $args['meta_key'] ) && substr( $args['meta_key'], -9 ) === '_starred' ) { + if ( isset( $args['meta_key'] ) && substr( $args['meta_key'], -8 ) === '_starred' ) { $args['meta_key'] = 'starred'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key } $searches = array(); diff --git a/templates/admin/dashboard-widget.php b/templates/admin/dashboard-widget.php index 426783d7..533848a1 100644 --- a/templates/admin/dashboard-widget.php +++ b/templates/admin/dashboard-widget.php @@ -25,7 +25,7 @@ - + display_name ); ?> diff --git a/templates/admin/edit-feeds.php b/templates/admin/edit-feeds.php index f4a1174c..d5bdf280 100644 --- a/templates/admin/edit-feeds.php +++ b/templates/admin/edit-feeds.php @@ -195,7 +195,7 @@

    Refresh this feed now.', 'friends' ), esc_url( wp_nonce_url( add_query_arg( 'user', $args['friend']->user_login, self_admin_url( 'admin.php?page=friends-refresh' ) ), 'friends-refresh' ) ) ); + echo wp_kses( sprintf( __( 'Refresh this feed now.', 'friends' ), esc_url( wp_nonce_url( add_query_arg( 'user', $args['friend']->user_login, self_admin_url( 'admin.php?page=friends-refresh' ) ), 'friends-refresh' ) ) ), array( 'a' => array( 'href' => array() ) ) ); ?>

    diff --git a/templates/admin/edit-friend.php b/templates/admin/edit-friend.php index 3918699a..0b58c5a9 100644 --- a/templates/admin/edit-friend.php +++ b/templates/admin/edit-friend.php @@ -24,7 +24,7 @@ $_title ) { ?> - <?php echo esc_attr( $_title ); ?> + <?php echo esc_attr( $_title ); ?>

    @@ -44,7 +44,7 @@

    @@ -57,7 +57,7 @@

    diff --git a/templates/email/accepted-friend-request-text.php b/templates/email/accepted-friend-request-text.php index 39e457d2..0e7a5c10 100644 --- a/templates/email/accepted-friend-request-text.php +++ b/templates/email/accepted-friend-request-text.php @@ -6,6 +6,9 @@ * @package Friends */ +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + // translators: %s is a user display name. printf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ); echo PHP_EOL; diff --git a/templates/email/accepted-friend-request.php b/templates/email/accepted-friend-request.php index 1a2f0652..8d0b3c48 100644 --- a/templates/email/accepted-friend-request.php +++ b/templates/email/accepted-friend-request.php @@ -10,20 +10,20 @@

    display_name ) ); + echo esc_html( sprintf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ) ); ?>

    display_name ) ); + echo esc_html( sprintf( __( 'Good news, %s has accepted your friend request.', 'friends' ), $args['friend_user']->display_name ) ); ?>

    friends page and look at their posts.', 'friends' ), esc_url( $args['friend_user']->get_local_friends_page_url() ) ); + echo wp_kses( sprintf( __( 'Go to your friends page and look at their posts.', 'friends' ), esc_url( $args['friend_user']->get_local_friends_page_url() ) ), array( 'a' => array( 'href' => true ) ) ); ?>

    diff --git a/templates/email/footer-text.php b/templates/email/footer-text.php index 0d0ede71..8fd0a66f 100644 --- a/templates/email/footer-text.php +++ b/templates/email/footer-text.php @@ -6,6 +6,9 @@ * @package Friends */ +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo PHP_EOL . PHP_EOL; // translators: %1$s is a site name, %2$s is a site url. diff --git a/templates/email/friend-message-received-text.php b/templates/email/friend-message-received-text.php index 18361f5a..99aea8b4 100644 --- a/templates/email/friend-message-received-text.php +++ b/templates/email/friend-message-received-text.php @@ -11,6 +11,9 @@ $normalized_whitespace = preg_replace( '/(' . PHP_EOL . '\s*' . PHP_EOL . ')+/m', PHP_EOL . PHP_EOL, $plain_text ); $quoted_text = '> ' . str_replace( PHP_EOL, PHP_EOL . '> ', trim( $normalized_whitespace ) ); +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + // translators: %s is a user display name. printf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ); echo PHP_EOL; diff --git a/templates/email/friend-message-received.php b/templates/email/friend-message-received.php index 811dc56d..0cef0551 100644 --- a/templates/email/friend-message-received.php +++ b/templates/email/friend-message-received.php @@ -10,14 +10,14 @@

    display_name ) ); + echo esc_html( sprintf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ) ); ?>

    display_name ) ); + echo esc_html( sprintf( __( 'We just received a message from %s:', 'friends' ), $args['friend_user']->display_name ) ); ?>

    @@ -31,6 +31,6 @@

    friends page to respond.', 'friends' ), esc_url( $args['friend_user']->get_local_friends_page_url() ) ); + echo wp_kses( sprintf( __( 'Go to your friends page to respond.', 'friends' ), esc_url( $args['friend_user']->get_local_friends_page_url() ) ), array( 'a' => array( 'href' => true ) ) ); ?>

    diff --git a/templates/email/keyword-match-post-text.php b/templates/email/keyword-match-post-text.php index ff8fac74..007f5ab0 100644 --- a/templates/email/keyword-match-post-text.php +++ b/templates/email/keyword-match-post-text.php @@ -11,6 +11,9 @@ $normalized_whitespace = preg_replace( '/(' . PHP_EOL . '\s*' . PHP_EOL . ')+/m', PHP_EOL . PHP_EOL, $plain_text ); $quoted_text = '> ' . str_replace( PHP_EOL, PHP_EOL . '> ', trim( $normalized_whitespace ) ); +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + // translators: %s is a keyword string specified by the user. printf( __( 'Keyword matched: %s', 'friends' ), $args['keyword'] ); diff --git a/templates/email/keyword-match-post.php b/templates/email/keyword-match-post.php index f4f7d212..7213ba4b 100644 --- a/templates/email/keyword-match-post.php +++ b/templates/email/keyword-match-post.php @@ -64,13 +64,20 @@

    global notification settings, change notifications for %3$s, or muffle posts like these.', 'friends' ), - '"' . esc_url( self_admin_url( 'admin.php?page=friends-settings' ) ) . '"', - '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend&user=' . $args['author']->ID ) ) . '"', - '' . esc_html( $args['author']->display_name ) . '', - '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend-rules&user=' . $args['author']->ID . '&post=' . $args['post']->ID ) ) . '"' + __( 'Manage your global notification settings, change notifications for %3$s, or muffle posts like these.', 'friends' ), + '"' . esc_url( self_admin_url( 'admin.php?page=friends-settings' ) ) . '"', + '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend&user=' . $args['author']->ID ) ) . '"', + '' . esc_html( $args['author']->display_name ) . '', + '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend-rules&user=' . $args['author']->ID . '&post=' . $args['post']->ID ) ) . '"' + ), + array( + 'em' => array(), + 'a' => array( 'href' => true ), + ) ); + ?>
    diff --git a/templates/email/lost-follower-text.php b/templates/email/lost-follower-text.php index 814ce9de..66cbf7f0 100644 --- a/templates/email/lost-follower-text.php +++ b/templates/email/lost-follower-text.php @@ -6,6 +6,9 @@ * @package Friends */ +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + // translators: %s is a user display name. printf( __( 'Hi %s!', 'friends' ), esc_html( $args['user']->display_name ) ); echo PHP_EOL; diff --git a/templates/email/lost-follower.php b/templates/email/lost-follower.php index b718e894..63393147 100644 --- a/templates/email/lost-follower.php +++ b/templates/email/lost-follower.php @@ -10,13 +10,13 @@

    display_name ) ); + echo esc_html( sprintf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ) ); ?>

    @@ -24,7 +24,7 @@ - <?php echo esc_attr( $args['follower']->get_name() ); ?> + <?php echo esc_attr( $args['follower']->get_name() ); ?> diff --git a/templates/email/new-follower-text.php b/templates/email/new-follower-text.php index 863064ac..fc2aeffa 100644 --- a/templates/email/new-follower-text.php +++ b/templates/email/new-follower-text.php @@ -6,6 +6,9 @@ * @package Friends */ +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + // translators: %s is a user display name. printf( __( 'Hi %s!', 'friends' ), esc_html( $args['user']->display_name ) ); echo PHP_EOL; diff --git a/templates/email/new-follower.php b/templates/email/new-follower.php index 74c5a669..fcbf29cc 100644 --- a/templates/email/new-follower.php +++ b/templates/email/new-follower.php @@ -10,13 +10,13 @@

    display_name ) ); + echo esc_html( sprintf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ) ); ?>

    @@ -24,7 +24,7 @@ - <?php echo esc_attr( $args['follower']->get_name() ); ?> + <?php echo esc_attr( $args['follower']->get_name() ); ?> @@ -45,7 +45,7 @@

    friends page to see what they recently posted about.', 'friends' ), esc_url( $args['following']->get_local_friends_page_url() ) ), array( 'a' => array( 'href' => array() ) ) ); diff --git a/templates/email/new-friend-post-text.php b/templates/email/new-friend-post-text.php index 050b610e..95c86dcd 100644 --- a/templates/email/new-friend-post-text.php +++ b/templates/email/new-friend-post-text.php @@ -1,6 +1,6 @@ ' . str_replace( PHP_EOL, PHP_EOL . '> ', trim( $normalized_whitespace ) ); +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped echo $quoted_text; echo PHP_EOL, PHP_EOL; diff --git a/templates/email/new-friend-post.php b/templates/email/new-friend-post.php index daf1c28e..b15318f9 100644 --- a/templates/email/new-friend-post.php +++ b/templates/email/new-friend-post.php @@ -56,13 +56,19 @@


    global notification settings, change notifications for %3$s, or muffle posts like these.', 'friends' ), - '"' . esc_url( self_admin_url( 'admin.php?page=friends-settings' ) ) . '"', - '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend&user=' . $args['author']->user_login ) ) . '"', - '' . esc_html( $args['author']->display_name ) . '', - '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend-rules&user=' . $args['author']->user_login . '&post=' . $args['post']->ID ) ) . '"' + __( 'Manage your global notification settings, change notifications for %3$s, or muffle posts like these.', 'friends' ), + '"' . esc_url( self_admin_url( 'admin.php?page=friends-settings' ) ) . '"', + '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend&user=' . $args['author']->user_login ) ) . '"', + '' . esc_html( $args['author']->display_name ) . '', + '"' . esc_url( self_admin_url( 'admin.php?page=edit-friend-rules&user=' . $args['author']->user_login . '&post=' . $args['post']->ID ) ) . '"' + ), + array( + 'em' => array(), + 'a' => array( 'href' => true ), + ) ); ?>
    diff --git a/templates/email/new-friend-request-text.php b/templates/email/new-friend-request-text.php index 3e280884..0a16f7a0 100644 --- a/templates/email/new-friend-request-text.php +++ b/templates/email/new-friend-request-text.php @@ -1,11 +1,14 @@ display_name ); echo PHP_EOL; diff --git a/templates/email/new-friend-request.php b/templates/email/new-friend-request.php index 3c96ebf3..86659ccd 100644 --- a/templates/email/new-friend-request.php +++ b/templates/email/new-friend-request.php @@ -10,20 +10,20 @@

    display_name ) ); + echo esc_html( sprintf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ) ); ?>

    display_name ) ); + echo esc_html( sprintf( __( 'You have received a new friend request from %s.', 'friends' ), $args['friend_user']->display_name ) ); ?>

    admin page to review the request and approve or delete it.', 'friends' ), esc_url( self_admin_url( 'users.php?role=friend_request' ) ) ); + echo wp_kses( sprintf( __( 'Go to your admin page to review the request and approve or delete it.', 'friends' ), esc_url( self_admin_url( 'users.php?role=friend_request' ) ) ), array( 'a' => array( 'href' => true ) ) ); ?>

    diff --git a/templates/email/unknown-friend-message-received-text.php b/templates/email/unknown-friend-message-received-text.php index 7f3e1c78..039b5913 100644 --- a/templates/email/unknown-friend-message-received-text.php +++ b/templates/email/unknown-friend-message-received-text.php @@ -1,6 +1,6 @@ ' . str_replace( PHP_EOL, PHP_EOL . '> ', trim( $normalized_whitespace ) ); +// This is a text e-mail, not a place for HTML escaping. +// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + // translators: %s is a user display name. -printf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ); +printf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo PHP_EOL; // translators: %s is a username. -printf( __( 'We just received a message from %s:', 'friends' ), $args['sender_name'] ); +printf( __( 'We just received a message from %s:', 'friends' ), $args['sender_name'] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo PHP_EOL . PHP_EOL; echo $quoted_text; // translators: %s is a URL. -printf( wp_strip_all_tags( __( 'Maybe you want to follow them to respond?', 'friends' ) ) ); +printf( wp_strip_all_tags( __( 'Maybe you want to follow them to respond?', 'friends' ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo PHP_EOL . PHP_EOL; -echo home_url( '?add-friend=' . esc_url( $args['feed_url'] ) ); +echo home_url( '?add-friend=' . esc_url( $args['feed_url'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped diff --git a/templates/email/unknown-friend-message-received.php b/templates/email/unknown-friend-message-received.php index 475ae3c1..8926cdb0 100644 --- a/templates/email/unknown-friend-message-received.php +++ b/templates/email/unknown-friend-message-received.php @@ -10,14 +10,14 @@

    display_name ) ); + echo esc_html( sprintf( __( 'Hi %s!', 'friends' ), $args['user']->display_name ) ); ?>

    @@ -31,6 +31,6 @@

    follow them to respond?', 'friends' ), esc_attr( home_url( '?add-friend=' . esc_url( $args['feed_url'] ) ) ) ); + echo wp_kses( sprintf( __( 'Maybe you want to follow them to respond?', 'friends' ), esc_attr( home_url( '?add-friend=' . esc_url( $args['feed_url'] ) ) ) ), array( 'a' => array( 'href' => true ) ) ); ?>

    diff --git a/templates/embed/embed-content.php b/templates/embed/embed-content.php index ac0d4e0a..770ac675 100644 --- a/templates/embed/embed-content.php +++ b/templates/embed/embed-content.php @@ -31,7 +31,7 @@