<!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>[48429] trunk: Feeds: Ensure that enclosures produce valid XML.</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/48429">48429</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/48429","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>whyisjake</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2020-07-10 22:21:22 +0000 (Fri, 10 Jul 2020)</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: Ensure that enclosures produce valid XML.

Metadata that is stored on newlines has the possibility of missing values, so rather then coercing values, we can check for them and then implicity set the values.

Fixes <a href="https://core.trac.wordpress.org/ticket/33591">#33591</a>.
Props jonnybot, stevenkword, vtieu, birgire, SergeyBiryukov, davidbaumwald, rebasaurus, whyisjake.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesfeedphp">trunk/src/wp-includes/feed.php</a></li>
<li><a href="#trunktestsphpunittestsfeedatomphp">trunk/tests/phpunit/tests/feed/atom.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    2020-07-10 22:01:57 UTC (rev 48428)
+++ trunk/src/wp-includes/feed.php      2020-07-10 22:21:22 UTC (rev 48429)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -519,6 +519,35 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'enclosure' === $key ) {
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                               $url    = '';
+                               $type   = '';
+                               $length = 0;
+
+                               $mimes = get_allowed_mime_types();
+
+                               // Parse url
+                               if ( isset( $enclosure[0] ) && is_string( $enclosure[0] ) ) {
+                                       $url = trim( $enclosure[0] );
+                               }
+
+                               // Parse length and type
+                               foreach ( range( 1, 2 ) as $i ) {
+                                       if ( isset( $enclosure[ $i ] ) ) {
+                                               if ( is_numeric( $enclosure[ $i ] ) ) {
+                                                       $length = trim( $enclosure[ $i ] );
+                                               } elseif ( in_array( $enclosure[ $i ], $mimes ) ) {
+                                                       $type = trim( $enclosure[ $i ] );
+                                               }
+                                       }
+                               }
+
+                               $html_link_tag = sprintf(
+                                       "<link href=\"%s\" rel=\"enclosure\" length=\"%d\" type=\"%s\" />\n",
+                                       esc_url( $url ),
+                                       esc_attr( $length ),
+                                       esc_attr( $type )
+                               );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 /**
</span><span class="cx" style="display: block; padding: 0 10px">                                 * Filters the atom enclosure HTML link tag for the current post.
</span><span class="cx" style="display: block; padding: 0 10px">                                 *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -526,7 +555,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                 *
</span><span class="cx" style="display: block; padding: 0 10px">                                 * @param string $html_link_tag The HTML link tag with a URI and other attributes.
</span><span class="cx" style="display: block; padding: 0 10px">                                 */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                echo apply_filters( 'atom_enclosure', '<link href="' . esc_url( trim( $enclosure[0] ) ) . '" rel="enclosure" length="' . absint( trim( $enclosure[1] ) ) . '" type="' . esc_attr( trim( $enclosure[2] ) ) . '" />' . "\n" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         echo apply_filters( 'atom_enclosure', $html_link_tag );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunktestsphpunittestsfeedatomphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/feed/atom.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/feed/atom.php   2020-07-10 22:01:57 UTC (rev 48428)
+++ trunk/tests/phpunit/tests/feed/atom.php     2020-07-10 22:21:22 UTC (rev 48429)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -205,4 +205,75 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @test 33591
+        */
+       function test_atom_enclosure_with_extended_url_length_type_parsing() {
+               $enclosures = array(
+                       array(
+                               'actual'   => "https://wordpress.dev/wp-content/uploads/2017/09/movie.mp4\n318465\nvideo/mp4",     // url length type
+                               'expected' => array(
+                                       'href'   => 'https://wordpress.dev/wp-content/uploads/2017/09/movie.mp4',
+                                       'length' => 318465,
+                                       'type'   => 'video/mp4',
+                               ),
+                       ),
+                       array(
+                               'actual'   => "https://wordpress.dev/wp-content/uploads/2017/09/movie.mp4\nvideo/mp4\n318465",     // url type length
+                               'expected' => array(
+                                       'href'   => 'https://wordpress.dev/wp-content/uploads/2017/09/movie.mp4',
+                                       'length' => 318465,
+                                       'type'   => 'video/mp4',
+                               ),
+                       ),
+                       array(
+                               'actual'   => "https://wordpress.dev/wp-content/uploads/2017/09/movie.mp4\n318465",                // url length
+                               'expected' => array(
+                                       'href'   => 'https://wordpress.dev/wp-content/uploads/2017/09/movie.mp4',
+                                       'length' => 318465,
+                                       'type'   => '',
+                               ),
+                       ),
+                       array(
+                               'actual'   => "https://wordpress.dev/wp-content/uploads/2017/01/audio.mp3\n\naudio/mpeg",          // url type
+                               'expected' => array(
+                                       'href'   => 'https://wordpress.dev/wp-content/uploads/2017/01/audio.mp3',
+                                       'length' => 0,
+                                       'type'   => 'audio/mpeg',
+                               ),
+                       ),
+                       array(
+                               'actual'   => 'https://wordpress.dev/wp-content/uploads/2016/01/test.mp4',                         // url
+                               'expected' => array(
+                                       'href'   => 'https://wordpress.dev/wp-content/uploads/2016/01/test.mp4',
+                                       'length' => 0,
+                                       'type'   => '',
+                               ),
+                       ),
+               );
+
+               $post_id = end( self::$posts );
+               foreach ( $enclosures as $enclosure ) {
+                       add_post_meta( $post_id, 'enclosure', $enclosure['actual'] );
+               }
+               $this->go_to( '/?feed=atom' );
+               $feed    = $this->do_atom();
+               $xml     = xml_to_array( $feed );
+               $entries = xml_find( $xml, 'feed', 'entry' );
+               $entries = array_slice( $entries, 0, 1 );
+
+               foreach ( $entries as $key => $entry ) {
+                       $links = xml_find( $entries[ $key ]['child'], 'link' );
+                       $i     = 0;
+                       foreach ( (array) $links as $link ) {
+                               if ( 'enclosure' == $link['attributes']['rel'] ) {
+                                       $this->assertEquals( $enclosures[ $i ]['expected']['href'], $link['attributes']['href'] );
+                                       $this->assertEquals( $enclosures[ $i ]['expected']['length'], $link['attributes']['length'] );
+                                       $this->assertEquals( $enclosures[ $i ]['expected']['type'], $link['attributes']['type'] );
+                                       $i++;
+                               }
+                       }
+               }
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>