From 4edc60427eaf3c741bdc21925a0e2411a184a855 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Tue, 15 Oct 2024 22:22:42 +0000 Subject: [PATCH] Feeds: Validate enclosures prior to generating tags. Prevent possible PHP warnings caused by malformed enclosure meta data. This change ensures the enclosure meta data has at least three lines of text before generating the tag in `rss_enclosure()`. Props arypneta, johnjamesjacoby, nihar007, rahmohn, rghedin, zahardoc. Fixes #58798. git-svn-id: https://develop.svn.wordpress.org/trunk@59241 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/feed.php | 4 + tests/phpunit/tests/feed/rssEnclosure.php | 139 ++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 tests/phpunit/tests/feed/rssEnclosure.php diff --git a/src/wp-includes/feed.php b/src/wp-includes/feed.php index 7ef7059ce45bd..810abfee6fa2d 100644 --- a/src/wp-includes/feed.php +++ b/src/wp-includes/feed.php @@ -482,6 +482,10 @@ function rss_enclosure() { foreach ( (array) $val as $enc ) { $enclosure = explode( "\n", $enc ); + if ( count( $enclosure ) < 3 ) { + continue; + } + // Only get the first element, e.g. 'audio/mpeg' from 'audio/mpeg mpga mp2 mp3'. $t = preg_split( '/[ \t]/', trim( $enclosure[2] ) ); $type = $t[0]; diff --git a/tests/phpunit/tests/feed/rssEnclosure.php b/tests/phpunit/tests/feed/rssEnclosure.php new file mode 100644 index 0000000000000..37aca73f2b830 --- /dev/null +++ b/tests/phpunit/tests/feed/rssEnclosure.php @@ -0,0 +1,139 @@ +post->create(); + $GLOBALS['post'] = $post_id; + + $valid_enclosure_string = "http://example.com/sound2.mp3\n12345\naudio/mpeg\n"; + + update_post_meta( $post_id, 'enclosure', $valid_enclosure_string ); + + add_filter( + 'rss_enclosure', + function () { + return 'filtered_html_link_tag'; + } + ); + + $this->assertSame( 'filtered_html_link_tag', get_echo( 'rss_enclosure' ), 'The `rss_enclosure` filter could not be applied.' ); + } + + /** + * @ticket 58798 + * + * @covers ::rss_enclosure + */ + public function test_rss_enclosure_when_global_post_is_empty() { + $this->assertEmpty( get_echo( 'rss_enclosure' ), 'It should return empty when the global post is not set.' ); + } + + /** + * @ticket 58798 + * + * @covers ::rss_enclosure + */ + public function test_rss_enclosure_when_enclosure_meta_field_is_empty() { + $post_id = self::factory()->post->create(); + $GLOBALS['post'] = $post_id; + + $this->assertEmpty( get_echo( 'rss_enclosure' ), 'The global post does not have the `enclosure` meta field and should return empty. ' ); + } + + /** + * @ticket 58798 + * + * @dataProvider data_rss_enclosure_with_multiline_enclosure_string + * @covers ::rss_enclosure + */ + public function test_rss_enclosure_with_multiline_enclosure_string( $enclosure_data, $enclosure_string ) { + $post_id = self::factory()->post->create(); + $GLOBALS['post'] = $post_id; + + update_post_meta( $post_id, 'enclosure', $enclosure_string ); + + $expected = '' . "\n"; + + $this->assertSame( $expected, get_echo( 'rss_enclosure' ), 'It should return a valid enclosure tag. ' ); + } + + /** + * Data provider for valid enclosure string. + * + * @return array[]. + */ + public function data_rss_enclosure_with_multiline_enclosure_string() { + return array( + 'two-break-lines' => array( + array( + 'url' => 'http://example.com/sound2.mp3', + 'length' => 12345, + 'type' => 'audio/mpeg', + ), + "http://example.com/sound2.mp3\n12345\naudio/mpeg", + ), + 'three-break-lines' => array( + array( + 'url' => 'http://example.com/sound2.mp3', + 'length' => 12345, + 'type' => 'audio/mpeg', + ), + "http://example.com/sound2.mp3\n12345\naudio/mpeg\n", + ), + 'extra-break-line-at-end' => array( + array( + 'url' => 'http://example.com/sound2.mp3', + 'length' => 12345, + 'type' => 'audio/mpeg', + ), + "http://example.com/sound2.mp3\n12345\naudio/mpeg\n\n", + ), + 'extra-type-elements' => array( + array( + 'url' => 'http://example.com/sound2.mp3', + 'length' => 12345, + 'type' => 'audio/mpeg', + ), + "http://example.com/sound2.mp3\n12345\naudio/mpeg mpga mp2 mp3\n", + ), + ); + } + + /** + * @ticket 58798 + * + * @dataProvider data_rss_enclosure_with_non_valid_enclosure_string + * @covers ::rss_enclosure + */ + public function test_rss_enclosure_with_non_valid_enclosure_string( $enclosure_string ) { + $post_id = self::factory()->post->create(); + $GLOBALS['post'] = $post_id; + + update_post_meta( $post_id, 'enclosure', $enclosure_string ); + + $this->assertEmpty( get_echo( 'rss_enclosure' ), 'It should return empty when the `enclosure` meta field is not saved in a multiline string.' ); + } + + /** + * Data provider for non-valid enclosure string. + * + * @return array[]. + */ + public function data_rss_enclosure_with_non_valid_enclosure_string() { + return array( + 'empty' => array( '' ), + 'no-break-lines' => array( 'http://example.com/sound2.mp3 12345 audio/mpeg' ), + 'one-break-line' => array( "http://example.com/sound2.mp3\n12345 audio/mpeg" ), + ); + } +}