<!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>[57740] trunk/src/wp-includes: Editor: Prevent infinite loops when filtering the font library folder.</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/57740">57740</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/57740","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>youknowriad</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-02-29 10:15:20 +0000 (Thu, 29 Feb 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'>Editor: Prevent infinite loops when filtering the font library folder.

Changing the font library is something we expect hosts to perform.
It's important that we make this filter as seemless as possible.
This commit prevents a potential infinite loop caused by calling wp_get_upload_dir() within the font_dir filter.

Props mmaattiiaass, ironprogrammer, costdev, swissspidy.
Fixes <a href="https://core.trac.wordpress.org/ticket/60652">#60652</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesfontsphp">trunk/src/wp-includes/fonts.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestfontfacescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesfontsphp"></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/fonts.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/fonts.php   2024-02-29 10:06:20 UTC (rev 57739)
+++ trunk/src/wp-includes/fonts.php     2024-02-29 10:15:20 UTC (rev 57740)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -96,16 +96,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 6.5.0
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param array $defaults {
- *     Array of information about the upload directory.
- *
- *     @type string       $path    Base directory and subdirectory or full path to the fonts upload directory.
- *     @type string       $url     Base URL and subdirectory or absolute URL to the fonts upload directory.
- *     @type string       $subdir  Subdirectory
- *     @type string       $basedir Path without subdir.
- *     @type string       $baseurl URL path without subdir.
- *     @type string|false $error   False or error message.
- * }
</del><span class="cx" style="display: block; padding: 0 10px">  * @return array $defaults {
</span><span class="cx" style="display: block; padding: 0 10px">  *     Array of information about the upload directory.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -117,19 +107,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *     @type string|false $error   False or error message.
</span><span class="cx" style="display: block; padding: 0 10px">  * }
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function wp_get_font_dir( $defaults = array() ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function wp_get_font_dir() {
</ins><span class="cx" style="display: block; padding: 0 10px">         $site_path = '';
</span><span class="cx" style="display: block; padding: 0 10px">        if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $site_path = '/sites/' . get_current_blog_id();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Sets the defaults.
-       $defaults['path']    = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path;
-       $defaults['url']     = untrailingslashit( content_url( 'fonts' ) ) . $site_path;
-       $defaults['subdir']  = '';
-       $defaults['basedir'] = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path;
-       $defaults['baseurl'] = untrailingslashit( content_url( 'fonts' ) ) . $site_path;
-       $defaults['error']   = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $defaults = array(
+               'path'    => path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path,
+               'url'     => untrailingslashit( content_url( 'fonts' ) ) . $site_path,
+               'subdir'  => '',
+               'basedir' => path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path,
+               'baseurl' => untrailingslashit( content_url( 'fonts' ) ) . $site_path,
+               'error'   => false,
+       );
</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">         * Filters the fonts directory data.
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestfontfacescontrollerphp"></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/rest-api/endpoints/class-wp-rest-font-faces-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php  2024-02-29 10:06:20 UTC (rev 57739)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php    2024-02-29 10:15:20 UTC (rev 57740)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -856,8 +856,22 @@
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        protected function handle_font_file_upload( $file ) {
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'upload_mimes', array( 'WP_Font_Utils', 'get_allowed_font_mime_types' ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                add_filter( 'upload_dir', 'wp_get_font_dir' );
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                /*
+                * Set the upload directory to the fonts directory.
+                *
+                * wp_get_font_dir() contains the 'font_dir' hook, whose callbacks are
+                * likely to call wp_get_upload_dir().
+                *
+                * To avoid an infinite loop, don't hook wp_get_font_dir() to 'upload_dir'.
+                * Instead, just pass its return value to the 'upload_dir' callback.
+                */
+               $font_dir       = wp_get_font_dir();
+               $set_upload_dir = function () use ( $font_dir ) {
+                       return $font_dir;
+               };
+               add_filter( 'upload_dir', $set_upload_dir );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $overrides = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'upload_error_handler' => array( $this, 'handle_font_file_upload_error' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        // Arbitrary string to avoid the is_uploaded_file() check applied
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -874,7 +888,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $uploaded_file = wp_handle_upload( $file, $overrides );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                remove_filter( 'upload_dir', 'wp_get_font_dir' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         remove_filter( 'upload_dir', $set_upload_dir );
</ins><span class="cx" style="display: block; padding: 0 10px">                 remove_filter( 'upload_mimes', array( 'WP_Font_Utils', 'get_allowed_font_mime_types' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return $uploaded_file;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -902,16 +916,16 @@
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        * Returns relative path to an uploaded font file.
-       *
-       * The path is relative to the current fonts directory.
-       *
-       * @since 6.5.0
-       * @access private
-       *
-       * @param string $path Full path to the file.
-       * @return string Relative path on success, unchanged path on failure.
-       */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Returns relative path to an uploaded font file.
+        *
+        * The path is relative to the current fonts directory.
+        *
+        * @since 6.5.0
+        * @access private
+        *
+        * @param string $path Full path to the file.
+        * @return string Relative path on success, unchanged path on failure.
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function relative_fonts_path( $path ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $new_path = $path;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>