Skip to content

Commit eedd8dc

Browse files
hweihwangicewind1991
authored andcommitted
fix(trashbin): keep metadata consistent on move
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
1 parent ac9c17c commit eedd8dc

1 file changed

Lines changed: 76 additions & 54 deletions

File tree

apps/files_trashbin/lib/Trashbin.php

Lines changed: 76 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,60 @@ public static function move2trash($file_path, $ownerOnly = false) {
299299

300300
$configuredTrashbinSize = static::getConfiguredTrashbinSize($owner);
301301
if ($configuredTrashbinSize >= 0 && $sourceInfo->getSize() >= $configuredTrashbinSize) {
302+
$trashStorage->releaseLock($trashInternalPath, ILockingProvider::LOCK_EXCLUSIVE, $lockingProvider);
302303
return false;
303304
}
304305

306+
// there is still a possibility that the file has been deleted by a remote user
307+
$deletedBy = self::overwriteDeletedBy($user);
308+
309+
$deleteTrashRow = static function () use ($owner, $filename, $timestamp): void {
310+
$query = Server::get(IDBConnection::class)->getQueryBuilder();
311+
$query->delete('files_trash')
312+
->where($query->expr()->eq('user', $query->createNamedParameter($owner)))
313+
->andWhere($query->expr()->eq('id', $query->createNamedParameter($filename)))
314+
->andWhere($query->expr()->eq('timestamp', $query->createNamedParameter($timestamp)));
315+
$query->executeStatement();
316+
};
317+
318+
$query = Server::get(IDBConnection::class)->getQueryBuilder();
319+
$query->insert('files_trash')
320+
->setValue('id', $query->createNamedParameter($filename))
321+
->setValue('timestamp', $query->createNamedParameter($timestamp))
322+
->setValue('location', $query->createNamedParameter($location))
323+
->setValue('user', $query->createNamedParameter($owner))
324+
->setValue('deleted_by', $query->createNamedParameter($deletedBy));
325+
$inserted = false;
305326
try {
306-
$moveSuccessful = true;
327+
$inserted = ($query->executeStatement() === 1);
328+
} catch (\Throwable $e) {
329+
Server::get(LoggerInterface::class)->error(
330+
'trash bin database insert failed',
331+
[
332+
'app' => 'files_trashbin',
333+
'exception' => $e,
334+
'user' => $owner,
335+
'filename' => $filename,
336+
'timestamp' => $timestamp,
337+
]
338+
);
339+
}
340+
if (!$inserted) {
341+
Server::get(LoggerInterface::class)->error(
342+
'trash bin database couldn\'t be updated, skipping trash move',
343+
[
344+
'app' => 'files_trashbin',
345+
'user' => $owner,
346+
'filename' => $filename,
347+
'timestamp' => $timestamp,
348+
]
349+
);
350+
$trashStorage->releaseLock($trashInternalPath, ILockingProvider::LOCK_EXCLUSIVE, $lockingProvider);
351+
return false;
352+
}
307353

354+
$moveSuccessful = true;
355+
try {
308356
$inCache = $sourceStorage->getCache()->inCache($sourceInternalPath);
309357
$trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
310358
if ($inCache) {
@@ -333,65 +381,39 @@ public static function move2trash($file_path, $ownerOnly = false) {
333381
} else {
334382
$trashStorage->getUpdater()->remove($trashInternalPath);
335383
}
336-
return false;
384+
$moveSuccessful = false;
337385
}
338386

339-
if ($moveSuccessful) {
340-
// there is still a possibility that the file has been deleted by a remote user
341-
$deletedBy = self::overwriteDeletedBy($user);
342-
343-
$query = Server::get(IDBConnection::class)->getQueryBuilder();
344-
$query->insert('files_trash')
345-
->setValue('id', $query->createNamedParameter($filename))
346-
->setValue('timestamp', $query->createNamedParameter($timestamp))
347-
->setValue('location', $query->createNamedParameter($location))
348-
->setValue('user', $query->createNamedParameter($owner))
349-
->setValue('deleted_by', $query->createNamedParameter($deletedBy));
350-
$inserted = false;
351-
try {
352-
$inserted = ($query->executeStatement() === 1);
353-
} catch (\Throwable $e) {
354-
Server::get(LoggerInterface::class)->error(
355-
'trash bin database insert failed',
356-
[
357-
'app' => 'files_trashbin',
358-
'exception' => $e,
359-
'user' => $owner,
360-
'filename' => $filename,
361-
'timestamp' => $timestamp,
362-
]
363-
);
364-
}
365-
if (!$inserted) {
366-
Server::get(LoggerInterface::class)->error(
367-
'trash bin database couldn\'t be updated, removing trash payload',
368-
[
369-
'app' => 'files_trashbin',
370-
'user' => $owner,
371-
'filename' => $filename,
372-
'timestamp' => $timestamp,
373-
]
374-
);
375-
if ($trashStorage->file_exists($trashInternalPath)) {
376-
if ($trashStorage->is_dir($trashInternalPath)) {
377-
$trashStorage->rmdir($trashInternalPath);
378-
} else {
379-
$trashStorage->unlink($trashInternalPath);
380-
}
387+
if (!$moveSuccessful) {
388+
Server::get(LoggerInterface::class)->error(
389+
'trash move failed, removing trash metadata and payload',
390+
[
391+
'app' => 'files_trashbin',
392+
'user' => $owner,
393+
'filename' => $filename,
394+
'timestamp' => $timestamp,
395+
]
396+
);
397+
$deleteTrashRow();
398+
if ($trashStorage->file_exists($trashInternalPath)) {
399+
if ($trashStorage->is_dir($trashInternalPath)) {
400+
$trashStorage->rmdir($trashInternalPath);
401+
} else {
402+
$trashStorage->unlink($trashInternalPath);
381403
}
382-
$trashStorage->getUpdater()->remove($trashInternalPath);
383-
$moveSuccessful = false;
384404
}
385-
if ($inserted) {
386-
Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path),
387-
'trashPath' => Filesystem::normalizePath(static::getTrashFilename($filename, $timestamp))]);
405+
$trashStorage->getUpdater()->remove($trashInternalPath);
406+
}
407+
408+
if ($moveSuccessful) {
409+
Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path),
410+
'trashPath' => Filesystem::normalizePath(static::getTrashFilename($filename, $timestamp))]);
388411

389-
self::retainVersions($filename, $owner, $ownerPath, $timestamp);
412+
self::retainVersions($filename, $owner, $ownerPath, $timestamp);
390413

391-
// if owner !== user we need to also add a copy to the users trash
392-
if ($user !== $owner && $ownerOnly === false) {
393-
self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
394-
}
414+
// if owner !== user we need to also add a copy to the users trash
415+
if ($user !== $owner && $ownerOnly === false) {
416+
self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
395417
}
396418
}
397419

0 commit comments

Comments
 (0)