<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[59241] trunk: Feeds: Validate enclosures prior to generating tags.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/59241">59241</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/59241","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>peterwilsoncc</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-10-15 22:22:42 +0000 (Tue, 15 Oct 2024)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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 <a href="https://core.trac.wordpress.org/ticket/58798">#58798</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesfeedphp">trunk/src/wp-includes/feed.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsfeedrssEnclosurephp">trunk/tests/phpunit/tests/feed/rssEnclosure.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesfeedphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed.php 2024-10-15 15:22:09 UTC (rev 59240)
+++ trunk/src/wp-includes/feed.php 2024-10-15 22:22:42 UTC (rev 59241)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -482,6 +482,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( (array) $val as $enc ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $enclosure = explode( "\n", $enc );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( count( $enclosure ) < 3 ) {
+ continue;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Only get the first element, e.g. 'audio/mpeg' from 'audio/mpeg mpga mp2 mp3'.
</span><span class="cx" style="display: block; padding: 0 10px"> $t = preg_split( '/[ \t]/', trim( $enclosure[2] ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $type = $t[0];
</span></span></pre></div>
<a id="trunktestsphpunittestsfeedrssEnclosurephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/feed/rssEnclosure.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/feed/rssEnclosure.php (rev 0)
+++ trunk/tests/phpunit/tests/feed/rssEnclosure.php 2024-10-15 22:22:42 UTC (rev 59241)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,139 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Test the feed.
+ *
+ * @group feed
+ */
+class Tests_rssEnclosure extends WP_UnitTestCase {
+ /**
+ * @ticket 58798
+ *
+ * @covers ::rss_enclosure
+ */
+ public function test_rss_enclosure_filter() {
+ $post_id = self::factory()->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 = '<enclosure url="' . $enclosure_data['url'] . '" length="' . $enclosure_data['length'] . '" type="' . $enclosure_data['type'] . '" />' . "\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" ),
+ );
+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/feed/rssEnclosure.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span></div>
</body>
</html>