From 77641003fa3827da6444c43fa8b87371549f9eed Mon Sep 17 00:00:00 2001 From: terrafrost <terrafrost@php.net> Date: Sat, 10 May 2014 19:52:38 -0500 Subject: [PATCH 1/4] SFTP: add file_exists, is_dir and is_file functions also expand caching layer --- phpseclib/Net/SFTP.php | 187 ++++++++++++++++++++++++++++++++++------- 1 file changed, 156 insertions(+), 31 deletions(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index c891db57..a0f1038f 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -229,18 +229,18 @@ class Net_SFTP extends Net_SSH2 var $sftp_errors = array(); /** - * Directory Cache + * Cache * * Rather than always having to open a directory and close it immediately there after to see if a file is a directory or * rather than always * - * @see Net_SFTP::_save_dir() - * @see Net_SFTP::_remove_dir() - * @see Net_SFTP::_is_dir() + * @see Net_SFTP::_update_cache() + * @see Net_SFTP::_remove_from_cache() + * @see Net_SFTP::_query_cache() * @var Array * @access private */ - var $dirs = array(); + var $cache = array(); /** * Max SFTP Packet Size @@ -252,6 +252,16 @@ class Net_SFTP extends Net_SSH2 */ var $max_sftp_packet; + /** + * Cache Flag + * + * @see Net_SFTP::disableCache() + * @see Net_SFTP::enableCache() + * @var Boolean + * @access private + */ + var $use_cache = true; + /** * Default Constructor. * @@ -522,11 +532,31 @@ class Net_SFTP extends Net_SSH2 $this->pwd = $this->_realpath('.'); - $this->_save_dir($this->pwd); + $this->_update_cache($this->pwd, array()); return true; } + /** + * Disable the cache + * + * @access public + */ + function disableCache() + { + $this->use_cache = false; + } + + /** + * Enable the cache + * + * @access public + */ + function enableCache() + { + $this->use_cache = true; + } + /** * Returns the current directory name * @@ -645,7 +675,7 @@ class Net_SFTP extends Net_SSH2 $dir = $this->_realpath($dir); // confirm that $dir is, in fact, a valid directory - if ($this->_is_dir($dir)) { + if ($this->use_cache && is_array($this->_query_cache($dir))) { $this->pwd = $dir; return true; } @@ -677,7 +707,7 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_save_dir($dir); + $this->_update_cache($dir, array()); $this->pwd = $dir; return true; @@ -752,7 +782,7 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_save_dir($dir); + $this->_update_cache($dir, array()); $contents = array(); while (true) { @@ -786,7 +816,9 @@ class Net_SFTP extends Net_SSH2 } if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) { - $this->_save_dir($dir . '/' . $shortname); + $this->_update_cache($dir . '/' . $shortname, array()); + } else { + $this->_update_cache($dir . '/' . $shortname, 1); } // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the // final SSH_FXP_STATUS packet should tell us that, already. @@ -836,36 +868,41 @@ class Net_SFTP extends Net_SSH2 } /** - * Save directories to cache + * Save files / directories to cache * - * @param String $dir + * @param String $path + * @param optional Boolean $file * @access private */ - function _save_dir($dir) + function _update_cache($path, $value) { - // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($dir, '/')) - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $dir)); + // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/')) + $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - $temp = &$this->dirs; + $temp = &$this->cache; foreach ($dirs as $dir) { if (!isset($temp[$dir])) { $temp[$dir] = array(); } + if ($dir == end($dirs)) { + $temp[$dir] = $value; + } $temp = &$temp[$dir]; } } /** - * Remove directories from cache + * Remove files / directories from cache * - * @param String $dir + * @param String $path + * @param optional Boolean $file * @access private */ - function _remove_dir($dir) + function _remove_from_cache($path) { - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $dir)); + $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - $temp = &$this->dirs; + $temp = &$this->cache; foreach ($dirs as $dir) { if ($dir == end($dirs)) { unset($temp[$dir]); @@ -879,26 +916,26 @@ class Net_SFTP extends Net_SSH2 } /** - * Checks cache for directory + * Checks cache for path * - * Mainly used by chdir, which is, in turn, also used for determining whether or not an individual - * file is a directory or not by stat() and lstat() + * Mainly used by file_exists * * @param String $dir + * @return Mixed * @access private */ - function _is_dir($dir) + function _query_cache($path) { - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $dir)); + $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - $temp = &$this->dirs; + $temp = &$this->cache; foreach ($dirs as $dir) { if (!isset($temp[$dir])) { return false; } $temp = &$temp[$dir]; } - return true; + return $temp; } /** @@ -923,8 +960,10 @@ class Net_SFTP extends Net_SSH2 $stat = $this->_stat($filename, NET_SFTP_STAT); if ($stat === false) { + $this->_update_cache($filename, 0); return false; } + $this->_update_cache($filename, 1); if (isset($stat['type'])) { return $stat; } @@ -955,6 +994,7 @@ class Net_SFTP extends Net_SSH2 $filename = $this->_realpath($filename); if ($filename === false) { + $this->_update_cache($filename, 0); return false; } @@ -962,6 +1002,7 @@ class Net_SFTP extends Net_SSH2 if ($lstat === false) { return false; } + $this->_update_cache($filename, 1); if (isset($lstat['type'])) { return $lstat; } @@ -1094,6 +1135,8 @@ class Net_SFTP extends Net_SSH2 return false; } + $this->_update_cache($filename, 1); + return $this->_setstat($filename, $attr, false); } @@ -1375,7 +1418,7 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_save_dir($dir); + $this->_update_cache($dir, array()); return true; } @@ -1415,7 +1458,8 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_remove_dir($dir); + //$this->_remove_from_cache($dir); + $this->_update_cache($dir, 0); return true; } @@ -1568,6 +1612,8 @@ class Net_SFTP extends Net_SSH2 fclose($fp); } + $this->_update_cache($remote_file, 1); + return $this->_close_handle($handle); } @@ -1739,6 +1785,8 @@ class Net_SFTP extends Net_SSH2 return false; } + $this->_update_cache($remote_file, 1); + // if $content isn't set that means a file was written to return isset($content) ? $content : true; } @@ -1786,6 +1834,8 @@ class Net_SFTP extends Net_SSH2 return $result; } + $this->_update_cache($path, 0); + return true; } @@ -1841,12 +1891,13 @@ class Net_SFTP extends Net_SSH2 $i = 0; } } + //$this->_remove_from_cache($path); + $this->_update_cache($path, 0); } if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) { return false; } - $this->_remove_dir($path); $i++; @@ -1860,6 +1911,77 @@ class Net_SFTP extends Net_SSH2 return true; } + /** + * Checks whether a file or directory exists + * + * @param String $path + * @return Boolean + * @access public + */ + function file_exists($path) + { + if ($this->use_cache) { + $path = $this->_realpath($path); + + $result = $this->_query_cache($path); + + if ($result !== false) { + // return true if $result is an array or if it's int(1) + return $result !== 0; + } + } + + return $this->stat($path) !== false; + } + + /** + * Tells whether the filename is a directory + * + * @param String $path + * @return Boolean + * @access public + */ + function is_dir($path) + { + if ($this->use_cache) { + $path = $this->_realpath($path); + + $result = $this->_query_cache($path); + + if ($result !== false) { + return is_array($result); + } + } + + $result = $this->stat($path); + + return $result['type'] === NET_SFTP_TYPE_DIRECTORY; + } + + /** + * Tells whether the filename is a regular file + * + * @param String $path + * @return Boolean + * @access public + */ + function is_file($path) + { + if ($this->use_cache) { + $path = $this->_realpath($path); + + $result = $this->_query_cache($path); + + if ($result !== false) { + return $result === 1; + } + } + + $result = $this->stat($path); + + return $result['type'] === NET_SFTP_TYPE_REGULAR; + } + /** * Renames a file or a directory on the SFTP server * @@ -1899,6 +2021,9 @@ class Net_SFTP extends Net_SSH2 return false; } + $this->_update_cache($oldname, 0); + $this->_update_cache($newname, 1); + return true; } From 0a0398268a28226aa879571bb96478430638a255 Mon Sep 17 00:00:00 2001 From: terrafrost <terrafrost@php.net> Date: Tue, 13 May 2014 17:10:32 -0500 Subject: [PATCH 2/4] SFTP: add support for recursive nlist and rawlist --- phpseclib/Net/SFTP.php | 72 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index a0f1038f..c50761c4 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -717,24 +717,88 @@ class Net_SFTP extends Net_SSH2 * Returns a list of files in the given directory * * @param optional String $dir + * @param optional Boolean $recursive * @return Mixed * @access public */ - function nlist($dir = '.') + function nlist($dir = '.', $recursive = false) { - return $this->_list($dir, false); + $dir = $this->_realpath($dir . '/'); + switch (true) { + case !$this->use_cache: + case !is_array($result = $this->_query_cache($dir)): + case !isset($result['.']): + case $recursive: + break; + default: + return array_keys($result); + } + $files = $this->_list($dir, false); + + if (!$recursive) { + return $files; + } + + static $relativeDir = ''; + + $result = array(); + foreach ($files as $value) { + if ($value == '.' || $value == '..') { + if ($relativeDir == '') { + $result[] = $value; + } + continue; + } + if (is_array($this->_query_cache($this->_realpath($dir . '/' . $value)))) { + $oldDir = $relativeDir; + $relativeDir.= $value . '/'; + $temp = $this->nlist($dir . '/' . $value, true); + $result = array_merge($result, $temp); + $relativeDir = $oldDir; + } else { + $result[] = $relativeDir . $value; + } + } + + return $result; } /** * Returns a detailed list of files in the given directory * * @param optional String $dir + * @param optional Boolean $recursive * @return Mixed * @access public */ - function rawlist($dir = '.') + function rawlist($dir = '.', $recursive = false) { - return $this->_list($dir, true); + $files = $this->_list($dir, true); + if (!$recursive || $files === false) { + return $files; + } + + static $depth = 0; + + foreach ($files as $key=>$value) { + if ($depth != 0 && $key == '..') { + unset($files[$key]); + continue; + } + if ($key != '.' && $key != '..' && is_array($this->_query_cache($this->_realpath($dir . '/' . $key)))) { + $depth++; + $files[$key] = $this->rawlist($dir . '/' . $key, true); + $depth--; + } else { + $temp = new StdClass(); + foreach ($value as $subkey=>$subvalue) { + $temp->$subkey = $subvalue; + } + $files[$key] = $temp; + } + } + + return $files; } /** From e09a6968da704dd26729e369b8f7a2b4a3df1a0a Mon Sep 17 00:00:00 2001 From: terrafrost <terrafrost@php.net> Date: Sun, 18 May 2014 15:34:10 -0500 Subject: [PATCH 3/4] SFTP: switch from using file existence cache to stat cache, like PHP also add a few new functions - is_link and filesize --- phpseclib/Net/SFTP.php | 214 +++++++++++++++++++++++++++-------------- 1 file changed, 140 insertions(+), 74 deletions(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index c50761c4..34b82bdb 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -229,18 +229,18 @@ class Net_SFTP extends Net_SSH2 var $sftp_errors = array(); /** - * Cache + * Stat Cache * - * Rather than always having to open a directory and close it immediately there after to see if a file is a directory or - * rather than always + * Rather than always having to open a directory and close it immediately there after to see if a file is a directory + * we'll cache the results. * - * @see Net_SFTP::_update_cache() - * @see Net_SFTP::_remove_from_cache() - * @see Net_SFTP::_query_cache() + * @see Net_SFTP::_update_stat_cache() + * @see Net_SFTP::_remove_from_stat_cache() + * @see Net_SFTP::_query_stat_cache() * @var Array * @access private */ - var $cache = array(); + var $stat_cache = array(); /** * Max SFTP Packet Size @@ -253,14 +253,14 @@ class Net_SFTP extends Net_SSH2 var $max_sftp_packet; /** - * Cache Flag + * Stat Cache Flag * - * @see Net_SFTP::disableCache() - * @see Net_SFTP::enableCache() + * @see Net_SFTP::disableStatCache() + * @see Net_SFTP::enableStatCache() * @var Boolean * @access private */ - var $use_cache = true; + var $use_stat_cache = true; /** * Default Constructor. @@ -532,7 +532,7 @@ class Net_SFTP extends Net_SSH2 $this->pwd = $this->_realpath('.'); - $this->_update_cache($this->pwd, array()); + $this->_update_stat_cache($this->pwd, array()); return true; } @@ -542,9 +542,9 @@ class Net_SFTP extends Net_SSH2 * * @access public */ - function disableCache() + function disableStatCache() { - $this->use_cache = false; + $this->use_stat_cache = false; } /** @@ -552,9 +552,9 @@ class Net_SFTP extends Net_SSH2 * * @access public */ - function enableCache() + function enableStatCache() { - $this->use_cache = true; + $this->use_stat_cache = true; } /** @@ -675,7 +675,7 @@ class Net_SFTP extends Net_SSH2 $dir = $this->_realpath($dir); // confirm that $dir is, in fact, a valid directory - if ($this->use_cache && is_array($this->_query_cache($dir))) { + if ($this->use_cache && is_array($this->_query_stat_cache($dir))) { $this->pwd = $dir; return true; } @@ -707,7 +707,7 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_update_cache($dir, array()); + $this->_update_stat_cache($dir, array()); $this->pwd = $dir; return true; @@ -723,24 +723,26 @@ class Net_SFTP extends Net_SSH2 */ function nlist($dir = '.', $recursive = false) { - $dir = $this->_realpath($dir . '/'); - switch (true) { - case !$this->use_cache: - case !is_array($result = $this->_query_cache($dir)): - case !isset($result['.']): - case $recursive: - break; - default: - return array_keys($result); - } + return $this->_nlist_helper($dir, $recursive, ''); + } + + /** + * Helper method for nlist + * + * @param String $dir + * @param Boolean $recursive + * @param String $relativeDir + * @return Mixed + * @access private + */ + function _nlist_helper($dir, $recursive, $relativeDir) + { $files = $this->_list($dir, false); if (!$recursive) { return $files; } - static $relativeDir = ''; - $result = array(); foreach ($files as $value) { if ($value == '.' || $value == '..') { @@ -749,12 +751,9 @@ class Net_SFTP extends Net_SSH2 } continue; } - if (is_array($this->_query_cache($this->_realpath($dir . '/' . $value)))) { - $oldDir = $relativeDir; - $relativeDir.= $value . '/'; - $temp = $this->nlist($dir . '/' . $value, true); + if (is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $value)))) { + $temp = $this->_nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/'); $result = array_merge($result, $temp); - $relativeDir = $oldDir; } else { $result[] = $relativeDir . $value; } @@ -785,16 +784,12 @@ class Net_SFTP extends Net_SSH2 unset($files[$key]); continue; } - if ($key != '.' && $key != '..' && is_array($this->_query_cache($this->_realpath($dir . '/' . $key)))) { + if ($key != '.' && $key != '..' && is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key)))) { $depth++; $files[$key] = $this->rawlist($dir . '/' . $key, true); $depth--; } else { - $temp = new StdClass(); - foreach ($value as $subkey=>$subvalue) { - $temp->$subkey = $subvalue; - } - $files[$key] = $temp; + $files[$key] = (object) $value; } } @@ -846,7 +841,7 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_update_cache($dir, array()); + $this->_update_stat_cache($dir, array()); $contents = array(); while (true) { @@ -880,9 +875,9 @@ class Net_SFTP extends Net_SSH2 } if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) { - $this->_update_cache($dir . '/' . $shortname, array()); + $this->_update_stat_cache($dir . '/' . $shortname, array()); } else { - $this->_update_cache($dir . '/' . $shortname, 1); + $this->_update_stat_cache($dir . '/' . $shortname, (object) $attributes); } // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the // final SSH_FXP_STATUS packet should tell us that, already. @@ -938,7 +933,7 @@ class Net_SFTP extends Net_SSH2 * @param optional Boolean $file * @access private */ - function _update_cache($path, $value) + function _update_stat_cache($path, $value) { // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/')) $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); @@ -962,7 +957,7 @@ class Net_SFTP extends Net_SSH2 * @param optional Boolean $file * @access private */ - function _remove_from_cache($path) + function _remove_from_stat_cache($path) { $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); @@ -988,7 +983,7 @@ class Net_SFTP extends Net_SSH2 * @return Mixed * @access private */ - function _query_cache($path) + function _query_stat_cache($path) { $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); @@ -1022,13 +1017,23 @@ class Net_SFTP extends Net_SSH2 return false; } + if ($this->use_stat_cache) { + $result = $this->_query_stat_cache($filename); + if (is_array($result)) { + return (array) $result['.']; + } + if ($result !== false) { + return (array) $result; + } + } + $stat = $this->_stat($filename, NET_SFTP_STAT); if ($stat === false) { - $this->_update_cache($filename, 0); + $this->_update_stat_cache($filename, 0); return false; } - $this->_update_cache($filename, 1); if (isset($stat['type'])) { + $this->_update_stat_cache($filename, $stat); return $stat; } @@ -1038,6 +1043,8 @@ class Net_SFTP extends Net_SSH2 NET_SFTP_TYPE_REGULAR; $this->pwd = $pwd; + $this->_update_stat_cache($filename, $stat); + return $stat; } @@ -1058,23 +1065,34 @@ class Net_SFTP extends Net_SSH2 $filename = $this->_realpath($filename); if ($filename === false) { - $this->_update_cache($filename, 0); return false; } + if ($this->use_stat_cache) { + $result = $this->_query_stat_cache($filename); + if (is_array($result)) { + return (array) $result['.']; + } + if ($result !== false) { + return (array) $result; + } + } + $lstat = $this->_stat($filename, NET_SFTP_LSTAT); if ($lstat === false) { return false; } - $this->_update_cache($filename, 1); if (isset($lstat['type'])) { + $this->_update_stat_cache($filename, $lstat); return $lstat; } $stat = $this->_stat($filename, NET_SFTP_STAT); if ($lstat != $stat) { - return array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK)); + $lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK)); + $this->_update_stat_cache($filename, $lstat); + return $stat; } $pwd = $this->pwd; @@ -1083,6 +1101,8 @@ class Net_SFTP extends Net_SSH2 NET_SFTP_TYPE_REGULAR; $this->pwd = $pwd; + $this->_update_stat_cache($filename, $lstat); + return $lstat; } @@ -1199,8 +1219,6 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_update_cache($filename, 1); - return $this->_setstat($filename, $attr, false); } @@ -1312,6 +1330,8 @@ class Net_SFTP extends Net_SSH2 return false; } + $this->_remove_from_stat_cache($filename); + if ($recursive) { $i = 0; $result = $this->_setstat_recursive($filename, $attr, $i); @@ -1482,8 +1502,6 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_update_cache($dir, array()); - return true; } @@ -1522,8 +1540,11 @@ class Net_SFTP extends Net_SSH2 return false; } - //$this->_remove_from_cache($dir); - $this->_update_cache($dir, 0); + $this->_remove_from_stat_cache($dir); + // the following will do a soft delete, which would be useful if you deleted a file + // and then tried to do a stat on the deleted file. the above, in contrast, does + // a hard delete + //$this->_update_stat_cache($dir, 0); return true; } @@ -1676,8 +1697,6 @@ class Net_SFTP extends Net_SSH2 fclose($fp); } - $this->_update_cache($remote_file, 1); - return $this->_close_handle($handle); } @@ -1849,8 +1868,6 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_update_cache($remote_file, 1); - // if $content isn't set that means a file was written to return isset($content) ? $content : true; } @@ -1898,7 +1915,7 @@ class Net_SFTP extends Net_SSH2 return $result; } - $this->_update_cache($path, 0); + $this->_remove_from_stat_cache($path); return true; } @@ -1955,8 +1972,7 @@ class Net_SFTP extends Net_SSH2 $i = 0; } } - //$this->_remove_from_cache($path); - $this->_update_cache($path, 0); + $this->_remove_from_stat_cache($path); } if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) { @@ -1984,10 +2000,10 @@ class Net_SFTP extends Net_SSH2 */ function file_exists($path) { - if ($this->use_cache) { + if ($this->use_stat_cache) { $path = $this->_realpath($path); - $result = $this->_query_cache($path); + $result = $this->_query_stat_cache($path); if ($result !== false) { // return true if $result is an array or if it's int(1) @@ -2007,10 +2023,10 @@ class Net_SFTP extends Net_SSH2 */ function is_dir($path) { - if ($this->use_cache) { + if ($this->use_stat_cache) { $path = $this->_realpath($path); - $result = $this->_query_cache($path); + $result = $this->_query_stat_cache($path); if ($result !== false) { return is_array($result); @@ -2031,13 +2047,13 @@ class Net_SFTP extends Net_SSH2 */ function is_file($path) { - if ($this->use_cache) { + if ($this->use_stat_cache) { $path = $this->_realpath($path); - $result = $this->_query_cache($path); + $result = $this->_query_stat_cache($path); if ($result !== false) { - return $result === 1; + return !is_array($result); } } @@ -2046,6 +2062,54 @@ class Net_SFTP extends Net_SSH2 return $result['type'] === NET_SFTP_TYPE_REGULAR; } + /** + * Tells whether the filename is a symbolic link + * + * @param String $path + * @return Boolean + * @access public + */ + function is_link($path) + { + if ($this->use_stat_cache) { + $path = $this->_realpath($path); + + $result = $this->_query_stat_cache($path); + + if (is_object($result) && isset($result->type)) { + return $result->type === NET_SFTP_TYPE_SYMLINK; + } + } + + $result = $this->stat($path); + + return $result['type'] === NET_SFTP_TYPE_SYMLINK; + } + + /** + * Gets file size + * + * @param String $path + * @return Boolean + * @access public + */ + function filesize($path) + { + if ($this->use_stat_cache) { + $path = $this->_realpath($path); + + $result = $this->_query_stat_cache($path); + + if (is_object($result) && isset($result->size)) { + return $result->size; + } + } + + $result = $this->stat($path); + + return $result['size']; + } + /** * Renames a file or a directory on the SFTP server * @@ -2085,8 +2149,10 @@ class Net_SFTP extends Net_SSH2 return false; } - $this->_update_cache($oldname, 0); - $this->_update_cache($newname, 1); + // don't move the stat cache entry over since this operation could very well change the + // atime and mtime attributes + //$this->_update_stat_cache($newname, $this->_query_stat_cache($oldname)); + $this->_remove_from_stat_cache($oldname); return true; } From 36fa9e4e487d10fce1de9ba0b4065c30cd4fc7b2 Mon Sep 17 00:00:00 2001 From: terrafrost <terrafrost@php.net> Date: Sun, 18 May 2014 15:55:12 -0500 Subject: [PATCH 4/4] SFTP: use_cache -> use_stat_cache --- phpseclib/Net/SFTP.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index 34b82bdb..a64b48cd 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -675,7 +675,7 @@ class Net_SFTP extends Net_SSH2 $dir = $this->_realpath($dir); // confirm that $dir is, in fact, a valid directory - if ($this->use_cache && is_array($this->_query_stat_cache($dir))) { + if ($this->use_stat_cache && is_array($this->_query_stat_cache($dir))) { $this->pwd = $dir; return true; }