diff options
author | Robin Appelman <robin@icewind.nl> | 2023-08-29 16:33:06 +0200 |
---|---|---|
committer | Andy Scherzinger <info@andy-scherzinger.de> | 2025-02-05 20:50:19 +0100 |
commit | 1871296041d4fa0a5e9459d16347121b1e20cc5b (patch) | |
tree | f7034a838cd6254502eedca12567684846a22161 /apps/files_external/lib/Lib | |
parent | d6007918055be45d91c7d81b3e08fa092c55f9c2 (diff) | |
download | nextcloud-server-1871296041d4fa0a5e9459d16347121b1e20cc5b.tar.gz nextcloud-server-1871296041d4fa0a5e9459d16347121b1e20cc5b.zip |
fix: don't believe sftp when it tells us the mtime is less than we know it issftp-known-mtime
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/files_external/lib/Lib')
-rw-r--r-- | apps/files_external/lib/Lib/Storage/SFTP.php | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/apps/files_external/lib/Lib/Storage/SFTP.php b/apps/files_external/lib/Lib/Storage/SFTP.php index 44073beedec..aebc61806fc 100644 --- a/apps/files_external/lib/Lib/Storage/SFTP.php +++ b/apps/files_external/lib/Lib/Storage/SFTP.php @@ -6,11 +6,13 @@ */ namespace OCA\Files_External\Lib\Storage; +use Icewind\Streams\CallbackWrapper; use Icewind\Streams\CountWrapper; use Icewind\Streams\IteratorDirectory; use Icewind\Streams\RetryWrapper; use OC\Files\Storage\Common; use OC\Files\View; +use OCP\Cache\CappedMemoryCache; use OCP\Constants; use OCP\Files\FileInfo; use OCP\Files\IMimeTypeDetector; @@ -32,6 +34,8 @@ class SFTP extends Common { * @var \phpseclib\Net\SFTP */ protected $client; + private CappedMemoryCache $knownMTimes; + private IMimeTypeDetector $mimeTypeDetector; public const COPY_CHUNK_SIZE = 8 * 1024 * 1024; @@ -87,6 +91,9 @@ class SFTP extends Common { $this->root = '/' . ltrim($this->root, '/'); $this->root = rtrim($this->root, '/') . '/'; + + $this->knownMTimes = new CappedMemoryCache(); + $this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class); } @@ -297,6 +304,7 @@ class SFTP extends Common { } public function fopen(string $path, string $mode) { + $path = $this->cleanPath($path); try { $absPath = $this->absPath($path); $connection = $this->getConnection(); @@ -317,7 +325,13 @@ class SFTP extends Common { // the SFTPWriteStream doesn't go through the "normal" methods so it doesn't clear the stat cache. $connection->_remove_from_stat_cache($absPath); $context = stream_context_create(['sftp' => ['session' => $connection]]); - return fopen('sftpwrite://' . trim($absPath, '/'), 'w', false, $context); + $fh = fopen('sftpwrite://' . trim($absPath, '/'), 'w', false, $context); + if ($fh) { + $fh = CallbackWrapper::wrap($fh, null, null, function () use ($path) { + $this->knownMTimes->set($path, time()); + }); + } + return $fh; case 'a': case 'ab': case 'r+': @@ -343,14 +357,13 @@ class SFTP extends Common { return false; } if (!$this->file_exists($path)) { - $this->getConnection()->put($this->absPath($path), ''); + return $this->getConnection()->put($this->absPath($path), ''); } else { return false; } } catch (\Exception $e) { return false; } - return true; } /** @@ -379,11 +392,17 @@ class SFTP extends Common { */ public function stat(string $path): array|false { try { + $path = $this->cleanPath($path); $stat = $this->getConnection()->stat($this->absPath($path)); $mtime = isset($stat['mtime']) ? (int)$stat['mtime'] : -1; $size = isset($stat['size']) ? (int)$stat['size'] : 0; + // the mtime can't be less than when we last touched it + if ($knownMTime = $this->knownMTimes->get($path)) { + $mtime = max($mtime, $knownMTime); + } + return [ 'mtime' => $mtime, 'size' => $size, |