<!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>[54815] trunk/src/wp-admin/includes: Filesystem: Return FTP/FTP Sockets `exists()` methods to a previous state.</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/54815">54815</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/54815","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>desrosj</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-11-11 15:53:19 +0000 (Fri, 11 Nov 2022)</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'>Filesystem: Return FTP/FTP Sockets `exists()` methods to a previous state.

This partially reverts <a href="https://core.trac.wordpress.org/changeset/53860">[53860]</a> and <a href="https://core.trac.wordpress.org/changeset/53862">[53862]</a>, which refactored the `exists()` method to rely on `ftp_rawlist()` instead of `ftp_nlist()`.

<a href="https://core.trac.wordpress.org/changeset/53860">[53860]</a> makes a similar attempt to the ones made in <a href="https://core.trac.wordpress.org/changeset/33648">[33648]</a> and <a href="https://core.trac.wordpress.org/changeset/34733">[34733]</a> (which were also reverted in <a href="https://core.trac.wordpress.org/changeset/35944">[35944]</a>). Being compliant with the specifications while continuing to work without issue for all FTP servers continues seem impossible. These little ghosts are the ones we're scared of the most.

Props jsh4, afragen, costdev, pkolenbr, SergeyBiryukov, dd32, peterwilsoncc, gamecreature, desrosj.
Fixes <a href="https://core.trac.wordpress.org/ticket/56966">#56966</a>.
See <a href="https://core.trac.wordpress.org/ticket/51170">#51170</a>, <a href="https://core.trac.wordpress.org/ticket/28013">#28013</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminincludesclasswpfilesystemftpextphp">trunk/src/wp-admin/includes/class-wp-filesystem-ftpext.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswpfilesystemftpsocketsphp">trunk/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminincludesclasswpfilesystemftpextphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-filesystem-ftpext.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-filesystem-ftpext.php        2022-11-11 15:29:13 UTC (rev 54814)
+++ trunk/src/wp-admin/includes/class-wp-filesystem-ftpext.php  2022-11-11 15:53:19 UTC (rev 54815)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -412,18 +412,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Checks if a file or directory exists.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 2.5.0
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @since 6.1.0 Uses WP_Filesystem_FTPext::is_dir() to check for directory existence
-        *              and ftp_rawlist() to check for file existence.
</del><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param string $path Path to file or directory.
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether $path exists or not.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public function exists( $path ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( $this->is_dir( $path ) ) {
-                       return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $list = ftp_nlist( $this->link, $path );
+
+               if ( empty( $list ) && $this->is_dir( $path ) ) {
+                       return true; // File is an empty directory.
</ins><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">-                return ! empty( ftp_rawlist( $this->link, $path ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return ! empty( $list ); // Empty list = no file, so invert.
</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="trunksrcwpadminincludesclasswpfilesystemftpsocketsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php    2022-11-11 15:29:13 UTC (rev 54814)
+++ trunk/src/wp-admin/includes/class-wp-filesystem-ftpsockets.php      2022-11-11 15:53:19 UTC (rev 54815)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -414,18 +414,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Checks if a file or directory exists.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 2.5.0
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @since 6.1.0 Uses WP_Filesystem_ftpsockets::is_dir() to check for directory existence
-        *              and file size to check for file existence.
</del><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param string $path Path to file or directory.
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether $path exists or not.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public function exists( $path ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( $this->is_dir( $path ) ) {
-                       return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $list = $this->ftp->nlist( $path );
+
+               if ( empty( $list ) && $this->is_dir( $path ) ) {
+                       return true; // File is an empty directory.
</ins><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">-                return is_numeric( $this->size( $path ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return ! empty( $list ); // Empty list = no file, so invert.
+               // Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
</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>
</div>

</body>
</html>