Skip to:
Content

bbPress.org

Changeset 7501


Ignore:
Timestamp:
09/14/2026 03:57:10 PM (6 days ago)
Author:
johnjamesjacoby
Message:

Subscriptions: Protect password-protected content.

Redact author names and post bodies from subscription emails for password-protected forums, topics, replies, and descendant content, while retaining titles and links. This keeps subscription alerts useful without disclosing protected content.

In trunk, for 2.7.

Props vvh1te3zz.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/includes/common/functions.php

    r7499 r7501  
    13511351        $topic_id = bbp_get_topic_id( $topic_id );
    13521352        $forum_id = bbp_get_forum_id( $forum_id );
     1353        $password_protected = bbp_is_password_protected( $reply_id );
    13531354
    13541355        /** Topic *****************************************************************/
     
    14081409        $forum_title       = wp_specialchars_decode( wp_strip_all_tags( bbp_get_forum_title( $forum_id ) ), ENT_QUOTES );
    14091410        $topic_title       = wp_specialchars_decode( wp_strip_all_tags( bbp_get_topic_title( $topic_id ) ), ENT_QUOTES );
    1410         $reply_author_name = wp_specialchars_decode( wp_strip_all_tags( $reply_author_name ), ENT_QUOTES );
    1411         $reply_content     = wp_specialchars_decode( wp_strip_all_tags( bbp_get_reply_content( $reply_id ) ), ENT_QUOTES );
    14121411        $reply_url         = bbp_get_reply_url( $reply_id );
    14131412
     1413        // Do not include protected content in subscription emails
     1414        if ( ! empty( $password_protected ) ) {
     1415                $message = sprintf(
     1416
     1417                        /* translators: %s: Reply URL */
     1418                        esc_html__(
     1419                                'A new reply was posted in a password-protected discussion.
     1420
     1421Post Link: %s
     1422
     1423-----------
     1424
     1425You are receiving this email because you subscribed to a forum topic.
     1426
     1427Login and visit the topic to unsubscribe from these emails.',
     1428                                'bbpress'
     1429                        ),
     1430                        $reply_url
     1431                );
     1432
     1433        // Include the reply details in normal subscription emails
     1434        } else {
     1435                $reply_author_name = wp_specialchars_decode( wp_strip_all_tags( $reply_author_name ), ENT_QUOTES );
     1436                $reply_content     = wp_specialchars_decode( wp_strip_all_tags( bbp_get_reply_content( $reply_id ) ), ENT_QUOTES );
     1437                $message           = sprintf(
     1438
     1439                        /* translators: 1: Reply author name, 2: Reply content, 3: Reply URL */
     1440                        esc_html__(
     1441                                '%1$s wrote:
     1442
     1443%2$s
     1444
     1445Post Link: %3$s
     1446
     1447-----------
     1448
     1449You are receiving this email because you subscribed to a forum topic.
     1450
     1451Login and visit the topic to unsubscribe from these emails.',
     1452                                'bbpress'
     1453                        ),
     1454                        $reply_author_name,
     1455                        $reply_content,
     1456                        $reply_url
     1457                );
     1458        }
     1459
    14141460        // For plugins to filter messages per reply/topic/user
    1415         $message = sprintf(
    1416 
    1417                 /* translators: 1: Reply author name, 2: Reply content, 3: Reply URL */
    1418                 esc_html__(
    1419                         '%1$s wrote:
    1420 
    1421 %2$s
    1422 
    1423 Post Link: %3$s
    1424 
    1425 -----------
    1426 
    1427 You are receiving this email because you subscribed to a forum topic.
    1428 
    1429 Login and visit the topic to unsubscribe from these emails.',
    1430                         'bbpress'
    1431                 ),
    1432                 $reply_author_name,
    1433                 $reply_content,
    1434                 $reply_url
    1435         );
    1436 
    14371461        $message = apply_filters( 'bbp_subscription_mail_message', $message, $reply_id, $topic_id );
    14381462        if ( empty( $message ) ) {
     
    15261550        $topic_id = bbp_get_topic_id( $topic_id );
    15271551        $forum_id = bbp_get_forum_id( $forum_id );
     1552        $password_protected = bbp_is_password_protected( $topic_id );
    15281553
    15291554        /**
     
    15831608        $forum_title       = wp_specialchars_decode( wp_strip_all_tags( bbp_get_forum_title( $forum_id ) ), ENT_QUOTES );
    15841609        $topic_title       = wp_specialchars_decode( wp_strip_all_tags( bbp_get_topic_title( $topic_id ) ), ENT_QUOTES );
    1585         $topic_author_name = wp_specialchars_decode( wp_strip_all_tags( $topic_author_name ), ENT_QUOTES );
    1586         $topic_content     = wp_specialchars_decode( wp_strip_all_tags( bbp_get_topic_content( $topic_id ) ), ENT_QUOTES );
    15871610        $topic_url         = bbp_get_topic_permalink( $topic_id );
    15881611
     1612        // Do not include protected content in subscription emails
     1613        if ( ! empty( $password_protected ) ) {
     1614                $message = sprintf(
     1615
     1616                        /* translators: %s: Topic URL */
     1617                        esc_html__(
     1618                                'A new topic was posted in a password-protected discussion.
     1619
     1620Topic Link: %s
     1621
     1622-----------
     1623
     1624You are receiving this email because you subscribed to a forum.
     1625
     1626Login and visit the topic to unsubscribe from these emails.',
     1627                                'bbpress'
     1628                        ),
     1629                        $topic_url
     1630                );
     1631
     1632        // Include the topic details in normal subscription emails
     1633        } else {
     1634                $topic_author_name = wp_specialchars_decode( wp_strip_all_tags( $topic_author_name ), ENT_QUOTES );
     1635                $topic_content     = wp_specialchars_decode( wp_strip_all_tags( bbp_get_topic_content( $topic_id ) ), ENT_QUOTES );
     1636                $message           = sprintf(
     1637
     1638                        /* translators: 1: Topic author name, 2: Topic content, 3: Topic URL */
     1639                        esc_html__(
     1640                                '%1$s wrote:
     1641
     1642%2$s
     1643
     1644Topic Link: %3$s
     1645
     1646-----------
     1647
     1648You are receiving this email because you subscribed to a forum.
     1649
     1650Login and visit the topic to unsubscribe from these emails.',
     1651                                'bbpress'
     1652                        ),
     1653                        $topic_author_name,
     1654                        $topic_content,
     1655                        $topic_url
     1656                );
     1657        }
     1658
    15891659        // For plugins to filter messages per reply/topic/user
    1590         $message = sprintf(
    1591 
    1592                 /* translators: 1: Topic author name, 2: Topic content, 3: Topic URL */
    1593                 esc_html__(
    1594                         '%1$s wrote:
    1595 
    1596 %2$s
    1597 
    1598 Topic Link: %3$s
    1599 
    1600 -----------
    1601 
    1602 You are receiving this email because you subscribed to a forum.
    1603 
    1604 Login and visit the topic to unsubscribe from these emails.',
    1605                         'bbpress'
    1606                 ),
    1607                 $topic_author_name,
    1608                 $topic_content,
    1609                 $topic_url
    1610         );
    1611 
    16121660        $message = apply_filters( 'bbp_forum_subscription_mail_message', $message, $topic_id, $forum_id, $user_id );
    16131661        if ( empty( $message ) ) {
  • trunk/src/includes/common/template.php

    r7499 r7501  
    452452        // Filter & return
    453453        return (bool) apply_filters( 'bbp_is_custom_post_type', $retval, $original_post_types );
     454}
     455
     456/**
     457 * Check if a bbPress object or any of its parents is password protected.
     458 *
     459 * @since 2.6.16
     460 *
     461 * @param int    $object_id   Optional. Object ID. Defaults to the current post.
     462 * @param string $object_type Optional. Object type. Defaults to 'post'.
     463 * @return bool True if the object is password protected, otherwise false.
     464 */
     465function bbp_is_password_protected( $object_id = 0, $object_type = 'post' ) {
     466        $retval = false;
     467
     468        // Posts
     469        if ( 'post' === $object_type ) {
     470                $post     = get_post( $object_id );
     471                $post_ids = array();
     472                $forum_id = 0;
     473
     474                // Include the object
     475                if ( ! empty( $post ) && bbp_is_custom_post_type( $post ) ) {
     476                        $object_id = $post->ID;
     477                        $post_ids  = array( $object_id );
     478
     479                        // Include the topic and forum for replies
     480                        if ( bbp_is_reply( $object_id ) ) {
     481                                $post_ids[] = bbp_get_reply_topic_id( $object_id );
     482                                $forum_id   = bbp_get_reply_forum_id( $object_id );
     483
     484                        // Include the forum for topics
     485                        } elseif ( bbp_is_topic( $object_id ) ) {
     486                                $forum_id = bbp_get_topic_forum_id( $object_id );
     487
     488                        // Include the forum itself
     489                        } elseif ( bbp_is_forum( $object_id ) ) {
     490                                $forum_id = $object_id;
     491                        }
     492
     493                        // Include the forum and its ancestors
     494                        if ( ! empty( $forum_id ) ) {
     495                                $post_ids[] = $forum_id;
     496                                $post_ids   = array_merge( $post_ids, bbp_get_forum_ancestors( $forum_id ) );
     497                        }
     498                }
     499
     500                // Check the object and its parents
     501                foreach ( array_unique( array_filter( $post_ids ) ) as $post_id ) {
     502                        if ( ! empty( get_post_field( 'post_password', $post_id ) ) ) {
     503                                $retval = true;
     504                                break;
     505                        }
     506                }
     507        }
     508
     509        // Filter & return
     510        return (bool) apply_filters( 'bbp_is_password_protected', $retval, $object_id, $object_type );
    454511}
    455512
  • trunk/tests/phpunit/testcases/common/functions.php

    r7499 r7501  
    13821382                $this->assertContains( 'Bcc: moderator@example.org', $mail['headers'] );
    13831383                $this->assertNotContains( 'Bcc: participant@example.org', $mail['headers'] );
     1384        }
     1385
     1386        /**
     1387         * @covers ::bbp_notify_topic_subscribers
     1388         */
     1389        public function test_bbp_notify_topic_subscribers_redacts_password_protected_content() {
     1390                $subscriber_id = $this->factory->user->create( array(
     1391                        'user_email' => 'subscriber@example.org',
     1392                ) );
     1393                $author_id = $this->factory->user->create( array(
     1394                        'display_name' => 'Secret Author',
     1395                ) );
     1396
     1397                bbp_set_user_role( $subscriber_id, bbp_get_participant_role() );
     1398                bbp_set_user_role( $author_id, bbp_get_keymaster_role() );
     1399
     1400                $forum_id = $this->factory->forum->create( array(
     1401                        'post_title' => 'Protected Forum',
     1402                ) );
     1403                $topic_id = $this->factory->topic->create( array(
     1404                        'post_author'   => $author_id,
     1405                        'post_parent'   => $forum_id,
     1406                        'post_password' => 'password',
     1407                        'post_title'    => 'Protected Topic',
     1408                        'topic_meta'    => array(
     1409                                'forum_id' => $forum_id,
     1410                        ),
     1411                ) );
     1412                $reply_id = $this->factory->reply->create( array(
     1413                        'post_author'  => $author_id,
     1414                        'post_content' => 'Confidential reply body',
     1415                        'post_parent'  => $topic_id,
     1416                        'reply_meta'   => array(
     1417                                'forum_id' => $forum_id,
     1418                                'topic_id' => $topic_id,
     1419                        ),
     1420                ) );
     1421
     1422                $this->assertTrue( bbp_add_user_topic_subscription( $subscriber_id, $topic_id ) );
     1423
     1424                $mail = null;
     1425                $pre_wp_mail = function( $return, $atts ) use ( &$mail ) {
     1426                        $mail = $atts;
     1427                        return true;
     1428                };
     1429                add_filter( 'pre_wp_mail', $pre_wp_mail, 10, 2 );
     1430
     1431                $result = bbp_notify_topic_subscribers( $reply_id, $topic_id, $forum_id, array(), $author_id );
     1432                remove_filter( 'pre_wp_mail', $pre_wp_mail, 10 );
     1433
     1434                $this->assertTrue( $result );
     1435                $this->assertStringContainsString( 'Protected Forum', $mail['subject'] );
     1436                $this->assertStringContainsString( 'Protected Topic', $mail['subject'] );
     1437                $this->assertStringContainsString( 'password-protected discussion', $mail['message'] );
     1438                $this->assertStringContainsString( bbp_get_reply_url( $reply_id ), $mail['message'] );
     1439                $this->assertStringNotContainsString( 'Secret Author', $mail['message'] );
     1440                $this->assertStringNotContainsString( 'Confidential reply body', $mail['message'] );
     1441        }
     1442
     1443        /**
     1444         * @covers ::bbp_notify_forum_subscribers
     1445         */
     1446        public function test_bbp_notify_forum_subscribers_redacts_password_protected_content() {
     1447                $subscriber_id = $this->factory->user->create( array(
     1448                        'user_email' => 'subscriber@example.org',
     1449                ) );
     1450                $author_id = $this->factory->user->create( array(
     1451                        'display_name' => 'Secret Author',
     1452                ) );
     1453
     1454                bbp_set_user_role( $subscriber_id, bbp_get_participant_role() );
     1455                bbp_set_user_role( $author_id, bbp_get_keymaster_role() );
     1456
     1457                $forum_id = $this->factory->forum->create( array(
     1458                        'post_password' => 'password',
     1459                        'post_title'    => 'Protected Forum',
     1460                ) );
     1461                $topic_id = $this->factory->topic->create( array(
     1462                        'post_author'  => $author_id,
     1463                        'post_content' => 'Confidential topic body',
     1464                        'post_parent'  => $forum_id,
     1465                        'post_title'   => 'Protected Topic',
     1466                        'topic_meta'   => array(
     1467                                'forum_id' => $forum_id,
     1468                        ),
     1469                ) );
     1470
     1471                $this->assertTrue( bbp_add_user_forum_subscription( $subscriber_id, $forum_id ) );
     1472
     1473                $mail = null;
     1474                $pre_wp_mail = function( $return, $atts ) use ( &$mail ) {
     1475                        $mail = $atts;
     1476                        return true;
     1477                };
     1478                add_filter( 'pre_wp_mail', $pre_wp_mail, 10, 2 );
     1479
     1480                $result = bbp_notify_forum_subscribers( $topic_id, $forum_id, array(), $author_id );
     1481                remove_filter( 'pre_wp_mail', $pre_wp_mail, 10 );
     1482
     1483                $this->assertTrue( $result );
     1484                $this->assertStringContainsString( 'Protected Forum', $mail['subject'] );
     1485                $this->assertStringContainsString( 'Protected Topic', $mail['subject'] );
     1486                $this->assertStringContainsString( 'password-protected discussion', $mail['message'] );
     1487                $this->assertStringContainsString( bbp_get_topic_permalink( $topic_id ), $mail['message'] );
     1488                $this->assertStringNotContainsString( 'Secret Author', $mail['message'] );
     1489                $this->assertStringNotContainsString( 'Confidential topic body', $mail['message'] );
    13841490        }
    13851491
     
    14921598
    14931599        /**
     1600         * @covers ::bbp_is_password_protected
     1601         */
     1602        public function test_bbp_is_password_protected() {
     1603                $parent_forum_id = $this->factory->forum->create( array(
     1604                        'post_password' => 'password',
     1605                ) );
     1606                $forum_id = $this->factory->forum->create( array(
     1607                        'post_parent' => $parent_forum_id,
     1608                ) );
     1609                $topic_id = $this->factory->topic->create( array(
     1610                        'post_parent' => $forum_id,
     1611                        'topic_meta'  => array(
     1612                                'forum_id' => $forum_id,
     1613                        ),
     1614                ) );
     1615                $reply_id = $this->factory->reply->create( array(
     1616                        'post_parent' => $topic_id,
     1617                        'reply_meta'  => array(
     1618                                'forum_id' => $forum_id,
     1619                                'topic_id' => $topic_id,
     1620                        ),
     1621                ) );
     1622                $post_id = $this->factory->post->create( array(
     1623                        'post_password' => 'password',
     1624                ) );
     1625
     1626                $this->assertTrue( bbp_is_password_protected( $parent_forum_id ) );
     1627                $this->assertTrue( bbp_is_password_protected( $forum_id ) );
     1628                $this->assertTrue( bbp_is_password_protected( $topic_id ) );
     1629                $this->assertTrue( bbp_is_password_protected( $reply_id ) );
     1630                $this->assertFalse( bbp_is_password_protected( $post_id ) );
     1631                $this->assertFalse( bbp_is_password_protected( 999999 ) );
     1632
     1633                $filter = function( $retval, $object_id, $object_type ) {
     1634                        $this->assertFalse( $retval );
     1635                        $this->assertSame( 123, $object_id );
     1636                        $this->assertSame( 'term', $object_type );
     1637
     1638                        return true;
     1639                };
     1640                add_filter( 'bbp_is_password_protected', $filter, 10, 3 );
     1641
     1642                $this->assertTrue( bbp_is_password_protected( 123, 'term' ) );
     1643
     1644                remove_filter( 'bbp_is_password_protected', $filter, 10 );
     1645        }
     1646
     1647        /**
    14941648         * @covers ::bbp_do_not_guess_404_permalink
    14951649         */
Note: See TracChangeset for help on using the changeset viewer.